diff --git a/.gitattributes b/.gitattributes index 22cea3dc1e3..d523e13f3c2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -24,11 +24,12 @@ admin/charsets/mapfiles/PTCP154 whitespace=cr-at-eol leim/MISC-DIC/cangjie-table.b5 whitespace=cr-at-eol leim/MISC-DIC/cangjie-table.cns whitespace=cr-at-eol leim/MISC-DIC/pinyin.map whitespace=cr-at-eol -lib-src/update-game-score.exe.manifest whitespace=cr-at-eol -nt/nmake.defs whitespace=cr-at-eol -test/etags/c-src/dostorture.c whitespace=cr-at-eol -test/etags/cp-src/c.C whitespace=cr-at-eol -test/etags/html-src/algrthms.html whitespace=cr-at-eol +test/manual/etags/c-src/dostorture.c whitespace=cr-at-eol +test/manual/etags/cp-src/c.C whitespace=cr-at-eol +test/manual/etags/html-src/algrthms.html whitespace=cr-at-eol + +# The todo-mode file format includes trailing whitespace. +*.tod[aorty] -whitespace=blank-at-eol # The upstream maintainer does not want to remove trailing whitespace. doc/misc/texinfo.tex -whitespace=blank-at-eol @@ -48,23 +49,23 @@ doc/misc/texinfo.tex -whitespace=blank-at-eol etc/e/eterm-color binary # Git's builtin diff hunk header styles. -*.ada diff=ada -*.[ch] diff=cpp +*.ad[abs] diff=ada +*.[Cch] diff=cpp *.cc diff=cpp -*.cpp diff=cpp +*.[ch]pp diff=cpp *.hh diff=cpp *.for diff=fortran *.html diff=html *.shtml diff=html *.xml diff=html *.java diff=java -*.m diff=objc +*.[HMm] diff=objc +*.pas diff=pascal *.perl diff=perl *.pl diff=perl *.php diff=php *.py diff=python *.rb diff=ruby -*.ruby diff=ruby *.tex diff=tex # Hooks for non-default diff hunk headers; see autogen.sh. @@ -74,7 +75,7 @@ etc/e/eterm-color binary *.mk diff=make *[Mm]akefile diff=make Makefile.in diff=make -*.sh diff=shell +*[-.]sh diff=shell *.texi diff=texinfo # # Diff hunk header special-case file names. @@ -87,6 +88,8 @@ admin/merge-pkg-config diff=shell admin/quick-install-emacs diff=shell admin/update-copyright diff=shell admin/update_autogen diff=shell +build-aux/config.guess diff=shell +build-aux/config.sub diff=shell build-aux/git-hooks/commit-msg diff=shell build-aux/git-hooks/pre-commit diff=shell build-aux/gitlog-to-emacslog diff=shell diff --git a/.gitignore b/.gitignore index 1bef664ac9e..f7b561e0b2e 100644 --- a/.gitignore +++ b/.gitignore @@ -26,14 +26,6 @@ # Built by 'autogen.sh'. /aclocal.m4 /configure -build-aux/ar-lib -build-aux/compile -build-aux/config.guess -build-aux/config.sub -build-aux/depcomp -build-aux/install-sh -build-aux/missing -lib/Makefile.in src/config.in # Built by 'configure'. @@ -42,29 +34,29 @@ InfoPlist.strings Makefile makefile !etc/refcards/Makefile -!modules/mod-test/Makefile !test/lisp/progmodes/flymake-resources/Makefile -!test/manual/indent/Makefile !test/manual/etags/Makefile !test/manual/etags/make-src/Makefile +!test/manual/indent/Makefile /*.cache /confdefs.h /config.status /configure.lineno /conftest* +lib/gnulib.mk src/config.h src/epaths.h +src/emacs-module.h # C-level sources built by 'make'. lib/alloca.h -lib/arg-nonnull.h lib/byteswap.h -lib/c++defs.h lib/dirent.h lib/errno.h lib/execinfo.h lib/fcntl.h lib/getopt.h +lib/getopt-cdefs.h lib/inttypes.h lib/libgnu.a lib/limits.h @@ -76,7 +68,6 @@ lib/string.h lib/sys/ lib/time.h lib/unistd.h -lib/warn-on-use.h src/buildobj.h src/globals.h src/lisp.mk @@ -131,8 +122,6 @@ deps/ *.stamp stamp_BLD src/gl-stamp -src/stamp-h.in -src/stamp-h1 # Object files and debugging. *.a @@ -143,7 +132,6 @@ src/stamp-h1 *.o *.res *.so -[0-9]*.core core core.*[0-9] gmon.out @@ -152,13 +140,12 @@ oo-spd/ src/*.map # Tests. -test/indent/*.new -test/make-test-deps.mk test/manual/biditest.txt test/manual/etags/srclist test/manual/etags/regexfile test/manual/etags/ETAGS test/manual/etags/CTAGS +test/manual/indent/*.new # ctags, etags. TAGS @@ -256,6 +243,7 @@ gnustmp* # Version control and locks. *.orig *.rej +*.swp *~ .#* \#*\# @@ -274,7 +262,7 @@ etc/emacs.tmpdesktop # Microsoft-related builds and installations. *.in-h _* -!build-aux/snippet/_Noreturn.h +!lib/_Noreturn.h /bin/ /BIN/ /data/ @@ -288,7 +276,6 @@ lib/SYS/ /site-lisp/ nt/emacs.rc nt/emacsclient.rc -nt/gnulib.mk src/gdb.ini /var/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000000..9b25ead37f1 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,41 @@ +# Copyright (C) 2017 Free Software Foundation, Inc. +# +# This file is part of GNU Emacs. +# +# GNU Emacs is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GNU Emacs is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Emacs. If not, see . + +# GNU Emacs support for the GitLab protocol for CI + +# The presence of this file does not imply any FSF/GNU endorsement of +# any particular service that uses that protocol. Also, it is intended for +# evaluation purposes, thus possibly temporary. + +# Maintainer: tzz@lifelogs.com +# URL: https://gitlab.com/emacs-ci/emacs + +image: debian:unstable + +before_script: + - apt update -qq + - apt install -y -qq build-essential autoconf automake libncurses-dev gnutls-dev + +stages: + - test + +test: + stage: test + script: + - ./autogen.sh + - ./configure --without-makeinfo + - make check diff --git a/INSTALL b/INSTALL index 035124f6453..a34e3f087db 100644 --- a/INSTALL +++ b/INSTALL @@ -258,12 +258,23 @@ inconvenient for Emacs when running as daemon or running via a remote ssh connection. In order to completely prevent the use of D-Bus, configure Emacs with the options '--without-dbus --without-gconf --without-gsettings'. +To read email via a network protocol like IMAP or POP, you can +configure Emacs with the option '--with-mailutils', so that it always +uses the GNU Mailutils 'movemail' program to retrieve mail. Otherwise +the Emacs build procedure builds and installs an auxiliary 'movemail' +program, a limited and insecure substitute that Emacs can use when +Mailutils is not installed; when this happens, there are several +configure options such as --without-pop that provide fine-grained +control over Emacs 'movemail' construction. + The Emacs mail reader RMAIL is configured to be able to read mail from a POP3 server by default. Versions of the POP protocol older than -POP3 are not supported. For Kerberos-authenticated POP add -'--with-kerberos', for Hesiod support add '--with-hesiod'. While POP3 -is always enabled, whether Emacs actually uses POP is controlled by -individual users--see the Rmail chapter of the Emacs manual. +POP3 are not supported. While POP3 support is typically enabled, +whether Emacs actually uses POP3 is controlled by individual users; +see the Rmail chapter of the Emacs manual. Unless you configure +--with-mailutils, it is a good idea to configure --without-pop so that +users are less likely to inadvertently read email via insecure +channels. For image support you may have to download, build, and install the appropriate image support libraries for image types other than XBM and @@ -302,7 +313,7 @@ build a small executable with very basic X support, use --without-all use --without-all --without-x. If you want to build with just a few features enabled, you can combine --without-all with --with-FEATURE. For example, you can use --without-all --without-x --with-dbus to -build with DBus support and nothing more. +build with D-Bus support and nothing more. Use --with-wide-int to implement Emacs values with the type 'long long', even on hosts where a narrower type would do. With this option, on a @@ -310,8 +321,9 @@ typical 32-bit host, Emacs integers have 62 bits instead of 30. Use --with-cairo to compile Emacs with Cairo drawing. -Use --with-modules to build Emacs with support for loading dynamic -modules. +Use --with-modules to build Emacs with support for dynamic modules. +This needs a C compiler that supports '__attribute__ ((cleanup (...)))', +as in GCC 3.4 and later. Use --enable-gcc-warnings to enable compile-time checks that warn about possibly-questionable C code. This is intended for developers @@ -537,7 +549,8 @@ information on this. Emacs info files. 8) If your system uses lock files to interlock access to mailer inbox files, -then you might need to make the movemail program setuid or setgid +and if you did not configure --with-mailutils, then you might need to +make the Emacs-specific 'movemail' program setuid or setgid in order to enable it to write the lock files. We believe this is safe. 9) You are done! You can remove executables and object files from diff --git a/INSTALL.REPO b/INSTALL.REPO index be4feaf841d..ce346bb246c 100644 --- a/INSTALL.REPO +++ b/INSTALL.REPO @@ -10,8 +10,6 @@ that are not needed when building from a release. You will need: autoconf - at least the version specified near the start of configure.ac (in the AC_PREREQ command). -automake - at least the version specified near the start of - configure.ac (in the AM_INIT_AUTOMAKE command). git - at least Git 1.7.1. If your repository was created by an older Git version, you may need to reclone it. makeinfo - not strictly necessary, but highly recommended, so that @@ -52,8 +50,21 @@ To update loaddefs.el (and similar files), do: $ make autoloads If either of the above partial procedures fails, try 'make bootstrap'. -If CPU time is not an issue, 'make bootstrap' is the most thorough way -to rebuild, and avoid any spurious problems. +If CPU time is not an issue, 'make bootstrap' is a more thorough way +to rebuild, avoiding spurious problems. + +Occasionally, there are changes that 'make bootstrap' won't be able to +handle. The most thorough cleaning can be achieved by 'git clean -fx' +which will leave you with only files from the git repository. Here +are some faster methods for a couple of particular error cases: + + /usr/bin/m4:aclocal.m4:9: cannot open `m4/count-leading-zeros.m4': No such file or directory + +This can be fixed with 'rm aclocal.m4'. + + make: *** No rule to make target 'lib/Makefile.am', needed by 'lib/Makefile.in' + +This can be fixed with 'rm lib/Makefile Makefile'. Because the repository version of Emacs is a work in progress, it will sometimes fail to build. Please wait a day or so (and check the diff --git a/Makefile.in b/Makefile.in index fcaa01d8f62..0344baf4b4c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -73,10 +73,6 @@ CDPATH= cache_file = @cache_file@ CONFIGURE_FLAGS = --cache-file=$(cache_file) -AUTOCONF = @AUTOCONF@ -AUTOMAKE = @AUTOMAKE@ -AUTOHEADER = @AUTOHEADER@ -ACLOCAL = @ACLOCAL@ AWK = @AWK@ EXEEXT=@EXEEXT@ @@ -162,7 +158,7 @@ libdir=@libdir@ # Where to install Emacs's man pages. # Note they contain cross-references that expect them to be in section 1. mandir=@mandir@ -man2dir=$(mandir)/man2 +man1dir=$(mandir)/man1 # Where to install and expect the info files describing Emacs. infodir=@infodir@ @@ -276,8 +272,15 @@ archlibdir=@archlibdir@ # Where to put the etc/DOC file. etcdocdir=@etcdocdir@ -# Where to install Emacs game score files. +# User or group of the auxiliary program update-game-score, which is +# installed on platforms with a game directory shared by multiple users. +# On other platforms Emacs can update the score files itself. +gameuser=@gameuser@ +gamegroup=@gamegroup@ +# Where to install game score files, if gameuser or gamegroup is nonempty. gamedir=@gamedir@ +# Nonempty if and only if a shared gamedir is used. +use_gamedir=$(gameuser)$(gamegroup) # ==================== Utility Programs for the Build ==================== @@ -344,6 +347,9 @@ etc-emacsver: ${srcdir}/build-aux/move-if-change emacsver.tex.$$$$ \ ${srcdir}/etc/refcards/emacsver.tex +# The shared gamedir name as a C string literal, or a null ptr if not in use. +PATH_GAME = $(if $(use_gamedir),"$(gamedir)",((char const *) 0)) + # Generate epaths.h from epaths.in. This target is invoked by 'configure'. # See comments in configure.ac for why it is done this way, as opposed # to just letting configure generate epaths.h from epaths.in in a @@ -369,7 +375,7 @@ epaths-force: -e 's;\(#.*PATH_DATA\).*$$;\1 "${etcdir}";' \ -e 's;\(#.*PATH_BITMAPS\).*$$;\1 "${bitmapdir}";' \ -e 's;\(#.*PATH_X_DEFAULTS\).*$$;\1 "${x_default_search_path}";' \ - -e 's;\(#.*PATH_GAME\).*$$;\1 "${gamedir}";' \ + -e 's;\(#.*PATH_GAME\).*$$;\1 $(PATH_GAME);' \ -e 's;\(#.*PATH_DOC\).*$$;\1 "${etcdocdir}";') && \ ${srcdir}/build-aux/move-if-change epaths.h.$$$$ src/epaths.h @@ -395,10 +401,6 @@ epaths-force-w32: -e "/^.*#/s|@SRC@|$${w32srcdir}|g") && \ ${srcdir}/build-aux/move-if-change epaths.h.$$$$ src/epaths.h -# If lib/Makefile would build files in '.', then build them before -# building 'lib', to avoid races with parallel makes. -lib: am--refresh - lib-src src: $(NTDIR) lib src: lib-src @@ -427,8 +429,10 @@ blessmail: Makefile src $(MAKE) -C lib-src maybe-blessmail # We used to have one rule per */Makefile.in, but that leads to race -# conditions with parallel makes, so let's assume that the time stamp on -# ./Makefile is representative of the time stamp on all the other Makefiles. +# conditions with parallel makes, so assume that the timestamp on +# ./Makefile represents the timestamp on all the other Makefiles. +# Similarly, assume the timestamp on ./configure represents the +# timestamp on src/config.in. # # config.status overrides MAKEFILE_NAME with a bogus name when creating # src/epaths.h, so that 'make epaths-force' does not recursively invoke @@ -438,7 +442,8 @@ blessmail: Makefile src # then attempts to build that file. This forces 'Makefile', 'lib/Makefile', # etc. to be built without running into similar recursion problems. MAKEFILE_NAME = Makefile -$(MAKEFILE_NAME): config.status $(srcdir)/src/config.in \ +$(MAKEFILE_NAME): config.status $(srcdir)/configure \ + $(srcdir)/lib/gnulib.mk.in \ $(srcdir)/Makefile.in $(SUBDIR_MAKEFILES_IN) $(CONFIG_STATUS_FILES_IN) MAKE='$(MAKE)' ./config.status @@ -452,40 +457,8 @@ config.status: ${srcdir}/configure $(CFG) $(srcdir)/configure $(CONFIGURE_FLAGS); \ fi -AUTOCONF_INPUTS = $(srcdir)/configure.ac $(srcdir)/aclocal.m4 - -$(srcdir)/configure: $(AUTOCONF_INPUTS) - cd ${srcdir} && ${AUTOCONF} - -ACLOCAL_PATH = @ACLOCAL_PATH@ -ACLOCAL_INPUTS = $(srcdir)/configure.ac $(srcdir)/m4/*.m4 -$(srcdir)/aclocal.m4: $(ACLOCAL_INPUTS) - cd $(srcdir) && ACLOCAL_PATH='$(ACLOCAL_PATH)' $(ACLOCAL) -I m4 - -AUTOMAKE_INPUTS = $(srcdir)/aclocal.m4 $(srcdir)/lib/Makefile.am \ - $(srcdir)/lib/gnulib.mk $(srcdir)/nt/gnulib.mk -$(srcdir)/lib/Makefile.in: $(AUTOMAKE_INPUTS) - cd $(srcdir) && $(AUTOMAKE) --gnu -a -c lib/Makefile - -$(srcdir)/nt/gnulib.mk: $(srcdir)/lib/gnulib.mk - $(MAKE) -C $(srcdir)/nt gnulib.mk - -# Regenerate files that this makefile would have made, if this makefile -# had been built by Automake. The name 'am--refresh' is for -# compatibility with subsidiary Automake-generated makefiles. -am--refresh: $(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/src/config.in -.PHONY: am--refresh - -$(srcdir)/src/config.in: $(srcdir)/src/stamp-h.in - @ # Usually, there's no need to rebuild src/config.in just - @ # because stamp-h.in has changed (since building stamp-h.in - @ # refreshes config.in as well), but if config.in is missing - @ # then we really need to do something more. - $(if $(wildcard $@),,cd $(srcdir) && $(AUTOHEADER)) -$(srcdir)/src/stamp-h.in: $(AUTOCONF_INPUTS) - cd ${srcdir} && ${AUTOHEADER} - rm -f $@ - echo timestamp > $@ +$(srcdir)/configure: $(srcdir)/configure.ac $(srcdir)/m4/*.m4 + cd $(srcdir) && ./autogen.sh # ==================== Installation ==================== @@ -526,7 +499,7 @@ ifeq (${ns_self_contained},no) -chmod 755 "$(DESTDIR)${bindir}/$(EMACSFULL)" ifndef NO_BIN_LINK rm -f "$(DESTDIR)${bindir}/$(EMACS)" - cd "$(DESTDIR)${bindir}" && $(LN_S_FILEONLY) $(EMACSFULL) $(EMACS) + cd "$(DESTDIR)${bindir}" && $(LN_S_FILEONLY) "$(EMACSFULL)" "$(EMACS)" endif else subdir=${ns_appresdir}/site-lisp && ${write_subdir} @@ -709,17 +682,17 @@ install-info: info ## ctags.1 is compressed or not. "gzip -f" is another option here, ## but not sure if portable. install-man: - umask 022; ${MKDIR_P} "$(DESTDIR)${man2dir}" + umask 022; ${MKDIR_P} "$(DESTDIR)${man1dir}" thisdir=`/bin/pwd`; \ cd ${mansrcdir}; \ for page in *.1; do \ test "$$page" = ChangeLog.1 && continue; \ dest=`echo "$${page}" | sed -e 's/\.1$$//' -e '$(TRANSFORM)'`.1; \ (cd "$${thisdir}"; \ - ${INSTALL_DATA} ${mansrcdir}/$${page} "$(DESTDIR)${man2dir}/$${dest}"); \ + ${INSTALL_DATA} ${mansrcdir}/$${page} "$(DESTDIR)${man1dir}/$${dest}"); \ [ -n "${GZIP_PROG}" ] || continue ; \ - rm -f "$(DESTDIR)${man2dir}/$${dest}.gz"; \ - ${GZIP_PROG} -9n "$(DESTDIR)${man2dir}/$${dest}" || true; \ + rm -f "$(DESTDIR)${man1dir}/$${dest}.gz"; \ + ${GZIP_PROG} -9n "$(DESTDIR)${man1dir}/$${dest}" || true; \ done ## Install those items from etc/ that need to end up elsewhere. @@ -730,10 +703,9 @@ EMACS_ICON=emacs install-etc: umask 022; ${MKDIR_P} "$(DESTDIR)${desktopdir}" - emacs_name=`echo remacs | sed '$(TRANSFORM)'`; \ - tmp=etc/$${emacs_name}.tmpdesktop; rm -f $${tmp}; \ - sed -e "/^Exec=remacs/ s/remacs/$${emacs_name}/" \ - -e "/^Icon=remacs/ s/remacs/$${emacs_name}/" \ + tmp=etc/emacs.tmpdesktop; rm -f $${tmp}; \ + sed -e "/^Exec=emacs/ s/emacs/${EMACS_NAME}/" \ + -e "/^Icon=emacs/ s/emacs/${EMACS_NAME}/" \ ${srcdir}/etc/remacs.desktop > $${tmp}; \ ${INSTALL_DATA} $${tmp} "$(DESTDIR)${desktopdir}/${EMACS_NAME}.desktop"; \ rm -f $${tmp} @@ -744,14 +716,12 @@ install-etc: ${INSTALL_DATA} $${tmp} "$(DESTDIR)${appdatadir}/${EMACS_NAME}.appdata.xml"; \ rm -f $${tmp} umask 022; $(MKDIR_P) "$(DESTDIR)$(systemdunitdir)" - tmp=etc/remacs.tmpservice; rm -f $${tmp}; \ - emacs_name=`echo remacs | sed '$(TRANSFORM)'`; \ - exe_name=$${emacs_name}${EXEEXT}; \ + tmp=etc/emacs.tmpservice; rm -f $${tmp}; \ client_name=`echo remacsclient | sed '$(TRANSFORM)'`${EXEEXT}; \ sed -e '/^##/d' \ - -e "/^Documentation/ s/remacs(1)/$${emacs_name}(1)/" \ - -e "/^ExecStart/ s|remacs|${bindir}/$${exe_name}|" \ - -e "/^ExecStop/ s|remacsclient|${bindir}/$${client_name}|" \ + -e "/^Documentation/ s/emacs(1)/${EMACS_NAME}(1)/" \ + -e "/^ExecStart/ s|emacs|${bindir}/${EMACS}|" \ + -e "/^ExecStop/ s|emacsclient|${bindir}/$${client_name}|" \ ${srcdir}/etc/remacs.service > $${tmp}; \ $(INSTALL_DATA) $${tmp} "$(DESTDIR)$(systemdunitdir)/${EMACS_NAME}.service"; \ rm -f $${tmp} @@ -810,21 +780,23 @@ uninstall: uninstall-$(NTDIR) uninstall-doc ext=.gz; else ext=; fi; \ if cd ${mansrcdir}; then \ for page in *.1; do \ - rm -f "$(DESTDIR)${man2dir}"/`echo "$${page}" | sed -e 's/\.1$$//' -e '$(TRANSFORM)'`.1$$ext; done; \ + rm -f "$(DESTDIR)${man1dir}"/`echo "$${page}" | sed -e 's/\.1$$//' -e '$(TRANSFORM)'`.1$$ext; done; \ fi) - (cd "$(DESTDIR)${bindir}" && rm -f $(EMACSFULL) $(EMACS) || true) + rm -f "$(DESTDIR)${bindir}/$(EMACS)" "$(DESTDIR)${bindir}/$(EMACSFULL)" (if cd "$(DESTDIR)${icondir}"; then \ - rm -f hicolor/*x*/apps/${EMACS_NAME}.png \ - hicolor/scalable/apps/${EMACS_NAME}.svg \ + rm -f hicolor/*x*/apps/"${EMACS_NAME}.png" \ + "hicolor/scalable/apps/${EMACS_NAME}.svg" \ hicolor/scalable/mimetypes/`echo emacs-document | sed '$(TRANSFORM)'`.svg; \ fi) -rm -f "$(DESTDIR)${desktopdir}/${EMACS_NAME}.desktop" -rm -f "$(DESTDIR)${appdatadir}/${EMACS_NAME}.appdata.xml" -rm -f "$(DESTDIR)$(systemdunitdir)/${EMACS_NAME}.service" + ifneq (,$(use_gamedir)) for file in snake-scores tetris-scores; do \ file="$(DESTDIR)${gamedir}/$${file}"; \ [ -s "$${file}" ] || rm -f "$$file"; \ done + endif ### Windows-specific uninstall target for removing programs produced ### in nt/, and its Posix do-nothing shadow. @@ -856,9 +828,7 @@ mostlyclean_dirs = src oldXMenu lwlib lib lib-src nt doc/emacs doc/misc \ $(foreach dir,$(mostlyclean_dirs),$(eval $(call submake_template,$(dir),mostlyclean))) mostlyclean: $(mostlyclean_dirs:=_mostlyclean) - for dir in test/automated; do \ - [ ! -d $$dir ] || $(MAKE) -C $$dir mostlyclean; \ - done + [ ! -d test ] || $(MAKE) -C test $@ ### 'clean' ### Delete all files from the current directory that are normally @@ -873,9 +843,8 @@ clean_dirs = $(mostlyclean_dirs) nextstep lisp admin/unidata $(foreach dir,$(clean_dirs),$(eval $(call submake_template,$(dir),clean))) clean: $(clean_dirs:=_clean) - for dir in test/automated admin/charsets; do \ - [ ! -d $$dir ] || $(MAKE) -C $$dir clean; \ - done + $(MAKE) -C admin/charsets $@ + [ ! -d test ] || $(MAKE) -C test $@ -rm -f *.tmp etc/*.tmp* -rm -rf info-dir.* -rm -rf *.elc @@ -894,18 +863,20 @@ top_bootclean=\ ### distribution. top_distclean=\ ${top_bootclean}; \ - rm -f config.status config.log~ Makefile stamp-h1 ${SUBDIR_MAKEFILES} + rm -f config.status config.log~ \ + Makefile lib/gnulib.mk ${SUBDIR_MAKEFILES} distclean_dirs = $(clean_dirs) leim $(foreach dir,$(distclean_dirs),$(eval $(call submake_template,$(dir),distclean))) -maybeclean_dirs = test/automated admin/grammars admin/unidata admin/charsets +maybeclean_dirs = test admin/grammars admin/unidata admin/charsets distclean: $(distclean_dirs:=_distclean) - for dir in ${maybeclean_dirs}; do \ - [ ! -d $$dir ] || $(MAKE) -C $$dir distclean; \ + for dir in $(filter-out test,$(maybeclean_dirs)); do \ + $(MAKE) -C $$dir $@ || exit; \ done + [ ! -d test ] || $(MAKE) -C test $@ ${top_distclean} ### 'bootstrap-clean' @@ -914,9 +885,10 @@ distclean: $(distclean_dirs:=_distclean) $(foreach dir,$(distclean_dirs),$(eval $(call submake_template,$(dir),bootstrap-clean))) bootstrap-clean: $(distclean_dirs:=_bootstrap-clean) - for dir in ${maybeclean_dirs}; do \ - [ ! -d $$dir ] || $(MAKE) -C $$dir bootstrap-clean; \ + for dir in $(filter-out test,$(maybeclean_dirs)); do \ + $(MAKE) -C $$dir $@ || exit; \ done + [ ! -d test ] || $(MAKE) -C test $@ [ ! -f config.log ] || mv -f config.log config.log~ rm -rf ${srcdir}/info rm -f ${srcdir}/etc/refcards/emacsver.tex @@ -942,9 +914,10 @@ maintainer_clean_dirs = src leim lisp $(foreach dir,$(maintainer_clean_dirs),$(eval $(call submake_template,$(dir),maintainer-clean))) maintainer-clean: bootstrap-clean $(maintainer_clean_dirs:=_maintainer-clean) - for dir in ${maybeclean_dirs}; do \ - [ ! -d $$dir ] || $(MAKE) -C $$dir maintainer-clean; \ + for dir in $(filter-out test,$(maybeclean_dirs)); do \ + $(MAKE) -C $$dir $@ || exit; \ done + [ ! -d test ] || $(MAKE) -C test $@ ${top_maintainer_clean} ### This doesn't actually appear in the coding standards, but Karl @@ -1133,9 +1106,7 @@ check-info: info # * Run autogen.sh. # * Rebuild Makefile, to update the build procedure itself. # * Do the actual build. -bootstrap: | bootstrap-clean bootstrap-build - -bootstrap-build: +bootstrap: bootstrap-clean cd $(srcdir) && ./autogen.sh $(MAKE) MAKEFILE_NAME=force-Makefile force-Makefile $(MAKE) all @@ -1198,18 +1169,3 @@ check-declare: exit 1; \ fi $(MAKE) -C lisp $@ - -## Generating ldefs-boot-auto.el requires a completely clean build so -## that we can see which autoloads are actually called. The build has -## to complete because we use Emacs to clean the results up! We use -## loaddefs.el in place of ldefs-boot-auto, because if we are running -## this there is the possibility that ldefs-boot-auto is not -## sufficient for bootstrap. -generate-ldefs-boot: all - echo "Generating Bootstrap ldefs" - cp lisp/loaddefs.el lisp/ldefs-boot-auto.el - $(MAKE) -j 1 bootstrap \ - GENERATE_LDEFS_BOOT="generate-ldefs-boot" \ - 2>&1 | tee lisp/ldefs-boot-auto.temp - $(EMACS) -batch --load admin/ldefs-clean.el --funcall ldefs-clean - rm lisp/ldefs-boot-auto.temp diff --git a/README b/README index 15d5812e134..b743d56ac52 100644 --- a/README +++ b/README @@ -45,11 +45,10 @@ The file 'configure.ac' is the input used by the autoconf program to construct the 'configure' script. The shell script 'autogen.sh' generates 'configure' and other files by -running the GNU build tools autoconf and automake, which in turn use -GNU m4 and Perl. If you want to use it, you will need to install -recent versions of these build tools. This should be needed only if -you edit files like 'configure.ac' that specify Emacs's autobuild -procedure. +running Autoconf, which in turn uses GNU m4. If you want to use it, +you will need to install recent versions of these build tools. This +should be needed only if you edit files like 'configure.ac' that +specify Emacs's autobuild procedure. The file 'Makefile.in' is a template used by 'configure' to create 'Makefile'. diff --git a/admin/CPP-DEFINES b/admin/CPP-DEFINES index 4f91c154fb0..e6b0efef74e 100644 --- a/admin/CPP-DEFINES +++ b/admin/CPP-DEFINES @@ -107,7 +107,6 @@ HAVE_CLOCK_GETTIME HAVE_CLOCK_SETTIME HAVE_COFF_H HAVE_COM_ERR_H -HAVE_COPYSIGN HAVE_DBUS HAVE_DBUS_TYPE_IS_VALID HAVE_DBUS_VALIDATE_BUS_NAME diff --git a/admin/MAINTAINERS b/admin/MAINTAINERS index f49654deaa9..679b7a35d05 100644 --- a/admin/MAINTAINERS +++ b/admin/MAINTAINERS @@ -75,11 +75,11 @@ Simen Heggestøyl Nicolas Petton lisp/emacs-lisp/map.el - test/automated/map-tests.el + test/lisp/emac-lisp/map-tests.el lisp/emacs-lisp/seq.el - test/automated/seq-tests.el + test/lisp/emac-lisp/seq-tests.el lisp/emacs-lisp/thunk.el - test/automated/thunk-tests.el + test/lisp/emac-lisp/thunk-tests.el The GNU AUCTeX maintainers (auctex-devel@gnu.org) RefTeX @@ -97,7 +97,7 @@ The GNU AUCTeX maintainers (auctex-devel@gnu.org) Dmitry Gutov lisp/progmodes/ruby-mode.el - test/automated/ruby-mode-tests.el + test/lisp/progmodes/ruby-mode-tests.el test/indent/ruby.rb lisp/progmodes/xref.el lisp/progmodes/project.el @@ -112,11 +112,11 @@ Ulf Jasper lisp/net/newst-ticker.el lisp/net/newst-treeview.el lisp/net/newsticker.el - test/automated/newsticker-tests.el + test/lisp/net/newsticker-tests.el Icalendar lisp/calendar/icalendar.el - test/automated/icalendar-tests.el + test/lisp/calendar/icalendar-tests.el ============================================================================== 2. Areas that someone is willing to maintain, although he would not diff --git a/admin/admin.el b/admin/admin.el index ea48493304c..2dccfac5021 100644 --- a/admin/admin.el +++ b/admin/admin.el @@ -132,6 +132,13 @@ Root must be the root of an Emacs source tree." (not (equal (cadr oldversion) (cadr newversion))))) (newsfile (expand-file-name "etc/NEWS" root)) (oldnewsfile (expand-file-name (format "etc/NEWS.%s" oldmajor) root))) + (unless (> (length newversion) 2) ; pretest or release candidate? + (with-temp-buffer + (insert-file-contents newsfile) + (if (re-search-forward "^\\(+++ *\\|--- *\\)$" nil t) + (display-warning 'admin + "NEWS file still contains temporary markup. +Documentation changes might not have been completed!")))) (when (and majorbump (not (file-exists-p oldnewsfile))) (rename-file newsfile oldnewsfile) @@ -635,7 +642,10 @@ style=\"text-align:left\">") ("@GZIP_PROG@" . "gzip") ("@INSTALL@" . "install -c") ("@INSTALL_DATA@" . "${INSTALL} -m 644") - ("@configure_input@" . "")) + ("@configure_input@" . "") + ("@AM_DEFAULT_VERBOSITY@" . "0") + ("@AM_V@" . "${V}") + ("@AM_DEFAULT_V@" . "${AM_DEFAULT_VERBOSITY}")) "Alist of (REGEXP . REPLACEMENT) pairs for `make-manuals-dist'.") (defun make-manuals-dist--1 (root type) @@ -655,7 +665,9 @@ style=\"text-align:left\">") (delete-directory stem t)) (make-directory stem) (copy-file "../doc/misc/texinfo.tex" stem) - (or (equal type "emacs") (copy-file "../doc/emacs/emacsver.texi" stem)) + (unless (equal type "emacs") + (copy-file "../doc/emacs/emacsver.texi" stem) + (copy-file "../doc/emacs/docstyle.texi" stem)) (dolist (file (directory-files (format "../doc/%s" type) t)) (if (or (string-match-p "\\(\\.texi\\'\\|/README\\'\\)" file) (and (equal type "lispintro") diff --git a/admin/authors.el b/admin/authors.el index 95570275f4c..83f884dd079 100644 --- a/admin/authors.el +++ b/admin/authors.el @@ -3,7 +3,7 @@ ;; Copyright (C) 2000-2017 Free Software Foundation, Inc. ;; Author: Gerd Moellmann -;; Maintainer: Kim F. Storm +;; Maintainer: emacs-devel@gnu.org ;; Keywords: maint ;; Package: emacs @@ -27,9 +27,6 @@ ;; Use M-x authors RET to create an *Authors* buffer that can used as ;; or merged with Emacs's AUTHORS file. -;; FIXME: This needs to modernized in the light of current practice, -;; which generates a single top-level ChangeLog file from commit logs. - ;;; Code: (defvar authors-coding-system 'utf-8 @@ -81,6 +78,7 @@ files.") ("François Pinard" "Francois Pinard") ("Francesco Potortì" "Francesco Potorti" "Francesco Potorti`") ("Frederic Pierresteguy" "Fred Pierresteguy") + (nil "^FSF") ("Gerd Möllmann" "Gerd Moellmann") ("Hallvard B. Furuseth" "Hallvard B Furuseth" "Hallvard Furuseth") ("Hrvoje Nikšić" "Hrvoje Niksic") @@ -141,6 +139,7 @@ files.") ("Peter J. Weisberg" "PJ Weisberg") ("Peter S. Galbraith" "Peter S Galbraith" "Peter Galbraith") ("Peter Runestig" "Peter 'luna' Runestig") + ("Philipp Stephani" "Philipp .*phst@google") ("Piotr Zieliński" "Piotr Zielinski") ("Przemysław Wojnowski" "Przemyslaw Wojnowski") ("Rainer Schöpf" "Rainer Schoepf") @@ -154,6 +153,7 @@ files.") ("Roland B. Roberts" "Roland B Roberts" "Roland Roberts") ("Ron Schnell" "Ronnie Schnell") ("Rui-Tao Dong" "Rui-Tao Dong ~{6-HpLN~}") + ("Ryan Thompson" "Ryan .*rct@thompsonclan") ("Sacha Chua" "Sandra Jean Chua") ("Sam Steingold" "Sam Shteingold") ("Satyaki Das" "Indexed search by Satyaki Das") @@ -170,6 +170,7 @@ files.") ("Takaaki Ota" "Tak Ota") ("Takahashi Naoto" "Naoto Takahashi") ("Teodor Zlatanov" "Ted Zlatanov") + (nil "The PCL-CVS Trust") ("Thomas Dye" "Tom Dye") ("Thomas Horsley" "Tom Horsley") ; FIXME ? ("Thomas Wurgler" "Tom Wurgler") @@ -209,7 +210,7 @@ If REALNAME is nil, ignore that author.") "David O'Toole" "Devon Sean McCullough" "Dominique de Waleffe" - "Edward O'Connor" + "Theresa O'Connor" "Exal de Jesus Garcia Carrillo" "George McNinch" "Greg McGary" @@ -261,7 +262,13 @@ If REALNAME is nil, ignore that author.") "\\.\\(bzr\\|cvs\\|git\\)ignore$" ; obsolete or uninteresting "\\.arch-inventory$" "ChangeLog\\(\\.[0-9]+\\)?\\'" - "automated/data/" ; not interesting + "\\(automated\\|test\\)/data/" ; not interesting + "cedet/tests/" + "test/etags/" + "\\`\\(indent\\|automated\\)\\'" "indent/" "mod-test/" + "-resources/" + "unidata/.*\\.txt\\'" + "BidiCharacterTest.txt" ;; TODO lib/? Matches other things? "build-aux/" "m4/" "Emacs.xcodeproj" "mapfiles" "\\.map\\'" "preferences\\.\\(nib\\|gorm\\)" @@ -273,7 +280,8 @@ Changes to files matching one of the regexps in this list are not listed.") (defconst authors-no-scan-regexps '("etc/nxml/" - "automated/data/") + "test/data/" + "test/.*-resources/") "Lists of regexps matching files not to scan for authorship.") (defconst authors-ignored-files @@ -315,6 +323,7 @@ Changes to files matching one of the regexps in this list are not listed.") "*.el" ;; Autogen: "cus-load.el" "finder-inf.el" "ldefs-boot.el" "loaddefs-boot.el" + "lisp/ldefs-boot-manual.el" "lisp/ldefs-boot-auto.el" "compile" "config.guess" "config.sub" "depcomp" "autogen/compile" "autogen/config.guess" "autogen/config.in" "autogen/config.sub" "autogen/depcomp" "autogen/install-sh" @@ -384,10 +393,12 @@ Changes to files matching one of the regexps in this list are not listed.") ;; Not in gnulib anymore "lib/qset-acl.c" "lib/qcopy-acl.c" "lib/file-has-acl.c" ;; files from old MS Windows build procedures + "nt/gnulib-modules-to-delete.cfg" "makefile.w32-in" "admin/unidata/makefile.w32-in" "unidata/makefile.w32-in" "lib/makefile.w32-in" + "lib-src/makefile.w32-in" "leim/makefile.w32-in" "lisp/makefile.w32-in" "src/makefile.w32-in" @@ -401,12 +412,13 @@ Changes to files matching one of the regexps in this list are not listed.") "src/paths.h" "envadd.bat" "multi-install-info.bat" - "INSTALL.OLD" + "INSTALL.OLD" "nt/INSTALL.OLD" "nt/src/paths.h" "nmake.defs" "gmake.defs" "zipdist.bat" "nt/makefile.w32-in" + "nt/subdirs.el" "config.nt" "nextstep/WISHLIST" ) @@ -652,9 +664,11 @@ Changes to files in this list are not listed.") "configure" "config.h" "is_exec.c" "sigaction.c" ;; nt/ - "ebuild.bat" "install.bat" "fast-install.bat" + "config.nt" "gmake.defs" "gnulib.mk" "nmake.defs" + "ebuild.bat" "envadd.bat" "fast-install.bat" "install.bat" + "multi-install-info.bat" "zipdist.bat" "debug.bat.in" "emacs.bat.in" "addsection.c" - "inc/sys/dir.h" "inc/gettext.h" + "inc/sys/dir.h" "inc/gettext.h" "nt/inc/socket.h" "time.h" ".gdbinit-union" "alloca.s" @@ -693,6 +707,7 @@ Changes to files in this list are not listed.") "images/gnus/reverse-smile.xpm" "notes/commits" "notes/changelogs" "revdiff" ; admin/ + "admin/ldefs-clean.el" "vcdiff" "rcs-checkin" "tindex.pl" "mac-fix-env.m" ;; Deleted vms stuff: @@ -732,7 +747,10 @@ Changes to files in this list are not listed.") "dns-mode.el" "run-at-time.el" "gnus-encrypt.el" "sha1-el.el" "gnus-gl.el" "gnus.sum.el" "proto-stream.el" "color.el" "color-lab.el" "eww.el" "shr-color.el" "shr.el" "earcon.el" "gnus-audio.el" "encrypt.el" - "format-spec.el" "gnus-move.el" + "format-spec.el" "gnus-move.el" "gnus-sync.el" + "auth-source.el" "ecomplete.el" "gravatar.el" "mailcap.el" "plstore.el" + "pop3.el" "qp.el" "registry.el" "rfc2231.el" "rtree.el" + "sieve.el" "sieve-mode.el" ;; doc "getopt.c" "texindex.c" "news.texi" "vc.texi" "vc2-xtra.texi" "back.texi" "vol1.texi" "vol2.texi" "elisp-covers.texi" "two.el" @@ -746,7 +764,11 @@ Changes to files in this list are not listed.") ;; lib/ "lib/stdio.c" "lib/gl_openssl.h" "lib/sigprocmask.c" "lib/pthread_sigprocmask.c" "lib/ldtoastr.c" "lib/dummy.c" - "lib/ignore-value.h" + "lib/ignore-value.h" "lib/Makefile.am" + "lib/pathmax.h" "lib/stat.c" "lib/strtoul.c" "lib/strtoull.c" + "lib/strtoumax.c" "lib/unsetenv.c" + "lib/getopt_cdefs.in.h" "lib/getopt_core.h" "lib/getopt_ext.h" + "lib/getopt_pfx_core.h" "lib/getopt_pfx_ext.h" ;; lib-src/ "cvtmail.c" "digest-doc.c" "emacsserver.c" "emacstool.c" "env.c" "etags-vmslib.c" "fakemail.c" "getdate.c" "getopt.h" "getopt1.c" @@ -762,11 +784,22 @@ Changes to files in this list are not listed.") "emacsclient.c" "etags.c" "hexl.c" "make-docfile.c" "movemail.c" "test-distrib.c" "testfile" "tpu-edt.doc" ; see below + "iso-swed.el" + "lisp/obsolete/vc-mcvs.el" "obsolete/vc-mcvs.el" "nnwarchive.el" "nnultimate.el" "nnslashdot.el" + "keyswap.el" + "mouse-sel.el" + "nxml-glyph.el" + "tramp-gw.el" "webmail.el" + "biditest.el" + "redisplay-testsuite.el" + "cedet-utests.el" "ede-tests.el" "semantic-ia-utest.el" + "semantic-tests.el" "semantic-utest-c.el" "semantic-utest.el" + "srecode-tests.el" "make-test-deps.emacs-lisp" ) "File names which are valid, but no longer exist (or cannot be found) in the repository.") @@ -877,11 +910,16 @@ in the repository.") ;; From lisp/ to etc/nxml. ("nxml/test.invalid.xml" . "test-invalid.xml") ("nxml/test.valid.xml" . "test-valid.xml") + ("automated/Makefile.in" . "test/Makefile.in") + ("rmailmm.el" . "test/rmailmm.el") ;; The one in lisp is eshell/eshell.el. - ("eshell.el" . "automated/eshell.el") - ("eshell/esh-test.el" . "automated/eshell.el") - ("automated/cl-lib.el" . "automated/cl-lib-tests.el") - ("automated/package-x-test.el" . "automated/package-test.el") + ("eshell.el" . "eshell-tests.el") + ("automated/eshell.el" . "eshell-tests.el") + ("eshell/esh-test.el" . "eshell-tests.el") + ("automated/cl-lib.el" . "cl-lib-tests.el") + ("automated/cl-lib-tests.el" . "cl-lib-tests.el") + ("automated/package-x-test.el" . "package-tests.el") + ("automated/package-test.el" . "package-tests.el") ("indent/js-indent-first-initialiser-t.js" . "indent/js-indent-init-t.js") ("indent/js-indent-first-initialiser-dynamic.js" . "indent/js-indent-init-dynamic.js") @@ -927,7 +965,20 @@ in the repository.") ("GNU.JOKES" . "JOKES") ("CHARACTERS" . "TODO") ("lisp/character-fold.el" . "lisp/char-fold.el") - ("test/automated/character-fold-tests.el" . "test/automated/char-fold-tests.el") + ("test/automated/character-fold-tests.el" . "char-fold-tests.el") + ("test/automated/char-fold-tests.el" . "char-fold-tests.el") + ("test/lisp/character-fold-tests.el" . "char-fold-tests.el") + ("test/manual/cycle-tests.el" . "fns-tests.el") + ("test/manual/cyclic-tests.el" . "fns-tests.el") + ("test/lisp/dns-mode-tests.el" . "dns-mode-tests.el") + ("test/lisp/legacy/core-elisp-tests.el" . "lisp-tests.el") + ("test/lisp/legacy/decoder-test.el" . "coding-tests.el") + ("test/lisp/legacy/files-tests.el" . "files-tests.el") + ("test/lisp/legacy/font-parse-tests.el" . "font-tests.el") + ("test/lisp/legacy/lexbind-tests.el" . "bytecomp-test.el") + ("test/lisp/legacy/occur-tests.el" . "replace-tests.el") + ("test/lisp/legacy/syntax-tests.el" . "syntax-tests.el") + ("test/file-organisation.org" . "file-organization.org") ("images/gnus/mail_send.xpm" . "mail-send.xpm") ; still in images/gnus ("schema/xhtml-basic-form.rnc" . "xhtml-bform.rnc" ) ("schema/xhtml-basic-table.rnc" . "xhtml-btable.rnc") @@ -947,6 +998,7 @@ in the repository.") ("icons/emacs21.ico" . "emacs21.ico") ("ja-dic" . "leim/ja-dic") ("quail" . "leim/quail") + ("admin/notes/triage" . "bug-triage") ;; Moved from autogen/ to admin/. ("autogen/update_autogen" . "update_autogen") ;; Moved from etc/ to admin/. @@ -977,7 +1029,7 @@ Elements are (OLDNAME . NEWNAME).") ;; Cf authors-renamed-files-alist. (defconst authors-renamed-files-regexps '(("\\`\\(arg-nonnull\\|c\\+\\+defs\\|warn-on-use\\)\\.h\\'" - "build-aux/snippet/\\&") + "lib/\\&") ("\\`\\(ebuild\\|emacs\\|install\\|fast-install\\)\\.cmd\\'" "\\1.bat") ("\\`\\(book-spine\\|cl\\|forms\\|functions\\|gnus\\|sc\\|texinfo\\|vip\\)\ \\.texinfo\\'" "\\1.texi") @@ -1037,9 +1089,13 @@ ediff\\|emerge\\|log-edit\\|log-view\\|pcvs\\|smerge-mode\\|vc\\)\\.el\\'" ;; From test/ to test/automated/. ("comint-testsuite.el" "automated/\\&") ("\\`\\(bytecomp\\|font-parse\\|icalendar\\|occur\\|newsticker\\)\ --testsuite\\.el" "automated/\\1-tests.el") +-testsuite\\.el" "\\1-tests.el") ("automated/flymake/warnpred/\\(Makefile\\|test\\.\\(?:c\\|pl\\)\\)\\'" "automated/data/flymake/\\1") + ;; More complicated than this, but we only use the basename of the RHS. + ("automated/\\([^/]*-test[^/]*\\.el\\)\\'" "\\1") + ;; Maybe not the exact new name, but disambiguates from lisp/. + ("automated/\\([^/]*\\)\\.el\\'" "\\1-tests.el") ;; NB lax rules should come last. ("^m/m-\\(.*\\.h\\)$" "m/\\1" t) ("^m-\\(.*\\.h\\)$" "\\1" t) @@ -1073,6 +1129,7 @@ Additionally, for these logs we apply the `lax' elements of (defvar authors-checked-files-alist) (defvar authors-invalid-file-names) +(defvar authors-ignored-names) ;; This has become rather yucky. :( (defun authors-disambiguate-file-name (fullname) @@ -1215,7 +1272,7 @@ author and what he did in hash table TABLE. See the description of (nconc entry (list (cons action 1)))))))) -(defun authors-canonical-author-name (author) +(defun authors-canonical-author-name (author file pos) "Return a canonicalized form of AUTHOR, an author name. If AUTHOR has an entry in `authors-aliases', use that. Remove email addresses. Capitalize words in the author's name, unless @@ -1237,7 +1294,11 @@ it is found in `authors-fixed-case'." (setq author (replace-regexp-in-string "\\`[ \t]+" "" author)) (setq author (replace-regexp-in-string "[ \t]+$" "" author)) (setq author (replace-regexp-in-string "[ \t]+" " " author)) + ;; NB this ignores the first name only case. (unless (string-match "[-, \t]" author) + (push (format-message "%s:%d: ignored `%s'" + file (1+ (count-lines (point-min) pos)) author) + authors-ignored-names) (setq author "")) (or (car (member author authors-fixed-case)) (capitalize author)))) @@ -1279,7 +1340,7 @@ with the file and the number of each action: Suggested\\|Trivial\\|Version\\|Originally\\|From:\\|Patch[ \t]+[Bb]y\\)"))) (push (authors-canonical-author-name (buffer-substring-no-properties - (point) (line-end-position))) authors) + (point) (line-end-position)) log-file pos) authors) (forward-line 1))) ((looking-at "^[ \t]+\\*") (let ((line (buffer-substring-no-properties @@ -1312,7 +1373,7 @@ TABLE is a hash table to add author information to." (enable-local-variables :safe) ; for find-file, hence let* (enable-local-eval nil) (buffer (find-file-noselect file))) - (setq file (authors-disambiguate-file-name (expand-file-name file))) + (setq file (expand-file-name file)) (with-current-buffer buffer (save-restriction (widen) @@ -1329,7 +1390,8 @@ TABLE is a hash table to add author information to." (skip-chars-forward "-0-9 \t") (push (authors-canonical-author-name (buffer-substring-no-properties - (point) (line-end-position))) authors) + (point) (line-end-position)) + file (line-beginning-position)) authors) ;; tips.texi says the continuation line should begin ;; with a tab, but often spaces are used. (setq continue @@ -1340,7 +1402,9 @@ TABLE is a hash table to add author information to." (and (> (length authors) 1) (setq action :cowrote)) (mapc (lambda (author) - (authors-add author file action table)) + (authors-add + author + (authors-disambiguate-file-name file) action table)) authors))))) (unless existing-buffer (kill-buffer buffer)))) @@ -1431,7 +1495,8 @@ and a buffer *Authors Errors* containing references to unknown files." (table (make-hash-table :test 'equal)) (buffer-name "*Authors*") authors-checked-files-alist - authors-invalid-file-names) + authors-invalid-file-names + authors-ignored-names) (authors-add-fixed-entries table) (dolist (log logs) (when (string-match "ChangeLog\\(.[0-9]+\\)?$" log) @@ -1495,14 +1560,20 @@ list of their contributions.\n") (symbol-name authors-coding-system) "\nEnd:\n") (message "Generating buffer %s... done" buffer-name) (unless noninteractive - (when authors-invalid-file-names + (when (or authors-invalid-file-names authors-ignored-names) (with-current-buffer (get-buffer-create "*Authors Errors*") (setq buffer-read-only nil) (erase-buffer) (set-buffer-file-coding-system authors-coding-system) - (insert "Unrecognized file entries found:\n\n") - (mapc (lambda (f) (if (not (string-match "^[A-Za-z]+$" f)) (insert f "\n"))) - (sort authors-invalid-file-names 'string-lessp)) + (when authors-invalid-file-names + (insert "Unrecognized file entries found:\n\n") + (mapc (lambda (f) (if (not (string-match "^[A-Za-z]+$" f)) (insert f "\n"))) + (sort authors-invalid-file-names 'string-lessp))) + (when authors-ignored-names + (insert "\n\nThese authors were ignored:\n\n" + (mapconcat + 'identity + (sort authors-ignored-names 'string-lessp) "\n"))) (goto-char (point-min)) (compilation-mode) (message "Errors were found. See buffer %s" (buffer-name)))) diff --git a/admin/gitmerge.el b/admin/gitmerge.el index 00c20ba7c67..a0efce5ea69 100644 --- a/admin/gitmerge.el +++ b/admin/gitmerge.el @@ -50,7 +50,7 @@ (defvar gitmerge-skip-regexp ;; We used to include "sync" in there, but in my experience it only ;; caused false positives. --Stef - "back[- ]?port\\|cherry picked from commit\\|\\(do not\\|no need to\\) merge\\|\ + "back[- ]?port\\|cherry picked from commit\\|\\(do\\( no\\|n['’]\\)t\\|no need to\\) merge\\|\ re-?generate\\|bump version\\|from trunk\\|Auto-commit" "Regexp matching logs of revisions that might be skipped. `gitmerge-missing' will ask you if it should skip any matches.") @@ -292,7 +292,7 @@ Returns non-nil if conflicts remain." )) ;; Try to resolve the conflicts. (cond - ((member file '("configure" "lisp/ldefs-boot-auto.el" + ((member file '("configure" "lisp/ldefs-boot.el" "lisp/emacs-lisp/cl-loaddefs.el")) ;; We are in the file's buffer, so names are relative. (call-process "git" nil t nil "checkout" "--" diff --git a/admin/ldefs-clean.el b/admin/ldefs-clean.el deleted file mode 100644 index c227a163604..00000000000 --- a/admin/ldefs-clean.el +++ /dev/null @@ -1,65 +0,0 @@ -;; Copyright (C) 2016-2017 Free Software Foundation, Inc. - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; This file takes the output from the "generate-ldefs-boot" make -;; target, takes the relevant autoload forms, removes everything else -;; and adds some comments. - -(defun ldefs-clean-uniquify-region-lines (beg end) - "Remove duplicate adjacent lines in region." - (save-excursion - (goto-char beg) - (while (re-search-forward "^\\(.*\n\\)\\1+" end t) - (replace-match "\\1")))) - -(defun ldefs-clean-uniquify-buffer-lines () - "Remove duplicate adjacent lines in the current buffer." - (interactive) - (ldefs-clean-uniquify-region-lines (point-min) (point-max))) - -(defun ldefs-clean-up () - "Clean up output from build and turn it into ldefs-boot-auto.el." - (interactive) - (goto-char (point-max)) - ;; We need to record autoloads till the point that emacs (as opposed - ;; to bootstrap-emacs) is dumped. After this point, we are not - ;; bootstrapping any more. - (search-backward "-l loadup dump") - (beginning-of-line) - (delete-region (point) (point-max)) - (keep-lines "(autoload" (point-min) (point-max)) - (sort-lines nil (point-min) (point-max)) - (ldefs-clean-uniquify-buffer-lines) - (goto-char (point-min)) - (insert - ";; This file is autogenerated by admin/ldefs-clean.el -;; Do not edit -") - (goto-char (point-max)) - (insert - ";; Local Variables: -;; no-byte-compile: t -;; no-update-autoloads: t -;; End:")) - - -(defun ldefs-clean () - (find-file "lisp/ldefs-boot-auto.temp") - (ldefs-clean-up) - (write-file "ldefs-boot-auto.el")) diff --git a/admin/make-tarball.txt b/admin/make-tarball.txt index 369d169cb9a..e5c77172c9f 100644 --- a/admin/make-tarball.txt +++ b/admin/make-tarball.txt @@ -9,7 +9,7 @@ Steps to take before starting on the first pretest in any release sequence: and you should use it for all that follows. Diffs from this branch should be going to the emacs-diffs mailing list. -1. Decide on versions of automake and autoconf, and ensure you will +1. Decide on versions of m4 and autoconf, and ensure you will have them available for the duration of the release process. 2. Consider increasing the value of the variable @@ -55,9 +55,12 @@ General steps (for each step, check for possible errors): M-x set-version RET). For a pretest, start at version .90. After .99, use .990 (so that it sorts). - The final pretest should be a release candidate. Set the version - number to that of the actual release. Pick a date about a week - from now when you intend to make the release. Use M-x + The final pretest should be a release candidate. + Before a release candidate is made, the tasks listed in + admin/release-process must be completed. + + Set the version number to that of the actual release. Pick a date + about a week from now when you intend to make the release. Use M-x add-release-logs to add entries to etc/HISTORY and the ChangeLog file. It's best not to commit these files until the release is actually made. Merge the entries from (unversioned) ChangeLog @@ -84,7 +87,9 @@ General steps (for each step, check for possible errors): make -C etc/refcards make -C etc/refcards clean -5. Commit ChangeLog.N, etc/AUTHORS, lisp/ldefs-boot.el, and the +5. Copy lisp/loaddefs.el to lisp/ldefs-boot.el. + + Commit ChangeLog.N, etc/AUTHORS, lisp/ldefs-boot.el, and the files changed by M-x set-version. If someone else made a commit between step 1 and now, @@ -189,6 +194,10 @@ emacs.html (for a new major release, a more thorough update is needed) history.html add the new NEWS file as news/NEWS.xx.y +For every new release, a banner is displayed on top of the emacs.html +page. Uncomment and the release banner in emacs.html. Keep it on the +page for about a month, then comment it again. + Use M-x make-manuals from admin/admin.el to regenerate the html manuals in manual/. If there are new manuals, add appropriate index pages in manual/ and add them to manual/index.html. In the diff --git a/admin/merge-gnulib b/admin/merge-gnulib index 6f0413fb14b..748f90cc25d 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib @@ -27,33 +27,35 @@ GNULIB_URL=git://git.savannah.gnu.org/gnulib.git GNULIB_MODULES=' alloca-opt binary-io byteswap c-ctype c-strcase - careadlinkat close-stream count-one-bits count-trailing-zeros + careadlinkat close-stream + count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 - dtoastr dtotimespec dup2 environ execinfo faccessat + diffseq dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat - manywarnings memrchr mkostemp mktime + manywarnings memrchr minmax mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat socklen stat-time std-gnu11 stdalign stddef stdio - stpcpy strftime strtoimax strtoumax symlink sys_stat + stpcpy strftime strtoimax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub - unsetenv update-copyright utimens + update-copyright unlocked-io utimens vla warnings ' +AVOIDED_MODULES=' + close dup fchdir fstat + malloc-posix msvc-inval msvc-nothrow + open openat-die opendir raise + save-cwd select setenv sigprocmask stat stdarg stdbool + threadlib tzset unsetenv utime utime-h +' + GNULIB_TOOL_FLAGS=' - --avoid=close --avoid=dup - --avoid=fchdir --avoid=fstat - --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow - --avoid=open --avoid=openat-die --avoid=opendir - --avoid=raise - --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask - --avoid=stdarg --avoid=stdbool - --avoid=threadlib --avoid=unsetenv --conditional-dependencies --import --no-changelog --no-vc-files - --makefile-name=gnulib.mk + --gnu-make + --makefile-name=gnulib.mk.in ' # The source directory, with a trailing '/'. @@ -93,11 +95,22 @@ test -x "$gnulib_srcdir"/gnulib-tool || { exit 1 } -"$gnulib_srcdir"/gnulib-tool --dir="$src" $GNULIB_TOOL_FLAGS $GNULIB_MODULES && +avoided_flags= +for module in $AVOIDED_MODULES; do + avoided_flags="$avoided_flags --avoid=$module" +done + +"$gnulib_srcdir"/gnulib-tool --dir="$src" $GNULIB_TOOL_FLAGS \ + $avoided_flags $GNULIB_MODULES && rm -- "$src"lib/gl_openssl.h "$src"m4/fcntl-o.m4 \ "$src"m4/gl-openssl.m4 \ - "$src"m4/gnulib-cache.m4 "$src"m4/warn-on-use.m4 "$src"m4/wint_t.m4 && + "$src"m4/gnulib-cache.m4 "$src"m4/gnulib-tool.m4 \ + "$src"m4/warn-on-use.m4 "$src"m4/wint_t.m4 && cp -- "$gnulib_srcdir"/build-aux/texinfo.tex "$src"doc/misc && -cp -- "$gnulib_srcdir"/build-aux/move-if-change "$src"build-aux && +cp -- "$gnulib_srcdir"/build-aux/config.guess \ + "$gnulib_srcdir"/build-aux/config.sub \ + "$gnulib_srcdir"/build-aux/install-sh \ + "$gnulib_srcdir"/build-aux/move-if-change \ + "$src"build-aux && { test -z "$src" || cd "$src"; } && ./autogen.sh diff --git a/admin/notes/copyright b/admin/notes/copyright index ea9c084a81a..d2b8cac0b43 100644 --- a/admin/notes/copyright +++ b/admin/notes/copyright @@ -45,9 +45,9 @@ available. The definition of triviality is a little vague, but a rule of thumb is that any file with less than 15 lines of actual content is trivial. If -a file is auto-generated from another one in the repository, then it -does not really matter about adding a copyright statement to the -generated file. +a file is auto-generated (eg ldefs-boot.el) from another one in the +repository, then it does not really matter about adding a copyright +statement to the generated file. Legal advice says that we could, if we wished, put a license notice even in trivial files, because copyright law in general looks at the @@ -531,19 +531,12 @@ of writing) GPL >= 2. rms says may as well leave the licenses of these alone (may import them from Gnulib again). These are: Gnulib: - build-aux/compile build-aux/config.guess build-aux/config.sub - build-aux/depcomp - build-aux/missing build-aux/move-if-change - build-aux/snippet/_Noreturn.h - build-aux/snippet/arg-nonnull.h - build-aux/snippet/c++defs.h - build-aux/snippet/warn-on-use.h doc/man/texinfo.tex lib/*.[ch] - lib/gnulib.mk + lib/gnulib.mk.in src/gmalloc.c src/termcap.c src/tparam.c diff --git a/admin/notes/unicode b/admin/notes/unicode index 9e9a6bea0fd..43ddd79cc8e 100644 --- a/admin/notes/unicode +++ b/admin/notes/unicode @@ -15,9 +15,10 @@ Emacs uses the following files from the Unicode Character Database . BidiBrackets.txt . IVD_Sequences.txt . NormalizationTest.txt + . SpecialCasing.txt . BidiCharacterTest.txt -First, the first 6 files need to be copied into admin/unidata/, and +First, the first 7 files need to be copied into admin/unidata/, and then Emacs should be rebuilt for them to take effect. Rebuilding Emacs updates several derived files elsewhere in the Emacs source tree, mainly in lisp/international/. diff --git a/admin/unidata/BidiBrackets.txt b/admin/unidata/BidiBrackets.txt index eb02a24bfc0..2114e632b9f 100644 --- a/admin/unidata/BidiBrackets.txt +++ b/admin/unidata/BidiBrackets.txt @@ -1,6 +1,6 @@ -# BidiBrackets-9.0.0.txt -# Date: 2016-06-07, 22:30:00 GMT [AG, LI, KW] -# © 2016 Unicode®, Inc. +# BidiBrackets-10.0.0.txt +# Date: 2017-04-12, 17:30:00 GMT [AG, LI, KW] +# © 2017 Unicode®, Inc. # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. # For terms of use, see http://www.unicode.org/terms_of_use.html # @@ -8,7 +8,7 @@ # For documentation, see http://www.unicode.org/reports/tr44/ # # Bidi_Paired_Bracket and Bidi_Paired_Bracket_Type Properties -# +# # This file is a normative contributory data file in the Unicode # Character Database. # diff --git a/admin/unidata/BidiMirroring.txt b/admin/unidata/BidiMirroring.txt index 68142c5e326..cbb61c4b570 100644 --- a/admin/unidata/BidiMirroring.txt +++ b/admin/unidata/BidiMirroring.txt @@ -1,13 +1,13 @@ -# BidiMirroring-9.0.0.txt -# Date: 2016-01-21, 22:00:00 GMT [KW, LI] -# © 2016 Unicode®, Inc. +# BidiMirroring-10.0.0.txt +# Date: 2017-04-12, 17:30:00 GMT [KW, LI] +# © 2017 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # # Unicode Character Database # For documentation, see http://www.unicode.org/reports/tr44/ # # Bidi_Mirroring_Glyph Property -# +# # This file is an informative contributory data file in the # Unicode Character Database. # @@ -15,20 +15,20 @@ # value, for which there is another Unicode character that typically has a glyph # that is the mirror image of the original character's glyph. # -# The repertoire covered by the file is Unicode 9.0.0. -# +# The repertoire covered by the file is Unicode 10.0.0. +# # The file contains a list of lines with mappings from one code point # to another one for character-based mirroring. # Note that for "real" mirroring, a rendering engine needs to select # appropriate alternative glyphs, and that many Unicode characters do not # have a mirror-image Unicode character. -# +# # Each mapping line contains two fields, separated by a semicolon (';'). # Each of the two fields contains a code point represented as a # variable-length hexadecimal value with 4 to 6 digits. # A comment indicates where the characters are "BEST FIT" mirroring. -# -# Code points for which Bidi_Mirrored=Yes, but for which no appropriate +# +# Code points for which Bidi_Mirrored=Yes, but for which no appropriate # characters exist with mirrored glyphs, are # listed as comments at the end of the file. # @@ -38,14 +38,14 @@ # point has the default value for the Bidi_Mirroring_Glyph property, # that means that no other character exists whose glyph is suitable # for character-based mirroring. -# +# # For information on bidi mirroring, see UAX #9: Unicode Bidirectional Algorithm, # at http://www.unicode.org/unicode/reports/tr9/ -# +# # This file was originally created by Markus Scherer. # Extended for Unicode 3.2, 4.0, 4.1, 5.0, 5.1, 5.2, and 6.0 by Ken Whistler, # and for subsequent versions by Ken Whistler and Laurentiu Iancu. -# +# # ############################################################ # # Property: Bidi_Mirroring_Glyph diff --git a/admin/unidata/Blocks.txt b/admin/unidata/Blocks.txt index 74c41e58a81..a4f851b14a5 100644 --- a/admin/unidata/Blocks.txt +++ b/admin/unidata/Blocks.txt @@ -1,6 +1,6 @@ -# Blocks-9.0.0.txt -# Date: 2016-02-05, 23:48:00 GMT [KW] -# © 2016 Unicode®, Inc. +# Blocks-10.0.0.txt +# Date: 2017-04-12, 17:30:00 GMT [KW] +# © 2017 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # # Unicode Character Database @@ -14,12 +14,12 @@ # Note: When comparing block names, casing, whitespace, hyphens, # and underbars are ignored. # For example, "Latin Extended-A" and "latin extended a" are equivalent. -# For more information on the comparison of property values, +# For more information on the comparison of property values, # see UAX #44: http://www.unicode.org/reports/tr44/ # # All block ranges start with a value where (cp MOD 16) = 0, # and end with a value where (cp MOD 16) = 15. In other words, -# the last hexadecimal digit of the start of range is ...0 +# the last hexadecimal digit of the start of range is ...0 # and the last hexadecimal digit of the end of range is ...F. # This constraint on block ranges guarantees that allocations # are done in terms of whole columns, and that code chart display @@ -51,6 +51,7 @@ 07C0..07FF; NKo 0800..083F; Samaritan 0840..085F; Mandaic +0860..086F; Syriac Supplement 08A0..08FF; Arabic Extended-A 0900..097F; Devanagari 0980..09FF; Bengali @@ -253,9 +254,12 @@ FFF0..FFFF; Specials 11680..116CF; Takri 11700..1173F; Ahom 118A0..118FF; Warang Citi +11A00..11A4F; Zanabazar Square +11A50..11AAF; Soyombo 11AC0..11AFF; Pau Cin Hau 11C00..11C6F; Bhaiksuki 11C70..11CBF; Marchen +11D00..11D5F; Masaram Gondi 12000..123FF; Cuneiform 12400..1247F; Cuneiform Numbers and Punctuation 12480..1254F; Early Dynastic Cuneiform @@ -270,6 +274,8 @@ FFF0..FFFF; Specials 17000..187FF; Tangut 18800..18AFF; Tangut Components 1B000..1B0FF; Kana Supplement +1B100..1B12F; Kana Extended-A +1B170..1B2FF; Nushu 1BC00..1BC9F; Duployan 1BCA0..1BCAF; Shorthand Format Controls 1D000..1D0FF; Byzantine Musical Symbols @@ -300,6 +306,7 @@ FFF0..FFFF; Specials 2A700..2B73F; CJK Unified Ideographs Extension C 2B740..2B81F; CJK Unified Ideographs Extension D 2B820..2CEAF; CJK Unified Ideographs Extension E +2CEB0..2EBEF; CJK Unified Ideographs Extension F 2F800..2FA1F; CJK Compatibility Ideographs Supplement E0000..E007F; Tags E0100..E01EF; Variation Selectors Supplement diff --git a/admin/unidata/IVD_Sequences.txt b/admin/unidata/IVD_Sequences.txt index fdf21e8a308..304bf91d9b0 100644 --- a/admin/unidata/IVD_Sequences.txt +++ b/admin/unidata/IVD_Sequences.txt @@ -2,6 +2,9 @@ # # History: # +# 2016-08-15 Combined registration of the MSARG collection and of +# sequences in that collection. +# # 2014-05-16 Combined registration of the Moji_Joho collection and of # sequences in that collection. # @@ -11,17 +14,17 @@ # collection. Registration of additional sequences in the # Hanyo-Denshi collection. # -# 2010-11-14 Combined registration of the Hanyo-Denshi collection and of -# sequences in that collection. +# 2010-11-14 Combined registration of the Hanyo-Denshi collection and +# of sequences in that collection. # -# 2007-12-14 Combined registration of the Adobe-Japan1 collection and of -# sequences in that collection. +# 2007-12-14 Combined registration of the Adobe-Japan1 collection and +# of sequences in that collection. # # This file is part of the Unicode Ideographic Variation Database (IVD). # For more details on the IVD, see UTS #37: # http://www.unicode.org/reports/tr37/ # -# Copyright 2006-2014 Unicode, Inc. +# Copyright 2006-2016 Unicode, Inc. # For terms of use, see: http://www.unicode.org/terms_of_use.html # 3402 E0100; Adobe-Japan1; CID+13698 @@ -268,6 +271,9 @@ 36C3 E0100; Hanyo-Denshi; IA1426 36C3 E0101; Hanyo-Denshi; TK01020180 36C3 E0102; Hanyo-Denshi; TK01020240 +36C7 E0100; MSARG; MA_9856 +36C7 E0101; MSARG; ME_36C7_001 +36C7 E0102; MSARG; ME_36C7_002 36CF E0100; Adobe-Japan1; CID+17494 36EE E0100; Moji_Joho; MJ000648 36EE E0101; Moji_Joho; MJ000649 @@ -4847,6 +4853,8 @@ 5554 E0101; Hanyo-Denshi; TK01014490 5556 E0100; Adobe-Japan1; CID+4394 5557 E0100; Adobe-Japan1; CID+4395 +5557 E0101; MSARG; MB_B0E8 +5557 E0102; MSARG; ME_5557_001 5558 E0100; Adobe-Japan1; CID+21280 555A E0100; Adobe-Japan1; CID+21281 555A E0101; Hanyo-Denshi; JB2162 @@ -8319,6 +8327,8 @@ 5EF8 E0100; Adobe-Japan1; CID+4762 5EF8 E0101; Moji_Joho; MJ011106 5EF8 E0102; Moji_Joho; MJ011107 +5EF8 E0103; MSARG; MA_9059 +5EF8 E0104; MSARG; ME_5EF8_001 5EF9 E0100; Adobe-Japan1; CID+16853 5EF9 E0101; Moji_Joho; MJ011108 5EF9 E0102; Moji_Joho; MJ011109 @@ -8529,6 +8539,8 @@ 5F55 E0100; Moji_Joho; MJ011232 5F55 E0101; Hanyo-Denshi; KS112100 5F55 E0101; Moji_Joho; MJ057475 +5F55 E0102; MSARG; MD_5F55 +5F55 E0103; MSARG; ME_5F55_001 5F56 E0100; Adobe-Japan1; CID+4780 5F56 E0101; Hanyo-Denshi; JA5533 5F56 E0101; Moji_Joho; MJ011233 @@ -26361,6 +26373,8 @@ 8846 E0105; Hanyo-Denshi; KS386520 8846 E0105; Moji_Joho; MJ058677 8846 E0106; Hanyo-Denshi; TK01083450 +8846 E0107; MSARG; MA_8FBC +8846 E0108; MSARG; ME_8846_001 8848 E0100; Adobe-Japan1; CID+22465 8849 E0100; Adobe-Japan1; CID+22466 884A E0100; Adobe-Japan1; CID+18635 @@ -31073,6 +31087,8 @@ 93C5 E0101; Hanyo-Denshi; JB6930 93C5 E0102; Hanyo-Denshi; TK01093900 93C6 E0100; Adobe-Japan1; CID+8679 +93C6 E0101; MSARG; MA_9264 +93C6 E0102; MSARG; ME_93C6_001 93C7 E0100; Adobe-Japan1; CID+18865 93C8 E0100; Adobe-Japan1; CID+7029 93C8 E0101; Hanyo-Denshi; JA7926 @@ -32678,6 +32694,8 @@ 98EB E0102; Moji_Joho; MJ028359 98EB E0103; Hanyo-Denshi; FT2689 98EB E0103; Moji_Joho; MJ028358 +98EC E0100; MSARG; MA_914B +98EC E0101; MSARG; ME_98EC_001 98ED E0100; Adobe-Japan1; CID+4289 98ED E0101; Hanyo-Denshi; JA5012 98ED E0101; Moji_Joho; MJ028362 @@ -33545,6 +33563,8 @@ 9AE3 E0100; Adobe-Japan1; CID+7278 9AE4 E0100; Adobe-Japan1; CID+22934 9AE5 E0100; Adobe-Japan1; CID+19007 +9AE5 E0101; MSARG; MD_9AE5 +9AE5 E0102; MSARG; ME_9AE5_001 9AE6 E0100; Adobe-Japan1; CID+7279 9AE7 E0100; Adobe-Japan1; CID+22935 9AE9 E0100; Adobe-Japan1; CID+19008 @@ -35487,6 +35507,8 @@ FA29 E0100; Adobe-Japan1; CID+8687 20C50 E0101; Moji_Joho; MJ057161 20C74 E0100; Hanyo-Denshi; KS041540 20C74 E0101; Hanyo-Denshi; TK01014200 +20C98 E0100; MSARG; MD_20C98 +20C98 E0101; MSARG; ME_20C98_001 20C9C E0100; Hanyo-Denshi; TK01014280 20C9C E0101; Hanyo-Denshi; TK01014620 20D45 E0100; Adobe-Japan1; CID+17359 @@ -35689,6 +35711,8 @@ FA29 E0100; Adobe-Japan1; CID+8687 21A41 E0101; Hanyo-Denshi; TK01022390 21A62 E0100; Hanyo-Denshi; KS082510 21A62 E0101; Hanyo-Denshi; TK01022590 +21A74 E0100; MSARG; MD_21A74 +21A74 E0101; MSARG; ME_21A74_001 21AA2 E0100; Moji_Joho; MJ034079 21AA2 E0101; Moji_Joho; MJ034080 21B33 E0100; Hanyo-Denshi; KS084630 diff --git a/admin/unidata/Makefile.in b/admin/unidata/Makefile.in index 161c81567f6..3eb3dbc4050 100644 --- a/admin/unidata/Makefile.in +++ b/admin/unidata/Makefile.in @@ -33,6 +33,9 @@ EMACS = ${top_builddir}/src/remacs unidir = ${top_srcdir}/lisp/international emacs = "${EMACS}" -batch --no-site-file --no-site-lisp +lparen = ( +unifiles = $(addprefix ${unidir}/,$(sort $(shell sed -n 's/^[ \t][ \t]*${lparen}"\(uni-[^"]*\)"$$/\1/p' ${srcdir}/unidata-gen.el))) + # 'make' verbosity. AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ @@ -51,9 +54,10 @@ am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = -.PHONY: all unifiles +.PHONY: all -all: ${top_srcdir}/src/macuvs.h unifiles ${unidir}/charscript.el +all: ${top_srcdir}/src/macuvs.h ${unifiles} ${unidir}/charscript.el \ + ${unidir}/charprop.el ## Specify .elc as an order-only prereq so as to not needlessly rebuild ## target just because the .elc is missing. @@ -71,30 +75,21 @@ unidata.txt: ${srcdir}/UnicodeData.txt $(AM_V_GEN)sed -e 's/\([^;]*\);\(.*\)/(#x\1 "\2")/' -e 's/;/" "/g' \ < $< > $@ -PHONY_EXTRAS = -.PHONY: $(PHONY_EXTRAS) +## charprop doesn't actually depend on unifiles, but for now at least +## pretend that it does since other Makefiles assume that if charprop +## is up-to-date, the unifiles are too. +${unidir}/charprop.el: ${unifiles} ${srcdir}/unidata-gen.el | ${srcdir}/unidata-gen.elc + $(AM_V_at)[ ! -f $@ ] || chmod +w $@ + $(AM_V_GEN)${emacs} -L ${srcdir} -l unidata-gen \ + -f unidata-gen-charprop $@ -${unidir}/charprop.el: ${srcdir}/unidata-gen.el \ +${unifiles}: ${srcdir}/unidata-gen.el \ ${srcdir}/UnicodeData.txt ${srcdir}/BidiMirroring.txt \ ${srcdir}/BidiBrackets.txt | \ ${srcdir}/unidata-gen.elc unidata.txt - ifneq (,$(wildcard $@)) - $(AM_V_at)cd $(unidir) && \ - for f in charprop.el `sed -n 's/^;; FILE: //p' < charprop.el`; do \ - [ ! -f $$f ] || [ -w $$f ] || chmod +w $$f || exit; \ - done - endif - $(AM_V_GEN)${emacs} -L ${srcdir} -l unidata-gen -f unidata-gen-files \ - ${srcdir} "${unidir}" - -## Check for deleted uni- files, and if any such, force a rebuild. -## Perhaps a more elegant way would be for the previous rule -## to generate a Makefile fragment explicitly listing the uni- files, -## which this file could include. If no fragment, rebuild everything. -unifiles: ${unidir}/charprop.el - $(AM_V_at)for f in `sed -n 's/^;; FILE: //p' < $<`; do \ - [ -f $(unidir)/$$f ] || exec $(MAKE) PHONY_EXTRAS=$< $<; \ - done + $(AM_V_at)[ ! -f $@ ] || chmod +w $@ + $(AM_V_GEN)${emacs} -L ${srcdir} -l unidata-gen \ + -f unidata-gen-file $@ ${srcdir} .PHONY: charscript.el @@ -123,7 +118,4 @@ maintainer-clean: distclean ## Cf leim/ja-dic (which is much slower). extraclean: rm -f ${top_srcdir}/src/macuvs.h ${unidir}/charscript.el* - ifneq (,$(wildcard $(unidir)/charprop.el)) - cd $(unidir) && \ - rm -f `sed -n 's/^;; FILE: //p' < charprop.el` charprop.el - endif + rm -f ${unifiles} ${unidir}/charprop.el diff --git a/admin/unidata/NormalizationTest.txt b/admin/unidata/NormalizationTest.txt index e133fa8a788..71f2371c5eb 100644 --- a/admin/unidata/NormalizationTest.txt +++ b/admin/unidata/NormalizationTest.txt @@ -1,6 +1,6 @@ -# NormalizationTest-9.0.0.txt -# Date: 2016-04-04, 11:41:55 GMT -# © 2016 Unicode®, Inc. +# NormalizationTest-10.0.0.txt +# Date: 2017-03-08, 08:41:55 GMT +# © 2017 Unicode®, Inc. # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. # For terms of use, see http://www.unicode.org/terms_of_use.html # @@ -17653,6 +17653,10 @@ FFEE;FFEE;FFEE;25CB;25CB; # (○; ○; ○; ○; ○; ) HALFWIDTH WHITE CIRCLE 0061 0CBC 3099 093C 0334 0062;0061 0334 0CBC 093C 3099 0062;0061 0334 0CBC 093C 3099 0062;0061 0334 0CBC 093C 3099 0062;0061 0334 0CBC 093C 3099 0062; # (a◌಼◌゙◌़◌̴b; a◌̴◌಼◌़◌゙b; a◌̴◌಼◌़◌゙b; a◌̴◌಼◌़◌゙b; a◌̴◌಼◌़◌゙b; ) LATIN SMALL LETTER A, KANNADA SIGN NUKTA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, DEVANAGARI SIGN NUKTA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B 0061 05B0 094D 3099 0CCD 0062;0061 3099 094D 0CCD 05B0 0062;0061 3099 094D 0CCD 05B0 0062;0061 3099 094D 0CCD 05B0 0062;0061 3099 094D 0CCD 05B0 0062; # (a◌ְ◌्◌゙◌್b; a◌゙◌्◌್◌ְb; a◌゙◌्◌್◌ְb; a◌゙◌्◌್◌ְb; a◌゙◌्◌್◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, KANNADA SIGN VIRAMA, LATIN SMALL LETTER B 0061 0CCD 05B0 094D 3099 0062;0061 3099 0CCD 094D 05B0 0062;0061 3099 0CCD 094D 05B0 0062;0061 3099 0CCD 094D 05B0 0062;0061 3099 0CCD 094D 05B0 0062; # (a◌್◌ְ◌्◌゙b; a◌゙◌್◌्◌ְb; a◌゙◌್◌्◌ְb; a◌゙◌್◌्◌ְb; a◌゙◌್◌्◌ְb; ) LATIN SMALL LETTER A, KANNADA SIGN VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B +0061 05B0 094D 3099 0D3B 0062;0061 3099 094D 0D3B 05B0 0062;0061 3099 094D 0D3B 05B0 0062;0061 3099 094D 0D3B 05B0 0062;0061 3099 094D 0D3B 05B0 0062; # (a◌ְ◌्◌゙◌഻b; a◌゙◌्◌഻◌ְb; a◌゙◌्◌഻◌ְb; a◌゙◌्◌഻◌ְb; a◌゙◌्◌഻◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, MALAYALAM SIGN VERTICAL BAR VIRAMA, LATIN SMALL LETTER B +0061 0D3B 05B0 094D 3099 0062;0061 3099 0D3B 094D 05B0 0062;0061 3099 0D3B 094D 05B0 0062;0061 3099 0D3B 094D 05B0 0062;0061 3099 0D3B 094D 05B0 0062; # (a◌഻◌ְ◌्◌゙b; a◌゙◌഻◌्◌ְb; a◌゙◌഻◌्◌ְb; a◌゙◌഻◌्◌ְb; a◌゙◌഻◌्◌ְb; ) LATIN SMALL LETTER A, MALAYALAM SIGN VERTICAL BAR VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B +0061 05B0 094D 3099 0D3C 0062;0061 3099 094D 0D3C 05B0 0062;0061 3099 094D 0D3C 05B0 0062;0061 3099 094D 0D3C 05B0 0062;0061 3099 094D 0D3C 05B0 0062; # (a◌ְ◌्◌゙◌഼b; a◌゙◌्◌഼◌ְb; a◌゙◌्◌഼◌ְb; a◌゙◌्◌഼◌ְb; a◌゙◌्◌഼◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, MALAYALAM SIGN CIRCULAR VIRAMA, LATIN SMALL LETTER B +0061 0D3C 05B0 094D 3099 0062;0061 3099 0D3C 094D 05B0 0062;0061 3099 0D3C 094D 05B0 0062;0061 3099 0D3C 094D 05B0 0062;0061 3099 0D3C 094D 05B0 0062; # (a◌഼◌ְ◌्◌゙b; a◌゙◌഼◌्◌ְb; a◌゙◌഼◌्◌ְb; a◌゙◌഼◌्◌ְb; a◌゙◌഼◌्◌ְb; ) LATIN SMALL LETTER A, MALAYALAM SIGN CIRCULAR VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B 0061 05B0 094D 3099 0D4D 0062;0061 3099 094D 0D4D 05B0 0062;0061 3099 094D 0D4D 05B0 0062;0061 3099 094D 0D4D 05B0 0062;0061 3099 094D 0D4D 05B0 0062; # (a◌ְ◌्◌゙◌്b; a◌゙◌्◌്◌ְb; a◌゙◌्◌്◌ְb; a◌゙◌्◌്◌ְb; a◌゙◌्◌്◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, MALAYALAM SIGN VIRAMA, LATIN SMALL LETTER B 0061 0D4D 05B0 094D 3099 0062;0061 3099 0D4D 094D 05B0 0062;0061 3099 0D4D 094D 05B0 0062;0061 3099 0D4D 094D 05B0 0062;0061 3099 0D4D 094D 05B0 0062; # (a◌്◌ְ◌्◌゙b; a◌゙◌്◌्◌ְb; a◌゙◌്◌्◌ְb; a◌゙◌്◌्◌ְb; a◌゙◌്◌्◌ְb; ) LATIN SMALL LETTER A, MALAYALAM SIGN VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B 0061 05B0 094D 3099 0DCA 0062;0061 3099 094D 0DCA 05B0 0062;0061 3099 094D 0DCA 05B0 0062;0061 3099 094D 0DCA 05B0 0062;0061 3099 094D 0DCA 05B0 0062; # (a◌ְ◌्◌゙◌්b; a◌゙◌्◌්◌ְb; a◌゙◌्◌්◌ְb; a◌゙◌्◌්◌ְb; a◌゙◌्◌්◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, SINHALA SIGN AL-LAKUNA, LATIN SMALL LETTER B @@ -17999,6 +18003,14 @@ FFEE;FFEE;FFEE;25CB;25CB; # (○; ○; ○; ○; ○; ) HALFWIDTH WHITE CIRCLE 0061 1DF4 0315 0300 05AE 0062;0061 05AE 1DF4 0300 0315 0062;0061 05AE 1DF4 0300 0315 0062;0061 05AE 1DF4 0300 0315 0062;0061 05AE 1DF4 0300 0315 0062; # (a◌ᷴ◌̕◌̀◌֮b; a◌֮◌ᷴ◌̀◌̕b; a◌֮◌ᷴ◌̀◌̕b; a◌֮◌ᷴ◌̀◌̕b; a◌֮◌ᷴ◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING LATIN SMALL LETTER U WITH DIAERESIS, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B 0061 0315 0300 05AE 1DF5 0062;00E0 05AE 1DF5 0315 0062;0061 05AE 0300 1DF5 0315 0062;00E0 05AE 1DF5 0315 0062;0061 05AE 0300 1DF5 0315 0062; # (a◌̕◌̀◌֮◌᷵b; à◌֮◌᷵◌̕b; a◌֮◌̀◌᷵◌̕b; à◌֮◌᷵◌̕b; a◌֮◌̀◌᷵◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING UP TACK ABOVE, LATIN SMALL LETTER B 0061 1DF5 0315 0300 05AE 0062;0061 05AE 1DF5 0300 0315 0062;0061 05AE 1DF5 0300 0315 0062;0061 05AE 1DF5 0300 0315 0062;0061 05AE 1DF5 0300 0315 0062; # (a◌᷵◌̕◌̀◌֮b; a◌֮◌᷵◌̀◌̕b; a◌֮◌᷵◌̀◌̕b; a◌֮◌᷵◌̀◌̕b; a◌֮◌᷵◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING UP TACK ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B +0061 035C 0315 0300 1DF6 0062;00E0 0315 1DF6 035C 0062;0061 0300 0315 1DF6 035C 0062;00E0 0315 1DF6 035C 0062;0061 0300 0315 1DF6 035C 0062; # (a◌͜◌̕◌̀◌᷶b; à◌̕◌᷶◌͜b; a◌̀◌̕◌᷶◌͜b; à◌̕◌᷶◌͜b; a◌̀◌̕◌᷶◌͜b; ) LATIN SMALL LETTER A, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, COMBINING KAVYKA ABOVE RIGHT, LATIN SMALL LETTER B +0061 1DF6 035C 0315 0300 0062;00E0 1DF6 0315 035C 0062;0061 0300 1DF6 0315 035C 0062;00E0 1DF6 0315 035C 0062;0061 0300 1DF6 0315 035C 0062; # (a◌᷶◌͜◌̕◌̀b; à◌᷶◌̕◌͜b; a◌̀◌᷶◌̕◌͜b; à◌᷶◌̕◌͜b; a◌̀◌᷶◌̕◌͜b; ) LATIN SMALL LETTER A, COMBINING KAVYKA ABOVE RIGHT, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, LATIN SMALL LETTER B +0061 0300 05AE 1D16D 1DF7 0062;00E0 1D16D 05AE 1DF7 0062;0061 1D16D 05AE 1DF7 0300 0062;00E0 1D16D 05AE 1DF7 0062;0061 1D16D 05AE 1DF7 0300 0062; # (a◌̀◌𝅭֮◌᷷b; à𝅭◌֮◌᷷b; a𝅭◌֮◌᷷◌̀b; à𝅭◌֮◌᷷b; a𝅭◌֮◌᷷◌̀b; ) LATIN SMALL LETTER A, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING AUGMENTATION DOT, COMBINING KAVYKA ABOVE LEFT, LATIN SMALL LETTER B +0061 1DF7 0300 05AE 1D16D 0062;00E0 1D16D 1DF7 05AE 0062;0061 1D16D 1DF7 05AE 0300 0062;00E0 1D16D 1DF7 05AE 0062;0061 1D16D 1DF7 05AE 0300 0062; # (a◌᷷◌̀◌𝅭֮b; à𝅭◌᷷◌֮b; a𝅭◌᷷◌֮◌̀b; à𝅭◌᷷◌֮b; a𝅭◌᷷◌֮◌̀b; ) LATIN SMALL LETTER A, COMBINING KAVYKA ABOVE LEFT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING AUGMENTATION DOT, LATIN SMALL LETTER B +0061 0300 05AE 1D16D 1DF8 0062;00E0 1D16D 05AE 1DF8 0062;0061 1D16D 05AE 1DF8 0300 0062;00E0 1D16D 05AE 1DF8 0062;0061 1D16D 05AE 1DF8 0300 0062; # (a◌̀◌𝅭֮◌᷸b; à𝅭◌֮◌᷸b; a𝅭◌֮◌᷸◌̀b; à𝅭◌֮◌᷸b; a𝅭◌֮◌᷸◌̀b; ) LATIN SMALL LETTER A, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING AUGMENTATION DOT, COMBINING DOT ABOVE LEFT, LATIN SMALL LETTER B +0061 1DF8 0300 05AE 1D16D 0062;00E0 1D16D 1DF8 05AE 0062;0061 1D16D 1DF8 05AE 0300 0062;00E0 1D16D 1DF8 05AE 0062;0061 1D16D 1DF8 05AE 0300 0062; # (a◌᷸◌̀◌𝅭֮b; à𝅭◌᷸◌֮b; a𝅭◌᷸◌֮◌̀b; à𝅭◌᷸◌֮b; a𝅭◌᷸◌֮◌̀b; ) LATIN SMALL LETTER A, COMBINING DOT ABOVE LEFT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING AUGMENTATION DOT, LATIN SMALL LETTER B +0061 059A 0316 302A 1DF9 0062;0061 302A 0316 1DF9 059A 0062;0061 302A 0316 1DF9 059A 0062;0061 302A 0316 1DF9 059A 0062;0061 302A 0316 1DF9 059A 0062; # (a◌֚◌̖◌〪◌᷹b; a◌〪◌̖◌᷹◌֚b; a◌〪◌̖◌᷹◌֚b; a◌〪◌̖◌᷹◌֚b; a◌〪◌̖◌᷹◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING WIDE INVERTED BRIDGE BELOW, LATIN SMALL LETTER B +0061 1DF9 059A 0316 302A 0062;0061 302A 1DF9 0316 059A 0062;0061 302A 1DF9 0316 059A 0062;0061 302A 1DF9 0316 059A 0062;0061 302A 1DF9 0316 059A 0062; # (a◌᷹◌֚◌̖◌〪b; a◌〪◌᷹◌̖◌֚b; a◌〪◌᷹◌̖◌֚b; a◌〪◌᷹◌̖◌֚b; a◌〪◌᷹◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING WIDE INVERTED BRIDGE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B 0061 0315 0300 05AE 1DFB 0062;00E0 05AE 1DFB 0315 0062;0061 05AE 0300 1DFB 0315 0062;00E0 05AE 1DFB 0315 0062;0061 05AE 0300 1DFB 0315 0062; # (a◌̕◌̀◌֮◌᷻b; à◌֮◌᷻◌̕b; a◌֮◌̀◌᷻◌̕b; à◌֮◌᷻◌̕b; a◌֮◌̀◌᷻◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING DELETION MARK, LATIN SMALL LETTER B 0061 1DFB 0315 0300 05AE 0062;0061 05AE 1DFB 0300 0315 0062;0061 05AE 1DFB 0300 0315 0062;0061 05AE 1DFB 0300 0315 0062;0061 05AE 1DFB 0300 0315 0062; # (a◌᷻◌̕◌̀◌֮b; a◌֮◌᷻◌̀◌̕b; a◌֮◌᷻◌̀◌̕b; a◌֮◌᷻◌̀◌̕b; a◌֮◌᷻◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING DELETION MARK, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B 0061 035D 035C 0315 1DFC 0062;0061 0315 035C 1DFC 035D 0062;0061 0315 035C 1DFC 035D 0062;0061 0315 035C 1DFC 035D 0062;0061 0315 035C 1DFC 035D 0062; # (a◌͝◌͜◌̕◌᷼b; a◌̕◌͜◌᷼◌͝b; a◌̕◌͜◌᷼◌͝b; a◌̕◌͜◌᷼◌͝b; a◌̕◌͜◌᷼◌͝b; ) LATIN SMALL LETTER A, COMBINING DOUBLE BREVE, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING DOUBLE INVERTED BREVE BELOW, LATIN SMALL LETTER B @@ -18397,8 +18409,20 @@ FFEE;FFEE;FFEE;25CB;25CB; # (○; ○; ○; ○; ○; ) HALFWIDTH WHITE CIRCLE 0061 116B7 3099 093C 0334 0062;0061 0334 116B7 093C 3099 0062;0061 0334 116B7 093C 3099 0062;0061 0334 116B7 093C 3099 0062;0061 0334 116B7 093C 3099 0062; # (a◌𑚷◌゙◌़◌̴b; a◌̴◌𑚷◌़◌゙b; a◌̴◌𑚷◌़◌゙b; a◌̴◌𑚷◌़◌゙b; a◌̴◌𑚷◌़◌゙b; ) LATIN SMALL LETTER A, TAKRI SIGN NUKTA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, DEVANAGARI SIGN NUKTA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B 0061 05B0 094D 3099 1172B 0062;0061 3099 094D 1172B 05B0 0062;0061 3099 094D 1172B 05B0 0062;0061 3099 094D 1172B 05B0 0062;0061 3099 094D 1172B 05B0 0062; # (a◌ְ◌्◌゙◌𑜫b; a◌゙◌्◌𑜫◌ְb; a◌゙◌्◌𑜫◌ְb; a◌゙◌्◌𑜫◌ְb; a◌゙◌्◌𑜫◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, AHOM SIGN KILLER, LATIN SMALL LETTER B 0061 1172B 05B0 094D 3099 0062;0061 3099 1172B 094D 05B0 0062;0061 3099 1172B 094D 05B0 0062;0061 3099 1172B 094D 05B0 0062;0061 3099 1172B 094D 05B0 0062; # (a◌𑜫◌ְ◌्◌゙b; a◌゙◌𑜫◌्◌ְb; a◌゙◌𑜫◌्◌ְb; a◌゙◌𑜫◌्◌ְb; a◌゙◌𑜫◌्◌ְb; ) LATIN SMALL LETTER A, AHOM SIGN KILLER, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B +0061 05B0 094D 3099 11A34 0062;0061 3099 094D 11A34 05B0 0062;0061 3099 094D 11A34 05B0 0062;0061 3099 094D 11A34 05B0 0062;0061 3099 094D 11A34 05B0 0062; # (a◌ְ◌्◌゙◌𑨴b; a◌゙◌्◌𑨴◌ְb; a◌゙◌्◌𑨴◌ְb; a◌゙◌्◌𑨴◌ְb; a◌゙◌्◌𑨴◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, ZANABAZAR SQUARE SIGN VIRAMA, LATIN SMALL LETTER B +0061 11A34 05B0 094D 3099 0062;0061 3099 11A34 094D 05B0 0062;0061 3099 11A34 094D 05B0 0062;0061 3099 11A34 094D 05B0 0062;0061 3099 11A34 094D 05B0 0062; # (a◌𑨴◌ְ◌्◌゙b; a◌゙◌𑨴◌्◌ְb; a◌゙◌𑨴◌्◌ְb; a◌゙◌𑨴◌्◌ְb; a◌゙◌𑨴◌्◌ְb; ) LATIN SMALL LETTER A, ZANABAZAR SQUARE SIGN VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B +0061 05B0 094D 3099 11A47 0062;0061 3099 094D 11A47 05B0 0062;0061 3099 094D 11A47 05B0 0062;0061 3099 094D 11A47 05B0 0062;0061 3099 094D 11A47 05B0 0062; # (a◌ְ◌्◌゙◌𑩇b; a◌゙◌्◌𑩇◌ְb; a◌゙◌्◌𑩇◌ְb; a◌゙◌्◌𑩇◌ְb; a◌゙◌्◌𑩇◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, ZANABAZAR SQUARE SUBJOINER, LATIN SMALL LETTER B +0061 11A47 05B0 094D 3099 0062;0061 3099 11A47 094D 05B0 0062;0061 3099 11A47 094D 05B0 0062;0061 3099 11A47 094D 05B0 0062;0061 3099 11A47 094D 05B0 0062; # (a◌𑩇◌ְ◌्◌゙b; a◌゙◌𑩇◌्◌ְb; a◌゙◌𑩇◌्◌ְb; a◌゙◌𑩇◌्◌ְb; a◌゙◌𑩇◌्◌ְb; ) LATIN SMALL LETTER A, ZANABAZAR SQUARE SUBJOINER, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B +0061 05B0 094D 3099 11A99 0062;0061 3099 094D 11A99 05B0 0062;0061 3099 094D 11A99 05B0 0062;0061 3099 094D 11A99 05B0 0062;0061 3099 094D 11A99 05B0 0062; # (a◌ְ◌्◌゙◌𑪙b; a◌゙◌्◌𑪙◌ְb; a◌゙◌्◌𑪙◌ְb; a◌゙◌्◌𑪙◌ְb; a◌゙◌्◌𑪙◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, SOYOMBO SUBJOINER, LATIN SMALL LETTER B +0061 11A99 05B0 094D 3099 0062;0061 3099 11A99 094D 05B0 0062;0061 3099 11A99 094D 05B0 0062;0061 3099 11A99 094D 05B0 0062;0061 3099 11A99 094D 05B0 0062; # (a◌𑪙◌ְ◌्◌゙b; a◌゙◌𑪙◌्◌ְb; a◌゙◌𑪙◌्◌ְb; a◌゙◌𑪙◌्◌ְb; a◌゙◌𑪙◌्◌ְb; ) LATIN SMALL LETTER A, SOYOMBO SUBJOINER, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B 0061 05B0 094D 3099 11C3F 0062;0061 3099 094D 11C3F 05B0 0062;0061 3099 094D 11C3F 05B0 0062;0061 3099 094D 11C3F 05B0 0062;0061 3099 094D 11C3F 05B0 0062; # (a◌ְ◌्◌゙◌𑰿b; a◌゙◌्◌𑰿◌ְb; a◌゙◌्◌𑰿◌ְb; a◌゙◌्◌𑰿◌ְb; a◌゙◌्◌𑰿◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, BHAIKSUKI SIGN VIRAMA, LATIN SMALL LETTER B 0061 11C3F 05B0 094D 3099 0062;0061 3099 11C3F 094D 05B0 0062;0061 3099 11C3F 094D 05B0 0062;0061 3099 11C3F 094D 05B0 0062;0061 3099 11C3F 094D 05B0 0062; # (a◌𑰿◌ְ◌्◌゙b; a◌゙◌𑰿◌्◌ְb; a◌゙◌𑰿◌्◌ְb; a◌゙◌𑰿◌्◌ְb; a◌゙◌𑰿◌्◌ְb; ) LATIN SMALL LETTER A, BHAIKSUKI SIGN VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B +0061 3099 093C 0334 11D42 0062;0061 0334 093C 11D42 3099 0062;0061 0334 093C 11D42 3099 0062;0061 0334 093C 11D42 3099 0062;0061 0334 093C 11D42 3099 0062; # (a◌゙◌़◌̴◌𑵂b; a◌̴◌़◌𑵂◌゙b; a◌̴◌़◌𑵂◌゙b; a◌̴◌़◌𑵂◌゙b; a◌̴◌़◌𑵂◌゙b; ) LATIN SMALL LETTER A, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, DEVANAGARI SIGN NUKTA, COMBINING TILDE OVERLAY, MASARAM GONDI SIGN NUKTA, LATIN SMALL LETTER B +0061 11D42 3099 093C 0334 0062;0061 0334 11D42 093C 3099 0062;0061 0334 11D42 093C 3099 0062;0061 0334 11D42 093C 3099 0062;0061 0334 11D42 093C 3099 0062; # (a◌𑵂◌゙◌़◌̴b; a◌̴◌𑵂◌़◌゙b; a◌̴◌𑵂◌़◌゙b; a◌̴◌𑵂◌़◌゙b; a◌̴◌𑵂◌़◌゙b; ) LATIN SMALL LETTER A, MASARAM GONDI SIGN NUKTA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, DEVANAGARI SIGN NUKTA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B +0061 05B0 094D 3099 11D44 0062;0061 3099 094D 11D44 05B0 0062;0061 3099 094D 11D44 05B0 0062;0061 3099 094D 11D44 05B0 0062;0061 3099 094D 11D44 05B0 0062; # (a◌ְ◌्◌゙◌𑵄b; a◌゙◌्◌𑵄◌ְb; a◌゙◌्◌𑵄◌ְb; a◌゙◌्◌𑵄◌ְb; a◌゙◌्◌𑵄◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, MASARAM GONDI SIGN HALANTA, LATIN SMALL LETTER B +0061 11D44 05B0 094D 3099 0062;0061 3099 11D44 094D 05B0 0062;0061 3099 11D44 094D 05B0 0062;0061 3099 11D44 094D 05B0 0062;0061 3099 11D44 094D 05B0 0062; # (a◌𑵄◌ְ◌्◌゙b; a◌゙◌𑵄◌्◌ְb; a◌゙◌𑵄◌्◌ְb; a◌゙◌𑵄◌्◌ְb; a◌゙◌𑵄◌्◌ְb; ) LATIN SMALL LETTER A, MASARAM GONDI SIGN HALANTA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B +0061 05B0 094D 3099 11D45 0062;0061 3099 094D 11D45 05B0 0062;0061 3099 094D 11D45 05B0 0062;0061 3099 094D 11D45 05B0 0062;0061 3099 094D 11D45 05B0 0062; # (a◌ְ◌्◌゙◌𑵅b; a◌゙◌्◌𑵅◌ְb; a◌゙◌्◌𑵅◌ְb; a◌゙◌्◌𑵅◌ְb; a◌゙◌्◌𑵅◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, MASARAM GONDI VIRAMA, LATIN SMALL LETTER B +0061 11D45 05B0 094D 3099 0062;0061 3099 11D45 094D 05B0 0062;0061 3099 11D45 094D 05B0 0062;0061 3099 11D45 094D 05B0 0062;0061 3099 11D45 094D 05B0 0062; # (a◌𑵅◌ְ◌्◌゙b; a◌゙◌𑵅◌्◌ְb; a◌゙◌𑵅◌्◌ְb; a◌゙◌𑵅◌्◌ְb; a◌゙◌𑵅◌्◌ְb; ) LATIN SMALL LETTER A, MASARAM GONDI VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B 0061 093C 0334 16AF0 0062;0061 0334 16AF0 093C 0062;0061 0334 16AF0 093C 0062;0061 0334 16AF0 093C 0062;0061 0334 16AF0 093C 0062; # (a◌़◌̴◌𖫰b; a◌̴◌𖫰◌़b; a◌̴◌𖫰◌़b; a◌̴◌𖫰◌़b; a◌̴◌𖫰◌़b; ) LATIN SMALL LETTER A, DEVANAGARI SIGN NUKTA, COMBINING TILDE OVERLAY, BASSA VAH COMBINING HIGH TONE, LATIN SMALL LETTER B 0061 16AF0 093C 0334 0062;0061 16AF0 0334 093C 0062;0061 16AF0 0334 093C 0062;0061 16AF0 0334 093C 0062;0061 16AF0 0334 093C 0062; # (a◌𖫰◌़◌̴b; a◌𖫰◌̴◌़b; a◌𖫰◌̴◌़b; a◌𖫰◌̴◌़b; a◌𖫰◌̴◌़b; ) LATIN SMALL LETTER A, BASSA VAH COMBINING HIGH TONE, DEVANAGARI SIGN NUKTA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B 0061 093C 0334 16AF1 0062;0061 0334 16AF1 093C 0062;0061 0334 16AF1 093C 0062;0061 0334 16AF1 093C 0062;0061 0334 16AF1 093C 0062; # (a◌़◌̴◌𖫱b; a◌̴◌𖫱◌़b; a◌̴◌𖫱◌़b; a◌̴◌𖫱◌़b; a◌̴◌𖫱◌़b; ) LATIN SMALL LETTER A, DEVANAGARI SIGN NUKTA, COMBINING TILDE OVERLAY, BASSA VAH COMBINING LOW TONE, LATIN SMALL LETTER B diff --git a/admin/unidata/README b/admin/unidata/README index 534670ce6db..f5881a1a149 100644 --- a/admin/unidata/README +++ b/admin/unidata/README @@ -5,22 +5,30 @@ copyright.html. The names, URLs, and dates for these files are as follows. +BidiBrackets.txt +http://www.unicode.org/Public/UNIDATA/BidiBrackets.txt +2017-04-20 + BidiMirroring.txt http://www.unicode.org/Public/UNIDATA/BidiMirroring.txt -2013-12-17 +2017-04-20 IVD_Sequences.txt -http://www.unicode.org/ivd/data/2014-05-16/IVD_Sequences.txt -2014-05-16 +http://www.unicode.org/ivd/ +2016-08-15 UnicodeData.txt http://www.unicode.org/Public/UNIDATA/UnicodeData.txt -2014-03-10 +2017-03-07 Blocks.txt http://www.unicode.org/Public/8.0.0/ucd/Blocks.txt -2014-11-10 +2017-04-20 NormalizationTest.txt http://www.unicode.org/Public/UNIDATA/NormalizationTest.txt -2016-07-16 +2017-03-08 + +SpecialCasing.txt +http://unicode.org/Public/UNIDATA/SpecialCasing.txt +2017-04-20 diff --git a/admin/unidata/SpecialCasing.txt b/admin/unidata/SpecialCasing.txt new file mode 100644 index 00000000000..cae11e9df71 --- /dev/null +++ b/admin/unidata/SpecialCasing.txt @@ -0,0 +1,280 @@ +# SpecialCasing-10.0.0.txt +# Date: 2017-04-14, 05:40:43 GMT +# © 2017 Unicode®, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see http://www.unicode.org/terms_of_use.html +# +# Unicode Character Database +# For documentation, see http://www.unicode.org/reports/tr44/ +# +# Special Casing +# +# This file is a supplement to the UnicodeData.txt file. It does not define any +# properties, but rather provides additional information about the casing of +# Unicode characters, for situations when casing incurs a change in string length +# or is dependent on context or locale. For compatibility, the UnicodeData.txt +# file only contains simple case mappings for characters where they are one-to-one +# and independent of context and language. The data in this file, combined with +# the simple case mappings in UnicodeData.txt, defines the full case mappings +# Lowercase_Mapping (lc), Titlecase_Mapping (tc), and Uppercase_Mapping (uc). +# +# Note that the preferred mechanism for defining tailored casing operations is +# the Unicode Common Locale Data Repository (CLDR). For more information, see the +# discussion of case mappings and case algorithms in the Unicode Standard. +# +# All code points not listed in this file that do not have a simple case mappings +# in UnicodeData.txt map to themselves. +# ================================================================================ +# Format +# ================================================================================ +# The entries in this file are in the following machine-readable format: +# +# ; ; ; <upper>; (<condition_list>;)? # <comment> +# +# <code>, <lower>, <title>, and <upper> provide the respective full case mappings +# of <code>, expressed as character values in hex. If there is more than one character, +# they are separated by spaces. Other than as used to separate elements, spaces are +# to be ignored. +# +# The <condition_list> is optional. Where present, it consists of one or more language IDs +# or casing contexts, separated by spaces. In these conditions: +# - A condition list overrides the normal behavior if all of the listed conditions are true. +# - The casing context is always the context of the characters in the original string, +# NOT in the resulting string. +# - Case distinctions in the condition list are not significant. +# - Conditions preceded by "Not_" represent the negation of the condition. +# The condition list is not represented in the UCD as a formal property. +# +# A language ID is defined by BCP 47, with '-' and '_' treated equivalently. +# +# A casing context for a character is defined by Section 3.13 Default Case Algorithms +# of The Unicode Standard. +# +# Parsers of this file must be prepared to deal with future additions to this format: +# * Additional contexts +# * Additional fields +# ================================================================================ + +# ================================================================================ +# Unconditional mappings +# ================================================================================ + +# The German es-zed is special--the normal mapping is to SS. +# Note: the titlecase should never occur in practice. It is equal to titlecase(uppercase(<es-zed>)) + +00DF; 00DF; 0053 0073; 0053 0053; # LATIN SMALL LETTER SHARP S + +# Preserve canonical equivalence for I with dot. Turkic is handled below. + +0130; 0069 0307; 0130; 0130; # LATIN CAPITAL LETTER I WITH DOT ABOVE + +# Ligatures + +FB00; FB00; 0046 0066; 0046 0046; # LATIN SMALL LIGATURE FF +FB01; FB01; 0046 0069; 0046 0049; # LATIN SMALL LIGATURE FI +FB02; FB02; 0046 006C; 0046 004C; # LATIN SMALL LIGATURE FL +FB03; FB03; 0046 0066 0069; 0046 0046 0049; # LATIN SMALL LIGATURE FFI +FB04; FB04; 0046 0066 006C; 0046 0046 004C; # LATIN SMALL LIGATURE FFL +FB05; FB05; 0053 0074; 0053 0054; # LATIN SMALL LIGATURE LONG S T +FB06; FB06; 0053 0074; 0053 0054; # LATIN SMALL LIGATURE ST + +0587; 0587; 0535 0582; 0535 0552; # ARMENIAN SMALL LIGATURE ECH YIWN +FB13; FB13; 0544 0576; 0544 0546; # ARMENIAN SMALL LIGATURE MEN NOW +FB14; FB14; 0544 0565; 0544 0535; # ARMENIAN SMALL LIGATURE MEN ECH +FB15; FB15; 0544 056B; 0544 053B; # ARMENIAN SMALL LIGATURE MEN INI +FB16; FB16; 054E 0576; 054E 0546; # ARMENIAN SMALL LIGATURE VEW NOW +FB17; FB17; 0544 056D; 0544 053D; # ARMENIAN SMALL LIGATURE MEN XEH + +# No corresponding uppercase precomposed character + +0149; 0149; 02BC 004E; 02BC 004E; # LATIN SMALL LETTER N PRECEDED BY APOSTROPHE +0390; 0390; 0399 0308 0301; 0399 0308 0301; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS +03B0; 03B0; 03A5 0308 0301; 03A5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS +01F0; 01F0; 004A 030C; 004A 030C; # LATIN SMALL LETTER J WITH CARON +1E96; 1E96; 0048 0331; 0048 0331; # LATIN SMALL LETTER H WITH LINE BELOW +1E97; 1E97; 0054 0308; 0054 0308; # LATIN SMALL LETTER T WITH DIAERESIS +1E98; 1E98; 0057 030A; 0057 030A; # LATIN SMALL LETTER W WITH RING ABOVE +1E99; 1E99; 0059 030A; 0059 030A; # LATIN SMALL LETTER Y WITH RING ABOVE +1E9A; 1E9A; 0041 02BE; 0041 02BE; # LATIN SMALL LETTER A WITH RIGHT HALF RING +1F50; 1F50; 03A5 0313; 03A5 0313; # GREEK SMALL LETTER UPSILON WITH PSILI +1F52; 1F52; 03A5 0313 0300; 03A5 0313 0300; # GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA +1F54; 1F54; 03A5 0313 0301; 03A5 0313 0301; # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA +1F56; 1F56; 03A5 0313 0342; 03A5 0313 0342; # GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI +1FB6; 1FB6; 0391 0342; 0391 0342; # GREEK SMALL LETTER ALPHA WITH PERISPOMENI +1FC6; 1FC6; 0397 0342; 0397 0342; # GREEK SMALL LETTER ETA WITH PERISPOMENI +1FD2; 1FD2; 0399 0308 0300; 0399 0308 0300; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA +1FD3; 1FD3; 0399 0308 0301; 0399 0308 0301; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA +1FD6; 1FD6; 0399 0342; 0399 0342; # GREEK SMALL LETTER IOTA WITH PERISPOMENI +1FD7; 1FD7; 0399 0308 0342; 0399 0308 0342; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI +1FE2; 1FE2; 03A5 0308 0300; 03A5 0308 0300; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA +1FE3; 1FE3; 03A5 0308 0301; 03A5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA +1FE4; 1FE4; 03A1 0313; 03A1 0313; # GREEK SMALL LETTER RHO WITH PSILI +1FE6; 1FE6; 03A5 0342; 03A5 0342; # GREEK SMALL LETTER UPSILON WITH PERISPOMENI +1FE7; 1FE7; 03A5 0308 0342; 03A5 0308 0342; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI +1FF6; 1FF6; 03A9 0342; 03A9 0342; # GREEK SMALL LETTER OMEGA WITH PERISPOMENI + +# IMPORTANT-when iota-subscript (0345) is uppercased or titlecased, +# the result will be incorrect unless the iota-subscript is moved to the end +# of any sequence of combining marks. Otherwise, the accents will go on the capital iota. +# This process can be achieved by first transforming the text to NFC before casing. +# E.g. <alpha><iota_subscript><acute> is uppercased to <ALPHA><acute><IOTA> + +# The following cases are already in the UnicodeData.txt file, so are only commented here. + +# 0345; 0345; 0345; 0399; # COMBINING GREEK YPOGEGRAMMENI + +# All letters with YPOGEGRAMMENI (iota-subscript) or PROSGEGRAMMENI (iota adscript) +# have special uppercases. +# Note: characters with PROSGEGRAMMENI are actually titlecase, not uppercase! + +1F80; 1F80; 1F88; 1F08 0399; # GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI +1F81; 1F81; 1F89; 1F09 0399; # GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI +1F82; 1F82; 1F8A; 1F0A 0399; # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI +1F83; 1F83; 1F8B; 1F0B 0399; # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI +1F84; 1F84; 1F8C; 1F0C 0399; # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI +1F85; 1F85; 1F8D; 1F0D 0399; # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI +1F86; 1F86; 1F8E; 1F0E 0399; # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI +1F87; 1F87; 1F8F; 1F0F 0399; # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI +1F88; 1F80; 1F88; 1F08 0399; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI +1F89; 1F81; 1F89; 1F09 0399; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI +1F8A; 1F82; 1F8A; 1F0A 0399; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI +1F8B; 1F83; 1F8B; 1F0B 0399; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI +1F8C; 1F84; 1F8C; 1F0C 0399; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI +1F8D; 1F85; 1F8D; 1F0D 0399; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI +1F8E; 1F86; 1F8E; 1F0E 0399; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI +1F8F; 1F87; 1F8F; 1F0F 0399; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI +1F90; 1F90; 1F98; 1F28 0399; # GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI +1F91; 1F91; 1F99; 1F29 0399; # GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI +1F92; 1F92; 1F9A; 1F2A 0399; # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI +1F93; 1F93; 1F9B; 1F2B 0399; # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI +1F94; 1F94; 1F9C; 1F2C 0399; # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI +1F95; 1F95; 1F9D; 1F2D 0399; # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI +1F96; 1F96; 1F9E; 1F2E 0399; # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI +1F97; 1F97; 1F9F; 1F2F 0399; # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI +1F98; 1F90; 1F98; 1F28 0399; # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI +1F99; 1F91; 1F99; 1F29 0399; # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI +1F9A; 1F92; 1F9A; 1F2A 0399; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI +1F9B; 1F93; 1F9B; 1F2B 0399; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI +1F9C; 1F94; 1F9C; 1F2C 0399; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI +1F9D; 1F95; 1F9D; 1F2D 0399; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI +1F9E; 1F96; 1F9E; 1F2E 0399; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI +1F9F; 1F97; 1F9F; 1F2F 0399; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI +1FA0; 1FA0; 1FA8; 1F68 0399; # GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI +1FA1; 1FA1; 1FA9; 1F69 0399; # GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI +1FA2; 1FA2; 1FAA; 1F6A 0399; # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI +1FA3; 1FA3; 1FAB; 1F6B 0399; # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI +1FA4; 1FA4; 1FAC; 1F6C 0399; # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI +1FA5; 1FA5; 1FAD; 1F6D 0399; # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI +1FA6; 1FA6; 1FAE; 1F6E 0399; # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI +1FA7; 1FA7; 1FAF; 1F6F 0399; # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI +1FA8; 1FA0; 1FA8; 1F68 0399; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI +1FA9; 1FA1; 1FA9; 1F69 0399; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI +1FAA; 1FA2; 1FAA; 1F6A 0399; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI +1FAB; 1FA3; 1FAB; 1F6B 0399; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI +1FAC; 1FA4; 1FAC; 1F6C 0399; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI +1FAD; 1FA5; 1FAD; 1F6D 0399; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI +1FAE; 1FA6; 1FAE; 1F6E 0399; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI +1FAF; 1FA7; 1FAF; 1F6F 0399; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI +1FB3; 1FB3; 1FBC; 0391 0399; # GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI +1FBC; 1FB3; 1FBC; 0391 0399; # GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI +1FC3; 1FC3; 1FCC; 0397 0399; # GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI +1FCC; 1FC3; 1FCC; 0397 0399; # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI +1FF3; 1FF3; 1FFC; 03A9 0399; # GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI +1FFC; 1FF3; 1FFC; 03A9 0399; # GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI + +# Some characters with YPOGEGRAMMENI also have no corresponding titlecases + +1FB2; 1FB2; 1FBA 0345; 1FBA 0399; # GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI +1FB4; 1FB4; 0386 0345; 0386 0399; # GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI +1FC2; 1FC2; 1FCA 0345; 1FCA 0399; # GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI +1FC4; 1FC4; 0389 0345; 0389 0399; # GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI +1FF2; 1FF2; 1FFA 0345; 1FFA 0399; # GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI +1FF4; 1FF4; 038F 0345; 038F 0399; # GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI + +1FB7; 1FB7; 0391 0342 0345; 0391 0342 0399; # GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI +1FC7; 1FC7; 0397 0342 0345; 0397 0342 0399; # GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI +1FF7; 1FF7; 03A9 0342 0345; 03A9 0342 0399; # GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI + +# ================================================================================ +# Conditional Mappings +# The remainder of this file provides conditional casing data used to produce +# full case mappings. +# ================================================================================ +# Language-Insensitive Mappings +# These are characters whose full case mappings do not depend on language, but do +# depend on context (which characters come before or after). For more information +# see the header of this file and the Unicode Standard. +# ================================================================================ + +# Special case for final form of sigma + +03A3; 03C2; 03A3; 03A3; Final_Sigma; # GREEK CAPITAL LETTER SIGMA + +# Note: the following cases for non-final are already in the UnicodeData.txt file. + +# 03A3; 03C3; 03A3; 03A3; # GREEK CAPITAL LETTER SIGMA +# 03C3; 03C3; 03A3; 03A3; # GREEK SMALL LETTER SIGMA +# 03C2; 03C2; 03A3; 03A3; # GREEK SMALL LETTER FINAL SIGMA + +# Note: the following cases are not included, since they would case-fold in lowercasing + +# 03C3; 03C2; 03A3; 03A3; Final_Sigma; # GREEK SMALL LETTER SIGMA +# 03C2; 03C3; 03A3; 03A3; Not_Final_Sigma; # GREEK SMALL LETTER FINAL SIGMA + +# ================================================================================ +# Language-Sensitive Mappings +# These are characters whose full case mappings depend on language and perhaps also +# context (which characters come before or after). For more information +# see the header of this file and the Unicode Standard. +# ================================================================================ + +# Lithuanian + +# Lithuanian retains the dot in a lowercase i when followed by accents. + +# Remove DOT ABOVE after "i" with upper or titlecase + +0307; 0307; ; ; lt After_Soft_Dotted; # COMBINING DOT ABOVE + +# Introduce an explicit dot above when lowercasing capital I's and J's +# whenever there are more accents above. +# (of the accents used in Lithuanian: grave, acute, tilde above, and ogonek) + +0049; 0069 0307; 0049; 0049; lt More_Above; # LATIN CAPITAL LETTER I +004A; 006A 0307; 004A; 004A; lt More_Above; # LATIN CAPITAL LETTER J +012E; 012F 0307; 012E; 012E; lt More_Above; # LATIN CAPITAL LETTER I WITH OGONEK +00CC; 0069 0307 0300; 00CC; 00CC; lt; # LATIN CAPITAL LETTER I WITH GRAVE +00CD; 0069 0307 0301; 00CD; 00CD; lt; # LATIN CAPITAL LETTER I WITH ACUTE +0128; 0069 0307 0303; 0128; 0128; lt; # LATIN CAPITAL LETTER I WITH TILDE + +# ================================================================================ + +# Turkish and Azeri + +# I and i-dotless; I-dot and i are case pairs in Turkish and Azeri +# The following rules handle those cases. + +0130; 0069; 0130; 0130; tr; # LATIN CAPITAL LETTER I WITH DOT ABOVE +0130; 0069; 0130; 0130; az; # LATIN CAPITAL LETTER I WITH DOT ABOVE + +# When lowercasing, remove dot_above in the sequence I + dot_above, which will turn into i. +# This matches the behavior of the canonically equivalent I-dot_above + +0307; ; 0307; 0307; tr After_I; # COMBINING DOT ABOVE +0307; ; 0307; 0307; az After_I; # COMBINING DOT ABOVE + +# When lowercasing, unless an I is before a dot_above, it turns into a dotless i. + +0049; 0131; 0049; 0049; tr Not_Before_Dot; # LATIN CAPITAL LETTER I +0049; 0131; 0049; 0049; az Not_Before_Dot; # LATIN CAPITAL LETTER I + +# When uppercasing, i turns into a dotted capital I + +0069; 0069; 0130; 0130; tr; # LATIN SMALL LETTER I +0069; 0069; 0130; 0130; az; # LATIN SMALL LETTER I + +# Note: the following case is already in the UnicodeData.txt file. + +# 0131; 0131; 0049; 0049; tr; # LATIN SMALL LETTER DOTLESS I + +# EOF diff --git a/admin/unidata/UnicodeData.txt b/admin/unidata/UnicodeData.txt index a756976461b..d89c64f526a 100644 --- a/admin/unidata/UnicodeData.txt +++ b/admin/unidata/UnicodeData.txt @@ -2072,6 +2072,17 @@ 085A;MANDAIC VOCALIZATION MARK;Mn;220;NSM;;;;;N;;;;; 085B;MANDAIC GEMINATION MARK;Mn;220;NSM;;;;;N;;;;; 085E;MANDAIC PUNCTUATION;Po;0;R;;;;;N;;;;; +0860;SYRIAC LETTER MALAYALAM NGA;Lo;0;AL;;;;;N;;;;; +0861;SYRIAC LETTER MALAYALAM JA;Lo;0;AL;;;;;N;;;;; +0862;SYRIAC LETTER MALAYALAM NYA;Lo;0;AL;;;;;N;;;;; +0863;SYRIAC LETTER MALAYALAM TTA;Lo;0;AL;;;;;N;;;;; +0864;SYRIAC LETTER MALAYALAM NNA;Lo;0;AL;;;;;N;;;;; +0865;SYRIAC LETTER MALAYALAM NNNA;Lo;0;AL;;;;;N;;;;; +0866;SYRIAC LETTER MALAYALAM BHA;Lo;0;AL;;;;;N;;;;; +0867;SYRIAC LETTER MALAYALAM RA;Lo;0;AL;;;;;N;;;;; +0868;SYRIAC LETTER MALAYALAM LLA;Lo;0;AL;;;;;N;;;;; +0869;SYRIAC LETTER MALAYALAM LLLA;Lo;0;AL;;;;;N;;;;; +086A;SYRIAC LETTER MALAYALAM SSA;Lo;0;AL;;;;;N;;;;; 08A0;ARABIC LETTER BEH WITH SMALL V BELOW;Lo;0;AL;;;;;N;;;;; 08A1;ARABIC LETTER BEH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;;;;; 08A2;ARABIC LETTER JEEM WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; @@ -2366,6 +2377,8 @@ 09F9;BENGALI CURRENCY DENOMINATOR SIXTEEN;No;0;L;;;;16;N;;;;; 09FA;BENGALI ISSHAR;So;0;L;;;;;N;;;;; 09FB;BENGALI GANDA MARK;Sc;0;ET;;;;;N;;;;; +09FC;BENGALI LETTER VEDIC ANUSVARA;Lo;0;L;;;;;N;;;;; +09FD;BENGALI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 0A01;GURMUKHI SIGN ADAK BINDI;Mn;0;NSM;;;;;N;;;;; 0A02;GURMUKHI SIGN BINDI;Mn;0;NSM;;;;;N;;;;; 0A03;GURMUKHI SIGN VISARGA;Mc;0;L;;;;;N;;;;; @@ -2530,6 +2543,12 @@ 0AF0;GUJARATI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 0AF1;GUJARATI RUPEE SIGN;Sc;0;ET;;;;;N;;;;; 0AF9;GUJARATI LETTER ZHA;Lo;0;L;;;;;N;;;;; +0AFA;GUJARATI SIGN SUKUN;Mn;0;NSM;;;;;N;;;;; +0AFB;GUJARATI SIGN SHADDA;Mn;0;NSM;;;;;N;;;;; +0AFC;GUJARATI SIGN MADDAH;Mn;0;NSM;;;;;N;;;;; +0AFD;GUJARATI SIGN THREE-DOT NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;; +0AFE;GUJARATI SIGN CIRCLE NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;; +0AFF;GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;; 0B01;ORIYA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0B02;ORIYA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0B03;ORIYA SIGN VISARGA;Mc;0;L;;;;;N;;;;; @@ -2876,6 +2895,7 @@ 0CEF;KANNADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0CF1;KANNADA SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; 0CF2;KANNADA SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; +0D00;MALAYALAM SIGN COMBINING ANUSVARA ABOVE;Mn;0;NSM;;;;;N;;;;; 0D01;MALAYALAM SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0D02;MALAYALAM SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0D03;MALAYALAM SIGN VISARGA;Mc;0;L;;;;;N;;;;; @@ -2931,6 +2951,8 @@ 0D38;MALAYALAM LETTER SA;Lo;0;L;;;;;N;;;;; 0D39;MALAYALAM LETTER HA;Lo;0;L;;;;;N;;;;; 0D3A;MALAYALAM LETTER TTTA;Lo;0;L;;;;;N;;;;; +0D3B;MALAYALAM SIGN VERTICAL BAR VIRAMA;Mn;9;NSM;;;;;N;;;;; +0D3C;MALAYALAM SIGN CIRCULAR VIRAMA;Mn;9;NSM;;;;;N;;;;; 0D3D;MALAYALAM SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0D3E;MALAYALAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0D3F;MALAYALAM VOWEL SIGN I;Mc;0;L;;;;;N;;;;; @@ -6413,6 +6435,7 @@ 1CF4;VEDIC TONE CANDRA ABOVE;Mn;230;NSM;;;;;N;;;;; 1CF5;VEDIC SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; 1CF6;VEDIC SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; +1CF7;VEDIC SIGN ATIKRAMA;Mc;0;L;;;;;N;;;;; 1CF8;VEDIC TONE RING ABOVE;Mn;230;NSM;;;;;N;;;;; 1CF9;VEDIC TONE DOUBLE RING ABOVE;Mn;230;NSM;;;;;N;;;;; 1D00;LATIN LETTER SMALL CAPITAL A;Ll;0;L;;;;;N;;;;; @@ -6661,6 +6684,10 @@ 1DF3;COMBINING LATIN SMALL LETTER O WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; 1DF4;COMBINING LATIN SMALL LETTER U WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; 1DF5;COMBINING UP TACK ABOVE;Mn;230;NSM;;;;;N;;;;; +1DF6;COMBINING KAVYKA ABOVE RIGHT;Mn;232;NSM;;;;;N;;;;; +1DF7;COMBINING KAVYKA ABOVE LEFT;Mn;228;NSM;;;;;N;;;;; +1DF8;COMBINING DOT ABOVE LEFT;Mn;228;NSM;;;;;N;;;;; +1DF9;COMBINING WIDE INVERTED BRIDGE BELOW;Mn;220;NSM;;;;;N;;;;; 1DFB;COMBINING DELETION MARK;Mn;230;NSM;;;;;N;;;;; 1DFC;COMBINING DOUBLE INVERTED BREVE BELOW;Mn;233;NSM;;;;;N;;;;; 1DFD;COMBINING ALMOST EQUAL TO BELOW;Mn;220;NSM;;;;;N;;;;; @@ -7339,6 +7366,7 @@ 20BC;MANAT SIGN;Sc;0;ET;;;;;N;;;;; 20BD;RUBLE SIGN;Sc;0;ET;;;;;N;;;;; 20BE;LARI SIGN;Sc;0;ET;;;;;N;;;;; +20BF;BITCOIN SIGN;Sc;0;ET;;;;;N;;;;; 20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;; 20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;; 20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;; @@ -8135,6 +8163,7 @@ 23FC;POWER ON-OFF SYMBOL;So;0;ON;;;;;N;;;;; 23FD;POWER ON SYMBOL;So;0;ON;;;;;N;;;;; 23FE;POWER SLEEP SYMBOL;So;0;ON;;;;;N;;;;; +23FF;OBSERVER EYE SYMBOL;So;0;ON;;;;;N;;;;; 2400;SYMBOL FOR NULL;So;0;ON;;;;;N;GRAPHIC FOR NULL;;;; 2401;SYMBOL FOR START OF HEADING;So;0;ON;;;;;N;GRAPHIC FOR START OF HEADING;;;; 2402;SYMBOL FOR START OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR START OF TEXT;;;; @@ -10083,6 +10112,7 @@ 2BCF;ROTATED WHITE FOUR POINTED CUSP;So;0;ON;;;;;N;;;;; 2BD0;SQUARE POSITION INDICATOR;So;0;ON;;;;;N;;;;; 2BD1;UNCERTAINTY SIGN;So;0;ON;;;;;N;;;;; +2BD2;GROUP MARK;So;0;ON;;;;;N;;;;; 2BEC;LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; 2BED;UPWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; 2BEE;RIGHTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; @@ -10615,6 +10645,11 @@ 2E42;DOUBLE LOW-REVERSED-9 QUOTATION MARK;Ps;0;ON;;;;;N;;;;; 2E43;DASH WITH LEFT UPTURN;Po;0;ON;;;;;N;;;;; 2E44;DOUBLE SUSPENSION MARK;Po;0;ON;;;;;N;;;;; +2E45;INVERTED LOW KAVYKA;Po;0;ON;;;;;N;;;;; +2E46;INVERTED LOW KAVYKA WITH KAVYKA ABOVE;Po;0;ON;;;;;N;;;;; +2E47;LOW KAVYKA;Po;0;ON;;;;;N;;;;; +2E48;LOW KAVYKA WITH DOT;Po;0;ON;;;;;N;;;;; +2E49;DOUBLE STACKED COMMA;Po;0;ON;;;;;N;;;;; 2E80;CJK RADICAL REPEAT;So;0;ON;;;;;N;;;;; 2E81;CJK RADICAL CLIFF;So;0;ON;;;;;N;;;;; 2E82;CJK RADICAL SECOND ONE;So;0;ON;;;;;N;;;;; @@ -11250,6 +11285,7 @@ 312B;BOPOMOFO LETTER NG;Lo;0;L;;;;;N;;;;; 312C;BOPOMOFO LETTER GN;Lo;0;L;;;;;N;;;;; 312D;BOPOMOFO LETTER IH;Lo;0;L;;;;;N;;;;; +312E;BOPOMOFO LETTER O WITH DOT ABOVE;Lo;0;L;;;;;N;;;;; 3131;HANGUL LETTER KIYEOK;Lo;0;L;<compat> 1100;;;;N;HANGUL LETTER GIYEOG;;;; 3132;HANGUL LETTER SSANGKIYEOK;Lo;0;L;<compat> 1101;;;;N;HANGUL LETTER SSANG GIYEOG;;;; 3133;HANGUL LETTER KIYEOK-SIOS;Lo;0;L;<compat> 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;; @@ -12016,7 +12052,7 @@ 4DFE;HEXAGRAM FOR AFTER COMPLETION;So;0;ON;;;;;N;;;;; 4DFF;HEXAGRAM FOR BEFORE COMPLETION;So;0;ON;;;;;N;;;;; 4E00;<CJK Ideograph, First>;Lo;0;L;;;;;N;;;;; -9FD5;<CJK Ideograph, Last>;Lo;0;L;;;;;N;;;;; +9FEA;<CJK Ideograph, Last>;Lo;0;L;;;;;N;;;;; A000;YI SYLLABLE IT;Lo;0;L;;;;;N;;;;; A001;YI SYLLABLE IX;Lo;0;L;;;;;N;;;;; A002;YI SYLLABLE I;Lo;0;L;;;;;N;;;;; @@ -17093,6 +17129,9 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 10321;OLD ITALIC NUMERAL FIVE;No;0;L;;;;5;N;;;;; 10322;OLD ITALIC NUMERAL TEN;No;0;L;;;;10;N;;;;; 10323;OLD ITALIC NUMERAL FIFTY;No;0;L;;;;50;N;;;;; +1032D;OLD ITALIC LETTER YE;Lo;0;L;;;;;N;;;;; +1032E;OLD ITALIC LETTER NORTHERN TSE;Lo;0;L;;;;;N;;;;; +1032F;OLD ITALIC LETTER SOUTHERN TSE;Lo;0;L;;;;;N;;;;; 10330;GOTHIC LETTER AHSA;Lo;0;L;;;;;N;;;;; 10331;GOTHIC LETTER BAIRKAN;Lo;0;L;;;;;N;;;;; 10332;GOTHIC LETTER GIBA;Lo;0;L;;;;;N;;;;; @@ -20068,6 +20107,158 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 118F1;WARANG CITI NUMBER EIGHTY;No;0;L;;;;80;N;;;;; 118F2;WARANG CITI NUMBER NINETY;No;0;L;;;;90;N;;;;; 118FF;WARANG CITI OM;Lo;0;L;;;;;N;;;;; +11A00;ZANABAZAR SQUARE LETTER A;Lo;0;L;;;;;N;;;;; +11A01;ZANABAZAR SQUARE VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11A02;ZANABAZAR SQUARE VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +11A03;ZANABAZAR SQUARE VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11A04;ZANABAZAR SQUARE VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11A05;ZANABAZAR SQUARE VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; +11A06;ZANABAZAR SQUARE VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11A07;ZANABAZAR SQUARE VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +11A08;ZANABAZAR SQUARE VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +11A09;ZANABAZAR SQUARE VOWEL SIGN REVERSED I;Mn;0;NSM;;;;;N;;;;; +11A0A;ZANABAZAR SQUARE VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;; +11A0B;ZANABAZAR SQUARE LETTER KA;Lo;0;L;;;;;N;;;;; +11A0C;ZANABAZAR SQUARE LETTER KHA;Lo;0;L;;;;;N;;;;; +11A0D;ZANABAZAR SQUARE LETTER GA;Lo;0;L;;;;;N;;;;; +11A0E;ZANABAZAR SQUARE LETTER GHA;Lo;0;L;;;;;N;;;;; +11A0F;ZANABAZAR SQUARE LETTER NGA;Lo;0;L;;;;;N;;;;; +11A10;ZANABAZAR SQUARE LETTER CA;Lo;0;L;;;;;N;;;;; +11A11;ZANABAZAR SQUARE LETTER CHA;Lo;0;L;;;;;N;;;;; +11A12;ZANABAZAR SQUARE LETTER JA;Lo;0;L;;;;;N;;;;; +11A13;ZANABAZAR SQUARE LETTER NYA;Lo;0;L;;;;;N;;;;; +11A14;ZANABAZAR SQUARE LETTER TTA;Lo;0;L;;;;;N;;;;; +11A15;ZANABAZAR SQUARE LETTER TTHA;Lo;0;L;;;;;N;;;;; +11A16;ZANABAZAR SQUARE LETTER DDA;Lo;0;L;;;;;N;;;;; +11A17;ZANABAZAR SQUARE LETTER DDHA;Lo;0;L;;;;;N;;;;; +11A18;ZANABAZAR SQUARE LETTER NNA;Lo;0;L;;;;;N;;;;; +11A19;ZANABAZAR SQUARE LETTER TA;Lo;0;L;;;;;N;;;;; +11A1A;ZANABAZAR SQUARE LETTER THA;Lo;0;L;;;;;N;;;;; +11A1B;ZANABAZAR SQUARE LETTER DA;Lo;0;L;;;;;N;;;;; +11A1C;ZANABAZAR SQUARE LETTER DHA;Lo;0;L;;;;;N;;;;; +11A1D;ZANABAZAR SQUARE LETTER NA;Lo;0;L;;;;;N;;;;; +11A1E;ZANABAZAR SQUARE LETTER PA;Lo;0;L;;;;;N;;;;; +11A1F;ZANABAZAR SQUARE LETTER PHA;Lo;0;L;;;;;N;;;;; +11A20;ZANABAZAR SQUARE LETTER BA;Lo;0;L;;;;;N;;;;; +11A21;ZANABAZAR SQUARE LETTER BHA;Lo;0;L;;;;;N;;;;; +11A22;ZANABAZAR SQUARE LETTER MA;Lo;0;L;;;;;N;;;;; +11A23;ZANABAZAR SQUARE LETTER TSA;Lo;0;L;;;;;N;;;;; +11A24;ZANABAZAR SQUARE LETTER TSHA;Lo;0;L;;;;;N;;;;; +11A25;ZANABAZAR SQUARE LETTER DZA;Lo;0;L;;;;;N;;;;; +11A26;ZANABAZAR SQUARE LETTER DZHA;Lo;0;L;;;;;N;;;;; +11A27;ZANABAZAR SQUARE LETTER ZHA;Lo;0;L;;;;;N;;;;; +11A28;ZANABAZAR SQUARE LETTER ZA;Lo;0;L;;;;;N;;;;; +11A29;ZANABAZAR SQUARE LETTER -A;Lo;0;L;;;;;N;;;;; +11A2A;ZANABAZAR SQUARE LETTER YA;Lo;0;L;;;;;N;;;;; +11A2B;ZANABAZAR SQUARE LETTER RA;Lo;0;L;;;;;N;;;;; +11A2C;ZANABAZAR SQUARE LETTER LA;Lo;0;L;;;;;N;;;;; +11A2D;ZANABAZAR SQUARE LETTER VA;Lo;0;L;;;;;N;;;;; +11A2E;ZANABAZAR SQUARE LETTER SHA;Lo;0;L;;;;;N;;;;; +11A2F;ZANABAZAR SQUARE LETTER SSA;Lo;0;L;;;;;N;;;;; +11A30;ZANABAZAR SQUARE LETTER SA;Lo;0;L;;;;;N;;;;; +11A31;ZANABAZAR SQUARE LETTER HA;Lo;0;L;;;;;N;;;;; +11A32;ZANABAZAR SQUARE LETTER KSSA;Lo;0;L;;;;;N;;;;; +11A33;ZANABAZAR SQUARE FINAL CONSONANT MARK;Mn;0;NSM;;;;;N;;;;; +11A34;ZANABAZAR SQUARE SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +11A35;ZANABAZAR SQUARE SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11A36;ZANABAZAR SQUARE SIGN CANDRABINDU WITH ORNAMENT;Mn;0;NSM;;;;;N;;;;; +11A37;ZANABAZAR SQUARE SIGN CANDRA WITH ORNAMENT;Mn;0;NSM;;;;;N;;;;; +11A38;ZANABAZAR SQUARE SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11A39;ZANABAZAR SQUARE SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11A3A;ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA;Lo;0;L;;;;;N;;;;; +11A3B;ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA;Mn;0;NSM;;;;;N;;;;; +11A3C;ZANABAZAR SQUARE CLUSTER-FINAL LETTER RA;Mn;0;NSM;;;;;N;;;;; +11A3D;ZANABAZAR SQUARE CLUSTER-FINAL LETTER LA;Mn;0;NSM;;;;;N;;;;; +11A3E;ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA;Mn;0;NSM;;;;;N;;;;; +11A3F;ZANABAZAR SQUARE INITIAL HEAD MARK;Po;0;L;;;;;N;;;;; +11A40;ZANABAZAR SQUARE CLOSING HEAD MARK;Po;0;L;;;;;N;;;;; +11A41;ZANABAZAR SQUARE MARK TSHEG;Po;0;L;;;;;N;;;;; +11A42;ZANABAZAR SQUARE MARK SHAD;Po;0;L;;;;;N;;;;; +11A43;ZANABAZAR SQUARE MARK DOUBLE SHAD;Po;0;L;;;;;N;;;;; +11A44;ZANABAZAR SQUARE MARK LONG TSHEG;Po;0;L;;;;;N;;;;; +11A45;ZANABAZAR SQUARE INITIAL DOUBLE-LINED HEAD MARK;Po;0;L;;;;;N;;;;; +11A46;ZANABAZAR SQUARE CLOSING DOUBLE-LINED HEAD MARK;Po;0;L;;;;;N;;;;; +11A47;ZANABAZAR SQUARE SUBJOINER;Mn;9;NSM;;;;;N;;;;; +11A50;SOYOMBO LETTER A;Lo;0;L;;;;;N;;;;; +11A51;SOYOMBO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11A52;SOYOMBO VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +11A53;SOYOMBO VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11A54;SOYOMBO VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11A55;SOYOMBO VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11A56;SOYOMBO VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; +11A57;SOYOMBO VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +11A58;SOYOMBO VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +11A59;SOYOMBO VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11A5A;SOYOMBO VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +11A5B;SOYOMBO VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;; +11A5C;SOYOMBO LETTER KA;Lo;0;L;;;;;N;;;;; +11A5D;SOYOMBO LETTER KHA;Lo;0;L;;;;;N;;;;; +11A5E;SOYOMBO LETTER GA;Lo;0;L;;;;;N;;;;; +11A5F;SOYOMBO LETTER GHA;Lo;0;L;;;;;N;;;;; +11A60;SOYOMBO LETTER NGA;Lo;0;L;;;;;N;;;;; +11A61;SOYOMBO LETTER CA;Lo;0;L;;;;;N;;;;; +11A62;SOYOMBO LETTER CHA;Lo;0;L;;;;;N;;;;; +11A63;SOYOMBO LETTER JA;Lo;0;L;;;;;N;;;;; +11A64;SOYOMBO LETTER JHA;Lo;0;L;;;;;N;;;;; +11A65;SOYOMBO LETTER NYA;Lo;0;L;;;;;N;;;;; +11A66;SOYOMBO LETTER TTA;Lo;0;L;;;;;N;;;;; +11A67;SOYOMBO LETTER TTHA;Lo;0;L;;;;;N;;;;; +11A68;SOYOMBO LETTER DDA;Lo;0;L;;;;;N;;;;; +11A69;SOYOMBO LETTER DDHA;Lo;0;L;;;;;N;;;;; +11A6A;SOYOMBO LETTER NNA;Lo;0;L;;;;;N;;;;; +11A6B;SOYOMBO LETTER TA;Lo;0;L;;;;;N;;;;; +11A6C;SOYOMBO LETTER THA;Lo;0;L;;;;;N;;;;; +11A6D;SOYOMBO LETTER DA;Lo;0;L;;;;;N;;;;; +11A6E;SOYOMBO LETTER DHA;Lo;0;L;;;;;N;;;;; +11A6F;SOYOMBO LETTER NA;Lo;0;L;;;;;N;;;;; +11A70;SOYOMBO LETTER PA;Lo;0;L;;;;;N;;;;; +11A71;SOYOMBO LETTER PHA;Lo;0;L;;;;;N;;;;; +11A72;SOYOMBO LETTER BA;Lo;0;L;;;;;N;;;;; +11A73;SOYOMBO LETTER BHA;Lo;0;L;;;;;N;;;;; +11A74;SOYOMBO LETTER MA;Lo;0;L;;;;;N;;;;; +11A75;SOYOMBO LETTER TSA;Lo;0;L;;;;;N;;;;; +11A76;SOYOMBO LETTER TSHA;Lo;0;L;;;;;N;;;;; +11A77;SOYOMBO LETTER DZA;Lo;0;L;;;;;N;;;;; +11A78;SOYOMBO LETTER ZHA;Lo;0;L;;;;;N;;;;; +11A79;SOYOMBO LETTER ZA;Lo;0;L;;;;;N;;;;; +11A7A;SOYOMBO LETTER -A;Lo;0;L;;;;;N;;;;; +11A7B;SOYOMBO LETTER YA;Lo;0;L;;;;;N;;;;; +11A7C;SOYOMBO LETTER RA;Lo;0;L;;;;;N;;;;; +11A7D;SOYOMBO LETTER LA;Lo;0;L;;;;;N;;;;; +11A7E;SOYOMBO LETTER VA;Lo;0;L;;;;;N;;;;; +11A7F;SOYOMBO LETTER SHA;Lo;0;L;;;;;N;;;;; +11A80;SOYOMBO LETTER SSA;Lo;0;L;;;;;N;;;;; +11A81;SOYOMBO LETTER SA;Lo;0;L;;;;;N;;;;; +11A82;SOYOMBO LETTER HA;Lo;0;L;;;;;N;;;;; +11A83;SOYOMBO LETTER KSSA;Lo;0;L;;;;;N;;;;; +11A86;SOYOMBO CLUSTER-INITIAL LETTER RA;Lo;0;L;;;;;N;;;;; +11A87;SOYOMBO CLUSTER-INITIAL LETTER LA;Lo;0;L;;;;;N;;;;; +11A88;SOYOMBO CLUSTER-INITIAL LETTER SHA;Lo;0;L;;;;;N;;;;; +11A89;SOYOMBO CLUSTER-INITIAL LETTER SA;Lo;0;L;;;;;N;;;;; +11A8A;SOYOMBO FINAL CONSONANT SIGN G;Mn;0;NSM;;;;;N;;;;; +11A8B;SOYOMBO FINAL CONSONANT SIGN K;Mn;0;NSM;;;;;N;;;;; +11A8C;SOYOMBO FINAL CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;; +11A8D;SOYOMBO FINAL CONSONANT SIGN D;Mn;0;NSM;;;;;N;;;;; +11A8E;SOYOMBO FINAL CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;; +11A8F;SOYOMBO FINAL CONSONANT SIGN B;Mn;0;NSM;;;;;N;;;;; +11A90;SOYOMBO FINAL CONSONANT SIGN M;Mn;0;NSM;;;;;N;;;;; +11A91;SOYOMBO FINAL CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;; +11A92;SOYOMBO FINAL CONSONANT SIGN L;Mn;0;NSM;;;;;N;;;;; +11A93;SOYOMBO FINAL CONSONANT SIGN SH;Mn;0;NSM;;;;;N;;;;; +11A94;SOYOMBO FINAL CONSONANT SIGN S;Mn;0;NSM;;;;;N;;;;; +11A95;SOYOMBO FINAL CONSONANT SIGN -A;Mn;0;NSM;;;;;N;;;;; +11A96;SOYOMBO SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11A97;SOYOMBO SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11A98;SOYOMBO GEMINATION MARK;Mn;0;NSM;;;;;N;;;;; +11A99;SOYOMBO SUBJOINER;Mn;9;NSM;;;;;N;;;;; +11A9A;SOYOMBO MARK TSHEG;Po;0;L;;;;;N;;;;; +11A9B;SOYOMBO MARK SHAD;Po;0;L;;;;;N;;;;; +11A9C;SOYOMBO MARK DOUBLE SHAD;Po;0;L;;;;;N;;;;; +11A9E;SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME;Po;0;L;;;;;N;;;;; +11A9F;SOYOMBO HEAD MARK WITH MOON AND SUN AND FLAME;Po;0;L;;;;;N;;;;; +11AA0;SOYOMBO HEAD MARK WITH MOON AND SUN;Po;0;L;;;;;N;;;;; +11AA1;SOYOMBO TERMINAL MARK-1;Po;0;L;;;;;N;;;;; +11AA2;SOYOMBO TERMINAL MARK-2;Po;0;L;;;;;N;;;;; 11AC0;PAU CIN HAU LETTER PA;Lo;0;L;;;;;N;;;;; 11AC1;PAU CIN HAU LETTER KA;Lo;0;L;;;;;N;;;;; 11AC2;PAU CIN HAU LETTER LA;Lo;0;L;;;;;N;;;;; @@ -20290,6 +20481,81 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 11CB4;MARCHEN VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 11CB5;MARCHEN SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 11CB6;MARCHEN SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11D00;MASARAM GONDI LETTER A;Lo;0;L;;;;;N;;;;; +11D01;MASARAM GONDI LETTER AA;Lo;0;L;;;;;N;;;;; +11D02;MASARAM GONDI LETTER I;Lo;0;L;;;;;N;;;;; +11D03;MASARAM GONDI LETTER II;Lo;0;L;;;;;N;;;;; +11D04;MASARAM GONDI LETTER U;Lo;0;L;;;;;N;;;;; +11D05;MASARAM GONDI LETTER UU;Lo;0;L;;;;;N;;;;; +11D06;MASARAM GONDI LETTER E;Lo;0;L;;;;;N;;;;; +11D08;MASARAM GONDI LETTER AI;Lo;0;L;;;;;N;;;;; +11D09;MASARAM GONDI LETTER O;Lo;0;L;;;;;N;;;;; +11D0B;MASARAM GONDI LETTER AU;Lo;0;L;;;;;N;;;;; +11D0C;MASARAM GONDI LETTER KA;Lo;0;L;;;;;N;;;;; +11D0D;MASARAM GONDI LETTER KHA;Lo;0;L;;;;;N;;;;; +11D0E;MASARAM GONDI LETTER GA;Lo;0;L;;;;;N;;;;; +11D0F;MASARAM GONDI LETTER GHA;Lo;0;L;;;;;N;;;;; +11D10;MASARAM GONDI LETTER NGA;Lo;0;L;;;;;N;;;;; +11D11;MASARAM GONDI LETTER CA;Lo;0;L;;;;;N;;;;; +11D12;MASARAM GONDI LETTER CHA;Lo;0;L;;;;;N;;;;; +11D13;MASARAM GONDI LETTER JA;Lo;0;L;;;;;N;;;;; +11D14;MASARAM GONDI LETTER JHA;Lo;0;L;;;;;N;;;;; +11D15;MASARAM GONDI LETTER NYA;Lo;0;L;;;;;N;;;;; +11D16;MASARAM GONDI LETTER TTA;Lo;0;L;;;;;N;;;;; +11D17;MASARAM GONDI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11D18;MASARAM GONDI LETTER DDA;Lo;0;L;;;;;N;;;;; +11D19;MASARAM GONDI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11D1A;MASARAM GONDI LETTER NNA;Lo;0;L;;;;;N;;;;; +11D1B;MASARAM GONDI LETTER TA;Lo;0;L;;;;;N;;;;; +11D1C;MASARAM GONDI LETTER THA;Lo;0;L;;;;;N;;;;; +11D1D;MASARAM GONDI LETTER DA;Lo;0;L;;;;;N;;;;; +11D1E;MASARAM GONDI LETTER DHA;Lo;0;L;;;;;N;;;;; +11D1F;MASARAM GONDI LETTER NA;Lo;0;L;;;;;N;;;;; +11D20;MASARAM GONDI LETTER PA;Lo;0;L;;;;;N;;;;; +11D21;MASARAM GONDI LETTER PHA;Lo;0;L;;;;;N;;;;; +11D22;MASARAM GONDI LETTER BA;Lo;0;L;;;;;N;;;;; +11D23;MASARAM GONDI LETTER BHA;Lo;0;L;;;;;N;;;;; +11D24;MASARAM GONDI LETTER MA;Lo;0;L;;;;;N;;;;; +11D25;MASARAM GONDI LETTER YA;Lo;0;L;;;;;N;;;;; +11D26;MASARAM GONDI LETTER RA;Lo;0;L;;;;;N;;;;; +11D27;MASARAM GONDI LETTER LA;Lo;0;L;;;;;N;;;;; +11D28;MASARAM GONDI LETTER VA;Lo;0;L;;;;;N;;;;; +11D29;MASARAM GONDI LETTER SHA;Lo;0;L;;;;;N;;;;; +11D2A;MASARAM GONDI LETTER SSA;Lo;0;L;;;;;N;;;;; +11D2B;MASARAM GONDI LETTER SA;Lo;0;L;;;;;N;;;;; +11D2C;MASARAM GONDI LETTER HA;Lo;0;L;;;;;N;;;;; +11D2D;MASARAM GONDI LETTER LLA;Lo;0;L;;;;;N;;;;; +11D2E;MASARAM GONDI LETTER KSSA;Lo;0;L;;;;;N;;;;; +11D2F;MASARAM GONDI LETTER JNYA;Lo;0;L;;;;;N;;;;; +11D30;MASARAM GONDI LETTER TRA;Lo;0;L;;;;;N;;;;; +11D31;MASARAM GONDI VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +11D32;MASARAM GONDI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11D33;MASARAM GONDI VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +11D34;MASARAM GONDI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11D35;MASARAM GONDI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +11D36;MASARAM GONDI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11D3A;MASARAM GONDI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11D3C;MASARAM GONDI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11D3D;MASARAM GONDI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11D3F;MASARAM GONDI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +11D40;MASARAM GONDI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11D41;MASARAM GONDI SIGN VISARGA;Mn;0;NSM;;;;;N;;;;; +11D42;MASARAM GONDI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +11D43;MASARAM GONDI SIGN CANDRA;Mn;0;NSM;;;;;N;;;;; +11D44;MASARAM GONDI SIGN HALANTA;Mn;9;NSM;;;;;N;;;;; +11D45;MASARAM GONDI VIRAMA;Mn;9;NSM;;;;;N;;;;; +11D46;MASARAM GONDI REPHA;Lo;0;L;;;;;N;;;;; +11D47;MASARAM GONDI RA-KARA;Mn;0;NSM;;;;;N;;;;; +11D50;MASARAM GONDI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11D51;MASARAM GONDI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11D52;MASARAM GONDI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11D53;MASARAM GONDI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11D54;MASARAM GONDI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11D55;MASARAM GONDI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11D56;MASARAM GONDI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11D57;MASARAM GONDI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11D58;MASARAM GONDI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11D59;MASARAM GONDI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 12000;CUNEIFORM SIGN A;Lo;0;L;;;;;N;;;;; 12001;CUNEIFORM SIGN A TIMES A;Lo;0;L;;;;;N;;;;; 12002;CUNEIFORM SIGN A TIMES BAD;Lo;0;L;;;;;N;;;;; @@ -24087,6 +24353,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 16F9E;MIAO LETTER REFORMED TONE-6;Lm;0;L;;;;;N;;;;; 16F9F;MIAO LETTER REFORMED TONE-8;Lm;0;L;;;;;N;;;;; 16FE0;TANGUT ITERATION MARK;Lm;0;L;;;;;N;;;;; +16FE1;NUSHU ITERATION MARK;Lm;0;L;;;;;N;;;;; 17000;<Tangut Ideograph, First>;Lo;0;L;;;;;N;;;;; 187EC;<Tangut Ideograph, Last>;Lo;0;L;;;;;N;;;;; 18800;TANGUT COMPONENT-001;Lo;0;L;;;;;N;;;;; @@ -24846,6 +25113,687 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 18AF2;TANGUT COMPONENT-755;Lo;0;L;;;;;N;;;;; 1B000;KATAKANA LETTER ARCHAIC E;Lo;0;L;;;;;N;;;;; 1B001;HIRAGANA LETTER ARCHAIC YE;Lo;0;L;;;;;N;;;;; +1B002;HENTAIGANA LETTER A-1;Lo;0;L;;;;;N;;;;; +1B003;HENTAIGANA LETTER A-2;Lo;0;L;;;;;N;;;;; +1B004;HENTAIGANA LETTER A-3;Lo;0;L;;;;;N;;;;; +1B005;HENTAIGANA LETTER A-WO;Lo;0;L;;;;;N;;;;; +1B006;HENTAIGANA LETTER I-1;Lo;0;L;;;;;N;;;;; +1B007;HENTAIGANA LETTER I-2;Lo;0;L;;;;;N;;;;; +1B008;HENTAIGANA LETTER I-3;Lo;0;L;;;;;N;;;;; +1B009;HENTAIGANA LETTER I-4;Lo;0;L;;;;;N;;;;; +1B00A;HENTAIGANA LETTER U-1;Lo;0;L;;;;;N;;;;; +1B00B;HENTAIGANA LETTER U-2;Lo;0;L;;;;;N;;;;; +1B00C;HENTAIGANA LETTER U-3;Lo;0;L;;;;;N;;;;; +1B00D;HENTAIGANA LETTER U-4;Lo;0;L;;;;;N;;;;; +1B00E;HENTAIGANA LETTER U-5;Lo;0;L;;;;;N;;;;; +1B00F;HENTAIGANA LETTER E-2;Lo;0;L;;;;;N;;;;; +1B010;HENTAIGANA LETTER E-3;Lo;0;L;;;;;N;;;;; +1B011;HENTAIGANA LETTER E-4;Lo;0;L;;;;;N;;;;; +1B012;HENTAIGANA LETTER E-5;Lo;0;L;;;;;N;;;;; +1B013;HENTAIGANA LETTER E-6;Lo;0;L;;;;;N;;;;; +1B014;HENTAIGANA LETTER O-1;Lo;0;L;;;;;N;;;;; +1B015;HENTAIGANA LETTER O-2;Lo;0;L;;;;;N;;;;; +1B016;HENTAIGANA LETTER O-3;Lo;0;L;;;;;N;;;;; +1B017;HENTAIGANA LETTER KA-1;Lo;0;L;;;;;N;;;;; +1B018;HENTAIGANA LETTER KA-2;Lo;0;L;;;;;N;;;;; +1B019;HENTAIGANA LETTER KA-3;Lo;0;L;;;;;N;;;;; +1B01A;HENTAIGANA LETTER KA-4;Lo;0;L;;;;;N;;;;; +1B01B;HENTAIGANA LETTER KA-5;Lo;0;L;;;;;N;;;;; +1B01C;HENTAIGANA LETTER KA-6;Lo;0;L;;;;;N;;;;; +1B01D;HENTAIGANA LETTER KA-7;Lo;0;L;;;;;N;;;;; +1B01E;HENTAIGANA LETTER KA-8;Lo;0;L;;;;;N;;;;; +1B01F;HENTAIGANA LETTER KA-9;Lo;0;L;;;;;N;;;;; +1B020;HENTAIGANA LETTER KA-10;Lo;0;L;;;;;N;;;;; +1B021;HENTAIGANA LETTER KA-11;Lo;0;L;;;;;N;;;;; +1B022;HENTAIGANA LETTER KA-KE;Lo;0;L;;;;;N;;;;; +1B023;HENTAIGANA LETTER KI-1;Lo;0;L;;;;;N;;;;; +1B024;HENTAIGANA LETTER KI-2;Lo;0;L;;;;;N;;;;; +1B025;HENTAIGANA LETTER KI-3;Lo;0;L;;;;;N;;;;; +1B026;HENTAIGANA LETTER KI-4;Lo;0;L;;;;;N;;;;; +1B027;HENTAIGANA LETTER KI-5;Lo;0;L;;;;;N;;;;; +1B028;HENTAIGANA LETTER KI-6;Lo;0;L;;;;;N;;;;; +1B029;HENTAIGANA LETTER KI-7;Lo;0;L;;;;;N;;;;; +1B02A;HENTAIGANA LETTER KI-8;Lo;0;L;;;;;N;;;;; +1B02B;HENTAIGANA LETTER KU-1;Lo;0;L;;;;;N;;;;; +1B02C;HENTAIGANA LETTER KU-2;Lo;0;L;;;;;N;;;;; +1B02D;HENTAIGANA LETTER KU-3;Lo;0;L;;;;;N;;;;; +1B02E;HENTAIGANA LETTER KU-4;Lo;0;L;;;;;N;;;;; +1B02F;HENTAIGANA LETTER KU-5;Lo;0;L;;;;;N;;;;; +1B030;HENTAIGANA LETTER KU-6;Lo;0;L;;;;;N;;;;; +1B031;HENTAIGANA LETTER KU-7;Lo;0;L;;;;;N;;;;; +1B032;HENTAIGANA LETTER KE-1;Lo;0;L;;;;;N;;;;; +1B033;HENTAIGANA LETTER KE-2;Lo;0;L;;;;;N;;;;; +1B034;HENTAIGANA LETTER KE-3;Lo;0;L;;;;;N;;;;; +1B035;HENTAIGANA LETTER KE-4;Lo;0;L;;;;;N;;;;; +1B036;HENTAIGANA LETTER KE-5;Lo;0;L;;;;;N;;;;; +1B037;HENTAIGANA LETTER KE-6;Lo;0;L;;;;;N;;;;; +1B038;HENTAIGANA LETTER KO-1;Lo;0;L;;;;;N;;;;; +1B039;HENTAIGANA LETTER KO-2;Lo;0;L;;;;;N;;;;; +1B03A;HENTAIGANA LETTER KO-3;Lo;0;L;;;;;N;;;;; +1B03B;HENTAIGANA LETTER KO-KI;Lo;0;L;;;;;N;;;;; +1B03C;HENTAIGANA LETTER SA-1;Lo;0;L;;;;;N;;;;; +1B03D;HENTAIGANA LETTER SA-2;Lo;0;L;;;;;N;;;;; +1B03E;HENTAIGANA LETTER SA-3;Lo;0;L;;;;;N;;;;; +1B03F;HENTAIGANA LETTER SA-4;Lo;0;L;;;;;N;;;;; +1B040;HENTAIGANA LETTER SA-5;Lo;0;L;;;;;N;;;;; +1B041;HENTAIGANA LETTER SA-6;Lo;0;L;;;;;N;;;;; +1B042;HENTAIGANA LETTER SA-7;Lo;0;L;;;;;N;;;;; +1B043;HENTAIGANA LETTER SA-8;Lo;0;L;;;;;N;;;;; +1B044;HENTAIGANA LETTER SI-1;Lo;0;L;;;;;N;;;;; +1B045;HENTAIGANA LETTER SI-2;Lo;0;L;;;;;N;;;;; +1B046;HENTAIGANA LETTER SI-3;Lo;0;L;;;;;N;;;;; +1B047;HENTAIGANA LETTER SI-4;Lo;0;L;;;;;N;;;;; +1B048;HENTAIGANA LETTER SI-5;Lo;0;L;;;;;N;;;;; +1B049;HENTAIGANA LETTER SI-6;Lo;0;L;;;;;N;;;;; +1B04A;HENTAIGANA LETTER SU-1;Lo;0;L;;;;;N;;;;; +1B04B;HENTAIGANA LETTER SU-2;Lo;0;L;;;;;N;;;;; +1B04C;HENTAIGANA LETTER SU-3;Lo;0;L;;;;;N;;;;; +1B04D;HENTAIGANA LETTER SU-4;Lo;0;L;;;;;N;;;;; +1B04E;HENTAIGANA LETTER SU-5;Lo;0;L;;;;;N;;;;; +1B04F;HENTAIGANA LETTER SU-6;Lo;0;L;;;;;N;;;;; +1B050;HENTAIGANA LETTER SU-7;Lo;0;L;;;;;N;;;;; +1B051;HENTAIGANA LETTER SU-8;Lo;0;L;;;;;N;;;;; +1B052;HENTAIGANA LETTER SE-1;Lo;0;L;;;;;N;;;;; +1B053;HENTAIGANA LETTER SE-2;Lo;0;L;;;;;N;;;;; +1B054;HENTAIGANA LETTER SE-3;Lo;0;L;;;;;N;;;;; +1B055;HENTAIGANA LETTER SE-4;Lo;0;L;;;;;N;;;;; +1B056;HENTAIGANA LETTER SE-5;Lo;0;L;;;;;N;;;;; +1B057;HENTAIGANA LETTER SO-1;Lo;0;L;;;;;N;;;;; +1B058;HENTAIGANA LETTER SO-2;Lo;0;L;;;;;N;;;;; +1B059;HENTAIGANA LETTER SO-3;Lo;0;L;;;;;N;;;;; +1B05A;HENTAIGANA LETTER SO-4;Lo;0;L;;;;;N;;;;; +1B05B;HENTAIGANA LETTER SO-5;Lo;0;L;;;;;N;;;;; +1B05C;HENTAIGANA LETTER SO-6;Lo;0;L;;;;;N;;;;; +1B05D;HENTAIGANA LETTER SO-7;Lo;0;L;;;;;N;;;;; +1B05E;HENTAIGANA LETTER TA-1;Lo;0;L;;;;;N;;;;; +1B05F;HENTAIGANA LETTER TA-2;Lo;0;L;;;;;N;;;;; +1B060;HENTAIGANA LETTER TA-3;Lo;0;L;;;;;N;;;;; +1B061;HENTAIGANA LETTER TA-4;Lo;0;L;;;;;N;;;;; +1B062;HENTAIGANA LETTER TI-1;Lo;0;L;;;;;N;;;;; +1B063;HENTAIGANA LETTER TI-2;Lo;0;L;;;;;N;;;;; +1B064;HENTAIGANA LETTER TI-3;Lo;0;L;;;;;N;;;;; +1B065;HENTAIGANA LETTER TI-4;Lo;0;L;;;;;N;;;;; +1B066;HENTAIGANA LETTER TI-5;Lo;0;L;;;;;N;;;;; +1B067;HENTAIGANA LETTER TI-6;Lo;0;L;;;;;N;;;;; +1B068;HENTAIGANA LETTER TI-7;Lo;0;L;;;;;N;;;;; +1B069;HENTAIGANA LETTER TU-1;Lo;0;L;;;;;N;;;;; +1B06A;HENTAIGANA LETTER TU-2;Lo;0;L;;;;;N;;;;; +1B06B;HENTAIGANA LETTER TU-3;Lo;0;L;;;;;N;;;;; +1B06C;HENTAIGANA LETTER TU-4;Lo;0;L;;;;;N;;;;; +1B06D;HENTAIGANA LETTER TU-TO;Lo;0;L;;;;;N;;;;; +1B06E;HENTAIGANA LETTER TE-1;Lo;0;L;;;;;N;;;;; +1B06F;HENTAIGANA LETTER TE-2;Lo;0;L;;;;;N;;;;; +1B070;HENTAIGANA LETTER TE-3;Lo;0;L;;;;;N;;;;; +1B071;HENTAIGANA LETTER TE-4;Lo;0;L;;;;;N;;;;; +1B072;HENTAIGANA LETTER TE-5;Lo;0;L;;;;;N;;;;; +1B073;HENTAIGANA LETTER TE-6;Lo;0;L;;;;;N;;;;; +1B074;HENTAIGANA LETTER TE-7;Lo;0;L;;;;;N;;;;; +1B075;HENTAIGANA LETTER TE-8;Lo;0;L;;;;;N;;;;; +1B076;HENTAIGANA LETTER TE-9;Lo;0;L;;;;;N;;;;; +1B077;HENTAIGANA LETTER TO-1;Lo;0;L;;;;;N;;;;; +1B078;HENTAIGANA LETTER TO-2;Lo;0;L;;;;;N;;;;; +1B079;HENTAIGANA LETTER TO-3;Lo;0;L;;;;;N;;;;; +1B07A;HENTAIGANA LETTER TO-4;Lo;0;L;;;;;N;;;;; +1B07B;HENTAIGANA LETTER TO-5;Lo;0;L;;;;;N;;;;; +1B07C;HENTAIGANA LETTER TO-6;Lo;0;L;;;;;N;;;;; +1B07D;HENTAIGANA LETTER TO-RA;Lo;0;L;;;;;N;;;;; +1B07E;HENTAIGANA LETTER NA-1;Lo;0;L;;;;;N;;;;; +1B07F;HENTAIGANA LETTER NA-2;Lo;0;L;;;;;N;;;;; +1B080;HENTAIGANA LETTER NA-3;Lo;0;L;;;;;N;;;;; +1B081;HENTAIGANA LETTER NA-4;Lo;0;L;;;;;N;;;;; +1B082;HENTAIGANA LETTER NA-5;Lo;0;L;;;;;N;;;;; +1B083;HENTAIGANA LETTER NA-6;Lo;0;L;;;;;N;;;;; +1B084;HENTAIGANA LETTER NA-7;Lo;0;L;;;;;N;;;;; +1B085;HENTAIGANA LETTER NA-8;Lo;0;L;;;;;N;;;;; +1B086;HENTAIGANA LETTER NA-9;Lo;0;L;;;;;N;;;;; +1B087;HENTAIGANA LETTER NI-1;Lo;0;L;;;;;N;;;;; +1B088;HENTAIGANA LETTER NI-2;Lo;0;L;;;;;N;;;;; +1B089;HENTAIGANA LETTER NI-3;Lo;0;L;;;;;N;;;;; +1B08A;HENTAIGANA LETTER NI-4;Lo;0;L;;;;;N;;;;; +1B08B;HENTAIGANA LETTER NI-5;Lo;0;L;;;;;N;;;;; +1B08C;HENTAIGANA LETTER NI-6;Lo;0;L;;;;;N;;;;; +1B08D;HENTAIGANA LETTER NI-7;Lo;0;L;;;;;N;;;;; +1B08E;HENTAIGANA LETTER NI-TE;Lo;0;L;;;;;N;;;;; +1B08F;HENTAIGANA LETTER NU-1;Lo;0;L;;;;;N;;;;; +1B090;HENTAIGANA LETTER NU-2;Lo;0;L;;;;;N;;;;; +1B091;HENTAIGANA LETTER NU-3;Lo;0;L;;;;;N;;;;; +1B092;HENTAIGANA LETTER NE-1;Lo;0;L;;;;;N;;;;; +1B093;HENTAIGANA LETTER NE-2;Lo;0;L;;;;;N;;;;; +1B094;HENTAIGANA LETTER NE-3;Lo;0;L;;;;;N;;;;; +1B095;HENTAIGANA LETTER NE-4;Lo;0;L;;;;;N;;;;; +1B096;HENTAIGANA LETTER NE-5;Lo;0;L;;;;;N;;;;; +1B097;HENTAIGANA LETTER NE-6;Lo;0;L;;;;;N;;;;; +1B098;HENTAIGANA LETTER NE-KO;Lo;0;L;;;;;N;;;;; +1B099;HENTAIGANA LETTER NO-1;Lo;0;L;;;;;N;;;;; +1B09A;HENTAIGANA LETTER NO-2;Lo;0;L;;;;;N;;;;; +1B09B;HENTAIGANA LETTER NO-3;Lo;0;L;;;;;N;;;;; +1B09C;HENTAIGANA LETTER NO-4;Lo;0;L;;;;;N;;;;; +1B09D;HENTAIGANA LETTER NO-5;Lo;0;L;;;;;N;;;;; +1B09E;HENTAIGANA LETTER HA-1;Lo;0;L;;;;;N;;;;; +1B09F;HENTAIGANA LETTER HA-2;Lo;0;L;;;;;N;;;;; +1B0A0;HENTAIGANA LETTER HA-3;Lo;0;L;;;;;N;;;;; +1B0A1;HENTAIGANA LETTER HA-4;Lo;0;L;;;;;N;;;;; +1B0A2;HENTAIGANA LETTER HA-5;Lo;0;L;;;;;N;;;;; +1B0A3;HENTAIGANA LETTER HA-6;Lo;0;L;;;;;N;;;;; +1B0A4;HENTAIGANA LETTER HA-7;Lo;0;L;;;;;N;;;;; +1B0A5;HENTAIGANA LETTER HA-8;Lo;0;L;;;;;N;;;;; +1B0A6;HENTAIGANA LETTER HA-9;Lo;0;L;;;;;N;;;;; +1B0A7;HENTAIGANA LETTER HA-10;Lo;0;L;;;;;N;;;;; +1B0A8;HENTAIGANA LETTER HA-11;Lo;0;L;;;;;N;;;;; +1B0A9;HENTAIGANA LETTER HI-1;Lo;0;L;;;;;N;;;;; +1B0AA;HENTAIGANA LETTER HI-2;Lo;0;L;;;;;N;;;;; +1B0AB;HENTAIGANA LETTER HI-3;Lo;0;L;;;;;N;;;;; +1B0AC;HENTAIGANA LETTER HI-4;Lo;0;L;;;;;N;;;;; +1B0AD;HENTAIGANA LETTER HI-5;Lo;0;L;;;;;N;;;;; +1B0AE;HENTAIGANA LETTER HI-6;Lo;0;L;;;;;N;;;;; +1B0AF;HENTAIGANA LETTER HI-7;Lo;0;L;;;;;N;;;;; +1B0B0;HENTAIGANA LETTER HU-1;Lo;0;L;;;;;N;;;;; +1B0B1;HENTAIGANA LETTER HU-2;Lo;0;L;;;;;N;;;;; +1B0B2;HENTAIGANA LETTER HU-3;Lo;0;L;;;;;N;;;;; +1B0B3;HENTAIGANA LETTER HE-1;Lo;0;L;;;;;N;;;;; +1B0B4;HENTAIGANA LETTER HE-2;Lo;0;L;;;;;N;;;;; +1B0B5;HENTAIGANA LETTER HE-3;Lo;0;L;;;;;N;;;;; +1B0B6;HENTAIGANA LETTER HE-4;Lo;0;L;;;;;N;;;;; +1B0B7;HENTAIGANA LETTER HE-5;Lo;0;L;;;;;N;;;;; +1B0B8;HENTAIGANA LETTER HE-6;Lo;0;L;;;;;N;;;;; +1B0B9;HENTAIGANA LETTER HE-7;Lo;0;L;;;;;N;;;;; +1B0BA;HENTAIGANA LETTER HO-1;Lo;0;L;;;;;N;;;;; +1B0BB;HENTAIGANA LETTER HO-2;Lo;0;L;;;;;N;;;;; +1B0BC;HENTAIGANA LETTER HO-3;Lo;0;L;;;;;N;;;;; +1B0BD;HENTAIGANA LETTER HO-4;Lo;0;L;;;;;N;;;;; +1B0BE;HENTAIGANA LETTER HO-5;Lo;0;L;;;;;N;;;;; +1B0BF;HENTAIGANA LETTER HO-6;Lo;0;L;;;;;N;;;;; +1B0C0;HENTAIGANA LETTER HO-7;Lo;0;L;;;;;N;;;;; +1B0C1;HENTAIGANA LETTER HO-8;Lo;0;L;;;;;N;;;;; +1B0C2;HENTAIGANA LETTER MA-1;Lo;0;L;;;;;N;;;;; +1B0C3;HENTAIGANA LETTER MA-2;Lo;0;L;;;;;N;;;;; +1B0C4;HENTAIGANA LETTER MA-3;Lo;0;L;;;;;N;;;;; +1B0C5;HENTAIGANA LETTER MA-4;Lo;0;L;;;;;N;;;;; +1B0C6;HENTAIGANA LETTER MA-5;Lo;0;L;;;;;N;;;;; +1B0C7;HENTAIGANA LETTER MA-6;Lo;0;L;;;;;N;;;;; +1B0C8;HENTAIGANA LETTER MA-7;Lo;0;L;;;;;N;;;;; +1B0C9;HENTAIGANA LETTER MI-1;Lo;0;L;;;;;N;;;;; +1B0CA;HENTAIGANA LETTER MI-2;Lo;0;L;;;;;N;;;;; +1B0CB;HENTAIGANA LETTER MI-3;Lo;0;L;;;;;N;;;;; +1B0CC;HENTAIGANA LETTER MI-4;Lo;0;L;;;;;N;;;;; +1B0CD;HENTAIGANA LETTER MI-5;Lo;0;L;;;;;N;;;;; +1B0CE;HENTAIGANA LETTER MI-6;Lo;0;L;;;;;N;;;;; +1B0CF;HENTAIGANA LETTER MI-7;Lo;0;L;;;;;N;;;;; +1B0D0;HENTAIGANA LETTER MU-1;Lo;0;L;;;;;N;;;;; +1B0D1;HENTAIGANA LETTER MU-2;Lo;0;L;;;;;N;;;;; +1B0D2;HENTAIGANA LETTER MU-3;Lo;0;L;;;;;N;;;;; +1B0D3;HENTAIGANA LETTER MU-4;Lo;0;L;;;;;N;;;;; +1B0D4;HENTAIGANA LETTER ME-1;Lo;0;L;;;;;N;;;;; +1B0D5;HENTAIGANA LETTER ME-2;Lo;0;L;;;;;N;;;;; +1B0D6;HENTAIGANA LETTER ME-MA;Lo;0;L;;;;;N;;;;; +1B0D7;HENTAIGANA LETTER MO-1;Lo;0;L;;;;;N;;;;; +1B0D8;HENTAIGANA LETTER MO-2;Lo;0;L;;;;;N;;;;; +1B0D9;HENTAIGANA LETTER MO-3;Lo;0;L;;;;;N;;;;; +1B0DA;HENTAIGANA LETTER MO-4;Lo;0;L;;;;;N;;;;; +1B0DB;HENTAIGANA LETTER MO-5;Lo;0;L;;;;;N;;;;; +1B0DC;HENTAIGANA LETTER MO-6;Lo;0;L;;;;;N;;;;; +1B0DD;HENTAIGANA LETTER YA-1;Lo;0;L;;;;;N;;;;; +1B0DE;HENTAIGANA LETTER YA-2;Lo;0;L;;;;;N;;;;; +1B0DF;HENTAIGANA LETTER YA-3;Lo;0;L;;;;;N;;;;; +1B0E0;HENTAIGANA LETTER YA-4;Lo;0;L;;;;;N;;;;; +1B0E1;HENTAIGANA LETTER YA-5;Lo;0;L;;;;;N;;;;; +1B0E2;HENTAIGANA LETTER YA-YO;Lo;0;L;;;;;N;;;;; +1B0E3;HENTAIGANA LETTER YU-1;Lo;0;L;;;;;N;;;;; +1B0E4;HENTAIGANA LETTER YU-2;Lo;0;L;;;;;N;;;;; +1B0E5;HENTAIGANA LETTER YU-3;Lo;0;L;;;;;N;;;;; +1B0E6;HENTAIGANA LETTER YU-4;Lo;0;L;;;;;N;;;;; +1B0E7;HENTAIGANA LETTER YO-1;Lo;0;L;;;;;N;;;;; +1B0E8;HENTAIGANA LETTER YO-2;Lo;0;L;;;;;N;;;;; +1B0E9;HENTAIGANA LETTER YO-3;Lo;0;L;;;;;N;;;;; +1B0EA;HENTAIGANA LETTER YO-4;Lo;0;L;;;;;N;;;;; +1B0EB;HENTAIGANA LETTER YO-5;Lo;0;L;;;;;N;;;;; +1B0EC;HENTAIGANA LETTER YO-6;Lo;0;L;;;;;N;;;;; +1B0ED;HENTAIGANA LETTER RA-1;Lo;0;L;;;;;N;;;;; +1B0EE;HENTAIGANA LETTER RA-2;Lo;0;L;;;;;N;;;;; +1B0EF;HENTAIGANA LETTER RA-3;Lo;0;L;;;;;N;;;;; +1B0F0;HENTAIGANA LETTER RA-4;Lo;0;L;;;;;N;;;;; +1B0F1;HENTAIGANA LETTER RI-1;Lo;0;L;;;;;N;;;;; +1B0F2;HENTAIGANA LETTER RI-2;Lo;0;L;;;;;N;;;;; +1B0F3;HENTAIGANA LETTER RI-3;Lo;0;L;;;;;N;;;;; +1B0F4;HENTAIGANA LETTER RI-4;Lo;0;L;;;;;N;;;;; +1B0F5;HENTAIGANA LETTER RI-5;Lo;0;L;;;;;N;;;;; +1B0F6;HENTAIGANA LETTER RI-6;Lo;0;L;;;;;N;;;;; +1B0F7;HENTAIGANA LETTER RI-7;Lo;0;L;;;;;N;;;;; +1B0F8;HENTAIGANA LETTER RU-1;Lo;0;L;;;;;N;;;;; +1B0F9;HENTAIGANA LETTER RU-2;Lo;0;L;;;;;N;;;;; +1B0FA;HENTAIGANA LETTER RU-3;Lo;0;L;;;;;N;;;;; +1B0FB;HENTAIGANA LETTER RU-4;Lo;0;L;;;;;N;;;;; +1B0FC;HENTAIGANA LETTER RU-5;Lo;0;L;;;;;N;;;;; +1B0FD;HENTAIGANA LETTER RU-6;Lo;0;L;;;;;N;;;;; +1B0FE;HENTAIGANA LETTER RE-1;Lo;0;L;;;;;N;;;;; +1B0FF;HENTAIGANA LETTER RE-2;Lo;0;L;;;;;N;;;;; +1B100;HENTAIGANA LETTER RE-3;Lo;0;L;;;;;N;;;;; +1B101;HENTAIGANA LETTER RE-4;Lo;0;L;;;;;N;;;;; +1B102;HENTAIGANA LETTER RO-1;Lo;0;L;;;;;N;;;;; +1B103;HENTAIGANA LETTER RO-2;Lo;0;L;;;;;N;;;;; +1B104;HENTAIGANA LETTER RO-3;Lo;0;L;;;;;N;;;;; +1B105;HENTAIGANA LETTER RO-4;Lo;0;L;;;;;N;;;;; +1B106;HENTAIGANA LETTER RO-5;Lo;0;L;;;;;N;;;;; +1B107;HENTAIGANA LETTER RO-6;Lo;0;L;;;;;N;;;;; +1B108;HENTAIGANA LETTER WA-1;Lo;0;L;;;;;N;;;;; +1B109;HENTAIGANA LETTER WA-2;Lo;0;L;;;;;N;;;;; +1B10A;HENTAIGANA LETTER WA-3;Lo;0;L;;;;;N;;;;; +1B10B;HENTAIGANA LETTER WA-4;Lo;0;L;;;;;N;;;;; +1B10C;HENTAIGANA LETTER WA-5;Lo;0;L;;;;;N;;;;; +1B10D;HENTAIGANA LETTER WI-1;Lo;0;L;;;;;N;;;;; +1B10E;HENTAIGANA LETTER WI-2;Lo;0;L;;;;;N;;;;; +1B10F;HENTAIGANA LETTER WI-3;Lo;0;L;;;;;N;;;;; +1B110;HENTAIGANA LETTER WI-4;Lo;0;L;;;;;N;;;;; +1B111;HENTAIGANA LETTER WI-5;Lo;0;L;;;;;N;;;;; +1B112;HENTAIGANA LETTER WE-1;Lo;0;L;;;;;N;;;;; +1B113;HENTAIGANA LETTER WE-2;Lo;0;L;;;;;N;;;;; +1B114;HENTAIGANA LETTER WE-3;Lo;0;L;;;;;N;;;;; +1B115;HENTAIGANA LETTER WE-4;Lo;0;L;;;;;N;;;;; +1B116;HENTAIGANA LETTER WO-1;Lo;0;L;;;;;N;;;;; +1B117;HENTAIGANA LETTER WO-2;Lo;0;L;;;;;N;;;;; +1B118;HENTAIGANA LETTER WO-3;Lo;0;L;;;;;N;;;;; +1B119;HENTAIGANA LETTER WO-4;Lo;0;L;;;;;N;;;;; +1B11A;HENTAIGANA LETTER WO-5;Lo;0;L;;;;;N;;;;; +1B11B;HENTAIGANA LETTER WO-6;Lo;0;L;;;;;N;;;;; +1B11C;HENTAIGANA LETTER WO-7;Lo;0;L;;;;;N;;;;; +1B11D;HENTAIGANA LETTER N-MU-MO-1;Lo;0;L;;;;;N;;;;; +1B11E;HENTAIGANA LETTER N-MU-MO-2;Lo;0;L;;;;;N;;;;; +1B170;NUSHU CHARACTER-1B170;Lo;0;L;;;;;N;;;;; +1B171;NUSHU CHARACTER-1B171;Lo;0;L;;;;;N;;;;; +1B172;NUSHU CHARACTER-1B172;Lo;0;L;;;;;N;;;;; +1B173;NUSHU CHARACTER-1B173;Lo;0;L;;;;;N;;;;; +1B174;NUSHU CHARACTER-1B174;Lo;0;L;;;;;N;;;;; +1B175;NUSHU CHARACTER-1B175;Lo;0;L;;;;;N;;;;; +1B176;NUSHU CHARACTER-1B176;Lo;0;L;;;;;N;;;;; +1B177;NUSHU CHARACTER-1B177;Lo;0;L;;;;;N;;;;; +1B178;NUSHU CHARACTER-1B178;Lo;0;L;;;;;N;;;;; +1B179;NUSHU CHARACTER-1B179;Lo;0;L;;;;;N;;;;; +1B17A;NUSHU CHARACTER-1B17A;Lo;0;L;;;;;N;;;;; +1B17B;NUSHU CHARACTER-1B17B;Lo;0;L;;;;;N;;;;; +1B17C;NUSHU CHARACTER-1B17C;Lo;0;L;;;;;N;;;;; +1B17D;NUSHU CHARACTER-1B17D;Lo;0;L;;;;;N;;;;; +1B17E;NUSHU CHARACTER-1B17E;Lo;0;L;;;;;N;;;;; +1B17F;NUSHU CHARACTER-1B17F;Lo;0;L;;;;;N;;;;; +1B180;NUSHU CHARACTER-1B180;Lo;0;L;;;;;N;;;;; +1B181;NUSHU CHARACTER-1B181;Lo;0;L;;;;;N;;;;; +1B182;NUSHU CHARACTER-1B182;Lo;0;L;;;;;N;;;;; +1B183;NUSHU CHARACTER-1B183;Lo;0;L;;;;;N;;;;; +1B184;NUSHU CHARACTER-1B184;Lo;0;L;;;;;N;;;;; +1B185;NUSHU CHARACTER-1B185;Lo;0;L;;;;;N;;;;; +1B186;NUSHU CHARACTER-1B186;Lo;0;L;;;;;N;;;;; +1B187;NUSHU CHARACTER-1B187;Lo;0;L;;;;;N;;;;; +1B188;NUSHU CHARACTER-1B188;Lo;0;L;;;;;N;;;;; +1B189;NUSHU CHARACTER-1B189;Lo;0;L;;;;;N;;;;; +1B18A;NUSHU CHARACTER-1B18A;Lo;0;L;;;;;N;;;;; +1B18B;NUSHU CHARACTER-1B18B;Lo;0;L;;;;;N;;;;; +1B18C;NUSHU CHARACTER-1B18C;Lo;0;L;;;;;N;;;;; +1B18D;NUSHU CHARACTER-1B18D;Lo;0;L;;;;;N;;;;; +1B18E;NUSHU CHARACTER-1B18E;Lo;0;L;;;;;N;;;;; +1B18F;NUSHU CHARACTER-1B18F;Lo;0;L;;;;;N;;;;; +1B190;NUSHU CHARACTER-1B190;Lo;0;L;;;;;N;;;;; +1B191;NUSHU CHARACTER-1B191;Lo;0;L;;;;;N;;;;; +1B192;NUSHU CHARACTER-1B192;Lo;0;L;;;;;N;;;;; +1B193;NUSHU CHARACTER-1B193;Lo;0;L;;;;;N;;;;; +1B194;NUSHU CHARACTER-1B194;Lo;0;L;;;;;N;;;;; +1B195;NUSHU CHARACTER-1B195;Lo;0;L;;;;;N;;;;; +1B196;NUSHU CHARACTER-1B196;Lo;0;L;;;;;N;;;;; +1B197;NUSHU CHARACTER-1B197;Lo;0;L;;;;;N;;;;; +1B198;NUSHU CHARACTER-1B198;Lo;0;L;;;;;N;;;;; +1B199;NUSHU CHARACTER-1B199;Lo;0;L;;;;;N;;;;; +1B19A;NUSHU CHARACTER-1B19A;Lo;0;L;;;;;N;;;;; +1B19B;NUSHU CHARACTER-1B19B;Lo;0;L;;;;;N;;;;; +1B19C;NUSHU CHARACTER-1B19C;Lo;0;L;;;;;N;;;;; +1B19D;NUSHU CHARACTER-1B19D;Lo;0;L;;;;;N;;;;; +1B19E;NUSHU CHARACTER-1B19E;Lo;0;L;;;;;N;;;;; +1B19F;NUSHU CHARACTER-1B19F;Lo;0;L;;;;;N;;;;; +1B1A0;NUSHU CHARACTER-1B1A0;Lo;0;L;;;;;N;;;;; +1B1A1;NUSHU CHARACTER-1B1A1;Lo;0;L;;;;;N;;;;; +1B1A2;NUSHU CHARACTER-1B1A2;Lo;0;L;;;;;N;;;;; +1B1A3;NUSHU CHARACTER-1B1A3;Lo;0;L;;;;;N;;;;; +1B1A4;NUSHU CHARACTER-1B1A4;Lo;0;L;;;;;N;;;;; +1B1A5;NUSHU CHARACTER-1B1A5;Lo;0;L;;;;;N;;;;; +1B1A6;NUSHU CHARACTER-1B1A6;Lo;0;L;;;;;N;;;;; +1B1A7;NUSHU CHARACTER-1B1A7;Lo;0;L;;;;;N;;;;; +1B1A8;NUSHU CHARACTER-1B1A8;Lo;0;L;;;;;N;;;;; +1B1A9;NUSHU CHARACTER-1B1A9;Lo;0;L;;;;;N;;;;; +1B1AA;NUSHU CHARACTER-1B1AA;Lo;0;L;;;;;N;;;;; +1B1AB;NUSHU CHARACTER-1B1AB;Lo;0;L;;;;;N;;;;; +1B1AC;NUSHU CHARACTER-1B1AC;Lo;0;L;;;;;N;;;;; +1B1AD;NUSHU CHARACTER-1B1AD;Lo;0;L;;;;;N;;;;; +1B1AE;NUSHU CHARACTER-1B1AE;Lo;0;L;;;;;N;;;;; +1B1AF;NUSHU CHARACTER-1B1AF;Lo;0;L;;;;;N;;;;; +1B1B0;NUSHU CHARACTER-1B1B0;Lo;0;L;;;;;N;;;;; +1B1B1;NUSHU CHARACTER-1B1B1;Lo;0;L;;;;;N;;;;; +1B1B2;NUSHU CHARACTER-1B1B2;Lo;0;L;;;;;N;;;;; +1B1B3;NUSHU CHARACTER-1B1B3;Lo;0;L;;;;;N;;;;; +1B1B4;NUSHU CHARACTER-1B1B4;Lo;0;L;;;;;N;;;;; +1B1B5;NUSHU CHARACTER-1B1B5;Lo;0;L;;;;;N;;;;; +1B1B6;NUSHU CHARACTER-1B1B6;Lo;0;L;;;;;N;;;;; +1B1B7;NUSHU CHARACTER-1B1B7;Lo;0;L;;;;;N;;;;; +1B1B8;NUSHU CHARACTER-1B1B8;Lo;0;L;;;;;N;;;;; +1B1B9;NUSHU CHARACTER-1B1B9;Lo;0;L;;;;;N;;;;; +1B1BA;NUSHU CHARACTER-1B1BA;Lo;0;L;;;;;N;;;;; +1B1BB;NUSHU CHARACTER-1B1BB;Lo;0;L;;;;;N;;;;; +1B1BC;NUSHU CHARACTER-1B1BC;Lo;0;L;;;;;N;;;;; +1B1BD;NUSHU CHARACTER-1B1BD;Lo;0;L;;;;;N;;;;; +1B1BE;NUSHU CHARACTER-1B1BE;Lo;0;L;;;;;N;;;;; +1B1BF;NUSHU CHARACTER-1B1BF;Lo;0;L;;;;;N;;;;; +1B1C0;NUSHU CHARACTER-1B1C0;Lo;0;L;;;;;N;;;;; +1B1C1;NUSHU CHARACTER-1B1C1;Lo;0;L;;;;;N;;;;; +1B1C2;NUSHU CHARACTER-1B1C2;Lo;0;L;;;;;N;;;;; +1B1C3;NUSHU CHARACTER-1B1C3;Lo;0;L;;;;;N;;;;; +1B1C4;NUSHU CHARACTER-1B1C4;Lo;0;L;;;;;N;;;;; +1B1C5;NUSHU CHARACTER-1B1C5;Lo;0;L;;;;;N;;;;; +1B1C6;NUSHU CHARACTER-1B1C6;Lo;0;L;;;;;N;;;;; +1B1C7;NUSHU CHARACTER-1B1C7;Lo;0;L;;;;;N;;;;; +1B1C8;NUSHU CHARACTER-1B1C8;Lo;0;L;;;;;N;;;;; +1B1C9;NUSHU CHARACTER-1B1C9;Lo;0;L;;;;;N;;;;; +1B1CA;NUSHU CHARACTER-1B1CA;Lo;0;L;;;;;N;;;;; +1B1CB;NUSHU CHARACTER-1B1CB;Lo;0;L;;;;;N;;;;; +1B1CC;NUSHU CHARACTER-1B1CC;Lo;0;L;;;;;N;;;;; +1B1CD;NUSHU CHARACTER-1B1CD;Lo;0;L;;;;;N;;;;; +1B1CE;NUSHU CHARACTER-1B1CE;Lo;0;L;;;;;N;;;;; +1B1CF;NUSHU CHARACTER-1B1CF;Lo;0;L;;;;;N;;;;; +1B1D0;NUSHU CHARACTER-1B1D0;Lo;0;L;;;;;N;;;;; +1B1D1;NUSHU CHARACTER-1B1D1;Lo;0;L;;;;;N;;;;; +1B1D2;NUSHU CHARACTER-1B1D2;Lo;0;L;;;;;N;;;;; +1B1D3;NUSHU CHARACTER-1B1D3;Lo;0;L;;;;;N;;;;; +1B1D4;NUSHU CHARACTER-1B1D4;Lo;0;L;;;;;N;;;;; +1B1D5;NUSHU CHARACTER-1B1D5;Lo;0;L;;;;;N;;;;; +1B1D6;NUSHU CHARACTER-1B1D6;Lo;0;L;;;;;N;;;;; +1B1D7;NUSHU CHARACTER-1B1D7;Lo;0;L;;;;;N;;;;; +1B1D8;NUSHU CHARACTER-1B1D8;Lo;0;L;;;;;N;;;;; +1B1D9;NUSHU CHARACTER-1B1D9;Lo;0;L;;;;;N;;;;; +1B1DA;NUSHU CHARACTER-1B1DA;Lo;0;L;;;;;N;;;;; +1B1DB;NUSHU CHARACTER-1B1DB;Lo;0;L;;;;;N;;;;; +1B1DC;NUSHU CHARACTER-1B1DC;Lo;0;L;;;;;N;;;;; +1B1DD;NUSHU CHARACTER-1B1DD;Lo;0;L;;;;;N;;;;; +1B1DE;NUSHU CHARACTER-1B1DE;Lo;0;L;;;;;N;;;;; +1B1DF;NUSHU CHARACTER-1B1DF;Lo;0;L;;;;;N;;;;; +1B1E0;NUSHU CHARACTER-1B1E0;Lo;0;L;;;;;N;;;;; +1B1E1;NUSHU CHARACTER-1B1E1;Lo;0;L;;;;;N;;;;; +1B1E2;NUSHU CHARACTER-1B1E2;Lo;0;L;;;;;N;;;;; +1B1E3;NUSHU CHARACTER-1B1E3;Lo;0;L;;;;;N;;;;; +1B1E4;NUSHU CHARACTER-1B1E4;Lo;0;L;;;;;N;;;;; +1B1E5;NUSHU CHARACTER-1B1E5;Lo;0;L;;;;;N;;;;; +1B1E6;NUSHU CHARACTER-1B1E6;Lo;0;L;;;;;N;;;;; +1B1E7;NUSHU CHARACTER-1B1E7;Lo;0;L;;;;;N;;;;; +1B1E8;NUSHU CHARACTER-1B1E8;Lo;0;L;;;;;N;;;;; +1B1E9;NUSHU CHARACTER-1B1E9;Lo;0;L;;;;;N;;;;; +1B1EA;NUSHU CHARACTER-1B1EA;Lo;0;L;;;;;N;;;;; +1B1EB;NUSHU CHARACTER-1B1EB;Lo;0;L;;;;;N;;;;; +1B1EC;NUSHU CHARACTER-1B1EC;Lo;0;L;;;;;N;;;;; +1B1ED;NUSHU CHARACTER-1B1ED;Lo;0;L;;;;;N;;;;; +1B1EE;NUSHU CHARACTER-1B1EE;Lo;0;L;;;;;N;;;;; +1B1EF;NUSHU CHARACTER-1B1EF;Lo;0;L;;;;;N;;;;; +1B1F0;NUSHU CHARACTER-1B1F0;Lo;0;L;;;;;N;;;;; +1B1F1;NUSHU CHARACTER-1B1F1;Lo;0;L;;;;;N;;;;; +1B1F2;NUSHU CHARACTER-1B1F2;Lo;0;L;;;;;N;;;;; +1B1F3;NUSHU CHARACTER-1B1F3;Lo;0;L;;;;;N;;;;; +1B1F4;NUSHU CHARACTER-1B1F4;Lo;0;L;;;;;N;;;;; +1B1F5;NUSHU CHARACTER-1B1F5;Lo;0;L;;;;;N;;;;; +1B1F6;NUSHU CHARACTER-1B1F6;Lo;0;L;;;;;N;;;;; +1B1F7;NUSHU CHARACTER-1B1F7;Lo;0;L;;;;;N;;;;; +1B1F8;NUSHU CHARACTER-1B1F8;Lo;0;L;;;;;N;;;;; +1B1F9;NUSHU CHARACTER-1B1F9;Lo;0;L;;;;;N;;;;; +1B1FA;NUSHU CHARACTER-1B1FA;Lo;0;L;;;;;N;;;;; +1B1FB;NUSHU CHARACTER-1B1FB;Lo;0;L;;;;;N;;;;; +1B1FC;NUSHU CHARACTER-1B1FC;Lo;0;L;;;;;N;;;;; +1B1FD;NUSHU CHARACTER-1B1FD;Lo;0;L;;;;;N;;;;; +1B1FE;NUSHU CHARACTER-1B1FE;Lo;0;L;;;;;N;;;;; +1B1FF;NUSHU CHARACTER-1B1FF;Lo;0;L;;;;;N;;;;; +1B200;NUSHU CHARACTER-1B200;Lo;0;L;;;;;N;;;;; +1B201;NUSHU CHARACTER-1B201;Lo;0;L;;;;;N;;;;; +1B202;NUSHU CHARACTER-1B202;Lo;0;L;;;;;N;;;;; +1B203;NUSHU CHARACTER-1B203;Lo;0;L;;;;;N;;;;; +1B204;NUSHU CHARACTER-1B204;Lo;0;L;;;;;N;;;;; +1B205;NUSHU CHARACTER-1B205;Lo;0;L;;;;;N;;;;; +1B206;NUSHU CHARACTER-1B206;Lo;0;L;;;;;N;;;;; +1B207;NUSHU CHARACTER-1B207;Lo;0;L;;;;;N;;;;; +1B208;NUSHU CHARACTER-1B208;Lo;0;L;;;;;N;;;;; +1B209;NUSHU CHARACTER-1B209;Lo;0;L;;;;;N;;;;; +1B20A;NUSHU CHARACTER-1B20A;Lo;0;L;;;;;N;;;;; +1B20B;NUSHU CHARACTER-1B20B;Lo;0;L;;;;;N;;;;; +1B20C;NUSHU CHARACTER-1B20C;Lo;0;L;;;;;N;;;;; +1B20D;NUSHU CHARACTER-1B20D;Lo;0;L;;;;;N;;;;; +1B20E;NUSHU CHARACTER-1B20E;Lo;0;L;;;;;N;;;;; +1B20F;NUSHU CHARACTER-1B20F;Lo;0;L;;;;;N;;;;; +1B210;NUSHU CHARACTER-1B210;Lo;0;L;;;;;N;;;;; +1B211;NUSHU CHARACTER-1B211;Lo;0;L;;;;;N;;;;; +1B212;NUSHU CHARACTER-1B212;Lo;0;L;;;;;N;;;;; +1B213;NUSHU CHARACTER-1B213;Lo;0;L;;;;;N;;;;; +1B214;NUSHU CHARACTER-1B214;Lo;0;L;;;;;N;;;;; +1B215;NUSHU CHARACTER-1B215;Lo;0;L;;;;;N;;;;; +1B216;NUSHU CHARACTER-1B216;Lo;0;L;;;;;N;;;;; +1B217;NUSHU CHARACTER-1B217;Lo;0;L;;;;;N;;;;; +1B218;NUSHU CHARACTER-1B218;Lo;0;L;;;;;N;;;;; +1B219;NUSHU CHARACTER-1B219;Lo;0;L;;;;;N;;;;; +1B21A;NUSHU CHARACTER-1B21A;Lo;0;L;;;;;N;;;;; +1B21B;NUSHU CHARACTER-1B21B;Lo;0;L;;;;;N;;;;; +1B21C;NUSHU CHARACTER-1B21C;Lo;0;L;;;;;N;;;;; +1B21D;NUSHU CHARACTER-1B21D;Lo;0;L;;;;;N;;;;; +1B21E;NUSHU CHARACTER-1B21E;Lo;0;L;;;;;N;;;;; +1B21F;NUSHU CHARACTER-1B21F;Lo;0;L;;;;;N;;;;; +1B220;NUSHU CHARACTER-1B220;Lo;0;L;;;;;N;;;;; +1B221;NUSHU CHARACTER-1B221;Lo;0;L;;;;;N;;;;; +1B222;NUSHU CHARACTER-1B222;Lo;0;L;;;;;N;;;;; +1B223;NUSHU CHARACTER-1B223;Lo;0;L;;;;;N;;;;; +1B224;NUSHU CHARACTER-1B224;Lo;0;L;;;;;N;;;;; +1B225;NUSHU CHARACTER-1B225;Lo;0;L;;;;;N;;;;; +1B226;NUSHU CHARACTER-1B226;Lo;0;L;;;;;N;;;;; +1B227;NUSHU CHARACTER-1B227;Lo;0;L;;;;;N;;;;; +1B228;NUSHU CHARACTER-1B228;Lo;0;L;;;;;N;;;;; +1B229;NUSHU CHARACTER-1B229;Lo;0;L;;;;;N;;;;; +1B22A;NUSHU CHARACTER-1B22A;Lo;0;L;;;;;N;;;;; +1B22B;NUSHU CHARACTER-1B22B;Lo;0;L;;;;;N;;;;; +1B22C;NUSHU CHARACTER-1B22C;Lo;0;L;;;;;N;;;;; +1B22D;NUSHU CHARACTER-1B22D;Lo;0;L;;;;;N;;;;; +1B22E;NUSHU CHARACTER-1B22E;Lo;0;L;;;;;N;;;;; +1B22F;NUSHU CHARACTER-1B22F;Lo;0;L;;;;;N;;;;; +1B230;NUSHU CHARACTER-1B230;Lo;0;L;;;;;N;;;;; +1B231;NUSHU CHARACTER-1B231;Lo;0;L;;;;;N;;;;; +1B232;NUSHU CHARACTER-1B232;Lo;0;L;;;;;N;;;;; +1B233;NUSHU CHARACTER-1B233;Lo;0;L;;;;;N;;;;; +1B234;NUSHU CHARACTER-1B234;Lo;0;L;;;;;N;;;;; +1B235;NUSHU CHARACTER-1B235;Lo;0;L;;;;;N;;;;; +1B236;NUSHU CHARACTER-1B236;Lo;0;L;;;;;N;;;;; +1B237;NUSHU CHARACTER-1B237;Lo;0;L;;;;;N;;;;; +1B238;NUSHU CHARACTER-1B238;Lo;0;L;;;;;N;;;;; +1B239;NUSHU CHARACTER-1B239;Lo;0;L;;;;;N;;;;; +1B23A;NUSHU CHARACTER-1B23A;Lo;0;L;;;;;N;;;;; +1B23B;NUSHU CHARACTER-1B23B;Lo;0;L;;;;;N;;;;; +1B23C;NUSHU CHARACTER-1B23C;Lo;0;L;;;;;N;;;;; +1B23D;NUSHU CHARACTER-1B23D;Lo;0;L;;;;;N;;;;; +1B23E;NUSHU CHARACTER-1B23E;Lo;0;L;;;;;N;;;;; +1B23F;NUSHU CHARACTER-1B23F;Lo;0;L;;;;;N;;;;; +1B240;NUSHU CHARACTER-1B240;Lo;0;L;;;;;N;;;;; +1B241;NUSHU CHARACTER-1B241;Lo;0;L;;;;;N;;;;; +1B242;NUSHU CHARACTER-1B242;Lo;0;L;;;;;N;;;;; +1B243;NUSHU CHARACTER-1B243;Lo;0;L;;;;;N;;;;; +1B244;NUSHU CHARACTER-1B244;Lo;0;L;;;;;N;;;;; +1B245;NUSHU CHARACTER-1B245;Lo;0;L;;;;;N;;;;; +1B246;NUSHU CHARACTER-1B246;Lo;0;L;;;;;N;;;;; +1B247;NUSHU CHARACTER-1B247;Lo;0;L;;;;;N;;;;; +1B248;NUSHU CHARACTER-1B248;Lo;0;L;;;;;N;;;;; +1B249;NUSHU CHARACTER-1B249;Lo;0;L;;;;;N;;;;; +1B24A;NUSHU CHARACTER-1B24A;Lo;0;L;;;;;N;;;;; +1B24B;NUSHU CHARACTER-1B24B;Lo;0;L;;;;;N;;;;; +1B24C;NUSHU CHARACTER-1B24C;Lo;0;L;;;;;N;;;;; +1B24D;NUSHU CHARACTER-1B24D;Lo;0;L;;;;;N;;;;; +1B24E;NUSHU CHARACTER-1B24E;Lo;0;L;;;;;N;;;;; +1B24F;NUSHU CHARACTER-1B24F;Lo;0;L;;;;;N;;;;; +1B250;NUSHU CHARACTER-1B250;Lo;0;L;;;;;N;;;;; +1B251;NUSHU CHARACTER-1B251;Lo;0;L;;;;;N;;;;; +1B252;NUSHU CHARACTER-1B252;Lo;0;L;;;;;N;;;;; +1B253;NUSHU CHARACTER-1B253;Lo;0;L;;;;;N;;;;; +1B254;NUSHU CHARACTER-1B254;Lo;0;L;;;;;N;;;;; +1B255;NUSHU CHARACTER-1B255;Lo;0;L;;;;;N;;;;; +1B256;NUSHU CHARACTER-1B256;Lo;0;L;;;;;N;;;;; +1B257;NUSHU CHARACTER-1B257;Lo;0;L;;;;;N;;;;; +1B258;NUSHU CHARACTER-1B258;Lo;0;L;;;;;N;;;;; +1B259;NUSHU CHARACTER-1B259;Lo;0;L;;;;;N;;;;; +1B25A;NUSHU CHARACTER-1B25A;Lo;0;L;;;;;N;;;;; +1B25B;NUSHU CHARACTER-1B25B;Lo;0;L;;;;;N;;;;; +1B25C;NUSHU CHARACTER-1B25C;Lo;0;L;;;;;N;;;;; +1B25D;NUSHU CHARACTER-1B25D;Lo;0;L;;;;;N;;;;; +1B25E;NUSHU CHARACTER-1B25E;Lo;0;L;;;;;N;;;;; +1B25F;NUSHU CHARACTER-1B25F;Lo;0;L;;;;;N;;;;; +1B260;NUSHU CHARACTER-1B260;Lo;0;L;;;;;N;;;;; +1B261;NUSHU CHARACTER-1B261;Lo;0;L;;;;;N;;;;; +1B262;NUSHU CHARACTER-1B262;Lo;0;L;;;;;N;;;;; +1B263;NUSHU CHARACTER-1B263;Lo;0;L;;;;;N;;;;; +1B264;NUSHU CHARACTER-1B264;Lo;0;L;;;;;N;;;;; +1B265;NUSHU CHARACTER-1B265;Lo;0;L;;;;;N;;;;; +1B266;NUSHU CHARACTER-1B266;Lo;0;L;;;;;N;;;;; +1B267;NUSHU CHARACTER-1B267;Lo;0;L;;;;;N;;;;; +1B268;NUSHU CHARACTER-1B268;Lo;0;L;;;;;N;;;;; +1B269;NUSHU CHARACTER-1B269;Lo;0;L;;;;;N;;;;; +1B26A;NUSHU CHARACTER-1B26A;Lo;0;L;;;;;N;;;;; +1B26B;NUSHU CHARACTER-1B26B;Lo;0;L;;;;;N;;;;; +1B26C;NUSHU CHARACTER-1B26C;Lo;0;L;;;;;N;;;;; +1B26D;NUSHU CHARACTER-1B26D;Lo;0;L;;;;;N;;;;; +1B26E;NUSHU CHARACTER-1B26E;Lo;0;L;;;;;N;;;;; +1B26F;NUSHU CHARACTER-1B26F;Lo;0;L;;;;;N;;;;; +1B270;NUSHU CHARACTER-1B270;Lo;0;L;;;;;N;;;;; +1B271;NUSHU CHARACTER-1B271;Lo;0;L;;;;;N;;;;; +1B272;NUSHU CHARACTER-1B272;Lo;0;L;;;;;N;;;;; +1B273;NUSHU CHARACTER-1B273;Lo;0;L;;;;;N;;;;; +1B274;NUSHU CHARACTER-1B274;Lo;0;L;;;;;N;;;;; +1B275;NUSHU CHARACTER-1B275;Lo;0;L;;;;;N;;;;; +1B276;NUSHU CHARACTER-1B276;Lo;0;L;;;;;N;;;;; +1B277;NUSHU CHARACTER-1B277;Lo;0;L;;;;;N;;;;; +1B278;NUSHU CHARACTER-1B278;Lo;0;L;;;;;N;;;;; +1B279;NUSHU CHARACTER-1B279;Lo;0;L;;;;;N;;;;; +1B27A;NUSHU CHARACTER-1B27A;Lo;0;L;;;;;N;;;;; +1B27B;NUSHU CHARACTER-1B27B;Lo;0;L;;;;;N;;;;; +1B27C;NUSHU CHARACTER-1B27C;Lo;0;L;;;;;N;;;;; +1B27D;NUSHU CHARACTER-1B27D;Lo;0;L;;;;;N;;;;; +1B27E;NUSHU CHARACTER-1B27E;Lo;0;L;;;;;N;;;;; +1B27F;NUSHU CHARACTER-1B27F;Lo;0;L;;;;;N;;;;; +1B280;NUSHU CHARACTER-1B280;Lo;0;L;;;;;N;;;;; +1B281;NUSHU CHARACTER-1B281;Lo;0;L;;;;;N;;;;; +1B282;NUSHU CHARACTER-1B282;Lo;0;L;;;;;N;;;;; +1B283;NUSHU CHARACTER-1B283;Lo;0;L;;;;;N;;;;; +1B284;NUSHU CHARACTER-1B284;Lo;0;L;;;;;N;;;;; +1B285;NUSHU CHARACTER-1B285;Lo;0;L;;;;;N;;;;; +1B286;NUSHU CHARACTER-1B286;Lo;0;L;;;;;N;;;;; +1B287;NUSHU CHARACTER-1B287;Lo;0;L;;;;;N;;;;; +1B288;NUSHU CHARACTER-1B288;Lo;0;L;;;;;N;;;;; +1B289;NUSHU CHARACTER-1B289;Lo;0;L;;;;;N;;;;; +1B28A;NUSHU CHARACTER-1B28A;Lo;0;L;;;;;N;;;;; +1B28B;NUSHU CHARACTER-1B28B;Lo;0;L;;;;;N;;;;; +1B28C;NUSHU CHARACTER-1B28C;Lo;0;L;;;;;N;;;;; +1B28D;NUSHU CHARACTER-1B28D;Lo;0;L;;;;;N;;;;; +1B28E;NUSHU CHARACTER-1B28E;Lo;0;L;;;;;N;;;;; +1B28F;NUSHU CHARACTER-1B28F;Lo;0;L;;;;;N;;;;; +1B290;NUSHU CHARACTER-1B290;Lo;0;L;;;;;N;;;;; +1B291;NUSHU CHARACTER-1B291;Lo;0;L;;;;;N;;;;; +1B292;NUSHU CHARACTER-1B292;Lo;0;L;;;;;N;;;;; +1B293;NUSHU CHARACTER-1B293;Lo;0;L;;;;;N;;;;; +1B294;NUSHU CHARACTER-1B294;Lo;0;L;;;;;N;;;;; +1B295;NUSHU CHARACTER-1B295;Lo;0;L;;;;;N;;;;; +1B296;NUSHU CHARACTER-1B296;Lo;0;L;;;;;N;;;;; +1B297;NUSHU CHARACTER-1B297;Lo;0;L;;;;;N;;;;; +1B298;NUSHU CHARACTER-1B298;Lo;0;L;;;;;N;;;;; +1B299;NUSHU CHARACTER-1B299;Lo;0;L;;;;;N;;;;; +1B29A;NUSHU CHARACTER-1B29A;Lo;0;L;;;;;N;;;;; +1B29B;NUSHU CHARACTER-1B29B;Lo;0;L;;;;;N;;;;; +1B29C;NUSHU CHARACTER-1B29C;Lo;0;L;;;;;N;;;;; +1B29D;NUSHU CHARACTER-1B29D;Lo;0;L;;;;;N;;;;; +1B29E;NUSHU CHARACTER-1B29E;Lo;0;L;;;;;N;;;;; +1B29F;NUSHU CHARACTER-1B29F;Lo;0;L;;;;;N;;;;; +1B2A0;NUSHU CHARACTER-1B2A0;Lo;0;L;;;;;N;;;;; +1B2A1;NUSHU CHARACTER-1B2A1;Lo;0;L;;;;;N;;;;; +1B2A2;NUSHU CHARACTER-1B2A2;Lo;0;L;;;;;N;;;;; +1B2A3;NUSHU CHARACTER-1B2A3;Lo;0;L;;;;;N;;;;; +1B2A4;NUSHU CHARACTER-1B2A4;Lo;0;L;;;;;N;;;;; +1B2A5;NUSHU CHARACTER-1B2A5;Lo;0;L;;;;;N;;;;; +1B2A6;NUSHU CHARACTER-1B2A6;Lo;0;L;;;;;N;;;;; +1B2A7;NUSHU CHARACTER-1B2A7;Lo;0;L;;;;;N;;;;; +1B2A8;NUSHU CHARACTER-1B2A8;Lo;0;L;;;;;N;;;;; +1B2A9;NUSHU CHARACTER-1B2A9;Lo;0;L;;;;;N;;;;; +1B2AA;NUSHU CHARACTER-1B2AA;Lo;0;L;;;;;N;;;;; +1B2AB;NUSHU CHARACTER-1B2AB;Lo;0;L;;;;;N;;;;; +1B2AC;NUSHU CHARACTER-1B2AC;Lo;0;L;;;;;N;;;;; +1B2AD;NUSHU CHARACTER-1B2AD;Lo;0;L;;;;;N;;;;; +1B2AE;NUSHU CHARACTER-1B2AE;Lo;0;L;;;;;N;;;;; +1B2AF;NUSHU CHARACTER-1B2AF;Lo;0;L;;;;;N;;;;; +1B2B0;NUSHU CHARACTER-1B2B0;Lo;0;L;;;;;N;;;;; +1B2B1;NUSHU CHARACTER-1B2B1;Lo;0;L;;;;;N;;;;; +1B2B2;NUSHU CHARACTER-1B2B2;Lo;0;L;;;;;N;;;;; +1B2B3;NUSHU CHARACTER-1B2B3;Lo;0;L;;;;;N;;;;; +1B2B4;NUSHU CHARACTER-1B2B4;Lo;0;L;;;;;N;;;;; +1B2B5;NUSHU CHARACTER-1B2B5;Lo;0;L;;;;;N;;;;; +1B2B6;NUSHU CHARACTER-1B2B6;Lo;0;L;;;;;N;;;;; +1B2B7;NUSHU CHARACTER-1B2B7;Lo;0;L;;;;;N;;;;; +1B2B8;NUSHU CHARACTER-1B2B8;Lo;0;L;;;;;N;;;;; +1B2B9;NUSHU CHARACTER-1B2B9;Lo;0;L;;;;;N;;;;; +1B2BA;NUSHU CHARACTER-1B2BA;Lo;0;L;;;;;N;;;;; +1B2BB;NUSHU CHARACTER-1B2BB;Lo;0;L;;;;;N;;;;; +1B2BC;NUSHU CHARACTER-1B2BC;Lo;0;L;;;;;N;;;;; +1B2BD;NUSHU CHARACTER-1B2BD;Lo;0;L;;;;;N;;;;; +1B2BE;NUSHU CHARACTER-1B2BE;Lo;0;L;;;;;N;;;;; +1B2BF;NUSHU CHARACTER-1B2BF;Lo;0;L;;;;;N;;;;; +1B2C0;NUSHU CHARACTER-1B2C0;Lo;0;L;;;;;N;;;;; +1B2C1;NUSHU CHARACTER-1B2C1;Lo;0;L;;;;;N;;;;; +1B2C2;NUSHU CHARACTER-1B2C2;Lo;0;L;;;;;N;;;;; +1B2C3;NUSHU CHARACTER-1B2C3;Lo;0;L;;;;;N;;;;; +1B2C4;NUSHU CHARACTER-1B2C4;Lo;0;L;;;;;N;;;;; +1B2C5;NUSHU CHARACTER-1B2C5;Lo;0;L;;;;;N;;;;; +1B2C6;NUSHU CHARACTER-1B2C6;Lo;0;L;;;;;N;;;;; +1B2C7;NUSHU CHARACTER-1B2C7;Lo;0;L;;;;;N;;;;; +1B2C8;NUSHU CHARACTER-1B2C8;Lo;0;L;;;;;N;;;;; +1B2C9;NUSHU CHARACTER-1B2C9;Lo;0;L;;;;;N;;;;; +1B2CA;NUSHU CHARACTER-1B2CA;Lo;0;L;;;;;N;;;;; +1B2CB;NUSHU CHARACTER-1B2CB;Lo;0;L;;;;;N;;;;; +1B2CC;NUSHU CHARACTER-1B2CC;Lo;0;L;;;;;N;;;;; +1B2CD;NUSHU CHARACTER-1B2CD;Lo;0;L;;;;;N;;;;; +1B2CE;NUSHU CHARACTER-1B2CE;Lo;0;L;;;;;N;;;;; +1B2CF;NUSHU CHARACTER-1B2CF;Lo;0;L;;;;;N;;;;; +1B2D0;NUSHU CHARACTER-1B2D0;Lo;0;L;;;;;N;;;;; +1B2D1;NUSHU CHARACTER-1B2D1;Lo;0;L;;;;;N;;;;; +1B2D2;NUSHU CHARACTER-1B2D2;Lo;0;L;;;;;N;;;;; +1B2D3;NUSHU CHARACTER-1B2D3;Lo;0;L;;;;;N;;;;; +1B2D4;NUSHU CHARACTER-1B2D4;Lo;0;L;;;;;N;;;;; +1B2D5;NUSHU CHARACTER-1B2D5;Lo;0;L;;;;;N;;;;; +1B2D6;NUSHU CHARACTER-1B2D6;Lo;0;L;;;;;N;;;;; +1B2D7;NUSHU CHARACTER-1B2D7;Lo;0;L;;;;;N;;;;; +1B2D8;NUSHU CHARACTER-1B2D8;Lo;0;L;;;;;N;;;;; +1B2D9;NUSHU CHARACTER-1B2D9;Lo;0;L;;;;;N;;;;; +1B2DA;NUSHU CHARACTER-1B2DA;Lo;0;L;;;;;N;;;;; +1B2DB;NUSHU CHARACTER-1B2DB;Lo;0;L;;;;;N;;;;; +1B2DC;NUSHU CHARACTER-1B2DC;Lo;0;L;;;;;N;;;;; +1B2DD;NUSHU CHARACTER-1B2DD;Lo;0;L;;;;;N;;;;; +1B2DE;NUSHU CHARACTER-1B2DE;Lo;0;L;;;;;N;;;;; +1B2DF;NUSHU CHARACTER-1B2DF;Lo;0;L;;;;;N;;;;; +1B2E0;NUSHU CHARACTER-1B2E0;Lo;0;L;;;;;N;;;;; +1B2E1;NUSHU CHARACTER-1B2E1;Lo;0;L;;;;;N;;;;; +1B2E2;NUSHU CHARACTER-1B2E2;Lo;0;L;;;;;N;;;;; +1B2E3;NUSHU CHARACTER-1B2E3;Lo;0;L;;;;;N;;;;; +1B2E4;NUSHU CHARACTER-1B2E4;Lo;0;L;;;;;N;;;;; +1B2E5;NUSHU CHARACTER-1B2E5;Lo;0;L;;;;;N;;;;; +1B2E6;NUSHU CHARACTER-1B2E6;Lo;0;L;;;;;N;;;;; +1B2E7;NUSHU CHARACTER-1B2E7;Lo;0;L;;;;;N;;;;; +1B2E8;NUSHU CHARACTER-1B2E8;Lo;0;L;;;;;N;;;;; +1B2E9;NUSHU CHARACTER-1B2E9;Lo;0;L;;;;;N;;;;; +1B2EA;NUSHU CHARACTER-1B2EA;Lo;0;L;;;;;N;;;;; +1B2EB;NUSHU CHARACTER-1B2EB;Lo;0;L;;;;;N;;;;; +1B2EC;NUSHU CHARACTER-1B2EC;Lo;0;L;;;;;N;;;;; +1B2ED;NUSHU CHARACTER-1B2ED;Lo;0;L;;;;;N;;;;; +1B2EE;NUSHU CHARACTER-1B2EE;Lo;0;L;;;;;N;;;;; +1B2EF;NUSHU CHARACTER-1B2EF;Lo;0;L;;;;;N;;;;; +1B2F0;NUSHU CHARACTER-1B2F0;Lo;0;L;;;;;N;;;;; +1B2F1;NUSHU CHARACTER-1B2F1;Lo;0;L;;;;;N;;;;; +1B2F2;NUSHU CHARACTER-1B2F2;Lo;0;L;;;;;N;;;;; +1B2F3;NUSHU CHARACTER-1B2F3;Lo;0;L;;;;;N;;;;; +1B2F4;NUSHU CHARACTER-1B2F4;Lo;0;L;;;;;N;;;;; +1B2F5;NUSHU CHARACTER-1B2F5;Lo;0;L;;;;;N;;;;; +1B2F6;NUSHU CHARACTER-1B2F6;Lo;0;L;;;;;N;;;;; +1B2F7;NUSHU CHARACTER-1B2F7;Lo;0;L;;;;;N;;;;; +1B2F8;NUSHU CHARACTER-1B2F8;Lo;0;L;;;;;N;;;;; +1B2F9;NUSHU CHARACTER-1B2F9;Lo;0;L;;;;;N;;;;; +1B2FA;NUSHU CHARACTER-1B2FA;Lo;0;L;;;;;N;;;;; +1B2FB;NUSHU CHARACTER-1B2FB;Lo;0;L;;;;;N;;;;; 1BC00;DUPLOYAN LETTER H;Lo;0;L;;;;;N;;;;; 1BC01;DUPLOYAN LETTER X;Lo;0;L;;;;;N;;;;; 1BC02;DUPLOYAN LETTER P;Lo;0;L;;;;;N;;;;; @@ -28269,6 +29217,12 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F248;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557;So;0;L;<compat> 3014 6557 3015;;;;N;;;;; 1F250;CIRCLED IDEOGRAPH ADVANTAGE;So;0;L;<circle> 5F97;;;;N;;;;; 1F251;CIRCLED IDEOGRAPH ACCEPT;So;0;L;<circle> 53EF;;;;N;;;;; +1F260;ROUNDED SYMBOL FOR FU;So;0;ON;;;;;N;;;;; +1F261;ROUNDED SYMBOL FOR LU;So;0;ON;;;;;N;;;;; +1F262;ROUNDED SYMBOL FOR SHOU;So;0;ON;;;;;N;;;;; +1F263;ROUNDED SYMBOL FOR XI;So;0;ON;;;;;N;;;;; +1F264;ROUNDED SYMBOL FOR SHUANGXI;So;0;ON;;;;;N;;;;; +1F265;ROUNDED SYMBOL FOR CAI;So;0;ON;;;;;N;;;;; 1F300;CYCLONE;So;0;ON;;;;;N;;;;; 1F301;FOGGY;So;0;ON;;;;;N;;;;; 1F302;CLOSED UMBRELLA;So;0;ON;;;;;N;;;;; @@ -29248,6 +30202,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F6D0;PLACE OF WORSHIP;So;0;ON;;;;;N;;;;; 1F6D1;OCTAGONAL SIGN;So;0;ON;;;;;N;;;;; 1F6D2;SHOPPING TROLLEY;So;0;ON;;;;;N;;;;; +1F6D3;STUPA;So;0;ON;;;;;N;;;;; +1F6D4;PAGODA;So;0;ON;;;;;N;;;;; 1F6E0;HAMMER AND WRENCH;So;0;ON;;;;;N;;;;; 1F6E1;SHIELD;So;0;ON;;;;;N;;;;; 1F6E2;OIL DRUM;So;0;ON;;;;;N;;;;; @@ -29268,6 +30224,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F6F4;SCOOTER;So;0;ON;;;;;N;;;;; 1F6F5;MOTOR SCOOTER;So;0;ON;;;;;N;;;;; 1F6F6;CANOE;So;0;ON;;;;;N;;;;; +1F6F7;SLED;So;0;ON;;;;;N;;;;; +1F6F8;FLYING SAUCER;So;0;ON;;;;;N;;;;; 1F700;ALCHEMICAL SYMBOL FOR QUINTESSENCE;So;0;ON;;;;;N;;;;; 1F701;ALCHEMICAL SYMBOL FOR AIR;So;0;ON;;;;;N;;;;; 1F702;ALCHEMICAL SYMBOL FOR FIRE;So;0;ON;;;;;N;;;;; @@ -29617,6 +30575,18 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F8AB;RIGHTWARDS FRONT-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8AC;WHITE ARROW SHAFT WIDTH ONE;So;0;ON;;;;;N;;;;; 1F8AD;WHITE ARROW SHAFT WIDTH TWO THIRDS;So;0;ON;;;;;N;;;;; +1F900;CIRCLED CROSS FORMEE WITH FOUR DOTS;So;0;ON;;;;;N;;;;; +1F901;CIRCLED CROSS FORMEE WITH TWO DOTS;So;0;ON;;;;;N;;;;; +1F902;CIRCLED CROSS FORMEE;So;0;ON;;;;;N;;;;; +1F903;LEFT HALF CIRCLE WITH FOUR DOTS;So;0;ON;;;;;N;;;;; +1F904;LEFT HALF CIRCLE WITH THREE DOTS;So;0;ON;;;;;N;;;;; +1F905;LEFT HALF CIRCLE WITH TWO DOTS;So;0;ON;;;;;N;;;;; +1F906;LEFT HALF CIRCLE WITH DOT;So;0;ON;;;;;N;;;;; +1F907;LEFT HALF CIRCLE;So;0;ON;;;;;N;;;;; +1F908;DOWNWARD FACING HOOK;So;0;ON;;;;;N;;;;; +1F909;DOWNWARD FACING NOTCHED HOOK;So;0;ON;;;;;N;;;;; +1F90A;DOWNWARD FACING HOOK WITH DOT;So;0;ON;;;;;N;;;;; +1F90B;DOWNWARD FACING NOTCHED HOOK WITH DOT;So;0;ON;;;;;N;;;;; 1F910;ZIPPER-MOUTH FACE;So;0;ON;;;;;N;;;;; 1F911;MONEY-MOUTH FACE;So;0;ON;;;;;N;;;;; 1F912;FACE WITH THERMOMETER;So;0;ON;;;;;N;;;;; @@ -29632,6 +30602,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F91C;RIGHT-FACING FIST;So;0;ON;;;;;N;;;;; 1F91D;HANDSHAKE;So;0;ON;;;;;N;;;;; 1F91E;HAND WITH INDEX AND MIDDLE FINGERS CROSSED;So;0;ON;;;;;N;;;;; +1F91F;I LOVE YOU HAND SIGN;So;0;ON;;;;;N;;;;; 1F920;FACE WITH COWBOY HAT;So;0;ON;;;;;N;;;;; 1F921;CLOWN FACE;So;0;ON;;;;;N;;;;; 1F922;NAUSEATED FACE;So;0;ON;;;;;N;;;;; @@ -29640,7 +30611,17 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F925;LYING FACE;So;0;ON;;;;;N;;;;; 1F926;FACE PALM;So;0;ON;;;;;N;;;;; 1F927;SNEEZING FACE;So;0;ON;;;;;N;;;;; +1F928;FACE WITH ONE EYEBROW RAISED;So;0;ON;;;;;N;;;;; +1F929;GRINNING FACE WITH STAR EYES;So;0;ON;;;;;N;;;;; +1F92A;GRINNING FACE WITH ONE LARGE AND ONE SMALL EYE;So;0;ON;;;;;N;;;;; +1F92B;FACE WITH FINGER COVERING CLOSED LIPS;So;0;ON;;;;;N;;;;; +1F92C;SERIOUS FACE WITH SYMBOLS COVERING MOUTH;So;0;ON;;;;;N;;;;; +1F92D;SMILING FACE WITH SMILING EYES AND HAND COVERING MOUTH;So;0;ON;;;;;N;;;;; +1F92E;FACE WITH OPEN MOUTH VOMITING;So;0;ON;;;;;N;;;;; +1F92F;SHOCKED FACE WITH EXPLODING HEAD;So;0;ON;;;;;N;;;;; 1F930;PREGNANT WOMAN;So;0;ON;;;;;N;;;;; +1F931;BREAST-FEEDING;So;0;ON;;;;;N;;;;; +1F932;PALMS UP TOGETHER;So;0;ON;;;;;N;;;;; 1F933;SELFIE;So;0;ON;;;;;N;;;;; 1F934;PRINCE;So;0;ON;;;;;N;;;;; 1F935;MAN IN TUXEDO;So;0;ON;;;;;N;;;;; @@ -29665,6 +30646,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F949;THIRD PLACE MEDAL;So;0;ON;;;;;N;;;;; 1F94A;BOXING GLOVE;So;0;ON;;;;;N;;;;; 1F94B;MARTIAL ARTS UNIFORM;So;0;ON;;;;;N;;;;; +1F94C;CURLING STONE;So;0;ON;;;;;N;;;;; 1F950;CROISSANT;So;0;ON;;;;;N;;;;; 1F951;AVOCADO;So;0;ON;;;;;N;;;;; 1F952;CUCUMBER;So;0;ON;;;;;N;;;;; @@ -29680,6 +30662,19 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F95C;PEANUTS;So;0;ON;;;;;N;;;;; 1F95D;KIWIFRUIT;So;0;ON;;;;;N;;;;; 1F95E;PANCAKES;So;0;ON;;;;;N;;;;; +1F95F;DUMPLING;So;0;ON;;;;;N;;;;; +1F960;FORTUNE COOKIE;So;0;ON;;;;;N;;;;; +1F961;TAKEOUT BOX;So;0;ON;;;;;N;;;;; +1F962;CHOPSTICKS;So;0;ON;;;;;N;;;;; +1F963;BOWL WITH SPOON;So;0;ON;;;;;N;;;;; +1F964;CUP WITH STRAW;So;0;ON;;;;;N;;;;; +1F965;COCONUT;So;0;ON;;;;;N;;;;; +1F966;BROCCOLI;So;0;ON;;;;;N;;;;; +1F967;PIE;So;0;ON;;;;;N;;;;; +1F968;PRETZEL;So;0;ON;;;;;N;;;;; +1F969;CUT OF MEAT;So;0;ON;;;;;N;;;;; +1F96A;SANDWICH;So;0;ON;;;;;N;;;;; +1F96B;CANNED FOOD;So;0;ON;;;;;N;;;;; 1F980;CRAB;So;0;ON;;;;;N;;;;; 1F981;LION FACE;So;0;ON;;;;;N;;;;; 1F982;SCORPION;So;0;ON;;;;;N;;;;; @@ -29698,7 +30693,36 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F98F;RHINOCEROS;So;0;ON;;;;;N;;;;; 1F990;SHRIMP;So;0;ON;;;;;N;;;;; 1F991;SQUID;So;0;ON;;;;;N;;;;; +1F992;GIRAFFE FACE;So;0;ON;;;;;N;;;;; +1F993;ZEBRA FACE;So;0;ON;;;;;N;;;;; +1F994;HEDGEHOG;So;0;ON;;;;;N;;;;; +1F995;SAUROPOD;So;0;ON;;;;;N;;;;; +1F996;T-REX;So;0;ON;;;;;N;;;;; +1F997;CRICKET;So;0;ON;;;;;N;;;;; 1F9C0;CHEESE WEDGE;So;0;ON;;;;;N;;;;; +1F9D0;FACE WITH MONOCLE;So;0;ON;;;;;N;;;;; +1F9D1;ADULT;So;0;ON;;;;;N;;;;; +1F9D2;CHILD;So;0;ON;;;;;N;;;;; +1F9D3;OLDER ADULT;So;0;ON;;;;;N;;;;; +1F9D4;BEARDED PERSON;So;0;ON;;;;;N;;;;; +1F9D5;PERSON WITH HEADSCARF;So;0;ON;;;;;N;;;;; +1F9D6;PERSON IN STEAMY ROOM;So;0;ON;;;;;N;;;;; +1F9D7;PERSON CLIMBING;So;0;ON;;;;;N;;;;; +1F9D8;PERSON IN LOTUS POSITION;So;0;ON;;;;;N;;;;; +1F9D9;MAGE;So;0;ON;;;;;N;;;;; +1F9DA;FAIRY;So;0;ON;;;;;N;;;;; +1F9DB;VAMPIRE;So;0;ON;;;;;N;;;;; +1F9DC;MERPERSON;So;0;ON;;;;;N;;;;; +1F9DD;ELF;So;0;ON;;;;;N;;;;; +1F9DE;GENIE;So;0;ON;;;;;N;;;;; +1F9DF;ZOMBIE;So;0;ON;;;;;N;;;;; +1F9E0;BRAIN;So;0;ON;;;;;N;;;;; +1F9E1;ORANGE HEART;So;0;ON;;;;;N;;;;; +1F9E2;BILLED CAP;So;0;ON;;;;;N;;;;; +1F9E3;SCARF;So;0;ON;;;;;N;;;;; +1F9E4;GLOVES;So;0;ON;;;;;N;;;;; +1F9E5;COAT;So;0;ON;;;;;N;;;;; +1F9E6;SOCKS;So;0;ON;;;;;N;;;;; 20000;<CJK Ideograph Extension B, First>;Lo;0;L;;;;;N;;;;; 2A6D6;<CJK Ideograph Extension B, Last>;Lo;0;L;;;;;N;;;;; 2A700;<CJK Ideograph Extension C, First>;Lo;0;L;;;;;N;;;;; @@ -29707,6 +30731,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 2B81D;<CJK Ideograph Extension D, Last>;Lo;0;L;;;;;N;;;;; 2B820;<CJK Ideograph Extension E, First>;Lo;0;L;;;;;N;;;;; 2CEA1;<CJK Ideograph Extension E, Last>;Lo;0;L;;;;;N;;;;; +2CEB0;<CJK Ideograph Extension F, First>;Lo;0;L;;;;;N;;;;; +2EBE0;<CJK Ideograph Extension F, Last>;Lo;0;L;;;;;N;;;;; 2F800;CJK COMPATIBILITY IDEOGRAPH-2F800;Lo;0;L;4E3D;;;;N;;;;; 2F801;CJK COMPATIBILITY IDEOGRAPH-2F801;Lo;0;L;4E38;;;;N;;;;; 2F802;CJK COMPATIBILITY IDEOGRAPH-2F802;Lo;0;L;4E41;;;;N;;;;; diff --git a/admin/unidata/unidata-gen.el b/admin/unidata/unidata-gen.el index 3c5119a8a3d..478099c831a 100644 --- a/admin/unidata/unidata-gen.el +++ b/admin/unidata/unidata-gen.el @@ -26,12 +26,12 @@ ;; SPECIAL NOTICE ;; ;; This file must be byte-compilable/loadable by `temacs' and also -;; the entry function `unidata-gen-files' must be runnable by `temacs'. +;; the entry function `unidata-gen-file' must be runnable by `temacs'. ;; FILES TO BE GENERATED ;; -;; The entry function `unidata-gen-files' generates these files in -;; in directory specified by its dest-dir argument. +;; The entry functions `unidata-gen-file' and `unidata-gen-charprop' +;; generate these files: ;; ;; charprop.el ;; It contains a series of forms of this format: @@ -94,7 +94,7 @@ ;; Name of the directory containing files of Unicode Character Database. -;; Dynamically bound in unidata-gen-files. +;; Dynamically bound in unidata-gen-file. (defvar unidata-dir nil) (defun unidata-setup-list (unidata-text-file) @@ -149,14 +149,14 @@ (setq unidata-list (cdr table)))) ;; Alist of this form: -;; (PROP INDEX GENERATOR FILENAME DOCSTRING DESCRIBER DEFAULT VAL-LIST) +;; (FILENAME (PROP INDEX GENERATOR DOCSTRING DESCRIBER DEFAULT VAL-LIST) ...) +;; FILENAME: filename to store the char-table(s) ;; PROP: character property ;; INDEX: index to each element of unidata-list for PROP. ;; It may be a function that generates an alist of character codes ;; vs. the corresponding property values. Currently, only character ;; codepoints or symbol values are supported in this case. ;; GENERATOR: function to generate a char-table -;; FILENAME: filename to store the char-table ;; DOCSTRING: docstring for the property ;; DESCRIBER: function to call to get a description string of property value ;; DEFAULT: the default value of the property. It may have the form @@ -166,139 +166,196 @@ ;; between FROMn and TOn is VALn. ;; VAL-LIST: list of specially ordered property values -(defconst unidata-prop-alist - '((name - 1 unidata-gen-table-name "uni-name.el" - "Unicode character name. +(defconst unidata-file-alist + '( + ;; NB this list is parsed by the Makefile to extract the names of + ;; the uni-*.el files, so preserve the formatting of those lines. + ("uni-name.el" + (name + 1 unidata-gen-table-name + "Unicode character name. Property value is a string or nil. The value nil stands for the default value \"null string\")." - nil - nil) - (general-category - 2 unidata-gen-table-symbol "uni-category.el" - "Unicode general category. + nil + nil)) + ("uni-category.el" + (general-category + 2 unidata-gen-table-symbol + "Unicode general category. Property value is one of the following symbols: Lu, Ll, Lt, Lm, Lo, Mn, Mc, Me, Nd, Nl, No, Pc, Pd, Ps, Pe, Pi, Pf, Po, Sm, Sc, Sk, So, Zs, Zl, Zp, Cc, Cf, Cs, Co, Cn" - unidata-describe-general-category - Cn - ;; The order of elements must be in sync with unicode_category_t - ;; in src/character.h. - (Lu Ll Lt Lm Lo Mn Mc Me Nd Nl No Pc Pd Ps Pe Pi Pf Po - Sm Sc Sk So Zs Zl Zp Cc Cf Cs Co Cn)) - (canonical-combining-class - 3 unidata-gen-table-integer "uni-combining.el" - "Unicode canonical combining class. + unidata-describe-general-category + Cn + ;; The order of elements must be in sync with + ;; unicode_category_t in src/character.h. + (Lu Ll Lt Lm Lo Mn Mc Me Nd Nl No Pc Pd Ps Pe Pi Pf Po + Sm Sc Sk So Zs Zl Zp Cc Cf Cs Co Cn))) + ("uni-combining.el" + (canonical-combining-class + 3 unidata-gen-table-integer + "Unicode canonical combining class. Property value is an integer." - unidata-describe-canonical-combining-class - 0) - (bidi-class - 4 unidata-gen-table-symbol "uni-bidi.el" - "Unicode bidi class. + unidata-describe-canonical-combining-class + 0)) + ("uni-bidi.el" + (bidi-class + 4 unidata-gen-table-symbol + "Unicode bidi class. Property value is one of the following symbols: L, LRE, LRO, LRI, R, AL, RLE, RLO, RLI, FSI, PDF, PDI, EN, ES, ET, AN, CS, NSM, BN, B, S, WS, ON" - unidata-describe-bidi-class - ;; The assignment of default values to blocks of code points - ;; follows the file DerivedBidiClass.txt from the Unicode - ;; Character Database (UCD). - (L (#x0600 #x06FF AL) (#xFB50 #xFDFF AL) (#xFE70 #xFEFF AL) - (#x0590 #x05FF R) (#x07C0 #x08FF R) - (#xFB1D #xFB4F R) (#x10800 #x10FFF R) (#x1E800 #x1EFFF R)) - ;; The order of elements must be in sync with bidi_type_t in - ;; src/dispextern.h. - (L R EN AN BN B AL LRE LRO RLE RLO PDF LRI RLI FSI PDI - ES ET CS NSM S WS ON)) - (decomposition - 5 unidata-gen-table-decomposition "uni-decomposition.el" - "Unicode decomposition mapping. + unidata-describe-bidi-class + ;; The assignment of default values to blocks of code points + ;; follows the file DerivedBidiClass.txt from the Unicode + ;; Character Database (UCD). + (L (#x0600 #x06FF AL) (#xFB50 #xFDFF AL) (#xFE70 #xFEFF AL) + (#x0590 #x05FF R) (#x07C0 #x08FF R) + (#xFB1D #xFB4F R) (#x10800 #x10FFF R) (#x1E800 #x1EFFF R)) + ;; The order of elements must be in sync with bidi_type_t in + ;; src/dispextern.h. + (L R EN AN BN B AL LRE LRO RLE RLO PDF LRI RLI FSI PDI + ES ET CS NSM S WS ON))) + ("uni-decomposition.el" + (decomposition + 5 unidata-gen-table-decomposition + "Unicode decomposition mapping. Property value is a list of characters. The first element may be one of these symbols representing compatibility formatting tag: font, noBreak, initial, medial, final, isolated, circle, super, sub, vertical, wide, narrow, small, square, fraction, compat" - unidata-describe-decomposition) - (decimal-digit-value - 6 unidata-gen-table-integer "uni-decimal.el" - "Unicode numeric value (decimal digit). + unidata-describe-decomposition)) + ("uni-decimal.el" + (decimal-digit-value + 6 unidata-gen-table-integer + "Unicode numeric value (decimal digit). Property value is an integer 0..9, or nil. -The value nil stands for NaN \"Numeric_Value\".") - (digit-value - 7 unidata-gen-table-integer "uni-digit.el" - "Unicode numeric value (digit). +The value nil stands for NaN \"Numeric_Value\".")) + ("uni-digit.el" + (digit-value + 7 unidata-gen-table-integer + "Unicode numeric value (digit). Property value is an integer 0..9, or nil. -The value nil stands for NaN \"Numeric_Value\".") - (numeric-value - 8 unidata-gen-table-numeric "uni-numeric.el" - "Unicode numeric value (numeric). +The value nil stands for NaN \"Numeric_Value\".")) + ("uni-numeric.el" + (numeric-value + 8 unidata-gen-table-numeric + "Unicode numeric value (numeric). Property value is an integer, a floating point, or nil. -The value nil stands for NaN \"Numeric_Value\".") - (mirrored - 9 unidata-gen-table-symbol "uni-mirrored.el" - "Unicode bidi mirrored flag. +The value nil stands for NaN \"Numeric_Value\".")) + ("uni-mirrored.el" + (mirrored + 9 unidata-gen-table-symbol + "Unicode bidi mirrored flag. Property value is a symbol `Y' or `N'. See also the property `mirroring'." - nil - N) - (old-name - 10 unidata-gen-table-name "uni-old-name.el" - "Unicode old names as published in Unicode 1.0. + nil + N) + (mirroring + unidata-gen-mirroring-list unidata-gen-table-character + "Unicode bidi-mirroring characters. +Property value is a character that has the corresponding mirroring image or nil. +The value nil means that the actual property value of a character +is the character itself.")) + ("uni-old-name.el" + (old-name + 10 unidata-gen-table-name + "Unicode old names as published in Unicode 1.0. Property value is a string or nil. -The value nil stands for the default value \"null string\").") - (iso-10646-comment - 11 unidata-gen-table-name "uni-comment.el" - "Unicode ISO 10646 comment. -Property value is a string.") - (uppercase - 12 unidata-gen-table-character "uni-uppercase.el" - "Unicode simple uppercase mapping. +The value nil stands for the default value \"null string\").")) + ("uni-comment.el" + (iso-10646-comment + 11 unidata-gen-table-name + "Unicode ISO 10646 comment. +Property value is a string.")) + ("uni-uppercase.el" + (uppercase + 12 unidata-gen-table-character + "Unicode simple uppercase mapping. Property value is a character or nil. The value nil means that the actual property value of a character is the character itself." - string) - (lowercase - 13 unidata-gen-table-character "uni-lowercase.el" - "Unicode simple lowercase mapping. + string)) + ("uni-lowercase.el" + (lowercase + 13 unidata-gen-table-character + "Unicode simple lowercase mapping. Property value is a character or nil. The value nil means that the actual property value of a character is the character itself." - string) - (titlecase - 14 unidata-gen-table-character "uni-titlecase.el" - "Unicode simple titlecase mapping. + string)) + ("uni-titlecase.el" + (titlecase + 14 unidata-gen-table-character + "Unicode simple titlecase mapping. Property value is a character or nil. The value nil means that the actual property value of a character is the character itself." - string) - (mirroring - unidata-gen-mirroring-list unidata-gen-table-character "uni-mirrored.el" - "Unicode bidi-mirroring characters. -Property value is a character that has the corresponding mirroring image or nil. -The value nil means that the actual property value of a character -is the character itself.") - (paired-bracket - unidata-gen-brackets-list unidata-gen-table-character "uni-brackets.el" - "Unicode bidi paired-bracket characters. + string)) + ("uni-special-uppercase.el" + (special-uppercase + 2 unidata-gen-table-special-casing + "Unicode unconditional special casing mapping. + +Property value is (possibly empty) string or nil. The value nil denotes that +`uppercase' property should be consulted instead. A string denotes what +sequence of characters given character maps into. + +This mapping includes language- and context-independent special casing rules +defined by Unicode only. It also does not include association which would +duplicate information from `uppercase' property." + nil)) + ("uni-special-lowercase.el" + (special-lowercase + 0 unidata-gen-table-special-casing + "Unicode unconditional special casing mapping. + +Property value is (possibly empty) string or nil. The value nil denotes that +`lowercase' property should be consulted instead. A string denotes what +sequence of characters given character maps into. + +This mapping includes language- and context-independent special casing rules +defined by Unicode only. It also does not include association which would +duplicate information from `lowercase' property." + nil)) + ("uni-special-titlecase.el" + (special-titlecase + 1 unidata-gen-table-special-casing + "Unicode unconditional special casing mapping. + +Property value is (possibly empty) string or nil. The value nil denotes that +`titlecase' property should be consulted instead. A string denotes what +sequence of characters given character maps into. + +This mapping includes language- and context-independent special casing rules +defined by Unicode only. It also does not include association which would +duplicate information from `titlecase' property." + nil)) + ("uni-brackets.el" + (paired-bracket + unidata-gen-brackets-list unidata-gen-table-character + "Unicode bidi paired-bracket characters. Property value is the paired bracket character, or nil. The value nil means that the character is neither an opening nor a closing paired bracket." - string) - (bracket-type - unidata-gen-bracket-type-list unidata-gen-table-symbol "uni-brackets.el" - "Unicode bidi paired-bracket type. + string) + (bracket-type + unidata-gen-bracket-type-list unidata-gen-table-symbol + "Unicode bidi paired-bracket type. Property value is a symbol `o' (Open), `c' (Close), or `n' (None)." - unidata-describe-bidi-bracket-type - n - ;; The order of elements must be in sync with bidi_bracket_type_t - ;; in src/dispextern.h. - (n o c)))) + unidata-describe-bidi-bracket-type + n + ;; The order of elements must be in sync with bidi_bracket_type_t + ;; in src/dispextern.h. + (n o c))))) ;; Functions to access the above data. -(defsubst unidata-prop-index (prop) (nth 1 (assq prop unidata-prop-alist))) -(defsubst unidata-prop-generator (prop) (nth 2 (assq prop unidata-prop-alist))) -(defsubst unidata-prop-file (prop) (nth 3 (assq prop unidata-prop-alist))) -(defsubst unidata-prop-docstring (prop) (nth 4 (assq prop unidata-prop-alist))) -(defsubst unidata-prop-describer (prop) (nth 5 (assq prop unidata-prop-alist))) -(defsubst unidata-prop-default (prop) (nth 6 (assq prop unidata-prop-alist))) -(defsubst unidata-prop-val-list (prop) (nth 7 (assq prop unidata-prop-alist))) +(defsubst unidata-prop-prop (proplist) (nth 0 proplist)) +(defsubst unidata-prop-index (proplist) (nth 1 proplist)) +(defsubst unidata-prop-generator (proplist) (nth 2 proplist)) +(defsubst unidata-prop-docstring (proplist) (nth 3 proplist)) +(defsubst unidata-prop-describer (proplist) (nth 4 proplist)) +(defsubst unidata-prop-default (proplist) (nth 5 proplist)) +(defsubst unidata-prop-val-list (proplist) (nth 6 proplist)) ;; SIMPLE TABLE @@ -326,9 +383,8 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' (None)." ;; 3rd: 0 (corresponding to uniprop_encode_character in chartab.c) ;; 4th to 5th: nil -(defun unidata-gen-table-character (prop &rest ignore) +(defun unidata-gen-table-character (prop prop-idx &rest ignore) (let ((table (make-char-table 'char-code-property-table)) - (prop-idx (unidata-prop-index prop)) (vec (make-vector 128 0)) (tail unidata-list) elt range val idx slot) @@ -433,13 +489,12 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' (None)." ;; Generate a char-table for the character property PROP. -(defun unidata-gen-table (prop val-func default-value val-list) +(defun unidata-gen-table (prop prop-idx val-func default-value val-list) (let ((table (make-char-table 'char-code-property-table)) - (prop-idx (unidata-prop-index prop)) (vec (make-vector 128 0)) ;; When this warning is printed, there's a need to make the ;; following changes: - ;; (1) update unidata-prop-alist with the new bidi-class values; + ;; (1) update unidata-file-alist with the new bidi-class values; ;; (2) extend bidi_type_t enumeration on src/dispextern.h to ;; include the new classes; ;; (3) possibly update the assertion in bidi.c:bidi_check_type; and @@ -560,8 +615,8 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' (None)." (set-char-table-extra-slot table 4 (vconcat (mapcar 'car val-list))) table)) -(defun unidata-gen-table-symbol (prop default-value val-list) - (let ((table (unidata-gen-table prop +(defun unidata-gen-table-symbol (prop index default-value val-list) + (let ((table (unidata-gen-table prop index #'(lambda (x) (and (> (length x) 0) (intern x))) default-value val-list))) @@ -569,8 +624,8 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' (None)." (set-char-table-extra-slot table 2 1) table)) -(defun unidata-gen-table-integer (prop default-value val-list) - (let ((table (unidata-gen-table prop +(defun unidata-gen-table-integer (prop index default-value val-list) + (let ((table (unidata-gen-table prop index #'(lambda (x) (and (> (length x) 0) (string-to-number x))) default-value val-list))) @@ -578,8 +633,8 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' (None)." (set-char-table-extra-slot table 2 1) table)) -(defun unidata-gen-table-numeric (prop default-value val-list) - (let ((table (unidata-gen-table prop +(defun unidata-gen-table-numeric (prop index default-value val-list) + (let ((table (unidata-gen-table prop index #'(lambda (x) (if (string-match "/" x) (/ (float (string-to-number x)) @@ -885,9 +940,8 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' (None)." ;; Generate a char-table for character names. -(defun unidata-gen-table-word-list (prop val-func) +(defun unidata-gen-table-word-list (prop prop-idx val-func) (let ((table (make-char-table 'char-code-property-table)) - (prop-idx (unidata-prop-index prop)) (word-list (list nil)) word-table block-list block-word-table block-end @@ -1032,8 +1086,8 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' (None)." (or (byte-code-function-p (symbol-function fun)) (byte-compile fun)))) -(defun unidata-gen-table-name (prop &rest ignore) - (let* ((table (unidata-gen-table-word-list prop 'unidata-split-name)) +(defun unidata-gen-table-name (prop index &rest ignore) + (let* ((table (unidata-gen-table-word-list prop index 'unidata-split-name)) (word-tables (char-table-extra-slot table 4))) (unidata--ensure-compiled 'unidata-get-name 'unidata-put-name) (set-char-table-extra-slot table 1 (symbol-function 'unidata-get-name)) @@ -1070,8 +1124,8 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' (None)." (nreverse l))))) -(defun unidata-gen-table-decomposition (prop &rest ignore) - (let* ((table (unidata-gen-table-word-list prop 'unidata-split-decomposition)) +(defun unidata-gen-table-decomposition (prop index &rest ignore) + (let* ((table (unidata-gen-table-word-list prop index 'unidata-split-decomposition)) (word-tables (char-table-extra-slot table 4))) (unidata--ensure-compiled 'unidata-get-decomposition 'unidata-put-decomposition) @@ -1083,6 +1137,50 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' (None)." table)) + + +(defvar unidata-gen-table-special-casing--cache nil + "Cached value for `unidata-gen-table-special-casing' function.") + +(defun unidata-gen-table-special-casing--do-load () + (let (result) + (with-temp-buffer + (insert-file-contents (expand-file-name "SpecialCasing.txt" unidata-dir)) + (goto-char (point-min)) + (while (not (eobp)) + ;; Ignore empty lines and comments. + (unless (or (eq (char-after) ?\n) (eq (char-after) ?#)) + (let ((line (split-string + (buffer-substring (point) (progn (end-of-line) (point))) + ";" ""))) + ;; Ignore entries with conditions, i.e. those with six values. + (when (= (length line) 5) + (let ((ch (string-to-number (pop line) 16))) + (setcdr (cddr line) nil) ; strip comment + (push + (cons ch + (mapcar (lambda (entry) + (mapcar (lambda (n) (string-to-number n 16)) + (split-string entry))) + line)) + result))))) + (forward-line))) + result)) + +(defun unidata-gen-table-special-casing (prop prop-idx &rest ignore) + (let ((table (make-char-table 'char-code-property-table))) + (set-char-table-extra-slot table 0 prop) + (mapc (lambda (entry) + (let ((ch (car entry)) (v (nth prop-idx (cdr entry)))) + ;; If character maps to a single character, the mapping is already + ;; covered by regular casing property. Don’t store those. + (when (/= (length v) 1) + (set-char-table-range table ch (apply 'string v))))) + (or unidata-gen-table-special-casing--cache + (setq unidata-gen-table-special-casing--cache + (unidata-gen-table-special-casing--do-load)))) + table)) + (defun unidata-describe-general-category (val) (cdr (assq val @@ -1241,137 +1339,142 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' (None)." ;; (unidata-check)) (defun unidata-check () - (dolist (elt unidata-prop-alist) - (let* ((prop (car elt)) - (index (unidata-prop-index prop)) - (generator (unidata-prop-generator prop)) - (default-value (unidata-prop-default prop)) - (val-list (unidata-prop-val-list prop)) - (table (progn - (message "Generating %S table..." prop) - (funcall generator prop default-value val-list))) - (decoder (char-table-extra-slot table 1)) - (alist (and (functionp index) - (funcall index))) - (check #x400)) - (dolist (e unidata-list) - (let* ((char (car e)) - (val1 - (if alist (nth 1 (assoc char alist)) - (nth index e))) - val2) - (if (and (stringp val1) (= (length val1) 0)) - (setq val1 nil)) - (unless (or (consp char) - (integerp decoder)) - (setq val2 - (cond ((functionp decoder) - (funcall decoder char (aref table char) table)) - (t ; must be nil - (aref table char)))) - (if val1 - (cond ((eq generator 'unidata-gen-table-symbol) - (setq val1 (intern val1))) - ((eq generator 'unidata-gen-table-integer) - (setq val1 (string-to-number val1))) - ((eq generator 'unidata-gen-table-character) - (setq val1 (string-to-number val1 16))) - ((eq generator 'unidata-gen-table-decomposition) - (setq val1 (unidata-split-decomposition val1)))) - (cond ((eq prop 'decomposition) - (setq val1 (list char))) - ((eq prop 'bracket-type) - (setq val1 'n)))) - (when (>= char check) - (message "%S %04X" prop check) - (setq check (+ check #x400))) - (or (equal val1 val2) - ;; <control> characters get a 'name' property of nil - (and (eq prop 'name) (string= val1 "<control>") (null val2)) - (insert (format "> %04X %S\n< %04X %S\n" - char val1 char val2))) - (sit-for 0))))))) - -;; The entry function. It generates files described in the header + (dolist (elt unidata-file-alist) + (dolist (proplist (cdr elt)) + (let* ((prop (unidata-prop-prop proplist)) + (index (unidata-prop-index proplist)) + (generator (unidata-prop-generator proplist)) + (default-value (unidata-prop-default proplist)) + (val-list (unidata-prop-val-list proplist)) + (check #x400) + table decoder alist) + ;; We compare values in unidata.txt with the ones returned by various + ;; generator functions. However, SpecialCasing.txt is read directly by + ;; unidata-gen-table-special-casing--do-load and there is no other file + ;; to compare those values with. This is why we’re skipping the check + ;; for special casing properties. + (unless (eq generator 'unidata-gen-table-special-casing) + (setq table (progn + (message "Generating %S table..." prop) + (funcall generator prop index default-value val-list)) + decoder (char-table-extra-slot table 1)) + (unless (integerp decoder) + (setq alist (and (functionp index) (funcall index))) + (dolist (e unidata-list) + (let ((char (car e)) val1 val2) + (unless (consp char) + (setq val1 (if alist + (nth 1 (assoc char alist)) + (nth index e))) + (and (stringp val1) + (= (length val1) 0) + (setq val1 nil)) + (if val1 + (cond ((eq generator 'unidata-gen-table-symbol) + (setq val1 (intern val1))) + ((eq generator 'unidata-gen-table-integer) + (setq val1 (string-to-number val1))) + ((eq generator 'unidata-gen-table-character) + (setq val1 (string-to-number val1 16))) + ((eq generator 'unidata-gen-table-decomposition) + (setq val1 (unidata-split-decomposition val1)))) + (cond ((eq prop 'decomposition) + (setq val1 (list char))) + ((eq prop 'bracket-type) + (setq val1 'n)))) + (setq val2 (aref table char)) + (when decoder + (setq val2 (funcall decoder char val2 table))) + (when (>= char check) + (message "%S %04X" prop check) + (setq check (+ check #x400))) + (or (equal val1 val2) + ;; <control> characters get a 'name' property of nil + (and (eq prop 'name) + (string= val1 "<control>") + (null val2)) + (insert (format "> %04X %S\n< %04X %S\n" + char val1 char val2))) + (sit-for 0)))))))))) + +;; The entry functions. They generate files described in the header ;; comment of this file. -;; Write files (charprop.el, uni-*.el) to dest-dir (default PWD), -;; using as input files from data-dir, and -;; unidata-text-file (default "unidata.txt" in PWD). -(defun unidata-gen-files (&optional data-dir dest-dir unidata-text-file) - (or data-dir - (setq data-dir (pop command-line-args-left) - dest-dir (or (pop command-line-args-left) default-directory) +(defun unidata-gen-file (&optional file data-dir unidata-text-file) + "Generate lisp file FILE from Unicode data." + (or file + (setq file (pop command-line-args-left) + data-dir (or (pop command-line-args-left) default-directory) unidata-text-file (or (pop command-line-args-left) (expand-file-name "unidata.txt")))) - (let ((coding-system-for-write 'utf-8-unix) - (coding-system-for-read 'utf-8) - (charprop-file (expand-file-name "charprop.el" dest-dir)) - (unidata-dir data-dir)) - (dolist (elt unidata-prop-alist) - (let* ((prop (car elt)) - (file (expand-file-name (unidata-prop-file prop) dest-dir))) - (if (file-exists-p file) - (delete-file file)))) - (unidata-setup-list unidata-text-file) - (with-temp-file charprop-file - (insert ";; Automatically generated by unidata-gen.el.\n") - (dolist (elt unidata-prop-alist) - (let* ((prop (car elt)) - (generator (unidata-prop-generator prop)) - (file (expand-file-name (unidata-prop-file prop) dest-dir)) - (basename (file-name-nondirectory file)) - (docstring (unidata-prop-docstring prop)) - (describer (unidata-prop-describer prop)) - (default-value (unidata-prop-default prop)) - (val-list (unidata-prop-val-list prop)) - ;; Avoid creating backup files for those uni-*.el files - ;; that hold more than one table. - (backup-inhibited t) - table) - ;; Filename in this comment line is extracted by sed in - ;; Makefile. - (insert (format ";; FILE: %s\n" basename)) - (insert (format "(define-char-code-property '%S %S\n %S)\n" - prop basename docstring)) - (with-temp-buffer - (or noninteractive (message "Generating %s..." file)) - (when (file-exists-p file) - (insert-file-contents file) - (goto-char (point-max)) - (search-backward ";; Local Variables:")) - (setq table (funcall generator prop default-value val-list)) - (when describer - (unless (subrp (symbol-function describer)) - (unidata--ensure-compiled describer) - (setq describer (symbol-function describer))) - (set-char-table-extra-slot table 3 describer)) - (if (bobp) - (insert ";; Copyright (C) 1991-2014 Unicode, Inc. -;; This file was generated from the Unicode data files at -;; http://www.unicode.org/Public/UNIDATA/. -;; See lisp/international/README for the copyright and permission notice.\n")) - (insert (format "(define-char-code-property '%S\n %S\n %S)\n" - prop table docstring)) - (if (eobp) - (insert ";; Local Variables:\n" - ";; coding: utf-8\n" - ";; version-control: never\n" - ";; no-byte-compile: t\n" - ";; no-update-autoloads: t\n" - ";; End:\n\n" - (format ";; %s ends here\n" basename))) - (write-file file) - (or noninteractive (message "Generating %s...done" file))))) - (message "Writing %s..." charprop-file) - (insert ";; Local Variables:\n" - ";; coding: utf-8\n" - ";; version-control: never\n" - ";; no-byte-compile: t\n" - ";; no-update-autoloads: t\n" - ";; End:\n\n" - (format ";; %s ends here\n" - (file-name-nondirectory charprop-file)))))) + (let* ((coding-system-for-write 'utf-8-unix) + (coding-system-for-read 'utf-8) + (unidata-dir data-dir) + (copyright (with-temp-buffer + (insert-file-contents + (expand-file-name "copyright.html" unidata-dir)) + (re-search-forward "^Copyright .*Unicode, Inc.") + (match-string 0)))) + (or unidata-list (unidata-setup-list unidata-text-file)) + (let* ((basename (file-name-nondirectory file)) + (elt (assoc basename unidata-file-alist))) + (or elt (user-error "Unknown output file: %s" basename)) + (or noninteractive (message "Generating %s..." file)) + (with-temp-file file + (insert ";; " copyright " +;; Generated from Unicode data files by unidata-gen.el. +;; The sources for this file are found in the admin/unidata/ directory in +;; the Emacs sources. The Unicode data files are used under the +;; Unicode Terms of Use, as contained in the file copyright.html in that +;; same directory.\n") + (dolist (proplist (cdr elt)) + (let ((prop (unidata-prop-prop proplist)) + (index (unidata-prop-index proplist)) + (generator (unidata-prop-generator proplist)) + (docstring (unidata-prop-docstring proplist)) + (describer (unidata-prop-describer proplist)) + (default-value (unidata-prop-default proplist)) + (val-list (unidata-prop-val-list proplist)) + table) + (setq table (funcall generator prop index default-value val-list)) + (when describer + (unless (subrp (symbol-function describer)) + (unidata--ensure-compiled describer) + (setq describer (symbol-function describer))) + (set-char-table-extra-slot table 3 describer)) + (insert (format "(define-char-code-property '%S\n %S\n %S)\n" + prop table docstring)))) + (insert ";; Local Variables:\n" + ";; coding: utf-8\n" + ";; version-control: never\n" + ";; no-byte-compile: t\n" + ";; no-update-autoloads: t\n" + ";; End:\n\n" + (format ";; %s ends here\n" basename))))) + (or noninteractive (message "Generating %s...done" file))) + +(defun unidata-gen-charprop (&optional charprop-file) + (or charprop-file (setq charprop-file (pop command-line-args-left))) + (with-temp-file charprop-file + (insert ";; Automatically generated by unidata-gen.el.\n" + ";; See the admin/unidata/ directory in the Emacs sources.\n") + (dolist (elt unidata-file-alist) + (dolist (proplist (cdr elt)) + (insert (format "(define-char-code-property '%S %S\n %S)\n" + (unidata-prop-prop proplist) (car elt) + (unidata-prop-docstring proplist))))) + (or noninteractive (message "Writing %s..." charprop-file)) + (insert "\n" + "(provide 'charprop)\n" + " \n" + ";; Local Variables:\n" + ";; coding: utf-8\n" + ";; version-control: never\n" + ";; no-byte-compile: t\n" + ";; no-update-autoloads: t\n" + ";; End:\n\n" + (format ";; %s ends here\n" + (file-name-nondirectory charprop-file))))) diff --git a/admin/update_autogen b/admin/update_autogen index dd59876f617..f0d2415012f 100755 --- a/admin/update_autogen +++ b/admin/update_autogen @@ -47,14 +47,7 @@ cd $PD cd ../ [ -d admin ] || die "Could not locate admin directory" -if [ -d .bzr ]; then - vcs=bzr -elif [ -e .git ]; then - vcs=git -else - die "Cannot determine vcs" -fi - +[ -d .git ] || die "No .git directory" usage () { @@ -92,16 +85,16 @@ changelog_flag= ## Parameters. ldefs_in=lisp/loaddefs.el -ldefs_boot=lisp/ldefs-boot.el +ldefs_out=lisp/ldefs-boot.el changelog_n=$(sed -n 's/CHANGELOG_HISTORY_INDEX_MAX *= *//p' Makefile.in) changelog_files="ChangeLog.$changelog_n" sources="configure.ac lib/Makefile.am" ## Files to copy into autogendir. ## Everything: genfiles=" - configure aclocal.m4 src/config.in lib/Makefile.in - build-aux/compile build-aux/config.guess build-aux/config.sub - build-aux/depcomp build-aux/install-sh build-aux/missing + configure aclocal.m4 src/config.in + build-aux/config.guess build-aux/config.sub + build-aux/install-sh " for g in $genfiles; do basegen="$basegen ${g##*/}" @@ -154,10 +147,7 @@ OPTIND=1 ## Run status on inputs, list modified files on stdout. status () { - local statflag="-S" - [ "$vcs" = "git" ] && statflag="-s" - - $vcs status $statflag "$@" >| $tempfile || die "$vcs status error for $@" + git status -s "$@" >| $tempfile || die "git status error for $@" local stat file modified @@ -231,11 +221,11 @@ commit () echo "Committing..." - $vcs commit -m "; Auto-commit of $type files." "$@" || return $? + git commit -m "; Auto-commit of $type files." "$@" || return $? - [ "$vcs" = "git" ] && { - $vcs push || return $? - } + ## In case someone else pushed something while we were working. + git pull --rebase || return $? + git push || return $? echo "Committed files: $@" } # function commit @@ -367,12 +357,19 @@ echo "Running lisp/ make..." make -C lisp "$@" autoloads EMACS=../src/bootstrap-emacs || die "make src error" + +## Ignore comment differences. +[ ! "$lboot_flag" ] || \ + diff -q -I '^;' $ldefs_in $ldefs_out || \ + cp $ldefs_in $ldefs_out || die "cp ldefs_boot error" + + echo "Checking status of loaddef files..." ## It probably would be fine to just check+commit lisp/, since ## making autoloads should not effect any other files. But better ## safe than sorry. -modified=$(status $genfiles) || die +modified=$(status $genfiles $ldefs_out) || die commit "loaddefs" $modified || die "commit error" @@ -386,14 +383,6 @@ commit "loaddefs" $modified || die "commit error" } - -## Regenerate ldefs-boot if we are told to -[ ! "$lboot_flag" ] || { - make generate-ldefs-boot || die - modified=$(status $ldefs_boot) || die - commit $ldefs_boot $modified || die "commit error" -} - exit 0 ### update_autogen ends here diff --git a/autogen.sh b/autogen.sh index ed21830efaf..20a99e49624 100755 --- a/autogen.sh +++ b/autogen.sh @@ -32,15 +32,11 @@ ## Tools we need: ## Note that we respect the values of AUTOCONF etc, like autoreconf does. -progs="autoconf automake" +progs="autoconf" ## Minimum versions we need: autoconf_min=`sed -n 's/^ *AC_PREREQ(\([0-9\.]*\)).*/\1/p' configure.ac` -## This will need improving if more options are ever added to the -## AM_INIT_AUTOMAKE call. -automake_min=`sed -n 's/^ *AM_INIT_AUTOMAKE(\([0-9\.]*\)).*/\1/p' configure.ac` - ## $1 = program, eg "autoconf". ## Echo the version string, eg "2.59". @@ -49,8 +45,8 @@ automake_min=`sed -n 's/^ *AM_INIT_AUTOMAKE(\([0-9\.]*\)).*/\1/p' configure.ac` ## Also note that we do not handle micro versions. get_version () { - ## Remove eg "./autogen.sh: line 50: autoconf: command not found". - $1 --version 2>&1 | sed -e '/not found/d' -e 's/.* //' -n -e '1 s/\([0-9][0-9\.]*\).*/\1/p' + vers=`($1 --version) 2> /dev/null` && expr "$vers" : '[^ +]* \([0-9][0-9.]*\).*' } ## $1 = version string, eg "2.59" @@ -75,16 +71,19 @@ minor_version () ## Return 3 for unexpected error (eg failed to parse version). check_version () { - ## Respect eg $AUTOMAKE if it is set, like autoreconf does. - uprog=`echo $1 | sed -e 's/-/_/g' -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` - - eval uprog=\$${uprog} + ## Respect, e.g., $AUTOCONF if it is set, like autoreconf does. + uprog0=`echo $1 | sed -e 's/-/_/g' -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` - [ x"$uprog" = x ] && uprog=$1 + eval uprog=\$${uprog0} - have_version=`get_version $uprog` + if [ x"$uprog" = x ]; then + uprog=$1 + else + printf '%s' "(using $uprog0=$uprog) " + fi - [ x"$have_version" = x ] && return 1 + command -v $uprog > /dev/null || return 1 + have_version=`get_version $uprog` || return 4 have_maj=`major_version $have_version` need_maj=`major_version $2` @@ -131,7 +130,7 @@ case $do_autoconf,$do_git in do_autoconf=true;; esac -# Generate Autoconf and Automake related files, if requested. +# Generate Autoconf-related files, if requested. if $do_autoconf; then @@ -158,6 +157,7 @@ if $do_autoconf; then 0) stat="ok" ;; 1) stat="missing" ;; 2) stat="too old" ;; + 4) stat="broken?" ;; *) stat="unable to check" ;; esac @@ -229,23 +229,23 @@ Please report any problems with this script to bug-gnu-emacs@gnu.org .' fi # do_check - ## Create nt/gnulib.mk if it doesn't exist, as autoreconf will need it. - if test ! -f nt/gnulib.mk; then - echo 'Inferring nt/gnulib.mk from lib/gnulib.mk ...' - metascript='/^[^#]/s|^.*$|/^## begin *gnulib module &/,/^## end *gnulib module &/d|p' - script=`sed -n "$metascript" nt/gnulib-modules-to-delete.cfg` || exit - sed "$script" lib/gnulib.mk > nt/gnulib.mk || exit - fi + # Build aclocal.m4 here so that autoreconf need not use aclocal. + # aclocal is part of Automake and might not be installed, and + # autoreconf skips aclocal if aclocal.m4 is already supplied. + ls m4/*.m4 | LC_ALL=C sort | sed 's,.*\.m4$,m4_include([&]),' \ + > aclocal.m4.tmp || exit + if cmp -s aclocal.m4.tmp aclocal.m4; then + rm -f aclocal.m4.tmp + else + echo "Building aclocal.m4 ..." + mv aclocal.m4.tmp aclocal.m4 + fi || exit echo "Running 'autoreconf -fi -I m4' ..." ## Let autoreconf figure out what, if anything, needs doing. ## Use autoreconf's -f option in case autoreconf itself has changed. - autoreconf -fi -I m4 || exit $? - - ## Create a timestamp, so that './autogen.sh; make' doesn't - ## cause 'make' to needlessly run 'autoheader'. - echo timestamp > src/stamp-h.in || exit + autoreconf -fi -I m4 || exit fi diff --git a/build-aux/config.guess b/build-aux/config.guess new file mode 100755 index 00000000000..2193702b12a --- /dev/null +++ b/build-aux/config.guess @@ -0,0 +1,1473 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2017 Free Software Foundation, Inc. + +timestamp='2017-05-27' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# +# Please send patches to <config-patches@gnu.org>. + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2017 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include <features.h> + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + /sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || \ + echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` + machine=${arch}${endian}-unknown + ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently (or will in the future) and ABI. + case "${UNAME_MACHINE_ARCH}" in + earm*) + os=netbsdelf + ;; + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # Determine ABI tags. + case "${UNAME_MACHINE_ARCH}" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}${abi}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:Sortix:*:*) + echo ${UNAME_MACHINE}-unknown-sortix + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE=alpha ;; + "EV4.5 (21064)") + UNAME_MACHINE=alpha ;; + "LCA4 (21066/21068)") + UNAME_MACHINE=alpha ;; + "EV5 (21164)") + UNAME_MACHINE=alphaev5 ;; + "EV5.6 (21164A)") + UNAME_MACHINE=alphaev56 ;; + "EV5.6 (21164PC)") + UNAME_MACHINE=alphapca56 ;; + "EV5.7 (21164PC)") + UNAME_MACHINE=alphapca57 ;; + "EV6 (21264)") + UNAME_MACHINE=alphaev6 ;; + "EV6.7 (21264A)") + UNAME_MACHINE=alphaev67 ;; + "EV6.8CB (21264C)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8AL (21264B)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8CX (21264D)") + UNAME_MACHINE=alphaev68 ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE=alphaev69 ;; + "EV7 (21364)") + UNAME_MACHINE=alphaev7 ;; + "EV7.9 (21364A)") + UNAME_MACHINE=alphaev79 ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH=i386 + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH=x86_64 + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = hppa2.0w ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH=hppa2.0w + else + HP_ARCH=hppa64 + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; + esac + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + e2k:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + k1om:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + mips64el:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = x86; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = 386; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit ;; +esac + +cat >&2 <<EOF +$0: unable to guess system type + +This script (version $timestamp), has failed to recognize the +operating system you are using. If your script is old, overwrite +config.guess and config.sub with the latest versions from: + + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +and + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build-aux/config.sub b/build-aux/config.sub new file mode 100755 index 00000000000..40ea5dfe115 --- /dev/null +++ b/build-aux/config.sub @@ -0,0 +1,1836 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2017 Free Software Foundation, Inc. + +timestamp='2017-04-02' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to <config-patches@gnu.org>. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2017 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | wasm32 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | ba-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | e2k-* | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ + | pyramid-* \ + | riscv32-* | riscv64-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | wasm32-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + asmjs) + basic_machine=asmjs-unknown + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + os=$os"spe" + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + wasm32) + basic_machine=wasm32-unknown + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -ios) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + pru-*) + os=-elf + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build-aux/install-sh b/build-aux/install-sh new file mode 100755 index 00000000000..0360b79e7d0 --- /dev/null +++ b/build-aux/install-sh @@ -0,0 +1,501 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2016-01-11.22; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/configure.ac b/configure.ac index e07db31b2be..b07c0998f21 100644 --- a/configure.ac +++ b/configure.ac @@ -67,8 +67,6 @@ done AC_CONFIG_HEADERS(src/config.h:src/config.in) AC_CONFIG_SRCDIR(src/lisp.h) AC_CONFIG_AUX_DIR(build-aux) -dnl automake 1.13 and later understand this, making -I m4 unnecessary. -dnl With older versions this is a no-op. AC_CONFIG_MACRO_DIR(m4) xcsdkdir= @@ -86,13 +84,7 @@ if test -n "$XCRUN"; then fi fi -dnl GNU Make is required, so don't test for its individual features. -am_cv_make_support_nested_variables=yes -AC_DEFUN([AC_PROG_MAKE_SET], - [SET_MAKE= - AC_SUBST([SET_MAKE])]) - -dnl Check for GNU Make and possibly set MAKE before running AM_INIT_AUTOMAKE. +dnl Check for GNU Make and possibly set MAKE. [emacs_check_gnu_make () { emacs_makeout=`($1 --version) 2>/dev/null` && @@ -132,9 +124,6 @@ For example, run '$0 MAKE=gnu-make'.]]) MAKE=$ac_cv_path_MAKE export MAKE -dnl Fairly arbitrary, older versions might work too. -AM_INIT_AUTOMAKE(1.11) - dnl Canonicalize the configuration name. AC_CANONICAL_HOST @@ -240,7 +229,21 @@ AC_DEFUN([OPTION_DEFAULT_ON], [dnl m4_bpatsubst([with_$1], [[^0-9a-z]], [_])=$with_features])dnl ])dnl -OPTION_DEFAULT_ON([pop],[don't support POP mail retrieval with movemail]) +# FIXME: The default options '--without-mailutils --with-pop' result +# in a movemail implementation that supports only unencrypted POP3 +# connections. Encrypted connections should be the default. + +OPTION_DEFAULT_OFF([mailutils], + [rely on GNU Mailutils, so that the --without-pop through --with-mailhost + options are irrelevant]) +if test "$with_mailutils" = no; then + with_mailutils= +fi +AC_SUBST([with_mailutils]) + +OPTION_DEFAULT_ON([pop], + [don't support POP mail retrieval with movemail (--without-pop or + --with-mailutils is recommended, as movemail POP is insecure)]) if test "$with_pop" = yes; then AC_DEFINE(MAIL_USE_POP) fi @@ -384,9 +387,6 @@ OPTION_DEFAULT_OFF([xwidgets], dnl http://lists.gnu.org/archive/html/emacs-devel/2008-04/msg01844.html OPTION_DEFAULT_ON([makeinfo],[don't require makeinfo for building manuals]) -## This might be a 'configure' arg. -AC_SUBST([ACLOCAL_PATH]) - ## Makefile.in needs the cache file name. AC_SUBST(cache_file) @@ -402,12 +402,9 @@ AC_ARG_WITH(gameuser,dnl An argument prefixed by ':' specifies a group instead.])]) gameuser= gamegroup= -# We don't test if we can actually chown/chgrp here, because configure -# may run without root privileges. lib-src/Makefile.in will handle -# any errors due to missing user/group gracefully. case ${with_gameuser} in - no) ;; - "" | yes) gamegroup=games ;; + '' | no) ;; + yes) gamegroup=games ;; :*) gamegroup=${with_gameuser#:} ;; *) gameuser=${with_gameuser} ;; esac @@ -755,14 +752,12 @@ fi dnl Emacs needs C99 or later. gl_PROG_CC_C99 -AM_PROG_CC_C_O +AC_PROG_CC_C_O if test x$GCC = xyes; then test "x$GCC_TEST_OPTIONS" != x && CC="$CC $GCC_TEST_OPTIONS" fi -AM_CONDITIONAL([BUILDING_FOR_WINDOWSNT], [test "x$opsys" = "xmingw32"]) - # Avoid gnulib's tests for -lcrypto, so that there's no static dependency on it. AC_DEFUN([gl_CRYPTO_CHECK]) # Avoid gnulib's tests for HAVE_WORKING_O_NOATIME and HAVE_WORKING_O_NOFOLLOW, @@ -872,9 +867,18 @@ AC_ARG_ENABLE([gcc-warnings], # just a release imported into Git for patch management. gl_gcc_warnings=no if test -e "$srcdir"/.git && test ! -f "$srcdir"/.tarball-version; then - gl_GCC_VERSION_IFELSE([5], [3], [gl_gcc_warnings=warn-only])] - fi -) + gl_GCC_VERSION_IFELSE([5], [3], [gl_gcc_warnings=warn-only]) + fi]) + +AC_ARG_ENABLE([check-lisp-object-type], + [AS_HELP_STRING([--enable-check-lisp-object-type], + [Enable compile-time checks for the Lisp_Object data type, + which can catch some bugs during development. + The default is "no" if --enable-gcc-warnings is "no".])]) +if test "${enable_check_lisp_object_type-$gl_gcc_warnings}" != "no"; then + AC_DEFINE([CHECK_LISP_OBJECT_TYPE], 1, + [Define to enable compile-time checks for the Lisp_Object data type.]) +fi # clang is unduly picky about some things. AC_CACHE_CHECK([whether the compiler is clang], [emacs_cv_clang], @@ -887,6 +891,7 @@ AC_CACHE_CHECK([whether the compiler is clang], [emacs_cv_clang], [emacs_cv_clang=yes], [emacs_cv_clang=no])]) +WERROR_CFLAGS= # When compiling with GCC, prefer -isystem to -I when including system # include files, to avoid generating useless diagnostics for the files. AS_IF([test $gl_gcc_warnings = no], @@ -896,7 +901,6 @@ AS_IF([test $gl_gcc_warnings = no], [ # Turn off some warnings if supported. gl_WARN_ADD([-Wno-switch]) - gl_WARN_ADD([-Wno-tautological-constant-out-of-range-compare]) gl_WARN_ADD([-Wno-pointer-sign]) gl_WARN_ADD([-Wno-string-plus-int]) gl_WARN_ADD([-Wno-unknown-attributes]) @@ -914,9 +918,10 @@ AS_IF([test $gl_gcc_warnings = no], ;; esac AS_IF([test $gl_gcc_warnings = yes], - [gl_WARN_ADD([-Werror], [WERROR_CFLAGS])]) - AC_SUBST([WERROR_CFLAGS]) + [WERROR_CFLAGS=-Werror]) + nw="$nw -Wduplicated-branches" # Too many false alarms + nw="$nw -Wformat-overflow=2" # False alarms due to GCC bug 80776 nw="$nw -Wsystem-headers" # Don't let system headers trigger warnings nw="$nw -Woverlength-strings" # Not a problem these days nw="$nw -Wformat-nonliteral" # we do this a lot @@ -952,11 +957,14 @@ AS_IF([test $gl_gcc_warnings = no], # This part is merely for shortening the command line, # since -Wno-FOO needs to be added below regardless. nw="$nw -Wmissing-field-initializers" + nw="$nw -Woverride-init" nw="$nw -Wtype-limits" nw="$nw -Wunused-parameter" - if test $emacs_cv_clang = yes; then + if test "$emacs_cv_clang" = yes; then nw="$nw -Wcast-align" + nw="$nw -Wdouble-promotion" + nw="$nw -Wmissing-braces" fi # This causes too much noise in the MinGW build @@ -971,15 +979,15 @@ AS_IF([test $gl_gcc_warnings = no], done gl_WARN_ADD([-Wredundant-decls]) # Prefer this, as we don't use Bison. gl_WARN_ADD([-Wno-missing-field-initializers]) # We need this one + gl_WARN_ADD([-Wno-override-init]) # More trouble than it is worth gl_WARN_ADD([-Wno-sign-compare]) # Too many warnings for now gl_WARN_ADD([-Wno-type-limits]) # Too many warnings for now gl_WARN_ADD([-Wno-unused-parameter]) # Too many warnings for now gl_WARN_ADD([-Wno-format-nonliteral]) - # More things that clang is unduly picky about. - if test $emacs_cv_clang = yes; then - gl_WARN_ADD([-Wno-tautological-compare]) - gl_WARN_ADD([-Wno-tautological-constant-out-of-range-compare]) + # clang is unduly picky about braces. + if test "$emacs_cv_clang" = yes; then + gl_WARN_ADD([-Wno-missing-braces]) fi # This causes too much noise in the MinGW build @@ -997,15 +1005,23 @@ AS_IF([test $gl_gcc_warnings = no], # define _FORTIFY_SOURCE 2 #endif ]) + ]) - # We use a slightly smaller set of warning options for lib/. - # Remove the following and save the result in GNULIB_WARN_CFLAGS. - nw= - nw="$nw -Wunused-macros" +# clang is picky about these regardless of whether +# --enable-gcc-warnings is specified. +if test "$emacs_cv_clang" = yes; then + gl_WARN_ADD([-Wno-initializer-overrides]) + gl_WARN_ADD([-Wno-tautological-compare]) + gl_WARN_ADD([-Wno-tautological-constant-out-of-range-compare]) +fi - gl_MANYWARN_COMPLEMENT([GNULIB_WARN_CFLAGS], [$WARN_CFLAGS], [$nw]) - AC_SUBST([GNULIB_WARN_CFLAGS]) - ]) +# Use a slightly smaller set of warning options for lib/. +nw= +nw="$nw -Wunused-macros" +gl_MANYWARN_COMPLEMENT([GNULIB_WARN_CFLAGS], [$WARN_CFLAGS], [$nw]) + +AC_SUBST([WERROR_CFLAGS]) +AC_SUBST([GNULIB_WARN_CFLAGS]) edit_cflags=" s,///*,/,g @@ -1024,7 +1040,7 @@ AC_ARG_ENABLE(link-time-optimization, recommended for typical use.])], if test "${enableval}" != "no"; then ac_lto_supported=no - if test $emacs_cv_clang = yes; then + if test "$emacs_cv_clang" = yes; then AC_MSG_CHECKING([whether link-time optimization is supported by clang]) GOLD_PLUGIN=`$CC -print-file-name=LLVMgold.so 2>/dev/null` if test -x "$GOLD_PLUGIN"; then @@ -1053,7 +1069,7 @@ if test "${enableval}" != "no"; then AC_MSG_RESULT([$ac_lto_supported]) if test "$ac_lto_supported" = "yes"; then CFLAGS="$CFLAGS $LTO" - if test x$emacs_cv_clang = xyes; then + if test "$emacs_cv_clang" = yes; then AC_MSG_WARN([Please read INSTALL before using link-time optimization with clang]) # WARNING: 'ar --plugin ...' doesn't work without # command, so plugin name is appended to ARFLAGS. @@ -1070,22 +1086,35 @@ if test "${enableval}" != "no"; then fi fi) + +dnl Automake replacements. +AC_DEFUN([AM_CONDITIONAL], + [$2 && $1=1 || $1= + AC_SUBST([$1])]) + dnl Prefer silent make output. For verbose output, use dnl 'configure --disable-silent-rules' or 'make V=1' . -AM_SILENT_RULES([yes]) -dnl Port to Automake 1.11. -dnl This section can be removed once we assume Automake 1.14 or later. -: ${AM_V=$AM_DEFAULT_VERBOSITY} -: ${AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY} +dnl This code is adapted from Automake. +dnl Although it can be simplified now that GNU Make is assumed, +dnl the simplification hasn't been done yet. +AC_ARG_ENABLE([silent-rules], + [AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])]) +if test "$enable_silent_rules" = no; then + AM_DEFAULT_VERBOSITY=1 +else + AM_DEFAULT_VERBOSITY=0 +fi +AM_V='$(V)' +AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' AC_SUBST([AM_V]) -AM_SUBST_NOTMAKE([AM_V]) AC_SUBST([AM_DEFAULT_V]) -AM_SUBST_NOTMAKE([AM_DEFAULT_V]) AC_SUBST([AM_DEFAULT_VERBOSITY]) dnl Some other nice autoconf tests. +AC_PROG_INSTALL dnl These are commented out, since gl_EARLY and/or Autoconf already does them. -dnl AC_PROG_INSTALL dnl AC_PROG_MKDIR_P dnl if test "x$RANLIB" = x; then dnl AC_PROG_RANLIB @@ -1160,6 +1189,16 @@ AC_PATH_PROG(GZIP_PROG, gzip) test $with_compress_install != yes && test -n "$GZIP_PROG" && \ GZIP_PROG=" # $GZIP_PROG # (disabled by configure --without-compress-install)" +AC_CACHE_CHECK([for 'find' args to delete a file], + [emacs_cv_find_delete], + [if touch conftest.tmp && find conftest.tmp -delete 2>/dev/null && + test ! -f conftest.tmp + then emacs_cv_find_delete="-delete" + else emacs_cv_find_delete="-exec rm -f {} ';'" + fi]) +FIND_DELETE=$emacs_cv_find_delete +AC_SUBST([FIND_DELETE]) + PAXCTL_dumped= PAXCTL_notdumped= if test $opsys = gnu-linux; then @@ -1210,10 +1249,7 @@ AC_SUBST([PAXCTL_dumped]) AC_SUBST([PAXCTL_notdumped]) ## Require makeinfo >= 4.13 (last of the 4.x series) to build the manuals. -if test "$MAKEINFO" != "no"; then - if test "$MAKEINFO" = "${am_missing_run}makeinfo"; then - MAKEINFO=makeinfo - fi +if test "${MAKEINFO:=makeinfo}" != "no"; then case `($MAKEINFO --version) 2>/dev/null` in *' (GNU texinfo) '4.1[[3-9]]* | \ *' (GNU texinfo) '[[5-9]]* | \ @@ -1244,6 +1280,7 @@ Either install a suitable version of makeinfo, or re-run configure with the '--without-makeinfo' option to build without the manuals.] ) fi fi +AC_SUBST([MAKEINFO]) AC_SUBST(HAVE_MAKEINFO) if test $opsys = mingw32; then @@ -1530,6 +1567,7 @@ esac AC_SUBST(LIB_MATH) AC_DEFINE_UNQUOTED(SYSTEM_TYPE, "$SYSTEM_TYPE", [The type of system you are compiling for; sets 'system-type'.]) +AC_SUBST([SYSTEM_TYPE]) pre_PKG_CONFIG_CFLAGS=$CFLAGS @@ -1714,6 +1752,7 @@ dnl AC_C_BIGENDIAN is done by gnulib. dnl check for Make feature AUTO_DEPEND=no +AUTODEPEND_PARENTS='lib src' dnl check if we have GCC and autodepend is on. if test "$GCC" = yes && test "$ac_enable_autodepend" = yes; then AC_MSG_CHECKING([whether gcc understands -MMD -MF]) @@ -1947,6 +1986,25 @@ AC_SUBST(ns_self_contained) AC_SUBST(NS_OBJ) AC_SUBST(NS_OBJC_OBJ) +if test "${HAVE_NS}" = yes; then + AC_CACHE_CHECK( + [if the Objective C compiler supports instancetype], + [emacs_cv_objc_instancetype], + [AC_LANG_PUSH([Objective C]) + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE([[@interface Test + + (instancetype)test; + @end]])], + emacs_cv_objc_instancetype=yes, + emacs_cv_objc_instancetype=no) + AC_LANG_POP([Objective C])]) + + if test x$emacs_cv_objc_instancetype = xyes ; then + AC_DEFINE(NATIVE_OBJC_INSTANCETYPE, 1, + [Define if ObjC compiler supports instancetype natively.]) + fi +fi + HAVE_W32=no W32_OBJ= W32_LIBS= @@ -1955,7 +2013,6 @@ CLIENTRES= CLIENTW= W32_RES_LINK= EMACS_MANIFEST= -UPDATE_MANIFEST= if test "${with_w32}" != no; then case "${opsys}" in cygwin) @@ -2023,7 +2080,6 @@ if test "${HAVE_W32}" = "yes"; then # the rc file), not a linker script. W32_RES_LINK="-Wl,emacs.res" else - UPDATE_MANIFEST=update-game-score.exe.manifest W32_OBJ="$W32_OBJ w32.o w32console.o w32heap.o w32inevt.o w32proc.o" W32_LIBS="$W32_LIBS -lwinmm -lgdi32 -lcomdlg32" W32_LIBS="$W32_LIBS -lmpr -lwinspool -lole32 -lcomctl32 -lusp10" @@ -2043,7 +2099,6 @@ AC_SUBST(W32_OBJ) AC_SUBST(W32_LIBS) AC_SUBST(EMACSRES) AC_SUBST(EMACS_MANIFEST) -AC_SUBST(UPDATE_MANIFEST) AC_SUBST(CLIENTRES) AC_SUBST(CLIENTW) AC_SUBST(W32_RES_LINK) @@ -2196,7 +2251,6 @@ else fi fi AC_SUBST([HYBRID_MALLOC]) -AM_CONDITIONAL([HYBRID_MALLOC_LIB], [test -n "$HYBRID_MALLOC"]) AC_SUBST(GMALLOC_OBJ) AC_SUBST(VMLIMIT_OBJ) @@ -2453,19 +2507,31 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${HAVE_W32}" ## 6.8.2 makes Emacs crash; see Bug#13867. IMAGEMAGICK_MODULE="Wand >= 6.3.5 Wand != 6.8.2" EMACS_CHECK_MODULES([IMAGEMAGICK], [$IMAGEMAGICK_MODULE]) - AC_SUBST(IMAGEMAGICK_CFLAGS) - AC_SUBST(IMAGEMAGICK_LIBS) if test $HAVE_IMAGEMAGICK = yes; then - AC_DEFINE(HAVE_IMAGEMAGICK, 1, [Define to 1 if using imagemagick.]) OLD_CFLAGS=$CFLAGS OLD_LIBS=$LIBS CFLAGS="$CFLAGS $IMAGEMAGICK_CFLAGS" LIBS="$IMAGEMAGICK_LIBS $LIBS" - AC_CHECK_FUNCS(MagickExportImagePixels MagickMergeImageLayers MagickAutoOrientImage) + AC_CHECK_FUNCS([MagickRelinquishMemory MagickExportImagePixels \ + MagickMergeImageLayers MagickAutoOrientImage]) CFLAGS=$OLD_CFLAGS LIBS=$OLD_LIBS + # Check that ImageMagick links. It does not link on Fedora 25 + # with './configure CC=clang', as pkg-config outputs flags like + # -lomp that work for GCC but not Clang. + if test "$ac_cv_func_MagickRelinquishMemory" != yes; then + HAVE_IMAGEMAGICK=no + fi + fi + if test $HAVE_IMAGEMAGICK = yes; then + AC_DEFINE([HAVE_IMAGEMAGICK], 1, [Define to 1 if using ImageMagick.]) + else + IMAGEMAGICK_CFLAGS= + IMAGEMAGICK_LIBS= fi + AC_SUBST([IMAGEMAGICK_CFLAGS]) + AC_SUBST([IMAGEMAGICK_LIBS]) fi fi @@ -3451,6 +3517,14 @@ if test "${HAVE_MODULES}" = yes; then fi AC_SUBST(MODULES_OBJ) AC_SUBST(LIBMODULES) +AC_SUBST(HAVE_MODULES) +AC_SUBST(MODULES_SUFFIX) + +AC_CONFIG_FILES([src/emacs-module.h]) +AC_SUBST_FILE([module_env_snippet_25]) +AC_SUBST_FILE([module_env_snippet_26]) +module_env_snippet_25="$srcdir/src/module-env-25.h" +module_env_snippet_26="$srcdir/src/module-env-26.h" ### Use -lpng if available, unless '--with-png=no'. HAVE_PNG=no @@ -3784,100 +3858,104 @@ fi AC_SUBST(LIBXML2_LIBS) AC_SUBST(LIBXML2_CFLAGS) -# Check for mail-locking functions in a "mail" library. Probably this should -# have the same check as for liblockfile below. -AC_CHECK_LIB(mail, maillock, have_mail=yes, have_mail=no) -if test $have_mail = yes; then - LIBS_MAIL=-lmail - AC_DEFINE(HAVE_LIBMAIL, 1, [Define to 1 if you have the 'mail' library (-lmail).]) - - OLD_LIBS=$LIBS - LIBS="$LIBS_MAIL $LIBS" - AC_CHECK_FUNCS(touchlock) - LIBS=$OLD_LIBS -else - LIBS_MAIL= -fi -dnl Debian, at least: -AC_CHECK_LIB(lockfile, maillock, have_lockfile=yes, have_lockfile=no) -if test $have_lockfile = yes; then - LIBS_MAIL=-llockfile - AC_DEFINE(HAVE_LIBLOCKFILE, 1, [Define to 1 if you have the 'lockfile' library (-llockfile).]) -else -# If we have the shared liblockfile, assume we must use it for mail -# locking (e.g. Debian). If we couldn't link against liblockfile -# (no liblockfile.a installed), ensure that we don't need to. - dnl This works for files generally, not just executables. - dnl Should we look elsewhere for it? Maybe examine /etc/ld.so.conf? - AC_CHECK_PROG(liblockfile, liblockfile.so, yes, no, - /usr/lib:/lib:/usr/local/lib:$LD_LIBRARY_PATH) - if test $ac_cv_prog_liblockfile = yes; then - AC_MSG_ERROR([Shared liblockfile found but can't link against it. +BLESSMAIL_TARGET= +LIBS_MAIL= +if test ! "$with_mailutils"; then + # Check for mail-locking functions in a "mail" library. Probably this should + # have the same check as for liblockfile below. + AC_CHECK_LIB([mail], [maillock], [have_mail=yes], [have_mail=no]) + if test $have_mail = yes; then + LIBS_MAIL=-lmail + AC_DEFINE([HAVE_LIBMAIL], [1], + [Define to 1 if you have the 'mail' library (-lmail).]) + + OLD_LIBS=$LIBS + LIBS="$LIBS_MAIL $LIBS" + AC_CHECK_FUNCS([touchlock]) + LIBS=$OLD_LIBS + fi + dnl Debian, at least: + AC_CHECK_LIB([lockfile], [maillock], [have_lockfile=yes], [have_lockfile=no]) + if test $have_lockfile = yes; then + LIBS_MAIL=-llockfile + AC_DEFINE([HAVE_LIBLOCKFILE], [1], + [Define to 1 if you have the 'lockfile' library (-llockfile).]) + else + # If we have the shared liblockfile, assume we must use it for mail + # locking (e.g. Debian). If we couldn't link against liblockfile + # (no liblockfile.a installed), ensure that we don't need to. + dnl This works for files generally, not just executables. + dnl Should we look elsewhere for it? Maybe examine /etc/ld.so.conf? + AC_CHECK_PROG([liblockfile], [liblockfile.so], [yes], [no], + [/usr/lib:/lib:/usr/local/lib:$LD_LIBRARY_PATH]) + if test "$ac_cv_prog_liblockfile" = yes; then + AC_MSG_ERROR([Shared liblockfile found but can't link against it. This probably means that movemail could lose mail. There may be a 'development' package to install containing liblockfile.]) + fi fi -fi -AC_CHECK_HEADERS_ONCE(maillock.h) -AC_SUBST(LIBS_MAIL) + AC_CHECK_HEADERS([maillock.h]) -## Define MAIL_USE_FLOCK (or LOCKF) if the mailer uses flock (or lockf) to -## interlock access to the mail spool. The alternative is a lock file named -## /usr/spool/mail/$USER.lock. -mail_lock=no -case "$opsys" in - aix4-2) mail_lock="lockf" ;; - - gnu|freebsd|dragonfly|netbsd|openbsd|darwin) mail_lock="flock" ;; - - ## On GNU/Linux systems, both methods are used by various mail programs. - ## I assume most people are using newer mailers that have heard of flock. - ## Change this if you need to. - ## Debian contains a patch which says: "On Debian/GNU/Linux systems, - ## configure gets the right answers, and that means *NOT* using flock. - ## Using flock is guaranteed to be the wrong thing. See Debian Policy - ## for details." and then uses '#ifdef DEBIAN'. Unfortunately the - ## Debian maintainer hasn't provided a clean fix for Emacs. - ## movemail.c will use 'maillock' when MAILDIR, HAVE_LIBMAIL and - ## HAVE_MAILLOCK_H are defined, so the following appears to be the - ## correct logic. -- fx - ## We must check for HAVE_LIBLOCKFILE too, as movemail does. - ## liblockfile is a Free Software replacement for libmail, used on - ## Debian systems and elsewhere. -rfr. - gnu-*) - mail_lock="flock" - if test $have_mail = yes || test $have_lockfile = yes; then - test $ac_cv_header_maillock_h = yes && mail_lock=no - fi - ;; + ## Define MAIL_USE_FLOCK (or LOCKF) if the mailer uses flock (or lockf) to + ## interlock access to the mail spool. The alternative is a lock file named + ## /usr/spool/mail/$USER.lock. + mail_lock=no + case $opsys in + aix4-2) mail_lock="lockf" ;; + + gnu|freebsd|dragonfly|netbsd|openbsd|darwin) mail_lock="flock" ;; + + ## On GNU/Linux systems, both methods are used by various mail programs. + ## I assume most people are using newer mailers that have heard of flock. + ## Change this if you need to. + ## Debian contains a patch which says: "On Debian/GNU/Linux systems, + ## configure gets the right answers, and that means *NOT* using flock. + ## Using flock is guaranteed to be the wrong thing. See Debian Policy + ## for details." and then uses '#ifdef DEBIAN'. Unfortunately the + ## Debian maintainer hasn't provided a clean fix for Emacs. + ## movemail.c will use 'maillock' when MAILDIR, HAVE_LIBMAIL and + ## HAVE_MAILLOCK_H are defined, so the following appears to be the + ## correct logic. -- fx + ## We must check for HAVE_LIBLOCKFILE too, as movemail does. + ## liblockfile is a Free Software replacement for libmail, used on + ## Debian systems and elsewhere. -rfr. + gnu-*) + mail_lock="flock" + if test $have_mail = yes || test $have_lockfile = yes; then + test $ac_cv_header_maillock_h = yes && mail_lock=no + fi ;; - mingw32) - mail_lock="none-needed" ;; -esac + mingw32) + mail_lock="none-needed" ;; + esac -BLESSMAIL_TARGET= -case "$mail_lock" in - flock) AC_DEFINE(MAIL_USE_FLOCK, 1, [Define if the mailer uses flock to interlock the mail spool.]) ;; + case $mail_lock in + flock) AC_DEFINE([MAIL_USE_FLOCK], [1], + [Define if the mailer uses flock to interlock the mail spool.]);; - lockf) AC_DEFINE(MAIL_USE_LOCKF, 1, [Define if the mailer uses lockf to interlock the mail spool.]) ;; + lockf) AC_DEFINE([MAIL_USE_LOCKF], [1], + [Define if the mailer uses lockf to interlock the mail spool.]);; - none-needed) ;; + none-needed) ;; - *) BLESSMAIL_TARGET="need-blessmail" ;; -esac -AC_SUBST(BLESSMAIL_TARGET) + *) BLESSMAIL_TARGET="need-blessmail" ;; + esac +fi +AC_SUBST([BLESSMAIL_TARGET]) +AC_SUBST([LIBS_MAIL]) OLD_LIBS=$LIBS LIBS="$LIB_PTHREAD $LIB_MATH $LIBS" AC_CHECK_FUNCS(accept4 fchdir gethostname \ getrusage get_current_dir_name \ -lrand48 random rint \ +lrand48 random rint trunc \ select getpagesize setlocale newlocale \ getrlimit setrlimit shutdown \ pthread_sigmask strsignal setitimer \ sendto recvfrom getsockname getifaddrs freeifaddrs \ gai_strerror sync \ getpwent endpwent getgrent endgrent \ -cfmakeraw cfsetspeed copysign __executable_start log2 prctl) +cfmakeraw cfsetspeed __executable_start log2 prctl) LIBS=$OLD_LIBS dnl No need to check for posix_memalign if aligned_alloc works. @@ -4164,7 +4242,7 @@ AC_CHECK_HEADERS(valgrind/valgrind.h) AC_CHECK_MEMBERS([struct unipair.unicode], [], [], [[#include <linux/kd.h>]]) -AC_CHECK_FUNCS_ONCE([sbrk tzset]) +AC_CHECK_FUNCS_ONCE([sbrk]) ok_so_far=yes AC_CHECK_FUNC(socket, , ok_so_far=no) @@ -4989,12 +5067,16 @@ else fi AC_SUBST(LIBX_OTHER) +HAVE_OLDXMENU=no if test "$HAVE_GTK" = yes || test "$HAVE_X11" != yes; then LIBXMENU= elif test "$USE_X_TOOLKIT" = none; then + HAVE_OLDXMENU=yes LIBXMENU='$(oldXMenudir)/libXMenu11.a' + AUTODEPEND_PARENTS="$AUTODEPEND_PARENTS oldXMenu" else LIBXMENU='$(lwlibdir)/liblw.a' + AUTODEPEND_PARENTS="$AUTODEPEND_PARENTS lwlib" fi AC_SUBST(LIBXMENU) @@ -5119,7 +5201,7 @@ AC_SUBST(CARGO_FLAGS) case "${opsys}" in darwin) RUST_DEPS="-ldl -lresolv" - REMACSLIB_CFLAGS="-pthread" ;; + REMACSLIB_CFLAGS="-pthread" ;; gnu*) RUST_DEPS="-ldl -lrt" REMACSLIB_CFLAGS="-pthread" ;; esac @@ -5312,7 +5394,7 @@ optsep= emacs_config_features= for opt in XAW3D XPM JPEG TIFF GIF PNG RSVG CAIRO IMAGEMAGICK SOUND GPM DBUS \ GCONF GSETTINGS NOTIFY ACL LIBSELINUX GNUTLS LIBXML2 FREETYPE M17N_FLT \ - LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS X_TOOLKIT X11 NS MODULES \ + LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS X_TOOLKIT OLDXMENU X11 NS MODULES \ XWIDGETS LIBSYSTEMD CANNOT_DUMP; do case $opt in @@ -5422,23 +5504,15 @@ if test "$HAVE_NS" = "yes"; then AC_SUBST(ns_check_file) fi +AC_CONFIG_FILES([Makefile lib/gnulib.mk]) + dnl config.status treats $srcdir specially, so I think this is ok... AC_CONFIG_FILES([$srcdir/doc/man/emacs.1]) -dnl Obviously there is duplication here wrt $SUBDIR_MAKEFILES. -dnl You _can_ use that variable in AC_CONFIG_FILES, so long as any directory -dnl using automake (ie lib/) is explicitly listed and not "hidden" in a variable -dnl (else you get "no 'Makefile.am' found for any configure output"). -dnl This will work, but you get a config.status that is not quite right -dnl (see http://lists.gnu.org/archive/html/bug-autoconf/2008-08/msg00028.html). -dnl That doesn't have any obvious consequences for Emacs, but on the whole -dnl it seems better to just live with the duplication. -SUBDIR_MAKEFILES="lib/Makefile lib-src/Makefile oldXMenu/Makefile doc/emacs/Makefile doc/misc/Makefile doc/lispintro/Makefile doc/lispref/Makefile src/Makefile lwlib/Makefile lisp/Makefile leim/Makefile nextstep/Makefile nt/Makefile" - -AC_CONFIG_FILES([Makefile lib/Makefile lib-src/Makefile oldXMenu/Makefile \ - doc/emacs/Makefile doc/misc/Makefile doc/lispintro/Makefile \ - doc/lispref/Makefile src/Makefile lwlib/Makefile lisp/Makefile \ - leim/Makefile nextstep/Makefile nt/Makefile]) +m4_define([subdir_makefiles], + [lib/Makefile lib-src/Makefile oldXMenu/Makefile doc/emacs/Makefile doc/misc/Makefile doc/lispintro/Makefile doc/lispref/Makefile src/Makefile lwlib/Makefile lisp/Makefile leim/Makefile nextstep/Makefile nt/Makefile]) +SUBDIR_MAKEFILES="subdir_makefiles" +AC_CONFIG_FILES(subdir_makefiles) dnl test/ is not present in release tarfiles. opt_makefile=test/Makefile @@ -5467,7 +5541,7 @@ AC_SUBST(SUBDIR_MAKEFILES_IN) dnl You might wonder (I did) why epaths.h is generated by running make, dnl rather than just letting configure generate it from epaths.in. dnl One reason is that the various paths are not fully expanded (see above); -dnl eg gamedir=${prefix}/var/games/emacs. +dnl e.g., gamedir='${localstatedir}/games/emacs'. dnl Secondly, the GNU Coding standards require that one should be able dnl to run 'make prefix=/some/where/else' and override the values set dnl by configure. This also explains the 'move-if-change' test and @@ -5508,6 +5582,34 @@ ${MAKE-make} -s MAKEFILE_NAME=do-not-make-Makefile etc-emacsver || \ AC_MSG_ERROR(['etc/refcards/emacsver.tex' could not be made.]) ]) +if test $AUTO_DEPEND = yes; then + for dir in $AUTODEPEND_PARENTS; do + AS_MKDIR_P([$dir/deps]) + done +fi + AC_OUTPUT +if test ! "$with_mailutils"; then + if test "$with_pop" = yes; then + AC_MSG_WARN([This configuration installs a 'movemail' program +that retrieves POP3 email via only insecure channels. +To omit insecure POP3, you can use '$0 --without-pop'.]) + fi + + case $opsys in + mingw32) + # Don't suggest GNU Mailutils, as it hasn't been ported. + ;; + *) + emacs_fix_movemail="use '$0 --with-mailutils'" + case `(movemail --version) 2>/dev/null` in + *Mailutils*) ;; + *) emacs_fix_movemail="install GNU Mailutils +<http://mailutils.org> and $emacs_fix_movemail";; + esac + AC_MSG_NOTICE([You might want to $emacs_fix_movemail.]);; + esac +fi + test "$MAKE" = make || AC_MSG_NOTICE([Now you can run '$MAKE'.]) diff --git a/doc/emacs/abbrevs.texi b/doc/emacs/abbrevs.texi index 8cb7a4838e9..117d07e2814 100644 --- a/doc/emacs/abbrevs.texi +++ b/doc/emacs/abbrevs.texi @@ -388,6 +388,9 @@ words that follow the expansion in its original context. Simply type @kbd{@key{SPC} M-/} for each additional word you want to copy. The spacing and punctuation between words is copied along with the words. + You can control the way @kbd{M-/} determines the word to expand and +how to expand it, see @ref{Dabbrev Customization}. + The command @kbd{C-M-/} (@code{dabbrev-completion}) performs completion of a dynamic abbrev. Instead of trying the possible expansions one by one, it finds all of them, then inserts the text @@ -437,12 +440,17 @@ copies the expansion verbatim including its case pattern. @vindex dabbrev-abbrev-char-regexp The variable @code{dabbrev-abbrev-char-regexp}, if non-@code{nil}, -controls which characters are considered part of a word, for dynamic expansion -purposes. The regular expression must match just one character, never -two or more. The same regular expression also determines which -characters are part of an expansion. The (default) value @code{nil} -has a special meaning: dynamic abbrevs are made of word characters, -but expansions are made of word and symbol characters. +controls which characters are considered part of a word, for dynamic +expansion purposes. The regular expression must match just one +character, never two or more. The same regular expression also +determines which characters are part of an expansion. The (default) +value @code{nil} has a special meaning: dynamic abbrevs (i.e.@: the +word at point) are made of word characters, but their expansions are +looked for as sequences of word and symbol characters. This is +generally appropriate for expanding symbols in a program source and +also for human-readable text in many languages, but may not be what +you want in a text buffer that includes unusual punctuation characters; +in that case, the value @code{"\\sw"} might produce better results. @vindex dabbrev-abbrev-skip-leading-regexp In shell scripts and makefiles, a variable name is sometimes prefixed diff --git a/doc/emacs/ack.texi b/doc/emacs/ack.texi index 1ebe852a3c6..8f592ec87a5 100644 --- a/doc/emacs/ack.texi +++ b/doc/emacs/ack.texi @@ -236,7 +236,7 @@ Andrew Cohen wrote @file{spam-wash.el}, to decode and clean email before it is analyzed for spam. @item -Edward O'Connor wrote @file{json.el}, a file for parsing and +Theresa O'Connor wrote @file{json.el}, a file for parsing and generating JSON files. @item diff --git a/doc/emacs/basic.texi b/doc/emacs/basic.texi index 6b66c18016b..5878e7da256 100644 --- a/doc/emacs/basic.texi +++ b/doc/emacs/basic.texi @@ -630,7 +630,8 @@ Display the line number of point. @item M-x line-number-mode @itemx M-x column-number-mode Toggle automatic display of the current line number or column number. -@xref{Optional Mode Line}. +@xref{Optional Mode Line}. If you want to have a line number +displayed before each line, see @ref{Display Custom}. @item M-= Display the number of lines, words, and characters that are present in diff --git a/doc/emacs/building.texi b/doc/emacs/building.texi index 8ce7f04022e..81496d02f1f 100644 --- a/doc/emacs/building.texi +++ b/doc/emacs/building.texi @@ -1478,7 +1478,9 @@ expression.) Emacs Lisp expression preceding point in the buffer, and displays the value in the echo area. When the result of an evaluation is an integer, it is displayed together with the value in other formats -(octal, hexadecimal, and character). +(octal, hexadecimal, and character if +@code{eval-expression-print-maximum-character}, described below, +allows it). If @kbd{M-:} or @kbd{C-x C-e} is given a prefix argument, it inserts the value into the current buffer at point, rather than displaying it @@ -1486,8 +1488,10 @@ in the echo area. If the prefix argument is zero, any integer output is inserted together with its value in other formats (octal, hexadecimal, and character). Such a prefix argument also prevents abbreviation of the output according to the variables -@code{eval-expression-print-level} and @code{eval-expression-print-length} -(see below). +@code{eval-expression-print-level} and +@code{eval-expression-print-length} (see below). Similarly, a prefix +argument of @code{-1} overrides the effect of +@code{eval-expression-print-length}. @kindex C-M-x @r{(Emacs Lisp mode)} @findex eval-defun @@ -1517,6 +1521,7 @@ eval-buffer} is similar but evaluates the entire buffer. @vindex eval-expression-print-level @vindex eval-expression-print-length +@vindex eval-expression-print-maximum-character @vindex eval-expression-debug-on-error The options @code{eval-expression-print-level} and @code{eval-expression-print-length} control the maximum depth and @@ -1526,6 +1531,8 @@ before abbreviating them. Supplying a zero prefix argument to printed in full. @code{eval-expression-debug-on-error} controls whether evaluation errors invoke the debugger when these commands are used; its default is @code{t}. +@code{eval-expression-print-maximum-character} prevents integers which +are larger than it from being displayed as characters. @node Lisp Interaction @section Lisp Interaction Buffers diff --git a/doc/emacs/cmdargs.texi b/doc/emacs/cmdargs.texi index f3618e31bff..a0a110b09f0 100644 --- a/doc/emacs/cmdargs.texi +++ b/doc/emacs/cmdargs.texi @@ -71,7 +71,7 @@ arguments.) * Font X:: Choosing a font for text, under X. * Colors X:: Choosing display colors. * Window Size X:: Start-up window size, under X. -* Borders X:: Internal and external borders, under X. +* Borders X:: Internal and outer borders, under X. * Title X:: Specifying the initial frame's title. * Icons X:: Choosing what sort of icon to use, under X. * Misc X:: Other display options. @@ -336,16 +336,16 @@ setting @code{inhibit-x-resources} to @code{t} (@pxref{Resources}). @opindex -daemon @itemx --daemon[=@var{name}] @opindex --daemon -@itemx --old-daemon[=@var{name}] -@itemx --new-daemon[=@var{name}] +@itemx --bg-daemon[=@var{name}] +@itemx --fg-daemon[=@var{name}] Start Emacs as a daemon---after Emacs starts up, it starts the Emacs server without opening any frames. (Optionally, you can specify an explicit @var{name} for the server.) You can then use the @command{emacsclient} command to connect to Emacs for editing. @xref{Emacs Server}, for information about using Emacs -as a daemon. An ``old-style'' daemon disconnects from the terminal +as a daemon. A ``background'' daemon disconnects from the terminal and runs in the background (@samp{--daemon} is an alias for -@samp{--old-daemon}). +@samp{--bg-daemon}). @item --no-desktop @opindex --no-desktop @@ -470,11 +470,11 @@ bus as well as autolaunching the D-Bus session bus if not running yet. Directory for the architecture-independent files that come with Emacs. This is used to initialize the variable @code{data-directory}. @item EMACSDOC -#vindex EMACSDOC, environment variable +@vindex EMACSDOC, environment variable Directory for the documentation string file, which is used to initialize the Lisp variable @code{doc-directory}. @item EMACSLOADPATH -#vindex EMACSLOADPATH, environment variable +@vindex EMACSLOADPATH, environment variable A colon-separated list of directories@footnote{Here and below, whenever we say ``colon-separated list of directories'', it pertains to Unix and GNU/Linux systems. On MS-Windows, the @@ -1017,15 +1017,15 @@ program-specified and user-specified positions. If these are set, Emacs fails to position the window correctly. @node Borders X -@appendixsec Internal and External Borders +@appendixsec Internal and Outer Borders @cindex borders (X Window System) - An Emacs frame has an internal border and an external border. The + An Emacs frame has an internal border and an outer border. The internal border is an extra strip of the background color around the -text portion of the frame. Emacs itself draws the internal border. -The external border is added by the window manager outside the frame; -depending on the window manager you use, it may contain various boxes -you can click on to move or iconify the window. +text portion of the frame. Emacs itself draws the internal border. The +outer border is drawn by X outside the tool and menu bars of the frame. +There is also an external border which is drawn by the window manager. +The size of the external border cannot be set from within Emacs. @table @samp @item -ib @var{width} @@ -1033,15 +1033,16 @@ you can click on to move or iconify the window. @itemx --internal-border=@var{width} @opindex --internal-border @cindex internal border width, command-line argument -Specify @var{width} as the width of the internal border (between the text -and the main border), in pixels. +Specify @var{width} as the width of the internal border (around the +frame's text area), in pixels. @item -bw @var{width} @opindex -bw @itemx --border-width=@var{width} @opindex --border-width @cindex main border width, command-line argument -Specify @var{width} as the width of the main border, in pixels. +@cindex outer border width, command-line argument +Specify @var{width} as the width of the outer border, in pixels. @end table When you specify the size of the frame, that does not count the @@ -1050,9 +1051,9 @@ external border. Use the @samp{-ib @var{n}} option to specify an internal border @var{n} pixels wide. The default is 1. Use @samp{-bw @var{n}} to -specify the width of the external border (though the window manager may -not pay attention to what you specify). The default width of the -external border is 2. +specify the width of the outer border (though the window manager may not +pay attention to what you specify). The default width of the outer +border is 2. @node Title X @appendixsec Frame Titles diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi index 0b6ab373752..06024fd0133 100644 --- a/doc/emacs/custom.texi +++ b/doc/emacs/custom.texi @@ -1698,7 +1698,6 @@ and mouse events: (global-set-key (kbd "C-c y") 'clipboard-yank) (global-set-key (kbd "C-M-q") 'query-replace) (global-set-key (kbd "<f5>") 'flyspell-mode) -(global-set-key (kbd "C-<f5>") 'linum-mode) (global-set-key (kbd "C-<right>") 'forward-sentence) (global-set-key (kbd "<mouse-2>") 'mouse-save-then-kill) @end example diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi index 1f3db1295d7..5dcc7558da6 100644 --- a/doc/emacs/dired.texi +++ b/doc/emacs/dired.texi @@ -875,25 +875,31 @@ treat it specially. @item Otherwise, if the command string contains @samp{?} surrounded by -whitespace, Emacs runs the shell command once @emph{for each file}, -substituting the current file name for @samp{?} each time. You can -use @samp{?} more than once in the command; the same file name -replaces each occurrence. +whitespace or @samp{`?`}, Emacs runs the shell command once +@emph{for each file}, substituting the current file name for @samp{?} +and @samp{`?`} each time. You can use both @samp{?} or @samp{`?`} more +than once in the command; the same file name replaces each occurrence. +If you mix them with @samp{*} the command signals an error. @item -If the command string contains neither @samp{*} nor @samp{?}, Emacs -runs the shell command once for each file, adding the file name at the +If the command string contains neither @samp{*} nor @samp{?} nor @samp{`?`}, +Emacs runs the shell command once for each file, adding the file name at the end. For example, @kbd{! uudecode @key{RET}} runs @code{uudecode} on each file. @end itemize - To iterate over the file names in a more complicated fashion, use an -explicit shell loop. For example, here is how to uuencode each file, -making the output file name by appending @samp{.uu} to the input file -name: + To iterate over the file names in a more complicated fashion, you might +prefer to use an explicit shell loop. For example, here is how to uuencode +each file, making the output file name by appending @samp{.uu} to the input +file name: @example for file in * ; do uuencode "$file" "$file" >"$file".uu; done +@end example + +The same example with @samp{`?`} notation: +@example +uuencode ? ? > `?`.uu @end example The @kbd{!} and @kbd{&} commands do not attempt to update the Dired diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index 15c700892bc..083fcdf97a6 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi @@ -308,7 +308,11 @@ displayed. When the text in a window is scrolled horizontally, text lines are truncated rather than continued (@pxref{Line Truncation}). If a window shows truncated lines, Emacs performs automatic horizontal scrolling whenever point moves off the left or right edge of the -screen. To disable automatic horizontal scrolling, set the variable +screen. By default, all the lines in the window are scrolled +horizontally together, but if you set the variable +@code{auto-hscroll-mode} to the special value of @code{current-line}, +only the line showing the cursor will be scrolled. To disable +automatic horizontal scrolling entirely, set the variable @code{auto-hscroll-mode} to @code{nil}. Note that when the automatic horizontal scrolling is turned off, if point moves off the edge of the screen, the cursor disappears to indicate that. (On text terminals, @@ -366,7 +370,10 @@ sufficiently large argument will restore the normal display. If you use those commands to scroll a window horizontally, that sets a lower bound for automatic horizontal scrolling. Automatic scrolling will continue to scroll the window, but never farther to the right -than the amount you previously set by @code{scroll-left}. +than the amount you previously set by @code{scroll-left}. When +@code{auto-hscroll-mode} is set to @code{current-line}, all the lines +other than the one showing the cursor will be scrolled by that minimal +amount. @node Narrowing @section Narrowing @@ -1326,7 +1333,7 @@ characters in the buffer, which means that @samp{k} for 10^3, @samp{M} for 10^6, @samp{G} for 10^9, etc., are used to abbreviate. @cindex line number display -@cindex display of line number +@cindex display of current line number @findex line-number-mode The current line number of point appears in the mode line when Line Number mode is enabled. Use the command @kbd{M-x line-number-mode} to @@ -1338,13 +1345,19 @@ indicate what it is. @cindex mode, Column Number @findex column-number-mode Similarly, you can display the current column number by turning on -Column number mode with @kbd{M-x column-number-mode}. The column +Column Number mode with @kbd{M-x column-number-mode}. The column number is indicated by the letter @samp{C}. However, when both of these modes are enabled, the line and column numbers are displayed in parentheses, the line number first, rather than with @samp{L} and @samp{C}. For example: @samp{(561,2)}. @xref{Minor Modes}, for more information about minor modes and about how to use these commands. +@vindex column-number-indicator-zero-based + In Column Number mode, the displayed column number counts from zero +starting at the left margin of the window. If you would prefer for +the displayed column number to count from one, you may set +@code{column-number-indicator-zero-based} to @code{nil}. + @cindex narrowing, and line number display If you have narrowed the buffer (@pxref{Narrowing}), the displayed line number is relative to the accessible portion of the buffer. @@ -1697,6 +1710,66 @@ variable @code{visual-line-fringe-indicators}. This section describes variables that control miscellaneous aspects of the appearance of the Emacs screen. Beginning users can skip it. +@vindex display-line-numbers +@cindex number lines in a buffer +@cindex display line numbers + If you want to have Emacs display line numbers for every line in the +buffer, customize the buffer-local variable +@code{display-line-numbers}; it is @code{nil} by default. This +variable can have several different values to support various modes of +line-number display: + +@table @asis +@item @code{t} +Display (an absolute) line number before each non-continuation screen +line that displays buffer text. If the line is a continuation line, +or if the entire screen line displays a display or an overlay string, +that line will not be numbered. + +@item @code{relative} +Display relative line numbers before non-continuation lines which show +buffer text. The line numbers are relative to the line showing point, +so the numbers grow both up and down as lines become farther from the +current line. + +@item @code{visual} +This value causes Emacs to count lines visually: only lines actually +shown on the display will be counted (disregarding any lines in +invisible parts of text), and lines which wrap to consume more than +one screen line will be numbered that many times. The displayed +numbers are relative, as with @code{relative} value above. This is +handy in modes that fold text, such as Outline mode (@pxref{Outline +Mode}), and need to move by exact number of screen lines. + +@item anything else +Any other non-@code{nil} value is treated as @code{t}. +@end table + +@vindex display-line-numbers-current-absolute +When Emacs displays relative line numbers, you can control the number +displayed before the current line, the line showing point. By +default, Emacs displays the absolute number of the current line there, +even though all the other line numbers are relative. If you customize +the variable @code{display-line-numbers-current-absolute} to a +@code{nil} value, the number displayed for the current line will be +zero. This is handy if you don't care about the number of the current +line, and want to leave more horizontal space for text in large +buffers. + +@vindex display-line-numbers-widen +In a narrowed buffer (@pxref{Narrowing}) lines are normally numbered +starting at the beginning of the narrowing. However, if you customize +the variable @code{display-line-numbers-widen} to a non-@code{nil} +value, line numbers will disregard any narrowing and will start at the +first character of the buffer. + +@cindex line-number face +The line numbers are displayed in a special face @code{line-number}. +The current line number is displayed in a different face, +@code{line-number-current-line}, so you can make the current line's +number have a distinct appearance, which will help locating the line +showing point. + @vindex visible-bell If the variable @code{visible-bell} is non-@code{nil}, Emacs attempts to make the whole screen blink when it would normally make an audible bell @@ -1750,3 +1823,9 @@ itself, in pixels; the default is 2. in text that is hard to read. Call the function @code{tty-suppress-bold-inverse-default-colors} with a non-@code{nil} argument to suppress the effect of bold-face in this case. + +@vindex display-raw-bytes-as-hex + Raw bytes are displayed in octal format by default, for example a +byte with a decimal value of 128 is displayed as @code{\200}. To +change display to the hexadecimal format of @code{\x80}, set the +variable @code{display-raw-bytes-as-hex} to @code{t}. diff --git a/doc/emacs/emacs-xtra.texi b/doc/emacs/emacs-xtra.texi index 94f25de350b..44dfc5b4eb0 100644 --- a/doc/emacs/emacs-xtra.texi +++ b/doc/emacs/emacs-xtra.texi @@ -9,6 +9,10 @@ @syncodeindex ky cp @comment %**end of header +@c This is a separate manual to avoid making the Emacs User manual too +@c large in print. In the Info format, the chapters included below +@c are part of the Emacs User manual. + @copying This manual describes specialized features of Emacs. diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi index e560b44919e..3dfdb3ade1a 100644 --- a/doc/emacs/emacs.texi +++ b/doc/emacs/emacs.texi @@ -1082,6 +1082,7 @@ Shell Command History Using Emacs as a Server +* TCP Emacs server:: Listening to a TCP socket. * Invoking emacsclient:: Connecting to the Emacs server. * emacsclient Options:: Emacs client startup options. @@ -1198,7 +1199,7 @@ Command Line Arguments for Emacs Invocation * Font X:: Choosing a font for text, under X. * Colors X:: Choosing display colors. * Window Size X:: Start-up window size, under X. -* Borders X:: Internal and external borders, under X. +* Borders X:: Internal and outer borders, under X. * Title X:: Specifying the initial frame's title. * Icons X:: Choosing what sort of icon to use, under X. * Misc X:: Other display options. @@ -1437,7 +1438,7 @@ Monnier, Keith Moore, Jan Moringen, Morioka Tomohiko, Glenn Morris, Don Morrison, Diane Murray, Riccardo Murri, Sen Nagata, Erik Naggum, Gergely Nagy, Nobuyoshi Nakada, Thomas Neumann, Mike Newton, Thien-Thi Nguyen, Jurgen Nickelsen, Dan Nicolaescu, Hrvoje Nikšić, Jeff Norden, -Andrew Norman, Edward O'Connor, Kentaro Ohkouchi, Christian Ohler, +Andrew Norman, Theresa O'Connor, Kentaro Ohkouchi, Christian Ohler, Kenichi Okada, Alexandre Oliva, Bob Olson, Michael Olson, Takaaki Ota, Pieter E. J. Pareit, Ross Patterson, David Pearson, Juan Pechiar, Jeff Peck, Damon Anton Permezel, Tom Perrine, William M. Perry, Per diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index 24bff7d76ed..7da919baf61 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -1040,12 +1040,23 @@ useful if it contains the deleted text. To reenable auto-saving after this happens, save the buffer with @kbd{C-x C-s}, or use @kbd{C-u 1 M-x auto-save-mode}. -@vindex auto-save-visited-file-name +@vindex auto-save-visited-mode If you want auto-saving to be done in the visited file rather than -in a separate auto-save file, set the variable -@code{auto-save-visited-file-name} to a non-@code{nil} value. In this -mode, there is no real difference between auto-saving and explicit -saving. +in a separate auto-save file, enable the global minor mode +@code{auto-save-visited-mode}. In this mode, auto-saving is identical +to explicit saving. Note that this mode is orthogonal to the +@code{auto-save} mode described above; you can enable both at the same +time. However, if @code{auto-save} mode is active in some buffer and +the obsolete @code{auto-save-visited-file-name} variable is set to a +non-@code{nil} value, that buffer won't be affected by +@code{auto-save-visited-mode}. + + You can use the variable @code{auto-save-visited-interval} to +customize the interval between auto-save operations in +@code{auto-save-visited-mode}; by default it's five seconds. +@code{auto-save-interval} and @code{auto-save-timeout} have no effect +on @code{auto-save-visited-mode}. @xref{Auto Save Control}, for +details on these variables. @vindex delete-auto-save-files A buffer's auto-save file is deleted when you save the buffer in its @@ -1089,6 +1100,12 @@ makes sure all your work is saved if you go away from the terminal for a while; second, it may avoid some auto-saving while you are actually typing. +@vindex auto-save-visited-interval + When @code{auto-save-visited-mode} is enabled, Emacs will auto-save +file-visiting buffers after five seconds of idle time. You can +customize the variable @code{auto-save-visited-interval} to change the +idle time interval. + Emacs also does auto-saving whenever it gets a fatal error. This includes killing the Emacs job with a shell command such as @samp{kill %emacs}, or disconnecting a phone line or network connection. @@ -1776,9 +1793,7 @@ syntax: @example @group -/@var{host}:@var{filename} -/@var{user}@@@var{host}:@var{filename} -/@var{user}@@@var{host}#@var{port}:@var{filename} +/@var{method}:@var{host}:@var{filename} /@var{method}:@var{user}@@@var{host}:@var{filename} /@var{method}:@var{user}@@@var{host}#@var{port}:@var{filename} @end group @@ -1787,11 +1802,11 @@ syntax: @noindent To carry out this request, Emacs uses a remote-login program such as @command{ftp}, @command{ssh}, @command{rlogin}, or @command{telnet}. -You can always specify in the file name which method to use---for +You must always specify in the file name which method to use---for example, @file{/ftp:@var{user}@@@var{host}:@var{filename}} uses FTP, whereas @file{/ssh:@var{user}@@@var{host}:@var{filename}} uses -@command{ssh}. When you don't specify a method in the file name, -Emacs chooses the method as follows: +@command{ssh}. When you specify the pseudo method @var{-} in the file +name, Emacs chooses the method as follows: @enumerate @item @@ -1883,7 +1898,7 @@ can refer to that file in Emacs as @samp{/:/foo:/bar}. If you want to quote only special characters in the local part of a remote file name, you can quote just the local part. -@samp{/baz:/:/foo:/bar} refers to the file @file{bar} of directory +@samp{/ssh:baz:/:/foo:/bar} refers to the file @file{bar} of directory @file{/foo:} on the host @file{baz}. @samp{/:} can also prevent @samp{~} from being treated as a special @@ -2053,7 +2068,7 @@ as a @dfn{fileset}. This lets you perform certain operations, such as visiting, @code{query-replace}, and shell commands on all the files at once. To make use of filesets, you must first add the expression @code{(filesets-init)} to your init file (@pxref{Init File}). This -adds a @samp{Filesets} menu to the menu bar. +adds a @samp{Filesets} sub-menu to the menu bar's @samp{File} menu. @findex filesets-add-buffer @findex filesets-remove-buffer diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index 92c62f4736e..efe8cd664ea 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -200,6 +200,15 @@ buffers are scrolled. The variable @code{mouse-wheel-progressive-speed} determines whether the scroll speed is linked to how fast you move the wheel. +@vindex mwheel-tilt-scroll-p +@vindex mwheel-flip-direction +Emacs can also support horizontal scrolling if your mouse's wheel can +be tilted. This feature is off by default; the variable +@code{mwheel-tilt-scroll-p} turns it on. If you'd like to reverse the +direction of horizontal scrolling, customize the variable +@code{mwheel-flip-direction} to a non-@code{nil} value. + + @node Word and Line Mouse @section Mouse Commands for Words and Lines @@ -1058,6 +1067,18 @@ file on a Dired buffer moves or copies the file (according to the conventions of the application it came from) into the directory displayed in that buffer. +@vindex mouse-drag-and-drop-region + Emacs can also optionally drag the region of text by mouse into +another portion of this or another buffer. To enable that, customize +the variable @code{mouse-drag-and-drop-region} to a non-nil value. +Normally, the text is moved, i.e. cut and pasted, when the destination +is the same buffer as the origin; dropping the region on another +buffer copies the text instead. If the value of this variable names a +modifier key, such as @samp{shift} or @samp{control} or @samp{alt}, +then pressing that modifier key when dropping the text will copy it +instead of cutting it, even if you drop on the same buffer as the one +from which the text came. + @vindex dnd-open-file-other-window Dropping a file normally visits it in the window you drop it on. If you prefer to visit the file in a new window in such cases, customize @@ -1125,6 +1146,12 @@ specific tool bar style, customize the variable @code{tool-bar-style}. bar with the frame parameter @code{tool-bar-position}. @xref{Frame Parameters,,, elisp, The Emacs Lisp Reference Manual}. + NS builds consider the tool bar to be a window decoration, and +therefore do not display it when a window is undecorated. @xref{Frame +Parameters,,, elisp, The Emacs Lisp Reference Manual}. On macOS the +tool bar is hidden when the frame is put into fullscreen, but can be +displayed by moving the mouse pointer to the top of the screen. + @node Dialog Boxes @section Using Dialog Boxes @cindex dialog boxes diff --git a/doc/emacs/help.texi b/doc/emacs/help.texi index 548ca6a1b48..fd6df1c7e53 100644 --- a/doc/emacs/help.texi +++ b/doc/emacs/help.texi @@ -203,9 +203,10 @@ string}, which describes exactly what the command does. describes the command corresponding to @var{key}. @kbd{C-h c}, @kbd{C-h k} and @kbd{C-h K} work for any sort of key -sequences, including function keys, menus, and mouse events. For -instance, after @kbd{C-h k} you can select a menu item from the menu -bar, to view the documentation string of the command it runs. +sequences, including function keys, menus, and mouse events (except +that @kbd{C-h c} ignores mouse movement events). For instance, after +@kbd{C-h k} you can select a menu item from the menu bar, to view the +documentation string of the command it runs. @kindex C-h w @findex where-is diff --git a/doc/emacs/killing.texi b/doc/emacs/killing.texi index 47de0531292..5165881739f 100644 --- a/doc/emacs/killing.texi +++ b/doc/emacs/killing.texi @@ -519,6 +519,10 @@ when exiting Emacs; if you wish to prevent Emacs from transferring data to the clipboard manager, change the variable @code{x-select-enable-clipboard-manager} to @code{nil}. + Since strings containing NUL bytes are usually truncated when passed +through the clipboard, Emacs replaces such characters with ``\0'' +before transferring them to the system's clipboard. + @vindex select-enable-primary @findex clipboard-kill-region @findex clipboard-kill-ring-save diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index 13fe754d4c6..0f84de7fa32 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -56,6 +56,7 @@ versions of a source file, storing information such as the creation time of each version, who made it, and a description of what was changed. +@cindex VC The Emacs version control interface is called @dfn{VC}@. VC commands work with several different version control systems; currently, it supports Bazaar, CVS, Git, Mercurial, Monotone, RCS, diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi index bcc20a6db16..84681f2269a 100644 --- a/doc/emacs/misc.texi +++ b/doc/emacs/misc.texi @@ -1661,10 +1661,68 @@ expression @code{(+ 1 2)} on the @samp{foo} server, and returns signaled.) Currently, this feature is mainly useful for developers. @menu +* TCP Emacs server:: Listening to a TCP socket. * Invoking emacsclient:: Connecting to the Emacs server. * emacsclient Options:: Emacs client startup options. @end menu +@node TCP Emacs server +@subsection TCP Emacs server +@cindex TCP Emacs server + +@vindex server-use-tcp + An Emacs server usually listens to connections on a local Unix +domain socket. Some operating systems, such as MS-Windows, do not +support local sockets; in that case, the server uses TCP sockets +instead. In some cases it is useful to have the server listen on a +TCP socket even if local sockets are supported, e.g., if you need to +contact the Emacs server from a remote machine. You can set +@code{server-use-tcp} to non-@code{nil} to have Emacs listen on a TCP +socket instead of a local socket. This is the default if your OS does +not support local sockets. + +@vindex server-host +@vindex server-port + If the Emacs server is set to use TCP, it will by default listen to +a random port on the localhost interface. This can be changed to +another interface and/or a fixed port using the variables +@code{server-host} and @code{server-port}. + +@vindex server-auth-key + A TCP socket is not subject to file system permissions. To retain +some control over which users can talk to an Emacs server over TCP +sockets, the @command{emacsclient} program must send an authorization +key to the server. This key is normally randomly generated by the +Emacs server. This is the recommended mode of operation. + +@findex server-generate-key + If needed, you can set the authorization key to a static value by +setting the @code{server-auth-key} variable. The key must consist of +64 ASCII printable characters except for space (this means characters +from @samp{!} to @samp{~}, or from decimal code 33 to 126). You can +use @kbd{M-x server-generate-key} to get a random key. + +@vindex server-auth-dir +@cindex server file + When you start a TCP Emacs server, Emacs creates a @dfn{server file} +containing the TCP information to be used by @command{emacsclient} to +connect to the server. The variable @code{server-auth-dir} specifies +the directory containing the server file; by default, this is +@file{~/.emacs.d/server/}. In the absence of a local socket with file +permissions, the permissions of this directory determine which users +can have their @command{emacsclient} processes talk to the Emacs +server. + +@vindex EMACS_SERVER_FILE@r{, environment variable} + To tell @command{emacsclient} to connect to the server over TCP with +a specific server file, use the @samp{-f} or @samp{--server-file} +option, or set the @env{EMACS_SERVER_FILE} environment variable +(@pxref{emacsclient Options}). If @code{server-auth-dir} is set to a +non-standard value, @command{emacsclient} needs an absolute file name +to the server file, as the default @code{server-auth-dir} is +hard-coded in @command{emacsclient} to be used as the directory for +resolving relative filenames. + @node Invoking emacsclient @subsection Invoking @code{emacsclient} @cindex @code{emacsclient} invocation @@ -1810,25 +1868,18 @@ evaluate, @emph{not} as a list of files to visit. @item -f @var{server-file} @itemx --server-file=@var{server-file} -@cindex @env{EMACS_SERVER_FILE} environment variable -Specify a @dfn{server file} for connecting to an Emacs server via TCP. - -An Emacs server usually uses a -local socket to listen for connections. Some operating systems, -such as Microsoft Windows, do not support local sockets; in that case, -the server communicates with @command{emacsclient} via TCP. - -@vindex server-auth-dir -@cindex server file -@vindex server-port -When you start a TCP Emacs server, Emacs creates a @dfn{server file} -containing the TCP information to be used by @command{emacsclient} to -connect to the server. The variable @code{server-auth-dir} specifies -the directory containing the server file; by default, this is -@file{~/.emacs.d/server/}. To tell @command{emacsclient} to connect -to the server over TCP with a specific server file, use the @samp{-f} -or @samp{--server-file} option, or set the @env{EMACS_SERVER_FILE} -environment variable. +Specify a server file (@pxref{TCP Emacs server}) for connecting to an +Emacs server via TCP. Alternatively, you can set the +@env{EMACS_SERVER_FILE} environment variable to point to the server +file. + +An Emacs server usually uses a local socket to listen for connections, +but also supports connections over TCP. To connect to a TCP Emacs +server, @command{emacsclient} needs to read a @dfn{server file} +containing the connection details of the Emacs server. The name of +this file is specified with this option, either as a file name +relative to @file{~/.emacs.d/server} or as an absolute file name. +@xref{TCP Emacs server}. @item -n @itemx --no-wait @@ -1872,6 +1923,37 @@ On MS-Windows, @samp{-t} behaves just like @samp{-c} if the Emacs server is using the graphical display, but if the Emacs server is running on a text terminal, it creates a new frame in the current text terminal. + +@item -T @var{tramp-prefix} +@itemx --tramp-prefix=@var{tramp-prefix} +Set the prefix to add to filenames for Emacs to locate files on remote +machines using TRAMP (@pxref{Top, The Tramp Manual,, tramp, The Tramp +Manual}). This is mostly useful in combination with using the Emacs +server over TCP (@pxref{TCP Emacs server}). By ssh-forwarding the +listening port and making the @var{server-file} available on a remote +machine, programs on the remote machine can use @command{emacsclient} +as the value for the @env{EDITOR} and similar environment variables, +but instead of talking to an Emacs server on the remote machine, the +files will be visited in the local Emacs session using TRAMP. + +@vindex EMACSCLIENT_TRAMP@r{, environment variable} +Setting the environment variable @env{EMACSCLIENT_TRAMP} has the same +effect as using the @samp{-T} option. If both are specified, the +command-line option takes precedence. + +For example, assume two hosts, @samp{local} and @samp{remote}, and +that the local Emacs listens on tcp port 12345. Assume further that +@file{/home} is on a shared file system, so that the server file +@file{~/.emacs.d/server/server} is readable on both hosts. + +@example +local$ ssh -R12345:localhost:12345 remote +remote$ export EDITOR="emacsclient \ + --server-file=server \ + --tramp=/ssh:remote:" +remote$ $EDITOR /tmp/foo.txt #Should open in local emacs. +@end example + @end table The new graphical or text terminal frames created by the @samp{-c} diff --git a/doc/emacs/modes.texi b/doc/emacs/modes.texi index 0acb82dc914..eb0c88b2901 100644 --- a/doc/emacs/modes.texi +++ b/doc/emacs/modes.texi @@ -66,7 +66,10 @@ process (@pxref{Interactive Shell}). first visit a file or create a buffer (@pxref{Choosing Modes}). You can explicitly select a new major mode by using an @kbd{M-x} command. Take the name of the mode and add @code{-mode} to get the name of the -command to select that mode (e.g., @kbd{M-x lisp-mode} enters Lisp mode). +command to select that mode (e.g., @kbd{M-x lisp-mode} enters Lisp +mode). Since every buffer has exactly one major mode, there is no way +to ``turn off'' a major mode; instead you must switch to a different +one. @vindex major-mode The value of the buffer-local variable @code{major-mode} is a symbol @@ -222,11 +225,6 @@ Font-Lock mode automatically highlights certain textual units found in programs. It is enabled globally by default, but you can disable it in individual buffers. @xref{Faces}. -@findex linum-mode -@cindex Linum mode -@item -Linum mode displays each line's line number in the window's left margin. - @item Outline minor mode provides similar facilities to the major mode called Outline mode. @xref{Outline Mode}. diff --git a/doc/emacs/mule.texi b/doc/emacs/mule.texi index eeff63d7378..bf7624be4cd 100644 --- a/doc/emacs/mule.texi +++ b/doc/emacs/mule.texi @@ -553,6 +553,15 @@ most input methods---some disable this feature). If possible characters to type next is displayed in the echo area (but not when you are in the minibuffer). +@vindex quail-activate-hook +@findex quail-translation-keymap + You can modify how an input method works by making your changes in a +function that you add to the hook variable @code{quail-activate-hook}. +@xref{Hooks}. For example, you can redefine some of the input +method's keys by defining key bindings in the keymap returned by the +function @code{quail-translation-keymap}, using @code{define-key}. +@xref{Init Rebinding}. + Another facility for typing characters not on your keyboard is by using @kbd{C-x 8 @key{RET}} (@code{insert-char}) to insert a single character based on its Unicode name or code-point; see @ref{Inserting @@ -1785,8 +1794,12 @@ of the first character you read precedes that of the next character. Reordering of bidirectional text into the @dfn{visual} order happens at display time. As result, character positions no longer increase monotonically with their positions on display. Emacs implements the -Unicode Bidirectional Algorithm described in the Unicode Standard -Annex #9, for reordering of bidirectional text for display. +Unicode Bidirectional Algorithm (UBA) described in the Unicode +Standard Annex #9, for reordering of bidirectional text for display. +It deviates from the UBA only in how continuation lines are displayed +when text direction is opposite to the base paragraph direction, +e.g. when a long line of English text appears in a right-to-left +paragraph. @vindex bidi-display-reordering The buffer-local variable @code{bidi-display-reordering} controls diff --git a/doc/emacs/package.texi b/doc/emacs/package.texi index d6f88aaec3c..ecc955d3efe 100644 --- a/doc/emacs/package.texi +++ b/doc/emacs/package.texi @@ -193,15 +193,22 @@ and use only third parties that you think you can trust! can have in their packages by @dfn{signing} them. They generate a private/public pair of cryptographic keys, and use the private key to create a @dfn{signature file} for each package. With the public key, you -can use the signature files to verify who created the package, and -that it has not been modified. A valid signature is not a cast-iron +can use the signature files to verify the package creator and make sure +the package has not been tampered with. Signature verification uses +@uref{https://www.gnupg.org/, the GnuPG package} via the EasyPG +interface (@pxref{Top,, EasyPG, epa, Emacs EasyPG Assistant Manual}). +A valid signature is not a cast-iron guarantee that a package is not malicious, so you should still exercise caution. Package archives should provide instructions on how you can obtain their public key. One way is to download the key from a server such as @url{http://pgp.mit.edu/}. Use @kbd{M-x package-import-keyring} to import the key into Emacs. -Emacs stores package keys in the @file{gnupg} subdirectory -of @code{package-user-dir}. +Emacs stores package keys in the directory specified by the variable +@code{package-gnupghome-dir}, by default in the @file{gnupg} +subdirectory of @code{package-user-dir}, which causes Emacs to invoke +GnuPG with the option @samp{--homedir} when verifying signatures. +If @code{package-gnupghome-dir} is @code{nil}, GnuPG's option +@samp{--homedir} is omitted. The public key for the GNU package archive is distributed with Emacs, in the @file{etc/package-keyring.gpg}. Emacs uses it automatically. diff --git a/doc/emacs/programs.texi b/doc/emacs/programs.texi index ad55d37a867..65ce13a33ed 100644 --- a/doc/emacs/programs.texi +++ b/doc/emacs/programs.texi @@ -248,11 +248,15 @@ the same as @kbd{C-M-a} with a positive argument. (@code{mark-defun}), which sets the mark at the end of the current defun and puts point at its beginning. @xref{Marking Objects}. This is the easiest way to get ready to kill the defun in order to move it -to a different place in the file. If you use the command while point -is between defuns, it uses the following defun. If you use the -command while the mark is already active, it sets the mark but does -not move point; furthermore, each successive use of @kbd{C-M-h} -extends the end of the region to include one more defun. +to a different place in the file. If the defun is directly preceded +by comments (with no intervening blank lines), they are marked, too. +If you use the command while point is between defuns, it uses the +following defun. If you use the command while the mark is already +active, it extends the end of the region to include one more defun. +With a prefix argument, it marks that many defuns or extends the +region by the appropriate number of defuns. With negative prefix +argument it marks defuns in the opposite direction and also changes +the direction of selecting for subsequent uses of @code{mark-defun}. In C mode, @kbd{C-M-h} runs the function @code{c-mark-function}, which is almost the same as @code{mark-defun}; the difference is that @@ -327,7 +331,7 @@ as you move around in a buffer. @vindex which-func-modes To either enable or disable Which Function mode, use the command @kbd{M-x which-function-mode}. Which Function mode is a global minor -mode. By default, it takes effect in all major modes major modes that +mode. By default, it takes effect in all major modes that know how to support it (i.e., all the major modes that support Imenu). You can restrict it to a specific list of major modes by changing the value of the variable @code{which-func-modes} from @@ -1142,9 +1146,12 @@ comment or for aligning an existing comment. It is set differently by various major modes. The function is called with no arguments, but with point at the beginning of the comment, or at the end of a line if a new comment is to be inserted. It should return the column in which the -comment ought to start. For example, in Lisp mode, the indent hook -function bases its decision on how many semicolons begin an existing -comment, and on the code in the preceding lines. +comment ought to start. For example, the default hook function bases +its decision on how many comment characters begin an existing comment. + +Emacs also tries to align comments on adjacent lines. To override +this, the function may return a cons of two (possibly equal) integers +to indicate an acceptable range of indentation. @node Documentation @section Documentation Lookup diff --git a/doc/emacs/rmail.texi b/doc/emacs/rmail.texi index d46398281fb..046087ef452 100644 --- a/doc/emacs/rmail.texi +++ b/doc/emacs/rmail.texi @@ -329,7 +329,7 @@ adding or removing this attribute. @xref{Rmail Attributes}. When you receive mail locally, the operating system places incoming mail for you in a file that we call your @dfn{inbox}. When you start -up Rmail, it runs a C program called @code{movemail} to copy the new +up Rmail, it runs a C program called @command{movemail} to copy the new messages from your local inbox into your primary Rmail file, which also contains other messages saved from previous Rmail sessions. It is in this file that you actually read the mail with Rmail. This @@ -397,7 +397,7 @@ check your mail via POP while traveling, so that your mail will remain on the server and you can save it later on your workstation. In some cases, Rmail copies the new mail from the inbox file -indirectly. First it runs the @code{movemail} program to move the mail +indirectly. First it runs the @command{movemail} program to move the mail from the inbox to an intermediate file called @file{.newmail-@var{inboxname}}, in the same directory as the Rmail file. Then Rmail merges the new mail from that file, saves the Rmail @@ -1373,22 +1373,24 @@ rot13-other-window}. This displays the current buffer in another window which applies the code when displaying the text. @node Movemail -@section @code{movemail} program -@cindex @code{movemail} program +@section @command{movemail} program +@cindex @command{movemail} program - Rmail uses the @code{movemail} program to move mail from your inbox to + Rmail uses the @command{movemail} program to move mail from your inbox to your Rmail file (@pxref{Rmail Inbox}). When loaded for the first time, -Rmail attempts to locate the @code{movemail} program and determine its -version. There are two versions of the @code{movemail} program: the -native one, shipped with GNU Emacs (the Emacs version) and the one -included in GNU mailutils (the mailutils version, -@pxref{movemail,,,mailutils,GNU mailutils}). They support the same +Rmail attempts to locate the @command{movemail} program and determine its +version. There are two versions of the @command{movemail} program: the +GNU Mailutils version (@pxref{movemail,,,mailutils,GNU mailutils}), +and an Emacs-specific version that is built and installed unless Emacs +was configured using the @option{--with-mailutils} option. +The two @command{mailtool} versions support the same command line syntax and the same basic subset of options. However, the Mailutils version offers additional features. - The Emacs version of @code{movemail} is able to retrieve mail from -the usual Unix mailbox formats and from remote mailboxes using the -POP3 protocol. + The Emacs version of @command{movemail} can retrieve mail from the +usual Unix mailbox formats. @strong{Warning}: Although it can also use the POP3 +protocol, this is not recommended because it does not support POP3 via +encrypted TLS channels. The Mailutils version is able to handle a wide set of mailbox formats, such as plain Unix mailboxes, @code{maildir} and @code{MH} @@ -1401,7 +1403,7 @@ in @ref{URL,,,mailutils,Mailbox URL Formats}. In short, a @acronym{URL} is: @smallexample -@var{proto}://[@var{user}[:@var{password}]@@]@var{host-or-file-name} +@var{proto}://[@var{user}[:@var{password}]@@]@var{host-or-file-name}[:@var{port}] @end smallexample @noindent @@ -1422,6 +1424,9 @@ User password to access the remote mailbox. @item host-or-file-name Hostname of the remote server for remote mailboxes or file name of a local mailbox. + +@item port +Optional port number, if not the default for that protocol. @end table @noindent @@ -1429,52 +1434,59 @@ local mailbox. @table @code @item mbox -Usual Unix mailbox format. In this case, neither @var{user} nor -@var{pass} are used, and @var{host-or-file-name} denotes the file name -of the mailbox file, e.g., @code{mbox://var/spool/mail/smith}. +Usual Unix mailbox format. In this case, @var{user}, @var{pass} and +@var{port} are not used, and @var{host-or-file-name} denotes the file +name of the mailbox file, e.g., @code{mbox:///var/spool/mail/smith}. @item mh -A local mailbox in the @acronym{MH} format. @var{user} and -@var{pass} are not used. @var{host-or-file-name} denotes the name of -@acronym{MH} folder, e.g., @code{mh://Mail/inbox}. +A local mailbox in the @acronym{MH} format. @var{user}, @var{pass} +and @var{port} are not used. @var{host-or-file-name} denotes the name +of @acronym{MH} folder, e.g., @code{mh:///Mail/inbox}. @item maildir -A local mailbox in the @acronym{maildir} format. @var{user} and -@var{pass} are not used, and @var{host-or-file-name} denotes the name of -@code{maildir} mailbox, e.g., @code{maildir://mail/inbox}. +A local mailbox in the @acronym{maildir} format. @var{user}, +@var{pass} and @var{port} are not used, and @var{host-or-file-name} +denotes the name of @code{maildir} mailbox, e.g., +@code{maildir:///mail/inbox}. @item file Any local mailbox format. Its actual format is detected automatically -by @code{movemail}. +by @command{movemail}. @item pop +@itemx pops A remote mailbox to be accessed via POP3 protocol. @var{user} specifies the remote user name to use, @var{pass} may be used to specify the user password, @var{host-or-file-name} is the name or IP -address of the remote mail server to connect to; e.g., -@code{pop://smith:guessme@@remote.server.net}. +address of the remote mail server to connect to, and @var{port} is the +port number; e.g., @code{pop://smith:guessme@@remote.server.net:995}. +If the server supports it, @command{movemail} tries to use an +encrypted connection---use the @samp{pops} form to require one. @item imap +@itemx imaps A remote mailbox to be accessed via IMAP4 protocol. @var{user} specifies the remote user name to use, @var{pass} may be used to specify the user password, @var{host-or-file-name} is the name or IP -address of the remote mail server to connect to; -e.g., @code{imap://smith:guessme@@remote.server.net}. +address of the remote mail server to connect to, and @var{port} is the +port number; e.g., @code{imap://smith:guessme@@remote.server.net:993}. +If the server supports it, @command{movemail} tries to use an +encrypted connection---use the @samp{imaps} form to require one. @end table Alternatively, you can specify the file name of the mailbox to use. This is equivalent to specifying the @samp{file} protocol: @smallexample -/var/spool/mail/@var{user} @equiv{} file://var/spool/mail/@var{user} +/var/spool/mail/@var{user} @equiv{} file:///var/spool/mail/@var{user} @end smallexample @vindex rmail-movemail-program @vindex rmail-movemail-search-path The variable @code{rmail-movemail-program} controls which version of -@code{movemail} to use. If that is a string, it specifies the -absolute file name of the @code{movemail} executable. If it is -@code{nil}, Rmail searches for @code{movemail} in the directories +@command{movemail} to use. If that is a string, it specifies the +absolute file name of the @command{movemail} executable. If it is +@code{nil}, Rmail searches for @command{movemail} in the directories listed in @code{rmail-movemail-search-path}, then in @code{exec-path} (@pxref{Shell}), then in @code{exec-directory}. @@ -1483,45 +1495,45 @@ listed in @code{rmail-movemail-search-path}, then in @code{exec-path} @pindex movemail Some sites use a method called POP for accessing users' inbox data -instead of storing the data in inbox files. By default, the @code{Emacs -movemail} can work with POP (unless the Emacs @code{configure} script -was run with the option @samp{--without-pop}). - -Similarly, the Mailutils @code{movemail} by default supports POP, unless -it was configured with the @samp{--disable-pop} option. - -Both versions of @code{movemail} only work with POP3, not with older -versions of POP. +instead of storing the data in inbox files. The Mailutils +@command{movemail} by default supports POP with TLS encryption. +@strong{Warning:} Although the @command{Emacs movemail} supports POP, +its use for this is not recommended since it does not support encrypted +connections---the Mailutils version does. +Both versions of @command{movemail} work only with POP3, not with +older versions of POP. @cindex @env{MAILHOST} environment variable @cindex POP mailboxes - No matter which flavor of @code{movemail} you use, you can specify + You can specify a POP inbox by using a POP @dfn{URL} (@pxref{Movemail}). A POP @acronym{URL} is of the form -@samp{pop://@var{username}@@@var{hostname}}, where -@var{hostname} is the host name or IP address of the remote mail +@samp{pop://@var{username}@@@var{hostname}:@var{port}}, where +@var{hostname} and @var{port} are the host name (or IP address) +and port number of the remote mail server and @var{username} is the user name on that server. Additionally, you may specify the password in the mailbox @acronym{URL}: -@samp{pop://@var{username}:@var{password}@@@var{hostname}}. In this +@samp{pop://@var{username}:@var{password}@@@var{hostname}:@var{port}}. In this case, @var{password} takes preference over the one set by @code{rmail-remote-password} (see below). This is especially useful if you have several remote mailboxes with different passwords. +If using Mailutils @command{movemail}, you may wish to use +@samp{pops} in place of @samp{pop}. For backward compatibility, Rmail also supports an alternative way of specifying remote POP mailboxes. Specifying an inbox name in the form -@samp{po:@var{username}:@var{hostname}} is equivalent to -@samp{pop://@var{username}@@@var{hostname}}. If you omit the +@samp{po:@var{username}:@var{hostname}:@var{port}} is equivalent to +@samp{pop://@var{username}@@@var{hostname}:@var{port}}. If you omit the @var{:hostname} part, the @env{MAILHOST} environment variable specifies the machine on which to look for the POP server. -@c FIXME mention --with-hesiod "support Hesiod to get the POP server host"? - @cindex IMAP mailboxes Another method for accessing remote mailboxes is IMAP@. This method is -supported only by the Mailutils @code{movemail}. To specify an IMAP +supported only by the Mailutils @command{movemail}. To specify an IMAP mailbox in the inbox list, use the following mailbox @acronym{URL}: -@samp{imap://@var{username}[:@var{password}]@@@var{hostname}}. The -@var{password} part is optional, as described above. +@samp{imap://@var{username}[:@var{password}]@@@var{hostname}:@var{port}}. The +@var{password} part is optional, as described above. You may wish to +use @samp{imaps} in place of @samp{imap}. @vindex rmail-remote-password @vindex rmail-remote-password-required @@ -1543,16 +1555,14 @@ Otherwise, Rmail will ask you for the password to use. @end enumerate @vindex rmail-movemail-flags - If you need to pass additional command-line flags to @code{movemail}, + If you need to pass additional command-line flags to @command{movemail}, set the variable @code{rmail-movemail-flags} a list of the flags you wish to use. Do not use this variable to pass the @samp{-p} flag to preserve your inbox contents; use @code{rmail-preserve-inbox} instead. @cindex Kerberos POP authentication - The @code{movemail} program installed at your site may support -Kerberos authentication (the Emacs @code{movemail} does so if Emacs was -configured with the option @code{--with-kerberos} or -@code{--with-kerberos5}). If it is supported, it is used by default + The @command{movemail} program installed at your site may support +Kerberos authentication. If it is supported, it is used by default whenever you attempt to retrieve POP mail when @code{rmail-remote-password} and @code{rmail-remote-password-required} are unset. @@ -1560,24 +1570,24 @@ are unset. @cindex reverse order in POP inboxes Some POP servers store messages in reverse order. If your server does this, and you would rather read your mail in the order in which it was -received, you can tell @code{movemail} to reverse the order of +received, you can tell @command{movemail} to reverse the order of downloaded messages by adding the @samp{-r} flag to @code{rmail-movemail-flags}. @cindex TLS encryption (Rmail) - Mailutils @code{movemail} supports TLS encryption. If you wish to + Mailutils @command{movemail} supports TLS encryption. If you wish to use it, add the @samp{--tls} flag to @code{rmail-movemail-flags}. @node Other Mailbox Formats @section Retrieving Mail from Local Mailboxes in Various Formats If your incoming mail is stored on a local machine in a format other -than Unix mailbox, you will need the Mailutils @code{movemail} to +than Unix mailbox, you will need the Mailutils @command{movemail} to retrieve it. @xref{Movemail}, for the detailed description of -@code{movemail} versions. For example, to access mail from a inbox in +@command{movemail} versions. For example, to access mail from a inbox in @code{maildir} format located in @file{/var/spool/mail/in}, you would include the following in the Rmail inbox list: @smallexample -maildir://var/spool/mail/in +maildir:///var/spool/mail/in @end smallexample diff --git a/doc/emacs/text.texi b/doc/emacs/text.texi index 3c46049b225..d1e451175ed 100644 --- a/doc/emacs/text.texi +++ b/doc/emacs/text.texi @@ -296,7 +296,7 @@ mark by one paragraph. The definition of a paragraph depends on the major mode. In Fundamental mode, as well as Text mode and related modes, a paragraph -is separated each neighboring paragraph another by one or more +is separated from neighboring paragraphs by one or more @dfn{blank lines}---lines that are either empty, or consist solely of space, tab and/or formfeed characters. In programming language modes, paragraphs are usually defined in a similar way, so that you can use @@ -1899,8 +1899,14 @@ between Latin-1 encoded files and @TeX{}-encoded equivalents. @findex html-mode The major modes for SGML and HTML provide indentation support and -commands for operating on tags. HTML mode is a slightly customized -variant of SGML mode. +commands for operating on tags. + + HTML consists of two modes---one, a basic mode called +@code{html-mode} is a slightly customized variant of SGML mode. The +other, which is used by default for HTML files, is called +@code{mhtml-mode}, and attempts to properly handle Javascript enclosed +in a @code{<script>} element and CSS embedded in a @code{<style>} +element. @table @kbd @item C-c C-n diff --git a/doc/lispref/backups.texi b/doc/lispref/backups.texi index b72ad374e4e..2834f69addc 100644 --- a/doc/lispref/backups.texi +++ b/doc/lispref/backups.texi @@ -547,6 +547,11 @@ effect in an existing buffer until the next time auto-save mode is reenabled in it. If auto-save mode is already enabled, auto-saves continue to go in the same file name until @code{auto-save-mode} is called again. + +Note that setting this variable to a non-@code{nil} value does not +change the fact that auto-saving is different from saving the buffer; +e.g., the hooks described in @ref{Saving Buffers} are @emph{not} run +when a buffer is auto-saved. @end defopt @defun recent-auto-save-p diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 424d25a384f..274f8b47063 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -484,7 +484,8 @@ I/O. @cindex region argument Point and the mark, as two numeric arguments, smallest first. This is the only code letter that specifies two successive arguments rather than -one. No I/O. +one. This will signal an error if the mark is not set in the buffer +which is current when the command is invoked. No I/O. @item s Arbitrary text, read in the minibuffer and returned as a string diff --git a/doc/lispref/compile.texi b/doc/lispref/compile.texi index b1cc04be09d..201d9fc2fa5 100644 --- a/doc/lispref/compile.texi +++ b/doc/lispref/compile.texi @@ -88,10 +88,14 @@ the @code{byte-compile} function. You can compile a whole file with @code{byte-compile-file}, or several files with @code{byte-recompile-directory} or @code{batch-byte-compile}. +@vindex byte-compile-debug Sometimes, the byte compiler produces warning and/or error messages -(@pxref{Compiler Errors}, for details). These messages are recorded -in a buffer called @file{*Compile-Log*}, which uses Compilation mode. -@xref{Compilation Mode,,,emacs, The GNU Emacs Manual}. +(@pxref{Compiler Errors}, for details). These messages are normally +recorded in a buffer called @file{*Compile-Log*}, which uses +Compilation mode. @xref{Compilation Mode,,,emacs, The GNU Emacs +Manual}. However, if the variable @code{byte-compile-debug} is +non-nil, error message will be signaled as Lisp errors instead +(@pxref{Errors}). @cindex macro compilation Be careful when writing macro calls in files that you intend to diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index f59e1ddb590..5f0dadad895 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -1974,6 +1974,94 @@ line, if present, in the return value. If it is @code{t}, include the height of both, if present, in the return value. @end defun +@code{window-text-pixel-size} treats the text displayed in a window as a +whole and does not care about the size of individual lines. The +following function does. + +@defun window-lines-pixel-dimensions &optional window first last body inverse +This function calculates the pixel dimensions of each line displayed in +the specified @var{window}. It does so by walking @var{window}'s +current glyph matrix---a matrix storing the glyph (@pxref{Glyphs}) of +each buffer character currently displayed in @var{window}. If +successful, it returns a list of cons pairs representing the x- and +y-coordinates of the lower right corner of the last character of each +line. Coordinates are measured in pixels from an origin (0, 0) at the +top-left corner of @var{window}. @var{window} must be a live window and +defaults to the selected one. + +If the optional argument @var{first} is an integer, it denotes the index +(starting with 0) of the first line of @var{window}'s glyph matrix to be +returned. Note that if @var{window} has a header line, the line with +index 0 is that header line. If @var{first} is nil, the first line to +be considered is determined by the value of the optional argument +@var{body}: If @var{body} is non-@code{nil}, this means to start with +the first line of @var{window}'s body, skipping any header line, if +present. Otherwise, this function will start with the first line of +@var{window}'s glyph matrix, possibly the header line. + +If the optional argument @var{last} is an integer, it denotes the index +of the last line of @var{window}'s glyph matrix that shall be returned. +If @var{last} is nil, the last line to be considered is determined by +the value of @var{body}: If @var{body} is non-@code{nil}, this means to +use the last line of @var{window}'s body, omitting @var{window}'s mode +line, if present. Otherwise, this means to use the last line of +@var{window} which may be the mode line. + +The optional argument @var{inverse}, if @code{nil}, means that the +y-pixel value returned for any line specifies the distance in pixels +from the left edge (body edge if @var{body} is non-@code{nil}) of +@var{window} to the right edge of the last glyph of that line. +@var{inverse} non-@code{nil} means that the y-pixel value returned for +any line specifies the distance in pixels from the right edge of the +last glyph of that line to the right edge (body edge if @var{body} is +non-@code{nil}) of @var{window}. This is useful for determining the +amount of slack space at the end of each line. + +The optional argument @var{left}, if non-@code{nil} means to return the +x- and y-coordinates of the lower left corner of the leftmost character +on each line. This is the value that should be used for windows that +mostly display text from right to left. + +If @var{left} is non-@code{nil} and @var{inverse} is @code{nil}, this +means that the y-pixel value returned for any line specifies the +distance in pixels from the left edge of the last (leftmost) glyph of +that line to the right edge (body edge if @var{body} is non-@code{nil}) +of @var{window}. If @var{left} and @var{inverse} are both +non-@code{nil}, the y-pixel value returned for any line specifies the +distance in pixels from the left edge (body edge if @var{body} is +non-@code{nil}) of @var{window} to the left edge of the last (leftmost) +glyph of that line. + +This function returns @code{nil} if the current glyph matrix of +@var{window} is not up-to-date which usually happens when Emacs is busy, +for example, when processing a command. The value should be retrievable +though when this function is run from an idle timer with a delay of zero +seconds. +@end defun + +@defun line-pixel-height +This function returns the height in pixels of the line at point in the +selected window. The value includes the line spacing of the line +(@pxref{Line Height}). +@end defun + +When a buffer is displayed with line numbers (@pxref{Display Custom,,, +emacs, The GNU Emacs Manual}), it is sometimes useful to know the +width taken for displaying the line numbers. The following function +is for Lisp programs which need this information for layout +calculations. + +@defun line-number-display-width &optional pixelwise +This function returns the width used for displaying the line numbers +in the selected window. Optional argument @var{pixelwise}, if +non-@code{nil}, means return the value in pixels; otherwise the value +is returned in column units of the font defined for the +@code{line-number} face. If line numbers are not displayed in the +selected window, the value is zero. Use @code{with-selected-window} +(@pxref{Selecting Windows}) if you need this information about another +window. +@end defun + @node Line Height @section Line Height @@ -2276,8 +2364,8 @@ Draw a box with lines of width 1, in color @var{color}. This way you can explicitly specify all aspects of the box. The value @var{width} specifies the width of the lines to draw; it defaults to 1. A negative width @var{-n} means to draw a line of width @var{n} -that occupies the space of the underlying text, thus avoiding any -increase in the character height or width. +whose top and bottom parts occupy the space of the underlying text, +thus avoiding any increase in the character height. The value @var{color} specifies the color to draw with. The default is the foreground color of the face for simple boxes, and the background @@ -2525,16 +2613,20 @@ This function also defines @var{face} as a valid face name if it is not already one, and (re)calculates its attributes on existing frames. @cindex override spec @r{(for a face)} -The argument @var{spec-type} determines which spec to set. If it is -@code{nil} or @code{face-override-spec}, this function sets the -@dfn{override spec}, which overrides over all other face specs on -@var{face}. If it is @code{customized-face} or @code{saved-face}, -this function sets the customized spec or the saved custom spec. If -it is @code{face-defface-spec}, this function sets the default face -spec (the same one set by @code{defface}). If it is @code{reset}, -this function clears out all customization specs and override specs -from @var{face} (in this case, the value of @var{spec} is ignored). -Any other value of @var{spec-type} is reserved for internal use. +The optional argument @var{spec-type} determines which spec to set. +If it is omitted or @code{nil} or @code{face-override-spec}, this +function sets the @dfn{override spec}, which overrides face specs on +@var{face} of all the other types mentioned below. This is useful +when calling this function outside of Custom code. If @var{spec-type} +is @code{customized-face} or @code{saved-face}, this function sets the +customized spec or the saved custom spec, respectively. If it is +@code{face-defface-spec}, this function sets the default face spec +(the same one set by @code{defface}). If it is @code{reset}, this +function clears out all customization specs and override specs from +@var{face} (in this case, the value of @var{spec} is ignored). The +effect of any other value of @var{spec-type} on the face specs is +reserved for internal use, but the function will still define +@var{face} itself and recalculate its attributes, as described above. @end defun @node Attribute Functions @@ -3792,6 +3884,10 @@ fringe, and likewise @var{right} for the right fringe. A value of @code{nil} for either one stands for the default width. If @var{outside-margins} is non-@code{nil}, that specifies that fringes should appear outside of the display margins. + +The values specified here may be later overridden by invoking +@code{set-window-buffer} (@pxref{Buffers and Windows}) on @var{window} +with its @var{keep-margins} argument @code{nil} or omitted. @end defun @defun window-fringes &optional window @@ -4194,7 +4290,8 @@ using the following function: @defun set-window-scroll-bars window &optional width vertical-type height horizontal-type This function sets the width and/or height and the types of scroll bars -for window @var{window}. +for window @var{window}. If @var{window} is @code{nil}, the selected +window is used. @var{width} specifies the width of the vertical scroll bar in pixels (@code{nil} means use the width specified for the frame). @@ -4209,7 +4306,9 @@ vertical scroll bar. The possible values are @code{bottom}, @code{t}, which means to use the frame's default, and @code{nil} for no horizontal scroll bar. -If @var{window} is @code{nil}, the selected window is used. +The values specified here may be later overridden by invoking +@code{set-window-buffer} (@pxref{Buffers and Windows}) on @var{window} +with its @var{keep-margins} argument @code{nil} or omitted. @end defun The following four functions take as argument a live window which @@ -4666,16 +4765,21 @@ a form. Emacs evaluates it to get the new height, with the symbol @item (raise @var{factor}) This kind of display specification raises or lowers the text -it applies to, relative to the baseline of the line. - -@var{factor} must be a number, which is interpreted as a multiple of the -height of the affected text. If it is positive, that means to display -the characters raised. If it is negative, that means to display them -lower down. - -If the text also has a @code{height} display specification, that does -not affect the amount of raising or lowering, which is based on the -faces used for the text. +it applies to, relative to the baseline of the line. It is mainly +meant to support display of subscripts and superscripts. + +The @var{factor} must be a number, which is interpreted as a multiple +of the height of the affected text. If it is positive, that means to +display the characters raised. If it is negative, that means to +display them lower down. + +Note that if the text also has a @code{height} display specification, +which was specified before (i.e.@: to the left of) @code{raise}, the +latter will affect the amount of raising or lowering in pixels, +because that is based on the height of the text being raised. +Therefore, if you want to display a sub- or superscript that is +smaller than the normal text height, consider specifying @code{raise} +before @code{height}. @end table @c We put all the '@code{(when ...)}' on one line to encourage @@ -4748,6 +4852,10 @@ Thus, you can make changes take effect by calling This function specifies the margin widths for window @var{window}, in character cell units. The argument @var{left} controls the left margin, and @var{right} controls the right margin (default @code{0}). + +The values specified here may be later overridden by invoking +@code{set-window-buffer} (@pxref{Buffers and Windows}) on @var{window} +with its @var{keep-margins} argument @code{nil} or omitted. @end defun @defun window-margins &optional window @@ -7183,20 +7291,22 @@ changing the value of the variable @code{x-gtk-use-system-tooltips} to @code{nil}. The rest of this subsection describes how to control non-GTK+ tooltips, which are presented by Emacs itself. -Since tooltips are special frames, they have their frame parameters -(@pxref{Frame Parameters}). Unlike other frames, the frame parameters -for tooltips are stored in a special variable. +@cindex tooltip frames +Tooltips are displayed in special frames called tooltip frames, which +have their own frame parameters (@pxref{Frame Parameters}). Unlike +other frames, the default parameters for tooltip frames are stored in a +special variable. @defvar tooltip-frame-parameters -This customizable option holds the frame parameters used for -displaying tooltips. Any font and color parameters are ignored, and -the corresponding attributes of the @code{tooltip} face are used -instead. If @code{left} or @code{top} parameters are included, they -are used as absolute frame-relative coordinates where the tooltip -should be shown. (Mouse-relative position of the tooltip can be -customized using the variables described in @ref{Tooltips,,, emacs, -The GNU Emacs Manual}.) Note that the @code{left} and @code{top} -parameters, if present, override the values of mouse-relative offsets. +This customizable option holds the default frame parameters used for +displaying tooltips. Any font and color parameters are ignored, and the +corresponding attributes of the @code{tooltip} face are used instead. +If @code{left} or @code{top} parameters are included, they are used as +absolute frame-relative coordinates where the tooltip should be shown. +(Mouse-relative position of the tooltip can be customized using the +variables described in @ref{Tooltips,,, emacs, The GNU Emacs Manual}.) +Note that the @code{left} and @code{top} parameters, if present, +override the values of mouse-relative offsets. @end defvar @vindex tooltip@r{ face} @@ -7267,7 +7377,11 @@ follows the Unicode Bidirectional Algorithm (a.k.a.@: @acronym{UBA}), which is described in Annex #9 of the Unicode standard (@url{http://www.unicode.org/reports/tr9/}). Emacs provides a ``Full Bidirectionality'' class implementation of the @acronym{UBA}, -consistent with the requirements of the Unicode Standard v8.0. +consistent with the requirements of the Unicode Standard v9.0. Note, +however, that the way Emacs displays continuation lines when text +direction is opposite to the base paragraph direction deviates from +the UBA, which requires to perform line wrapping before reordering +text for display. @defvar bidi-display-reordering If the value of this buffer-local variable is non-@code{nil} (the diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi index e0bd337e53b..4bedea3bdd1 100644 --- a/doc/lispref/elisp.texi +++ b/doc/lispref/elisp.texi @@ -180,6 +180,7 @@ To view this manual in other formats, click * Sequences Arrays Vectors:: Lists, strings and vectors are called sequences. Certain functions act on any kind of sequence. The description of vectors is here as well. +* Records:: Compound objects with programmer-defined types. * Hash Tables:: Very fast lookup-tables. * Symbols:: Symbols represent names, uniquely. @@ -314,6 +315,8 @@ Programming Types expression, more fundamental but less pretty. * Primitive Function Type:: A function written in C, callable from Lisp. * Byte-Code Type:: A function written in Lisp, then compiled. +* Record Type:: Compound objects with programmer-defined types. +* Type Descriptors:: Objects holding information about types. * Autoload Type:: A type used for automatically loading seldom-used functions. * Finalizer Type:: Runs code when no longer reachable. @@ -418,6 +421,11 @@ Sequences, Arrays, and Vectors * Bool-Vectors:: How to work with bool-vectors. * Rings:: Managing a fixed-size ring of objects. +Records + +* Record Functions:: Functions for records. +* Backward Compatibility:: Compatibility for cl-defstruct. + Hash Tables * Creating Hash:: Functions to create hash tables. @@ -1054,6 +1062,7 @@ Windows * Vertical Scrolling:: Moving the contents up and down on the window. * Horizontal Scrolling:: Moving the contents sideways on the window. * Coordinates and Windows:: Converting coordinates to windows. +* Mouse Window Auto-selection:: Automatically selecting windows with the mouse. * Window Configurations:: Saving and restoring the state of the screen. * Window Parameters:: Associating additional information with windows. * Window Hooks:: Hooks for scrolling, window size changes, @@ -1081,16 +1090,16 @@ Frames * Minibuffers and Frames:: How a frame finds the minibuffer to use. * Input Focus:: Specifying the selected frame. * Visibility of Frames:: Frames may be visible or invisible, or icons. -* Raising and Lowering:: Raising a frame makes it hide other windows; - lowering it makes the others hide it. +* Raising and Lowering:: Raising, Lowering and Restacking Frames. * Frame Configurations:: Saving the state of all frames. +* Child Frames:: Making a frame the child of another. * Mouse Tracking:: Getting events that say when the mouse moves. * Mouse Position:: Asking where the mouse is, or moving it. * Pop-Up Menus:: Displaying a menu for the user to select from. * Dialog Boxes:: Displaying a box to ask yes or no. * Pointer Shape:: Specifying the shape of the mouse pointer. * Window System Selections::Transferring text to and from other X clients. -* Drag and Drop:: Internals of Drag-and-Drop implementation. +* Drag and Drop:: Internals of Drag-and-Drop implementation. * Color Names:: Getting the definitions of color names. * Text Terminal Colors:: Defining colors for text terminals. * Resources:: Getting resource values from the server. @@ -1100,7 +1109,8 @@ Frame Geometry * Frame Layout:: Basic layout of frames. * Frame Font:: The default font of a frame and how to set it. -* Size and Position:: Changing the size and position of a frame. +* Frame Position:: The position of a frame on its display. +* Frame Size:: Specifying and retrieving a frame's size. * Implied Frame Resizing:: Implied resizing of frames and how to prevent it. Frame Parameters @@ -1118,6 +1128,10 @@ Window Frame Parameters * Layout Parameters:: Size of parts of the frame, and enabling or disabling some parts. * Buffer Parameters:: Which buffers have been or should be shown. +* Frame Interaction Parameters:: Parameters for interacting with other + frames. +* Mouse Dragging Parameters:: Parameters for resizing and moving + frames with the mouse. * Management Parameters:: Communicating with the window manager. * Cursor Parameters:: Controlling the cursor appearance. * Font and Color Parameters:: Fonts and colors for the frame text. @@ -1594,6 +1608,7 @@ Object Internals @include lists.texi @include sequences.texi +@include records.texi @include hash.texi @include symbols.texi @include eval.texi diff --git a/doc/lispref/errors.texi b/doc/lispref/errors.texi index 2ec1a108ea9..1f67819c34e 100644 --- a/doc/lispref/errors.texi +++ b/doc/lispref/errors.texi @@ -186,6 +186,12 @@ The message is @samp{Undefined color}. @xref{Color Names}. @item user-error The message is the empty string. @xref{Signaling Errors}. +@item user-search-failed +This is like @samp{search-failed}, but doesn't trigger the debugger, +like @samp{user-error}. @xref{Signaling Errors}, and @xref{Searching +and Matching}. This is used for searching in Info files, @xref{Search +Text,,,info,Info}. + @item void-function The message is @samp{Symbol's function definition is void}. @xref{Function Cells}. diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 4023530e97d..59419007a69 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -408,7 +408,11 @@ buffer name instead. @end deffn Saving a buffer runs several hooks. It also performs format -conversion (@pxref{Format Conversion}). +conversion (@pxref{Format Conversion}). Note that these hooks, +described below, are only run by @code{save-buffer}, they are not run +by other primitives and functions that write buffer text to files, and +in particular auto-saving (@pxref{Auto-Saving}) doesn't run these +hooks. @defvar write-file-functions The value of this variable is a list of functions to be called before diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 68aa40fe4dd..b430f7c6fad 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -77,6 +77,13 @@ displayed on that terminal; the list of possible values is the same as for @code{framep} above. @end defun +@cindex top-level frame +On a graphical terminal we distinguish two types of frames: A normal +@dfn{top-level frame} is a frame whose window-system window is a child +of the window-system's root window for that terminal. A child frame is +a frame whose window-system window is the child of the window-system +window of another Emacs frame. @xref{Child Frames}. + @menu * Creating Frames:: Creating additional frames. * Multiple Terminals:: Displaying on several different devices. @@ -89,9 +96,9 @@ for @code{framep} above. * Minibuffers and Frames:: How a frame finds the minibuffer to use. * Input Focus:: Specifying the selected frame. * Visibility of Frames:: Frames may be visible or invisible, or icons. -* Raising and Lowering:: Raising a frame makes it hide other windows; - lowering it makes the others hide it. +* Raising and Lowering:: Raising, Lowering and Restacking Frames. * Frame Configurations:: Saving the state of all frames. +* Child Frames:: Making a frame the child of another. * Mouse Tracking:: Getting events that say when the mouse moves. * Mouse Position:: Asking where the mouse is, or moving it. * Pop-Up Menus:: Displaying a menu for the user to select from. @@ -436,7 +443,8 @@ has to specify a live frame (@pxref{Deleting Frames}). If omitted or @menu * Frame Layout:: Basic layout of frames. * Frame Font:: The default font of a frame and how to set it. -* Size and Position:: Changing the size and position of a frame. +* Frame Position:: The position of a frame on its display. +* Frame Size:: Specifying and retrieving a frame's size. * Implied Frame Resizing:: Implied resizing of frames and how to prevent it. @end menu @@ -446,14 +454,16 @@ has to specify a live frame (@pxref{Deleting Frames}). If omitted or @cindex frame layout @cindex layout of frame -The drawing below sketches the layout of a frame on a graphical -terminal: +A visible frame occupies a rectangular area on its terminal's display. +This area may contain a number of nested rectangles, each serving a +different purpose. The drawing below sketches the layout of a frame on +a graphical terminal: @smallexample @group <------------ Outer Frame Width -----------> - ___________________________________________ - ^(0) ___________ External Border __________ | + ____________________________________________ + ^(0) ________ External/Outer Border _______ | | | |_____________ Title Bar ______________| | | | (1)_____________ Menu Bar ______________| | ^ | | (2)_____________ Tool Bar ______________| | ^ @@ -468,14 +478,14 @@ Height | | | Height | | | Height | | | | | | | | | | | | |___v______________________________| | | | | | |___________ Internal Border __________| | v - v |______________ External Border _____________| + v |___________ External/Outer Border __________| <-------- Native Frame Width --------> @end group @end smallexample In practice not all of the areas shown in the drawing will or may be -present. The meaning of these areas is: +present. The meaning of these areas is described below. @table @samp @item Outer Frame @@ -483,50 +493,103 @@ present. The meaning of these areas is: @cindex outer edges @cindex outer width @cindex outer height +@cindex outer size The @dfn{outer frame} is a rectangle comprising all areas shown in the drawing. The edges of that rectangle are called the @dfn{outer edges} -of the frame. The @dfn{outer width} and @dfn{outer height} of the frame -specify the size of that rectangle. +of the frame. Together, the @dfn{outer width} and @dfn{outer height} of +the frame specify the @dfn{outer size} of that rectangle. + +Knowing the outer size of a frame is useful for fitting a frame into the +working area of its display (@pxref{Multiple Terminals}) or for placing +two frames adjacent to each other on the screen. Usually, the outer +size of a frame is available only after the frame has been mapped (made +visible, @pxref{Visibility of Frames}) at least once. For the initial +frame or a frame that has not been created yet, the outer size can be +only estimated or must be calculated from the window-system's or window +manager's defaults. One workaround is to obtain the differences of the +outer and native (see below) sizes of a mapped frame and use them for +calculating the outer size of the new frame. @cindex outer position -The upper left corner of the outer frame (indicated by @samp{(0)} in the -drawing above) is the @dfn{outer position} or the frame. It is -specified by and settable via the @code{left} and @code{top} frame -parameters (@pxref{Position Parameters}) as well as the functions -@code{frame-position} and @code{set-frame-position} (@pxref{Size and -Position}). +The position of the upper left corner of the outer frame (indicated by +@samp{(0)} in the drawing above) is the @dfn{outer position} of the +frame. The outer position of a graphical frame is also referred to as +``the position'' of the frame because it usually remains unchanged on +its display whenever the frame is resized or its layout is changed. + +The outer position is specified by and can be set via the @code{left} +and @code{top} frame parameters (@pxref{Position Parameters}). For a +normal, top-level frame these parameters usually represent its absolute +position (see below) with respect to its display's origin. For a child +frame (@pxref{Child Frames}) these parameters represent its position +relative to the native position (see below) of its parent frame. For +frames on text terminals the values of these parameters are meaningless +and always zero. @item External Border @cindex external border The @dfn{external border} is part of the decorations supplied by the -window manager. It's typically used for resizing the frame with the -mouse. The external border is normally not shown on ``fullboth'' and -maximized frames (@pxref{Size Parameters}) and doesn't exist for text -terminal frames. - - The external border should not be confused with the @dfn{outer -border} specified by the @code{border-width} frame parameter -(@pxref{Layout Parameters}). Since the outer border is usually ignored -on most platforms it is not covered here. +window manager. It is typically used for resizing the frame with the +mouse and is therefore not shown on ``fullboth'' and maximized frames +(@pxref{Size Parameters}). Its width is determined by the window +manager and cannot be changed by Emacs' functions. + +External borders don't exist on text terminal frames. For graphical +frames, their display can be suppressed by setting the +@code{override-redirect} or @code{undecorated} frame parameter +(@pxref{Management Parameters}). + +@item Outer Border +@cindex outer border +The @dfn{outer border} is a separate border whose width can be specified +with the @code{border-width} frame parameter (@pxref{Layout +Parameters}). In practice, either the external or the outer border of a +frame are displayed but never both at the same time. Usually, the outer +border is shown only for special frames that are not (fully) controlled +by the window manager like tooltip frames (@pxref{Tooltips}), child +frames (@pxref{Child Frames}) and @code{undecorated} or +@code{override-redirect} frames (@pxref{Management Parameters}). + +Outer borders are never shown on text terminal frames and on frames +generated by GTK+ routines. On MS-Windows, the outer border is emulated +with the help of a one pixel wide external border. Non-toolkit builds +on X allow to change the color of the outer border by setting the +@code{border-color} frame parameter (@pxref{Layout Parameters}). @item Title Bar @cindex title bar -The @dfn{title bar} is also part of the window manager's decorations and -typically displays the title of the frame (@pxref{Frame Titles}) as well -as buttons for minimizing, maximizing and deleting the frame. The title -bar is usually not displayed on fullboth (@pxref{Size Parameters}) -or tooltip frames. Title bars don't exist for text terminal frames. +@cindex caption bar +The @dfn{title bar}, a.k.a.@ @dfn{caption bar}, is also part of the +window manager's decorations and typically displays the title of the +frame (@pxref{Frame Titles}) as well as buttons for minimizing, +maximizing and deleting the frame. It can be also used for dragging +the frame with the mouse. The title bar is usually not displayed for +fullboth (@pxref{Size Parameters}), tooltip (@pxref{Tooltips}) and +child frames (@pxref{Child Frames}) and doesn't exist for terminal +frames. Display of the title bar can be suppressed by setting the +@code{override-redirect} or the @code{undecorated} frame parameters +(@pxref{Management Parameters}). @item Menu Bar @cindex internal menu bar @cindex external menu bar The menu bar (@pxref{Menu Bar}) can be either internal (drawn by Emacs -itself) or external (drawn by a toolkit). Most builds (GTK+, Lucid, -Motif and Windows) rely on an external menu bar. NS also uses an +itself) or external (drawn by the toolkit). Most builds (GTK+, Lucid, +Motif and MS-Windows) rely on an external menu bar. NS also uses an external menu bar which, however, is not part of the outer frame. Non-toolkit builds can provide an internal menu bar. On text terminal frames, the menu bar is part of the frame's root window (@pxref{Windows -and Frames}). +and Frames}). As a rule, menu bars are never shown on child frames +(@pxref{Child Frames}). Display of the menu bar can be suppressed by +setting the @code{menu-bar-lines} parameter (@pxref{Layout Parameters}) +to zero. + +Whether the menu bar is wrapped or truncated whenever its width +becomes too large to fit on its frame depends on the toolkit . +Usually, only Motif and MS-Windows builds can wrap the menu bar. When +they (un-)wrap the menu bar, they try to keep the outer height of the +frame unchanged, so the native height of the frame (see below) will +change instead. @item Tool Bar @cindex internal tool bar @@ -536,59 +599,91 @@ internal (drawn by Emacs itself) or external (drawn by a toolkit). The GTK+ and NS builds have the tool bar drawn by the toolkit. The remaining builds use internal tool bars. With GTK+ the tool bar can be located on either side of the frame, immediately outside the internal -border, see below. +border, see below. Tool bars are usually not shown for child frames +(@pxref{Child Frames}). Display of the tool bar can be suppressed by +setting the @code{tool-bar-lines} parameter (@pxref{Layout +Parameters}) to zero. + +If the variable @code{auto-resize-tool-bars} is non-@code{nil}, Emacs +wraps the internal tool bar when its width becomes too large for its +frame. If and when Emacs (un-)wraps the internal tool bar, it by +default keeps the outer height of the frame unchanged, so the native +height of the frame (see below) will change instead. Emacs built with +GTK+, on the other hand, never wraps the tool bar but may +automatically increase the outer width of a frame in order to +accommodate an overlong tool bar. @item Native Frame @cindex native frame @cindex native edges @cindex native width @cindex native height -@cindex display area +@cindex native size The @dfn{native frame} is a rectangle located entirely within the outer -frame. It excludes the areas occupied by the external border, the title -bar and any external menu or external tool bar. The area enclosed by -the native frame is sometimes also referred to as the @dfn{display area} -of the frame. The edges of the native frame are called the @dfn{native -edges} of the frame. The @dfn{native width} and @dfn{native height} of -the frame specify the size of the rectangle. +frame. It excludes the areas occupied by an external or outer border, +the title bar and any external menu or tool bar. The edges of the +native frame are called the @dfn{native edges} of the frame. Together, +the @dfn{native width} and @dfn{native height} of a frame specify the +@dfn{native size} of the frame. + +The native size of a frame is the size Emacs passes to the window-system +or window manager when creating or resizing the frame from within Emacs. +It is also the size Emacs receives from the window-system or window +manager whenever these resize the frame's window-system window, for +example, after maximizing the frame by clicking on the corresponding +button in the title bar or when dragging its external border with the +mouse. @cindex native position -The top left corner of the native frame specifies the @dfn{native -position} of the frame. (1)--(3) in the drawing above indicate that -position for the various builds: +The position of the top left corner of the native frame specifies the +@dfn{native position} of the frame. (1)--(3) in the drawing above +indicate that position for the various builds: @itemize @w{} @item (1) non-toolkit and terminal frames -@item (2) Lucid, Motif and Windows frames +@item (2) Lucid, Motif and MS-Windows frames @item (3) GTK+ and NS frames @end itemize -Accordingly, the native height of a frame includes the height of the -tool bar but not that of the menu bar (Lucid, Motif, Windows) or those -of the menu bar and the tool bar (non-toolkit and text terminal frames). +Accordingly, the native height of a frame may include the height of the +tool bar but not that of the menu bar (Lucid, Motif, MS-Windows) or +those of the menu bar and the tool bar (non-toolkit and text terminal +frames). -The native position of a frame is the reference position of functions +The native position of a frame is the reference position for functions that set or return the current position of the mouse (@pxref{Mouse Position}) and for functions dealing with the position of windows like @code{window-edges}, @code{window-at} or @code{coordinates-in-window-p} -(@pxref{Coordinates and Windows}). +(@pxref{Coordinates and Windows}). It also specifies the (0, 0) origin +for locating and positioning child frames within this frame +(@pxref{Child Frames}). + +Note also that the native position of a frame usually remains unaltered +on its display when removing or adding the window manager decorations by +changing the frame's @code{override-redirect} or @code{undecorated} +parameter (@pxref{Management Parameters}). @item Internal Border -The internal border (@pxref{Layout Parameters}) is a border drawn by -Emacs around the inner frame (see below). +The internal border is a border drawn by Emacs around the inner frame +(see below). Its width is specified by the @code{internal-border-width} +frame parameter (@pxref{Layout Parameters}). Its color is specified by +the background of the @code{internal-border} face. @item Inner Frame @cindex inner frame @cindex inner edges @cindex inner width @cindex inner height +@cindex inner size +@cindex display area The @dfn{inner frame} is the rectangle reserved for the frame's windows. It's enclosed by the internal border which, however, is not part of the inner frame. Its edges are called the @dfn{inner edges} of the frame. -The @dfn{inner width} and @dfn{inner height} specify the size of the -rectangle. +The @dfn{inner width} and @dfn{inner height} specify the @dfn{inner +size} of the rectangle. The inner frame is sometimes also referred to +as the @dfn{display area} of the frame. @cindex minibuffer-less frame @cindex minibuffer-only frame @@ -603,22 +698,39 @@ configurations. @item Text Area @cindex text area -The @dfn{text area} of a frame is a somewhat fictitious area located -entirely within the native frame. It can be obtained by removing from -the native frame any internal borders, one vertical and one horizontal -scroll bar, and one left and one right fringe as specified for this -frame, see @ref{Layout Parameters}. +The @dfn{text area} of a frame is a somewhat fictitious area that can be +embedded in the native frame. Its position is unspecified. Its width +can be obtained by removing from that of the native width the widths of +the internal border, one vertical scroll bar, and one left and one right +fringe if they are specified for this frame, see @ref{Layout +Parameters}. Its height can be obtained by removing from that of the +native height the widths of the internal border and the heights of the +frame's internal menu and tool bars and one horizontal scroll bar if +specified for this frame. @end table @cindex absolute position -The @dfn{absolute position} of a frame or its edges is usually given in -terms of pixels counted from an origin at position (0, 0) of the frame's -display. Note that with multiple monitors the origin does not -necessarily coincide with the top left corner of the entire usable -display area. Hence the absolute outer position of a frame or the -absolute positions of the edges of the outer, native or inner frame can -be negative in such an environment even when that frame is completely -visible. +@cindex absolute frame position +@cindex absolute edges +@cindex absolute frame edges +@cindex display origin +@cindex origin of display +The @dfn{absolute position} of a frame is given as a pair (X, Y) of +horizontal and vertical pixel offsets relative to an origin (0, 0) of +the frame's display. Correspondingly, the @dfn{absolute edges} of a +frame are given as pixel offsets from that origin. + + Note that with multiple monitors, the origin of the display does not +necessarily coincide with the top-left corner of the entire usable +display area of the terminal. Hence the absolute position of a frame +can be negative in such an environment even when that frame is +completely visible. + + By convention, vertical offsets increase ``downwards''. This means +that the height of a frame is obtained by subtracting the offset of its +top edge from that of its bottom edge. Horizontal offsets increase +``rightwards'', as expected, so a frame's width is calculated by +subtracting the offset of its left edge from that of its right edge. For a frame on a graphical terminal the following function returns the sizes of the areas described above: @@ -626,13 +738,16 @@ sizes of the areas described above: @defun frame-geometry &optional frame This function returns geometric attributes of @var{frame}. The return value is an association list of the attributes listed below. All -coordinate, height and width values are integers counting pixels. +coordinate, height and width values are integers counting pixels. Note +that if @var{frame} has not been mapped yet, (@pxref{Visibility of +Frames}) some of the return values may only represent approximations of +the actual values---those that can be seen after the frame has been +mapped. @table @code @item outer-position -A cons of the absolute X- and Y-coordinates of the outer position of -@var{frame}, relative to the origin at position (0, 0) of @var{frame}'s -display. +A cons representing the absolute position of the outer @var{frame}, +relative to the origin at position (0, 0) of @var{frame}'s display. @item outer-size A cons of the outer width and height of @var{frame}. @@ -643,6 +758,10 @@ borders as supplied by the window manager. If the window manager doesn't supply these values, Emacs will try to guess them from the coordinates of the outer and inner frame. +@item outer-border-width +The width of the outer border of @var{frame}. The value is meaningful +for non-GTK+ X builds only. + @item title-bar-size A cons of the width and height of the title bar of @var{frame} as supplied by the window manager or operating system. If both of them are @@ -677,24 +796,28 @@ The following function can be used to retrieve the edges of the outer, native and inner frame. @defun frame-edges &optional frame type -This function returns the edges of the outer, native or inner frame of -@var{frame}. @var{frame} must be a live frame and defaults to the -selected one. The list returned has the form (@var{left} @var{top} -@var{right} @var{bottom}) where all values are in pixels relative to the -position (0, 0) of @var{frame}'s display. For terminal frames -@var{left} and @var{top} are both zero. +This function returns the absolute edges of the outer, native or inner +frame of @var{frame}. @var{frame} must be a live frame and defaults to +the selected one. The returned list has the form @w{@code{(@var{left} +@var{top} @var{right} @var{bottom})}} where all values are in pixels +relative to the origin of @var{frame}'s display. For terminal frames +the values returned for @var{left} and @var{top} are always zero. Optional argument @var{type} specifies the type of the edges to return: -@var{type} @code{outer-edges} means to return the outer edges of -@var{frame}, @code{native-edges} (or @code{nil}) means to return its -native edges and @code{inner-edges} means to return its inner edges. - -Notice that the pixels at the positions @var{bottom} and @var{right} -lie immediately outside the corresponding frame. This means that if you -have, for example, two side-by-side frames positioned such that the -right outer edge of the frame on the left equals the left outer edge of -the frame on the right, the pixels representing that edge are part -of the frame on the right. +@code{outer-edges} means to return the outer edges of @var{frame}, +@code{native-edges} (or @code{nil}) means to return its native edges and +@code{inner-edges} means to return its inner edges. + +By convention, the pixels of the display at the values returned for +@var{left} and @var{top} are considered to be inside (part of) +@var{frame}. Hence, if @var{left} and @var{top} are both zero, the +pixel at the display's origin is part of @var{frame}. The pixels at +@var{bottom} and @var{right}, on the other hand, are considered to lie +immediately outside @var{frame}. This means that if you have, for +example, two side-by-side frames positioned such that the right outer +edge of the frame on the left equals the left outer edge of the frame on +the right, the pixels at that edge show a part of the frame on the +right. @end defun @@ -751,63 +874,107 @@ and all future graphical frames. @end deffn -@node Size and Position -@subsection Size and Position -@cindex frame size +@node Frame Position +@subsection Frame Position @cindex frame position @cindex position of frame -You can read or change the position of a frame using the frame -parameters @code{left} and @code{top} (@pxref{Position Parameters}) and -its size using the @code{height} and @code{width} parameters -(@pxref{Size Parameters}). Here are some special features for working -with sizes and positions. For all of these functions the argument -@var{frame} must denote a live frame and defaults to the selected frame. +On graphical systems, the position of a normal top-level frame is +specified as the absolute position of its outer frame (@pxref{Frame +Geometry}). The position of a child frame (@pxref{Child Frames}) is +specified via pixel offsets of its outer edges relative to the native +position of its parent frame. + + You can access or change the position of a frame using the frame +parameters @code{left} and @code{top} (@pxref{Position Parameters}). +Here are two additional functions for working with the positions of an +existing, visible frame. For both functions, the argument @var{frame} +must denote a live frame and defaults to the selected frame. @defun frame-position &optional frame -This function returns the outer position (@pxref{Frame Layout}) of -@var{frame} in pixels. The value is a cons giving the coordinates of -the top left corner of the outer frame of @var{frame} relative to an -origin at the position (0, 0) of the frame's display. On a text -terminal frame both values are zero. +For a normal, non-child frame this function returns a cons of the pixel +coordinates of its outer position (@pxref{Frame Layout}) with respect to +the origin @code{(0, 0)} of its display. For a child frame +(@pxref{Child Frames}) this function returns the pixel coordinates of +its outer position with respect to an origin @code{(0, 0)} at the native +position of @var{frame}'s parent. + +Negative values never indicate an offset from the right or bottom +edge of @var{frame}'s display or parent frame. Rather, they mean that +@var{frame}'s outer position is on the left and/or above the origin of +its display or the native position of its parent frame. This usually +means that @var{frame} is only partially visible (or completely +invisible). However, on systems where the display's origin does not +coincide with its top-left corner, the frame may be visible on a +secondary monitor. + +On a text terminal frame both values are zero. @end defun @defun set-frame-position frame x y -This function sets the outer frame position of @var{frame} to @var{x} -and @var{y}. The latter arguments specify pixels and normally count -from an origin at the position (0, 0) of @var{frame}'s display. +This function sets the outer frame position of @var{frame} to (@var{x}, +@var{y}). The latter arguments specify pixels and normally count from +the origin at the position (0, 0) of @var{frame}'s display. For child +frames, they count from the native position of @var{frame}'s parent +frame. -A negative parameter value positions the right edge of the outer frame -by @var{-x} pixels left from the right edge of the screen or the bottom -edge by @var{-y} pixels up from the bottom edge of the screen. +Negative parameter values position the right edge of the outer frame by +@var{-x} pixels left from the right edge of the screen (or the parent +frame's native rectangle) and the bottom edge by @var{-y} pixels up from +the bottom edge of the screen (or the parent frame's native rectangle). + +Note that negative values do not permit to align the right or bottom +edge of @var{frame} exactly at the right or bottom edge of its display +or parent frame. Neither do they allow to specify a position that does +not lie within the edges of the display or parent frame. The frame +parameters @code{left} and @code{top} (@pxref{Position Parameters}) +allow to do that, but may still fail to provide good results for the +initial or a new frame. This function has no effect on text terminal frames. @end defun -@defun frame-pixel-height &optional frame -@defunx frame-pixel-width &optional frame - These functions return the inner height and width (the height and -width of the display area, see @ref{Frame Layout}) of @var{frame} in -pixels. For a text terminal, the results are in characters rather than -pixels. -@end defun +@defvar move-frame-functions +@cindex frame position changes, a hook +This hook specifies the functions that are run when an Emacs frame is moved +(assigned a new position) by the window-system or window manager. The +functions are run with one argument, the frame that moved. For a child +frame (@pxref{Child Frames}), the functions are run only when the +position of the frame changes in relation to that of its parent frame. +@end defvar -@defun frame-text-height &optional frame -@defunx frame-text-width &optional frame -These functions return the height and width of the text area of -@var{frame} (@pxref{Frame Layout}), measured in pixels. For a text -terminal, the results are in characters rather than pixels. -The value returned by @code{frame-text-height} differs from that -returned by @code{frame-pixel-height} by not including the heights of -any internal tool bar or menu bar, the height of one horizontal scroll -bar and the widths of the internal border. +@node Frame Size +@subsection Frame Size +@cindex frame size +@cindex text width of a frame +@cindex text height of a frame +@cindex text size of a frame +The canonical way to specify the @dfn{size of a frame} from within Emacs +is by specifying its @dfn{text size}---a tuple of the width and height +of the frame's text area (@pxref{Frame Layout}). It can be measured +either in pixels or in terms of the frame's canonical character size +(@pxref{Frame Font}). -The value returned by @code{frame-text-width} differs from that returned -by @code{frame-pixel-width} by not including the width of one vertical -scroll bar, the widths of one left and one right fringe and the widths -of the internal border. -@end defun + For frames with an internal menu or tool bar, the frame's native +height cannot be told exactly before the frame has been actually drawn. +This means that in general you cannot use the native size to specify the +initial size of a frame. As soon as you know the native size of a +visible frame, you can calculate its outer size (@pxref{Frame Layout}) +by adding in the remaining components from the return value of +@code{frame-geometry}. For invisible frames or for frames that have +yet to be created, however, the outer size can only be estimated. This +also means that calculating an exact initial position of a frame +specified via offsets from the right or bottom edge of the screen +(@pxref{Frame Position}) is impossible. + + The text size of any frame can be set and retrieved with the help of +the @code{height} and @code{width} frame parameters (@pxref{Size +Parameters}). The text size of the initial frame can be also set with +the help of an X-style geometry specification. @xref{Emacs Invocation,, +Command Line Arguments for Emacs Invocation, emacs, The GNU Emacs +Manual}. Below we list some functions to access and set the size of an +existing, visible frame, by default the selected one. @defun frame-height &optional frame @defunx frame-width &optional frame @@ -823,12 +990,50 @@ rounded down to the number of characters of the default font that fully fit into the text area. @end defun +The functions following next return the pixel widths and heights of the +native, outer and inner frame and the text area (@pxref{Frame Layout}) +of a given frame. For a text terminal, the results are in characters +rather than pixels. + +@defun frame-outer-width &optional frame +@defunx frame-outer-height &optional frame +These functions return the outer width and height of @var{frame} in +pixels. +@end defun + +@defun frame-native-height &optional frame +@defunx frame-native-width &optional frame +These functions return the native width and height of @var{frame} in +pixels. +@end defun + +@defun frame-inner-width &optional frame +@defunx frame-inner-height &optional frame +These functions return the inner width and height of @var{frame} in +pixels. +@end defun + +@defun frame-text-width &optional frame +@defunx frame-text-height &optional frame +These functions return the width and height of the text area of +@var{frame} in pixels. +@end defun + +On window systems that support it, Emacs tries by default to make the +text size of a frame measured in pixels a multiple of the frame's +character size. This, however, usually means that a frame can be +resized only in character size increments when dragging its external +borders. It also may break attempts to truly maximize the frame or +making it ``fullheight'' or ``fullwidth'' (@pxref{Size Parameters}) +leaving some empty space below and/or on the right of the frame. The +following option may help in that case. + @defopt frame-resize-pixelwise -If this option is @code{nil}, a frame's size is usually rounded to a -multiple of the current values of that frame's @code{frame-char-height} -and @code{frame-char-width} whenever the frame is resized. If this is -non-@code{nil}, no rounding occurs, hence frame sizes can -increase/decrease by one pixel. +If this option is @code{nil} (the default), a frame's text pixel size is +usually rounded to a multiple of the current values of that frame's +@code{frame-char-height} and @code{frame-char-width} whenever the frame +is resized. If this is non-@code{nil}, no rounding occurs, hence frame +sizes can increase/decrease by one pixel. Setting this variable usually causes the next resize operation to pass the corresponding size hints to the window manager. This means that @@ -855,7 +1060,7 @@ terms of the canonical height and width of a character on @var{frame} The optional argument @var{pixelwise} non-@code{nil} means to measure the new width and height in units of pixels instead. Note that if @code{frame-resize-pixelwise} is @code{nil}, some toolkits may refuse to -fully honor the request if it does not increase/decrease the frame size +truly honor the request if it does not increase/decrease the frame size to a multiple of its character size. @end defun @@ -876,9 +1081,9 @@ text terminals. The optional fourth argument @var{pixelwise} non-@code{nil} means that @var{frame} should be @var{height} pixels high. Note that if -@code{frame-resize-pixelwise} is @code{nil}, some toolkits may refuse to -fully honor the request if it does not increase/decrease the frame -height to a multiple of its character height. +@code{frame-resize-pixelwise} is @code{nil}, some window managers may +refuse to truly honor the request if it does not increase/decrease the +frame height to a multiple of its character height. @end defun @defun set-frame-width frame width &optional pretend pixelwise @@ -888,9 +1093,9 @@ in characters. The argument @var{pretend} has the same meaning as in The optional fourth argument @var{pixelwise} non-@code{nil} means that @var{frame} should be @var{width} pixels wide. Note that if -@code{frame-resize-pixelwise} is @code{nil}, some toolkits may refuse to -fully honor the request if it does not increase/decrease the frame width -to a multiple of its character width. +@code{frame-resize-pixelwise} is @code{nil}, some window managers may +refuse to fully honor the request if it does not increase/decrease the +frame width to a multiple of its character width. @end defun None of these three functions will make a frame smaller than needed to @@ -899,7 +1104,25 @@ margins, dividers, mode and header lines. This contrasts with requests by the window manager triggered, for example, by dragging the external border of a frame with the mouse. Such requests are always honored by clipping, if necessary, portions that cannot be displayed at the right, -bottom corner of the frame. +bottom corner of the frame. The parameters @code{min-width} and +@code{min-height} (@pxref{Size Parameters}) can be used to obtain a +similar behavior when changing the frame size from within Emacs. + +@cindex tracking frame size changes + The abnormal hook @code{window-size-change-functions} (@pxref{Window +Hooks}) tracks all changes of the inner size of a frame including those +induced by request of the window-system or window manager. To rule out +false positives that might occur when changing only the sizes of a +frame's windows without actually changing the size of the inner frame, +use the following function. + +@defun frame-size-changed-p &optional frame +This function returns non-@code{nil} when the inner width or height of +@var{frame} has changed since @code{window-size-change-functions} was +run the last time for @var{frame}. It always returns @code{nil} +immediately after running @code{window-size-change-functions} for +@var{frame}. +@end defun @node Implied Frame Resizing @@ -916,7 +1139,7 @@ size change. Note that wrapping a menu or tool bar usually does not resize the frame's outer size, hence this will alter the number of displayed lines. - Occasionally, such @dfn{implied frame resizing} may be unwanted, for + Occasionally, such @dfn{implied frame resizing} may be unwanted, for example, when the frame is maximized or made full-screen (where it's turned off by default). In other cases you can disable implied resizing with the following option: @@ -928,7 +1151,7 @@ implicitly resize the frame's display area in order to preserve the number of columns or lines the frame displays. If this option is non-@code{nil}, no implied resizing is done. -The value of this option can be also be a list of frame parameters. In +The value of this option can be also a list of frame parameters. In that case, implied resizing is inhibited when changing a parameter that appears in this list. The frame parameters currently handled by this option are: @code{font}, @code{font-backend}, @@ -946,7 +1169,7 @@ unchanged if this option is either @code{t} or a list containing @code{vertical-scroll-bars}. The default value is @code{'(tool-bar-lines)} for Lucid, Motif and -Windows (which means that adding/removing a tool bar there does not +MS-Windows (which means that adding/removing a tool bar there does not change the outer frame height), @code{nil} on all other window systems including GTK+ (which means that changing any of the parameters listed above may change the size of the outer frame), and @code{t} otherwise @@ -1135,6 +1358,10 @@ text terminals. * Layout Parameters:: Size of parts of the frame, and enabling or disabling some parts. * Buffer Parameters:: Which buffers have been or should be shown. +* Frame Interaction Parameters:: Parameters for interacting with other + frames. +* Mouse Dragging Parameters:: Parameters for resizing and moving + frames with the mouse. * Management Parameters:: Communicating with the window manager. * Cursor Parameters:: Controlling the cursor appearance. * Font and Color Parameters:: Fonts and colors for the frame text. @@ -1180,64 +1407,108 @@ If you specify the frame name explicitly when you create the frame, the name is also used (instead of the name of the Emacs executable) when looking up X resources for the frame. +@vindex explicit-name, a frame parameter @item explicit-name If the frame name was specified explicitly when the frame was created, this parameter will be that name. If the frame wasn't explicitly named, this parameter will be @code{nil}. @end table + @node Position Parameters @subsubsection Position Parameters @cindex window position on display @cindex frame position - Position parameters' values are measured in pixels. (Note that none -of these parameters exist on TTY frames.) +Parameters describing the X- and Y-offsets of a frame are always +measured in pixels. For a normal, non-child frame they specify the +frame's outer position (@pxref{Frame Geometry}) relative to its +display's origin. For a child frame (@pxref{Child Frames}) they specify +the frame's outer position relative to the native position of the +frame's parent frame. (Note that none of these parameters is meaningful +on TTY frames.) @table @code @vindex left, a frame parameter @item left -The position, in pixels, of the left (or right) edge of the frame with -respect to the left (or right) edge of the screen. The value may be: +The position, in pixels, of the left outer edge of the frame with +respect to the left edge of the frame's display or parent frame. It can +be specified in one of the following ways. @table @asis @item an integer -A positive integer relates the left edge of the frame to the left edge -of the screen. A negative integer relates the right frame edge to the -right screen edge. +A positive integer always relates the left edge of the frame to the left +edge of its display or parent frame. A negative integer relates the +right frame edge to the right edge of the display or parent frame. @item @code{(+ @var{pos})} This specifies the position of the left frame edge relative to the left -screen edge. The integer @var{pos} may be positive or negative; a -negative value specifies a position outside the screen or on a monitor -other than the primary one (for multi-monitor displays). +edge of its display or parent frame. The integer @var{pos} may be +positive or negative; a negative value specifies a position outside the +screen or parent frame or on a monitor other than the primary one (for +multi-monitor displays). @item @code{(- @var{pos})} -This specifies the position of the right frame edge relative to the right -screen edge. The integer @var{pos} may be positive or negative; a -negative value specifies a position outside the screen or on a monitor -other than the primary one (for multi-monitor displays). +This specifies the position of the right frame edge relative to the +right edge of the display or parent frame. The integer @var{pos} may be +positive or negative; a negative value specifies a position outside the +screen or parent frame or on a monitor other than the primary one (for +multi-monitor displays). + +@cindex left position ratio +@cindex top position ratio +@item a floating-point value +A floating-point value in the range 0.0 to 1.0 specifies the left edge's +offset via the @dfn{left position ratio} of the frame---the ratio of the +left edge of its outer frame to the width of the frame's workarea +(@pxref{Multiple Terminals}) or its parent's native frame (@pxref{Child +Frames}) minus the width of the outer frame. Thus, a left position +ratio of 0.0 flushes a frame to the left, a ratio of 0.5 centers it and +a ratio of 1.0 flushes it to the right of its display or parent frame. +Similarly, the @dfn{top position ratio} of a frame is the ratio of the +frame's top position to the height of its workarea or parent frame minus +the height of the frame. + +Emacs will try to keep the position ratios of a child frame unaltered if +that frame has a non-@code{nil} @code{keep-ratio} parameter +(@pxref{Frame Interaction Parameters}) and its parent frame is resized. + +Since the outer size of a frame (@pxref{Frame Geometry}) is usually +unavailable before a frame has been made visible, it is generally not +advisable to use floating-point values when creating decorated frames. +Floating-point values are more suited for ensuring that an (undecorated) +child frame is positioned nicely within the area of its parent frame. @end table Some window managers ignore program-specified positions. If you want to be sure the position you specify is not ignored, specify a -non-@code{nil} value for the @code{user-position} parameter as well. - -If the window manager refuses to align a frame at the left or top screen -edge, combining position notation and @code{user-position} as in +non-@code{nil} value for the @code{user-position} parameter as in the +following example: @example (modify-frame-parameters nil '((user-position . t) (left . (+ -4)))) @end example -may help to override that. +In general, it is not a good idea to position a frame relative to the +right or bottom edge of its display. Positioning the initial or a new +frame is either not accurate (because the size of the outer frame is not +yet fully known before the frame has been made visible) or will cause +additional flicker (if the frame has to be repositioned after becoming +visible). + + Note also, that positions specified relative to the right/bottom edge +of a display, workarea or parent frame as well as floating-point offsets +are stored internally as integer offsets relative to the left/top edge +of the display, workarea or parent frame edge. They are also returned +as such by functions like @code{frame-parameters} and restored as such +by the desktop saving routines. @vindex top, a frame parameter @item top The screen position of the top (or bottom) edge, in pixels, with respect -to the top (or bottom) edge of the screen. It works just like -@code{left}, except vertically instead of horizontally. +to the top (or bottom) edge of the display or parent frame. It works +just like @code{left}, except vertically instead of horizontally. @vindex icon-left, a frame parameter @item icon-left @@ -1273,6 +1544,22 @@ When you call @code{make-frame}, you should specify a non-@code{nil} value for this parameter if the values of the @code{left} and @code{top} parameters represent the user's stated preference; otherwise, use @code{nil}. + +@vindex z-group, a frame parameter +@item z-group +This parameter specifies a relative position of the frame's +window-system window in the stacking (Z-) order of the frame's display. + +If this is @code{above}, the frame's window-system window is displayed +above all other window-system windows that do not have the @code{above} +property set. If this is nil, the frame's window is displayed below all +windows that have the @code{above} property set and above all windows +that have the @code{below} property set. If this is @code{below}, the +frame's window is displayed below all windows that do not have the +@code{below} property set. + +To position the frame above or below a specific other frame use the +function @code{frame-restack} (@pxref{Raising and Lowering}). @end table @@ -1280,20 +1567,61 @@ parameters represent the user's stated preference; otherwise, use @subsubsection Size Parameters @cindex window size on display - Frame parameters specify frame sizes in character units. On -graphical displays, the @code{default} face determines the actual -pixel sizes of these character units (@pxref{Face Attributes}). +Frame parameters usually specify frame sizes in character units. On +graphical displays, the @code{default} face determines the actual pixel +sizes of these character units (@pxref{Face Attributes}). @table @code -@vindex height, a frame parameter -@item height -The height of the frame's text area (@pxref{Frame Geometry}), in -characters. - @vindex width, a frame parameter @item width -The width of the frame's text area (@pxref{Frame Geometry}), in -characters. +This parameter specifies the width of the frame. It can be specified as +in the following ways: + +@table @asis +@item an integer +A positive integer specifies the width of the frame's text area +(@pxref{Frame Geometry}) in characters. + +@item a cons cell +If this is a cons cell with the symbol @code{text-pixels} in its +@sc{car}, the @sc{cdr} of that cell specifies the width of the frame's +text area in pixels. + +@cindex frame width ratio +@cindex frame height ratio +@item a floating-point value +A floating-point number between 0.0 and 1.0 can be used to specify the +width of a frame via its @dfn{width ratio}---the ratio of its outer +width (@pxref{Frame Geometry}) to the width of the frame's workarea +(@pxref{Multiple Terminals}) or its parent frame's (@pxref{Child +Frames}) native frame. Thus, a value of 0.5 makes the frame occupy half +of the width of its workarea or parent frame, a value of 1.0 the full +width. Similarly, the @dfn{height ratio} of a frame is the ratio of its +outer height to the height of its workarea or its parent's native frame. + +Emacs will try to keep the width and height ratio of a child frame +unaltered if that frame has a non-@code{nil} @code{keep-ratio} parameter +(@pxref{Frame Interaction Parameters}) and its parent frame is resized. + +Since the outer size of a frame is usually unavailable before a frame +has been made visible, it is generally not advisable to use +floating-point values when creating decorated frames. Floating-point +values are more suited to ensure that a child frame always fits within +the area of its parent frame as, for example, when customizing +@code{display-buffer-alist} (@pxref{Choosing Window}) via +@code{display-buffer-in-child-frame}. +@end table + +Regardless of how this parameter was specified, functions reporting the +value of this parameter like @code{frame-parameters} always report the +width of the frame's text area in characters as an integer rounded, if +necessary, to a multiple of the frame's default character width. That +value is also used by the desktop saving routines. + +@vindex height, a frame parameter +@item height +This parameter specifies the height of the frame. It works just like +@code{width}, except vertically instead of horizontally. @vindex user-size, a frame parameter @item user-size @@ -1302,6 +1630,28 @@ the @code{user-position} parameter (@pxref{Position Parameters, user-position}) does for the position parameters @code{top} and @code{left}. +@vindex min-width, a frame parameter +@item min-width +This parameter specifies the minimum native width (@pxref{Frame +Geometry}) of the frame, in characters. Normally, the functions that +establish a frame's initial width or resize a frame horizontally make +sure that all the frame's windows, vertical scroll bars, fringes, +margins and vertical dividers can be displayed. This parameter, if +non-@code{nil} allows to make a frame narrower than that with the +consequence that any components that do not fit will be clipped by the +window manager. + +@vindex min-height, a frame parameter +@item min-height +This parameter specifies the minimum native height (@pxref{Frame +Geometry}) of the frame, in characters. Normally, the functions that +establish a frame's initial size or resize a frame make sure that all +the frame's windows, horizontal scroll bars and dividers, mode and +header lines, the echo area and the internal menu and tool bar can be +displayed. This parameter, if non-@code{nil} allows to make a frame +smaller than that with the consequence that any components that do not +fit will be clipped by the window manager. + @cindex fullboth frames @cindex fullheight frames @cindex fullwidth frames @@ -1327,12 +1677,16 @@ of maximized and full-height frames and the widths of maximized and full-width frames often differ by a few pixels. With some window managers you may have to customize the variable -@code{frame-resize-pixelwise} (@pxref{Size and Position}) in order to -make a frame truly appear maximized or full-screen. Moreover, -some window managers might not support smooth transition between the -various full-screen or maximization states. Customizing the variable +@code{frame-resize-pixelwise} (@pxref{Frame Size}) in order to make a +frame truly appear maximized or full-screen. Moreover, some window +managers might not support smooth transition between the various +full-screen or maximization states. Customizing the variable @code{x-frame-normalize-before-maximize} can help to overcome that. +Full-screen on macOS hides both the tool-bar and the menu-bar, however +both will be displayed if the mouse pointer is moved to the top of the +screen. + @vindex fullscreen-restore, a frame parameter @item fullscreen-restore This parameter specifies the desired fullscreen state of the frame @@ -1350,6 +1704,20 @@ file as, for example This will give a new frame full height after typing in it @key{F11} for the first time. + +@vindex fit-frame-to-buffer-margins, a frame parameter +@item fit-frame-to-buffer-margins +This parameter allows to override the value of the option +@code{fit-frame-to-buffer-margins} when fitting this frame to the buffer +of its root window with @code{fit-frame-to-buffer} (@pxref{Resizing +Windows}). + +@vindex fit-frame-to-buffer-sizes, a frame parameter +@item fit-frame-to-buffer-sizes +This parameter allows to override the value of the option +@code{fit-frame-to-buffer-sizes} when fitting this frame to the buffer +of its root window with @code{fit-frame-to-buffer} (@pxref{Resizing +Windows}). @end table @@ -1364,17 +1732,18 @@ frame, or control their sizes. @table @code @vindex border-width, a frame parameter @item border-width -The width in pixels of the frame's border. +The width in pixels of the frame's outer border (@pxref{Frame Geometry}). @vindex internal-border-width, a frame parameter @item internal-border-width -The distance in pixels between text (or fringe) and the frame's border. +The width in pixels of the frame's internal border (@pxref{Frame +Geometry}). @vindex vertical-scroll-bars, a frame parameter @item vertical-scroll-bars -Whether the frame has scroll bars for vertical scrolling, and which side -of the frame they should be on. The possible values are @code{left}, -@code{right}, and @code{nil} for no scroll bars. +Whether the frame has scroll bars (@pxref{Scroll Bars}) for vertical +scrolling, and which side of the frame they should be on. The possible +values are @code{left}, @code{right}, and @code{nil} for no scroll bars. @vindex horizontal-scroll-bars, a frame parameter @item horizontal-scroll-bars @@ -1418,28 +1787,43 @@ to not draw bottom dividers. @vindex menu-bar-lines frame parameter @item menu-bar-lines -The number of lines to allocate at the top of the frame for a menu -bar. The default is 1 if Menu Bar mode is enabled, and 0 otherwise. -@xref{Menu Bars,,,emacs, The GNU Emacs Manual}. +The number of lines to allocate at the top of the frame for a menu bar +(@pxref{Menu Bar}). The default is one if Menu Bar mode is enabled and +zero otherwise. @xref{Menu Bars,,,emacs, The GNU Emacs Manual}. For an +external menu bar (@pxref{Frame Layout}), this value remains unchanged +even when the menu bar wraps to two or more lines. In that case, the +@code{menu-bar-size} value returned by @code{frame-geometry} +(@pxref{Frame Geometry}) allows to derive whether the menu bar actually +occupies one or more lines. @vindex tool-bar-lines frame parameter @item tool-bar-lines -The number of lines to use for the tool bar. The default is 1 if Tool -Bar mode is enabled, and 0 otherwise. @xref{Tool Bars,,,emacs, The -GNU Emacs Manual}. +The number of lines to use for the tool bar (@pxref{Tool Bar}). The +default is one if Tool Bar mode is enabled and zero otherwise. +@xref{Tool Bars,,,emacs, The GNU Emacs Manual}. This value may change +whenever the tool bar wraps (@pxref{Frame Layout}). @vindex tool-bar-position frame parameter @item tool-bar-position -The position of the tool bar. Currently only for the GTK tool bar. -Value can be one of @code{top}, @code{bottom} @code{left}, @code{right}. -The default is @code{top}. +The position of the tool bar when Emacs was built with GTK+. Its value +can be one of @code{top}, @code{bottom} @code{left}, @code{right}. The +default is @code{top}. @vindex line-spacing, a frame parameter @item line-spacing Additional space to leave below each text line, in pixels (a positive integer). @xref{Line Height}, for more information. + +@vindex no-special-glyphs, a frame parameter +@item no-special-glyphs +If this is non-@code{nil}, it suppresses the display of any truncation +and continuation glyphs (@pxref{Truncation}) for all buffers displayed +by this frame. This is useful to eliminate such glyphs when fitting a +frame to its buffer via @code{fit-frame-to-buffer} (@pxref{Resizing +Windows}). @end table + @node Buffer Parameters @subsubsection Buffer Parameters @cindex frame, which buffers to display @@ -1478,13 +1862,149 @@ most-recently-selected first. If non-@code{nil}, this frame's window is never split automatically. @end table +@node Frame Interaction Parameters +@subsubsection Frame Interaction Parameters +@cindex frame interaction parameters +@cindex interaction parameters between frames + +These parameters supply forms of interactions between different frames. + +@table @code +@vindex parent-frame, a frame parameter +@item parent-frame +If non-@code{nil}, this means that this frame is a child frame +(@pxref{Child Frames}), and this parameter specifies its parent frame. +If nil, this means that this frame is a normal, top-level frame. + +@vindex delete-before, a frame parameter +@item delete-before +If non-@code{nil}, this parameter specifies another frame whose deletion +will automatically trigger the deletion of this frame. @xref{Deleting +Frames}. + +@vindex mouse-wheel-frame, a frame parameter +@item mouse-wheel-frame +If non-@code{nil}, this parameter specifies the frame whose windows will +be scrolled whenever the mouse wheel is scrolled with the mouse pointer +hovering over this frame, see @ref{Mouse Commands,,, emacs, The GNU +Emacs Manual}. + +@vindex no-other-frame, a frame parameter +@item no-other-frame +If this is non-@code{nil}, then this frame is not eligible as candidate +for the functions @code{next-frame}, @code{previous-frame} +(@pxref{Finding All Frames}) and @code{other-frame}, see @ref{Frame +Commands,,, emacs, The GNU Emacs Manual}. + +@vindex auto-hide-function, a frame parameter +@item auto-hide-function +When this parameter specifies a function, that function will be called +instead of the function specified by the variable +@code{frame-auto-hide-function} when quitting the frame's only window +(@pxref{Quitting Windows}) and there are other frames left. + +@vindex minibuffer-exit, a frame parameter +@item minibuffer-exit +When this parameter is non-@code{nil}, Emacs will by default make this +frame invisible whenever the minibuffer (@pxref{Minibuffers}) is exited. +Alternatively, it can specify the functions @code{iconify-frame} and +@code{delete-frame}. This parameter is useful to make a child frame +disappear automatically (similar to how Emacs deals with a window) when +exiting the minibuffer. + +@vindex keep-ratio, a frame parameter +@item keep-ratio +This parameter is currently meaningful for child frames (@pxref{Child +Frames}) only. If it is non-@code{nil}, then Emacs will try to keep the +frame's size (width and height) ratios (@pxref{Size Parameters}) as well +as its left and right position ratios (@pxref{Position Parameters}) +unaltered whenever its parent frame is resized. + +If the value of this parameter is @code{nil}, the frame's position and +size remain unaltered when the parent frame is resized, so the position +and size ratios may change. If the value of this parameter is @code{t}, +Emacs will try to preserve the frame's size and position ratios, hence +the frame's size and position relative to its parent frame may change. + +More individual control is possible by using a cons cell: In that case +the frame's width ratio is preserved if the @sc{car} of the cell is +either @code{t} or @code{width-only}. The height ratio is preserved if +the @sc{car} of the cell is either @code{t} or @code{height-only}. The +left position ratio is preserved if the @sc{cdr} of the cell is either +@code{t} or @code{left-only}. The top position ratio is preserved if +the @sc{cdr} of the cell is either @code{t} or @code{top-only}. +@end table + + +@node Mouse Dragging Parameters +@subsubsection Mouse Dragging Parameters +@cindex mouse dragging parameters +@cindex parameters for resizing frames with the mouse +@cindex parameters for moving frames with the mouse + +The parameters described below provide support for resizing a frame by +dragging its internal borders with the mouse. They also allow moving a +frame with the mouse by dragging the header line of its topmost or the +mode line of its bottommost window. + +These parameters are mostly useful for child frames (@pxref{Child +Frames}) that come without window manager decorations. If necessary, +they can be used for undecorated top-level frames as well. + +@table @code +@vindex drag-internal-border, a frame parameter +@item drag-internal-border +If non-@code{nil}, the frame can be resized by dragging its internal +borders, if present, with the mouse. + +@vindex drag-with-header-line, a frame parameter +@item drag-with-header-line +If non-@code{nil}, the frame can be moved with the mouse by dragging the +header line of its topmost window. + +@vindex drag-with-mode-line, a frame parameter +@item drag-with-mode-line +If non-@code{nil}, the frame can be moved with the mouse by dragging the +mode line of its bottommost window. Note that such a frame is not +allowed to have its own minibuffer window. + +@vindex snap-width, a frame parameter +@item snap-width +A frame that is moved with the mouse will ``snap'' at the border(s) of +the display or its parent frame whenever it is dragged as near to such +an edge as the number of pixels specified by this parameter. + +@vindex top-visible, a frame parameter +@item top-visible +If this parameter is a number, the top edge of the frame never appears +above the top edge of its display or parent frame. Moreover, as many +pixels of the frame as specified by that number will remain visible when +the frame is moved against any of the remaining edges of its display or +parent frame. Setting this parameter is useful to guard against +dragging a child frame with a non-@code{nil} +@code{drag-with-header-line} parameter completely out of the area +of its parent frame. + +@vindex bottom-visible, a frame parameter +@item bottom-visible +If this parameter is a number, the bottom edge of the frame never +appears below the bottom edge of its display or parent frame. Moreover, +as many pixels of the frame as specified by that number will remain +visible when the frame is moved against any of the remaining edges of +its display or parent frame. Setting this parameter is useful to guard +against dragging a child frame with a non-@code{nil} +@code{drag-with-mode-line} parameter completely out of the area of +its parent frame. +@end table + + @node Management Parameters @subsubsection Window Management Parameters @cindex window manager interaction, and frame parameters - The following frame parameters control various aspects of the -frame's interaction with the window manager. They have no effect on -text terminals. + The following frame parameters control various aspects of the frame's +interaction with the window manager or window system. They have no +effect on text terminals. @table @code @vindex visibility, a frame parameter @@ -1541,10 +2061,60 @@ with virtual desktops. @vindex inhibit-double-buffering, a frame parameter @item inhibit-double-buffering -If non-@code{nil}, the frame is drawn to the screen without double buffering. -Emacs normally attempts to use double buffering, where available, to -reduce flicker. Set this property if you experience display bugs or -pine for that retro, flicker-y feeling. +If non-@code{nil}, the frame is drawn to the screen without double +buffering. Emacs normally attempts to use double buffering, where +available, to reduce flicker. Set this property if you experience +display bugs or pine for that retro, flicker-y feeling. + +@vindex skip-taskbar, a frame parameter +@item skip-taskbar +If non-@code{nil}, this tells the window manager to remove the frame's +icon from the taskbar associated with the frame's display and inhibit +switching to the frame's window via the combination @kbd{Alt-@key{TAB}}. +On MS-Windows, iconifying such a frame will "roll in" its window-system +window at the bottom of the desktop. Some window managers may not honor +this parameter. + +@vindex no-focus-on-map, a frame parameter +@item no-focus-on-map +If non-@code{nil}, this means that the frame does not want to receive +input focus when it is mapped (@pxref{Visibility of Frames}). Some +window managers may not honor this parameter. + +@vindex no-accept-focus, a frame parameter +@item no-accept-focus +If non-@code{nil}, this means that the frame does not want to receive +input focus via explicit mouse clicks or when moving the mouse into it +either via @code{focus-follows-mouse} (@pxref{Input Focus}) or +@code{mouse-autoselect-window} (@pxref{Mouse Window Auto-selection}). +This may have the unwanted side-effect that a user cannot scroll a +non-selected frame with the mouse. Some window managers may not honor +this parameter. + +@vindex undecorated, a frame parameter +@item undecorated +If non-@code{nil}, this frame's window-system window is drawn without +decorations, like the title, minimize/maximize boxes and external +borders. This usually means that the window cannot be dragged, resized, +iconified, maximized or deleted with the mouse. If nil, the frame's +window is usually drawn with all the elements listed above unless their +display has been suspended via window manager settings. + +Under X, Emacs uses the Motif window manager hints to turn off +decorations. Some window managers may not honor these hints. + +NS builds consider the tool bar to be a decoration, and therefore hide +it on an undecorated frame. + +@vindex override-redirect, a frame parameter +@item override-redirect +@cindex override redirect frames +If non-@code{nil}, this means that this is an @dfn{override redirect} +frame---a frame not handled by window managers under X. Override +redirect frames have no window manager decorations, can be positioned +and resized only via Emacs' positioning and resizing functions and are +usually drawn on top of all other frames. Setting this parameter has +no effect on MS-Windows. @ignore @vindex parent-id, a frame parameter @@ -1557,6 +2127,7 @@ it and see if it works.) @end ignore @end table + @node Cursor Parameters @subsubsection Cursor Parameters @cindex cursor, and frame parameters @@ -1715,6 +2286,9 @@ The @code{alpha} frame parameter can also be a cons cell @code{(@var{active} . @var{inactive})}, where @var{active} is the opacity of the frame when it is selected, and @var{inactive} is the opacity when it is not selected. + +Some window systems do not support the @code{alpha} parameter for child +frames (@pxref{Child Frames}). @end table The following frame parameters are semi-obsolete in that they are @@ -1878,7 +2452,7 @@ frame is redisplayed. This variable specifies how to compute a name for a frame when you have not explicitly specified one. The variable's value is actually a mode line construct, just like @code{mode-line-format}, except that the -@samp{%c} and @samp{%l} constructs are ignored. @xref{Mode Line +@samp{%c}, @samp{%C}, and @samp{%l} constructs are ignored. @xref{Mode Line Data}. @end defvar @@ -1904,21 +2478,28 @@ while processing @code{frame-title-format} or @section Deleting Frames @cindex deleting frames - A @dfn{live frame} is one that has not been deleted. When a frame -is deleted, it is removed from its terminal display, although it may -continue to exist as a Lisp object until there are no more references -to it. +A @dfn{live frame} is one that has not been deleted. When a frame is +deleted, it is removed from its terminal display, although it may +continue to exist as a Lisp object until there are no more references to +it. @deffn Command delete-frame &optional frame force @vindex delete-frame-functions This function deletes the frame @var{frame}. The argument @var{frame} must specify a live frame (see below) and defaults to the selected -frame. Unless @var{frame} specifies a tooltip, this function first runs -the hook @code{delete-frame-functions} (each function getting one -argument, @var{frame}). +frame. -A frame cannot be deleted as long as its minibuffer serves as surrogate -minibuffer for another frame (@pxref{Minibuffers and Frames}). +It first deletes any child frame of @var{frame} (@pxref{Child Frames}) +and any frame whose @code{delete-before} frame parameter (@pxref{Frame +Interaction Parameters}) specifies @var{frame}. All such deletions are +performed recursively; so this step makes sure that no other frames with +@var{frame} as their ancestor will exist. Then, unless @var{frame} +specifies a tooltip, this function runs the hook +@code{delete-frame-functions} (each function getting one argument, +@var{frame}) before actually killing the frame. + +Note that a frame cannot be deleted as long as its minibuffer serves as +surrogate minibuffer for another frame (@pxref{Minibuffers and Frames}). Normally, you cannot delete a frame if all other frames are invisible, but if @var{force} is non-@code{nil}, then you are allowed to do so. @end deffn @@ -1942,8 +2523,13 @@ minibuffer frame is left untouched. The argument @var{frame} must specify a live frame and defaults to the selected frame. Internally, this command works by calling @code{delete-frame} with @var{force} @code{nil} for all frames that shall be deleted. + +This function does not delete any of @var{frame}'s child frames +(@pxref{Child Frames}). If @var{frame} is a child frame, it deletes +@var{frame}'s siblings only. @end deffn + @node Finding All Frames @section Finding All Frames @cindex frames, scanning all @@ -1962,12 +2548,29 @@ This function returns a list of just the currently visible frames. visible, even though only the selected one is actually displayed. @end defun +@defun frame-list-z-order &optional display +This function returns a list of Emacs' frames, in Z (stacking) order +(@pxref{Raising and Lowering}). The optional argument @var{display} +specifies which display to poll. @var{display} should be either a frame +or a display name (a string). If omitted or @code{nil}, that stands for +the selected frame's display. It returns @code{nil} if @var{display} +contains no Emacs frame. + +Frames are listed from topmost (first) to bottommost (last). As a +special case, if @var{display} is non-@code{nil} and specifies a live +frame, it returns the child frames of that frame in Z (stacking) order. + +This function is not meaningful on text terminals. +@end defun + @defun next-frame &optional frame minibuf This function lets you cycle conveniently through all the frames on a specific terminal from an arbitrary starting point. It returns the frame following @var{frame}, in the list of all live frames, on @var{frame}'s terminal. The argument @var{frame} must specify a live -frame and defaults to the selected frame. +frame and defaults to the selected frame. It never returns a frame +whose @code{no-other-frame} parameter (@pxref{Frame Interaction +Parameters}) is non-@code{nil}. The second argument, @var{minibuf}, says which frames to consider: @@ -1998,8 +2601,8 @@ Window Ordering}. @section Minibuffers and Frames Normally, each frame has its own minibuffer window at the bottom, which -is used whenever that frame is selected. If the frame has a minibuffer, -you can get it with @code{minibuffer-window} (@pxref{Minibuffer Windows}). +is used whenever that frame is selected. You can get that window with +the function @code{minibuffer-window} (@pxref{Minibuffer Windows}). @cindex frame without a minibuffer @cindex surrogate minibuffer frame @@ -2009,9 +2612,10 @@ will serve as @dfn{surrogate minibuffer frame} for this frame and cannot be deleted via @code{delete-frame} (@pxref{Deleting Frames}) as long as this frame is live. -When you create the frame, you can explicitly specify the minibuffer -window to use (in some other frame). If you don't, then the minibuffer -is found in the frame which is the value of the variable +When you create the frame, you can explicitly specify its minibuffer +window (in some other frame) with the @code{minibuffer} frame parameter +(@pxref{Buffer Parameters}). If you don't, then the minibuffer is found +in the frame which is the value of the variable @code{default-minibuffer-frame}. Its value should be a frame that does have a minibuffer. @@ -2026,13 +2630,14 @@ the current terminal and cannot be buffer-local. @xref{Multiple Terminals}. @end defvar + @node Input Focus @section Input Focus @cindex input focus -@c @cindex selected frame Duplicates selected-frame, same for selected-window. +@cindex selected frame -At any time, one frame in Emacs is the @dfn{selected frame}. The selected -window always resides on the selected frame. +At any time, one frame in Emacs is the @dfn{selected frame}. The +selected window always resides on the selected frame. When Emacs displays its frames on several terminals (@pxref{Multiple Terminals}), each terminal has its own selected frame. But only one @@ -2077,6 +2682,26 @@ same meaning as for @code{select-frame} (see below). The return value of this function is not significant. @end defun +Ideally, the function described next should focus a frame without also +raising it above other frames. Unfortunately, many window-systems or +window managers may refuse to comply. + +@defun x-focus-frame &optional frame noactivate +This function gives @var{frame} the focus of the X server without +necessarily raising it. @var{frame} @code{nil} means use the selected +frame. Under X, the optional argument @var{noactivate}, if +non-@code{nil}, means to avoid making @var{frame}'s window-system window +the ``active'' window which should insist a bit more on avoiding to +raise @var{frame} above other frames. + +On MS-Windows the @var{noactivate} argument has no effect. However, if +@var{frame} is a child frame (@pxref{Child Frames}), this function +usually focuses @var{frame} without raising it above other child +frames. + +If there is no window system support, this function does nothing. +@end defun + @deffn Command select-frame frame &optional norecord This function selects frame @var{frame}, temporarily disregarding the focus of the X server if any. The selection of @var{frame} lasts until @@ -2091,7 +2716,7 @@ becomes the selected terminal. This function then calls @code{select-window} as a subroutine, passing the window selected within @var{frame} as its first argument and @var{norecord} as its second argument (hence, if @var{norecord} is non-@code{nil}, this -avoids changing the order of recently selected windows nor the buffer +avoids changing the order of recently selected windows and the buffer list). @xref{Selecting Windows}. This function returns @var{frame}, or @code{nil} if @var{frame} has @@ -2147,20 +2772,64 @@ change it. @end defun @defvar focus-in-hook -This is a normal hook run when an Emacs frame gains input focus. +This is a normal hook run when an Emacs frame gains input focus. The +frame gaining focus is selected when this hook is run. @end defvar @defvar focus-out-hook -This is a normal hook run when an Emacs frame loses input focus. +This is a normal hook run when an Emacs frame has lost input focus and +no other Emacs frame has gained input focus instead. @end defvar @defopt focus-follows-mouse -This option is how you inform Emacs whether the window manager transfers -focus when the user moves the mouse. Non-@code{nil} says that it does. -When this is so, the command @code{other-frame} moves the mouse to a -position consistent with the new selected frame. +This option informs Emacs whether and how the window manager transfers +focus when you move the mouse pointer into a frame. It can have three +meaningful values: + +@table @asis +@item @code{nil} +The default value @code{nil} should be used when your window manager +follows a ``click-to-focus'' policy where you have to click the mouse +inside of a frame in order for that frame to gain focus. + +@item @code{t} +The value @code{t} should be used when your window manager has the focus +automatically follow the position of the mouse pointer but a frame that +gains focus is not raised automatically and may even remain occluded by +other window-system windows. + +@item @code{auto-raise} +The value @code{auto-raise} should be used when your window manager has +the focus automatically follow the position of the mouse pointer and a +frame that gains focus is raised automatically. +@end table + +If this option is non-@code{nil}, Emacs moves the mouse pointer to the +frame selected by @code{select-frame-set-input-focus}. That function is +used by a number of commands like, for example, @code{other-frame} and +@code{pop-to-buffer}. + +The distinction between the values @code{t} and @code{auto-raise} is not +needed for ``normal'' frames because the window manager usually takes +care of raising them. It is useful to automatically raise child frames +via @code{mouse-autoselect-window} (@pxref{Mouse Window +Auto-selection}). + +Note that this option does not distinguish ``sloppy'' focus (where the +frame that previously had focus retains focus as long as the mouse +pointer does not move into another window manager window) from +``strict'' focus (where a frame immediately loses focus when it's left +by the mouse pointer). Neither does it recognize whether your window +manager supports delayed focusing or auto-raising where you can +explicitly specify the time until a new frame gets focus or is +auto-raised. + +You can supply a ``focus follows mouse'' policy for individual Emacs +windows by customizing the variable @code{mouse-autoselect-window} +(@pxref{Mouse Window Auto-selection}). @end defopt + @node Visibility of Frames @section Visibility of Frames @cindex visible frame @@ -2169,16 +2838,26 @@ position consistent with the new selected frame. @cindex minimized frame @cindex frame visibility -A frame on a graphical display may be @dfn{visible}, @dfn{invisible}, -or @dfn{iconified}. If it is visible, its contents are displayed in -the usual manner. If it is iconified, its contents are not displayed, -but there is a little icon somewhere to bring the frame back into view -(some window managers refer to this state as @dfn{minimized} rather -than @dfn{iconified}, but from Emacs' point of view they are the same -thing). If a frame is invisible, it is not displayed at all. +A frame on a graphical display may be @dfn{visible}, @dfn{invisible}, or +@dfn{iconified}. If it is visible, its contents are displayed in the +usual manner. If it is iconified, its contents are not displayed, but +there is a little icon somewhere to bring the frame back into view (some +window managers refer to this state as @dfn{minimized} rather than +@dfn{iconified}, but from Emacs' point of view they are the same thing). +If a frame is invisible, it is not displayed at all. + +@cindex mapped frame +@cindex unmapped frame + The concept of visibility is strongly related to that of (un-)mapped +frames. A frame (or, more precisely, its window-system window) is and +becomes @dfn{mapped} when it is displayed for the first time and +whenever it changes its state of visibility from @code{iconified} or +@code{invisible} to @code{visible}. Conversely, a frame is and becomes +@dfn{unmapped} whenever it changes its status from @code{visible} to +@code{iconified} or @code{invisible}. Visibility is meaningless on text terminals, since only the selected -one is actually displayed in any case. +frame is actually displayed in any case. @defun frame-visible-p frame This function returns the visibility status of frame @var{frame}. The @@ -2192,22 +2871,28 @@ purposes of this function, even though only one frame is displayed. @deffn Command iconify-frame &optional frame This function iconifies frame @var{frame}. If you omit @var{frame}, it -iconifies the selected frame. +iconifies the selected frame. This usually makes all child frames of +@var{frame} (and their descendants) invisible (@pxref{Child Frames}). @end deffn @deffn Command make-frame-visible &optional frame -This function makes frame @var{frame} visible. If you omit -@var{frame}, it makes the selected frame visible. This does not raise -the frame, but you can do that with @code{raise-frame} if you wish -(@pxref{Raising and Lowering}). +This function makes frame @var{frame} visible. If you omit @var{frame}, +it makes the selected frame visible. This does not raise the frame, but +you can do that with @code{raise-frame} if you wish (@pxref{Raising and +Lowering}). + +Making a frame visible usually makes all its child frames (and their +descendants) visible as well (@pxref{Child Frames}). @end deffn @deffn Command make-frame-invisible &optional frame force This function makes frame @var{frame} invisible. If you omit -@var{frame}, it makes the selected frame invisible. +@var{frame}, it makes the selected frame invisible. Usually, this makes +all child frames of @var{frame} (and their descendants) invisible too +(@pxref{Child Frames}). Unless @var{force} is non-@code{nil}, this function refuses to make -@var{frame} invisible if all other frames are invisible.. +@var{frame} invisible if all other frames are invisible. @end deffn The visibility status of a frame is also available as a frame @@ -2223,27 +2908,80 @@ being rendered with double buffering. @var{frame} defaults to the selected frame. @end defun + @node Raising and Lowering -@section Raising and Lowering Frames +@section Raising, Lowering and Restacking Frames @cindex raising a frame @cindex lowering a frame - Most window systems use a desktop metaphor. Part of this metaphor -is the idea that system-level windows (e.g., Emacs frames) are -stacked in a notional third dimension perpendicular to the screen -surface. Where two overlap, the one higher up covers the one -underneath. You can @dfn{raise} or @dfn{lower} a frame using the -functions @code{raise-frame} and @code{lower-frame}. +@cindex restacking a frame +@cindex frame stacking order +@cindex frame Z-order +@cindex Z-order + Most window systems use a desktop metaphor. Part of this metaphor is +the idea that system-level windows (representing, e.g., Emacs frames) +are stacked in a notional third dimension perpendicular to the screen +surface. The order induced by stacking is total and usually referred to +as stacking (or Z-) order. Where the areas of two windows overlap, the +one higher up in that order will (partially) cover the one underneath. + + You can @dfn{raise} a frame to the top of that order or @dfn{lower} a +frame to its bottom by using the functions @code{raise-frame} and +@code{lower-frame}. You can @dfn{restack} a frame directly above or +below another frame using the function @code{frame-restack}. + + Note that all functions described below will respect the adherence of +frames (and all other window-system windows) to their respective z-group +(@pxref{Position Parameters}). For example, you usually cannot lower a +frame below that of the desktop window and you cannot raise a frame +whose @code{z-group} parameter is @code{nil} above the window-system's +taskbar or tooltip window. @deffn Command raise-frame &optional frame -This function raises frame @var{frame} (default, the selected frame). -If @var{frame} is invisible or iconified, this makes it visible. +This function raises frame @var{frame} (default, the selected frame) +above all other frames belonging to the same or a lower z-group as +@var{frame}. If @var{frame} is invisible or iconified, this makes it +visible. If @var{frame} is a child frame (@pxref{Child Frames}), this +raises @var{frame} above all other child frames of its parent. @end deffn @deffn Command lower-frame &optional frame -This function lowers frame @var{frame} (default, the selected frame). +This function lowers frame @var{frame} (default, the selected frame) +below all other frames belonging to the same or a higher z-group as +@var{frame}. If @var{frame} is a child frame (@pxref{Child Frames}), +this lowers @var{frame} below all other child frames of its parent. @end deffn +@defun frame-restack frame1 frame2 &optional above +This function restacks @var{frame1} below @var{frame2}. This implies +that if both frames are visible and their display areas overlap, +@var{frame2} will (partially) obscure @var{frame1}. If the optional +third argument @var{above} is non-@code{nil}, this function restacks +@var{frame1} above @var{frame2}. This means that if both frames are +visible and their display areas overlap, @var{frame1} will (partially) +obscure @var{frame2}. + +Technically, this function may be thought of as an atomic action +performed in two steps: The first step removes @var{frame1}'s +window-system window from the display. The second step reinserts +@var{frame1}'s window into the display below (above if @var{above} is +true) that of @var{frame2}. Hence the position of @var{frame2} in its +display's Z (stacking) order relative to all other frames excluding +@var{frame1} remains unaltered. + +Some window managers may refuse to restack windows. +@end defun + +Note that the effect of restacking will only hold as long as neither of +the involved frames is iconified or made invisible. You can use the +@code{z-group} (@pxref{Position Parameters}) frame parameter to add a +frame to a group of frames permanently shown above or below other +frames. As long as a frame belongs to one of these groups, restacking +it will only affect its relative stacking position within that group. +The effect of restacking frames belonging to different z-groups is +undefined. You can list frames in their current stacking order with the +function @code{frame-list-z-order} (@pxref{Finding All Frames}). + @defopt minibuffer-auto-raise If this is non-@code{nil}, activation of the minibuffer raises the frame that the minibuffer window is in. @@ -2265,6 +3003,7 @@ or @code{nil} (meaning the selected frame's terminal). If it does not refer to a text terminal, the return value is @code{nil}. @end defun + @node Frame Configurations @section Frame Configurations @cindex frame configuration @@ -2288,6 +3027,215 @@ Ordinarily, this function deletes all existing frames not listed in unwanted frames are iconified instead. @end defun + +@node Child Frames +@section Child Frames +@cindex child frames +@cindex parent frames + +Child frames are objects halfway between windows (@pxref{Windows}) and +``normal'' frames. Like windows, they are attached to an owning frame. +Unlike windows, they may overlap each other---changing the size or +position of one child frame does not change the size or position of any +of its sibling child frames. + + By design, operations to make or modify child frames are implemented +with the help of frame parameters (@pxref{Frame Parameters}) without any +specialized functions or customizable variables. Note that child frames +are meaningful on graphical terminals only. + + To create a new child frame or to convert a normal frame into a child +frame, set that frame's @code{parent-frame} parameter (@pxref{Frame +Interaction Parameters}) to that of an already existing frame. The +frame specified by that parameter will then be the frame's parent frame +as long as the parameter is not changed or reset. Technically, this +makes the child frame's window-system window a child window of the +parent frame's window-system window. + +@cindex top-level frame +@cindex reparent frame +@cindex nest frame + The @code{parent-frame} parameter can be changed at any time. Setting +it to another frame @dfn{reparents} the child frame. Setting it to +another child frame makes the frame a @dfn{nested} child frame. Setting +it to @code{nil} restores the frame's status as a @dfn{top-level +frame}---a frame whose window-system window is a child of its display's +root window. + + Since child frames can be arbitrarily nested, a frame can be both a +child and a parent frame. Also, the relative roles of child and parent +frame may be reversed at any time (though it's usually a good idea to +keep the size of a child frame sufficiently smaller than that of its +parent). An error will be signaled for the attempt to make a frame an +ancestor of itself. + + Most window-systems clip a child frame at the native edges +(@pxref{Frame Geometry}) of its parent frame---everything outside these +edges is usually invisible. A child frame's @code{left} and @code{top} +parameters specify a position relative to the top-left corner of its +parent's native frame. When the parent frame is resized, this position +remains conceptually unaltered. + + NS builds do not clip child frames at the parent frame's edges, +allowing them to be positioned so they do not obscure the parent frame +while still being visible themselves. + + Usually, moving a parent frame moves along all its child frames and +their descendants as well, keeping their relative positions unaltered. +Note that the hook @code{move-frame-functions} (@pxref{Frame Position}) +is run for a child frame only when the position of the child frame +relative to its parent frame changes. It is not run for a child frame +when the position of the parent frame changes. + + When a parent frame is resized, its child frames conceptually retain +their previous sizes and their positions relative to the left upper +corner of the parent. This means that a child frame may become +(partially) invisible when its parent frame shrinks. The parameter +@code{keep-ratio} (@pxref{Frame Interaction Parameters}) can be used to +resize and reposition a child frame proportionally whenever its parent +frame is resized. This may avoid obscuring parts of a frame when its +parent frame is shrunk. + + A visible child frame always appears on top of its parent frame thus +obscuring parts of it, except on NS builds where it may be positioned +beneath the parent. This is comparable to the window-system window of a +top-level frame which also always appears on top of its parent +window---the desktop's root window. When a parent frame is iconified or +made invisible (@pxref{Visibility of Frames}), its child frames are made +invisible. When a parent frame is deiconified or made visible, its +child frames are made visible. When a parent frame is about to be +deleted (@pxref{Deleting Frames}), its child frames are recursively +deleted before it. + + Whether a child frame can have a menu or tool bar is window-system or +window manager dependent. Most window-systems explicitly disallow menus +bars for child frames. It seems advisable to disable both, menu and +tool bars, via the frame's initial parameters settings. + + Usually, child frames do not exhibit window manager decorations like a +title bar or external borders (@pxref{Frame Geometry}). When the child +frame does not show a menu or tool bar, any other of the frame's borders +(@pxref{Layout Parameters}) can be used instead of the external borders. + + In particular, under X (but not when building with GTK+), the frame's +outer border can be used. On MS-Windows, specifying a non-zero outer +border width will show a one-pixel wide external border. Under all +window-systems, the internal border can be used. In either case, it's +advisable to disable a child frame's window manager decorations with the +@code{undecorated} frame parameter (@pxref{Management Parameters}). + + To resize or move an undecorated child frame with the mouse, special +frame parameters (@pxref{Mouse Dragging Parameters}) have to be used. +The internal border of a child frame, if present, can be used to resize +the frame with the mouse, provided that frame has a non-@code{nil} +@code{drag-internal-border} parameter. If set, the @code{snap-width} +parameter indicates the number of pixels where the frame @dfn{snaps} at +the respective edge or corner of its parent frame. + + There are two ways to drag an entire child frame with the mouse: The +@code{drag-with-mode-line} parameter, if non-@code{nil}, allows to drag +a frame without minibuffer window (@pxref{Minibuffer Windows}) via the +mode line area of its bottommost window. The +@code{drag-with-header-line} parameter, if non-@code{nil}, allows to +drag the frame via the header line area of its topmost window. + + In order to give a child frame a draggable header or mode line, the +window parameters @code{mode-line-format} and @code{header-line-format} +are handy (@pxref{Window Parameters}). These allow to remove an +unwanted mode line (when @code{drag-with-header-line} is chosen) and to +remove mouse-sensitive areas which might interfere with frame dragging. + + To avoid that dragging moves a frame completely out of its parent's +native frame, something which might happen when the mouse cursor +overshoots and makes the frame difficult to retrieve once the mouse +button has been released, it is advisable to set the frame's +@code{top-visible} or @code{bottom-visible} parameter correspondingly. + + The @code{top-visible} parameter specifies the number of pixels at the +top of the frame that always remain visible within the parent's native +frame during dragging and should be set when specifying a non-@code{nil} +@code{drag-with-header-line} parameter. The @code{bottom-visible} +parameter specifies the number of pixels at the bottom of the frame that +always remain visible within the parent's native frame during dragging +and should be preferred when specifying a non-@code{nil} +@code{drag-with-mode-line} parameter. + + When a child frame is used for displaying a buffer via +@code{display-buffer-in-child-frame} (@pxref{Display Action Functions}), +the frame's @code{auto-hide-function} parameter (@pxref{Frame +Interaction Parameters}) can be set to a function, in order to +appropriately deal with the frame when the window displaying the buffer +shall be quit. + + When a child frame is used during minibuffer interaction, for example, +to display completions in a separate window, the @code{minibuffer-exit} +parameter (@pxref{Frame Interaction Parameters}) is useful in order to +deal with the frame when the minibuffer is exited. + + The behavior of child frames deviates from that of top-level frames in +a number of other ways as well. Here we sketch a few of them: + +@itemize @bullet +@item +The semantics of maximizing and iconifying child frames is highly +window-system dependent. As a rule, applications should never invoke +these operations for child frames. + +@item +Raising, lowering and restacking child frames (@pxref{Raising and +Lowering}) or changing the @code{z-group} (@pxref{Position Parameters}) +of a child frame changes only the stacking order of child frames with +the same parent. + +@item +Many window-systems are not able to change the opacity (@pxref{Font and +Color Parameters}) of child frames. + +@item +Transferring focus from a child frame to an ancestor that is not its +parent by clicking with the mouse in a visible part of that ancestor's +window may fail with some window-systems. You may have to click into +the direct parent's window-system window first. + +@item +Window managers might not bother to extend their focus follows mouse +policy to child frames. Customizing @code{mouse-autoselect-window} can +help in this regard (@pxref{Mouse Window Auto-selection}). + +@item +Dropping (@pxref{Drag and Drop}) on child frames is not guaranteed to +work on all window-systems. Some will drop the object on the parent +frame or on some ancestor instead. +@end itemize + + The following two functions can be useful when working with child and +parent frames: + +@defun frame-parent &optional frame +This function returns the parent frame of @var{frame}. The parent frame +of @var{frame} is the Emacs frame whose window-system window is the +parent window of @var{frame}'s window-system window. If such a frame +exists, @var{frame} is considered a child frame of that frame. + +This function returns @code{nil} if @var{frame} has no parent frame. +@end defun + +@defun frame-ancestor-p &optional ancestor descendant +This functions returns non-@code{nil} if @var{ancestor} is an ancestor +of @var{descendant}. @var{ancestor} is an ancestor of @var{descendant} +when it is either @var{descendant}'s parent frame or it is an ancestor +of @var{descendant}'s parent frame. Both, @var{ancestor} and +@var{descendant} must specify live frames and default to the selected +frame. +@end defun + +Note also the function @code{window-largest-empty-rectangle} +(@pxref{Coordinates and Windows}) which can be used to inscribe a child +frame in the largest empty area of an existing window. This can be +useful to avoid that a child frame obscures any text shown in that +window. + + @node Mouse Tracking @section Mouse Tracking @cindex mouse tracking @@ -3203,9 +4151,3 @@ ever be developed and distributed noncommercially. This variable's value is @code{t} if no X window manager is in use. @end defvar @end ignore - -@ignore -@item -The functions @code{x-pixel-width} and @code{x-pixel-height} return the -width and height of an X Window frame, measured in pixels. -@end ignore diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi index 81e3eee10cf..283f74ff5d2 100644 --- a/doc/lispref/functions.texi +++ b/doc/lispref/functions.texi @@ -1862,6 +1862,13 @@ More specifically, the composition of the two functions behaves like: @node Porting old advice @subsection Adapting code using the old defadvice @cindex old advices, porting +@c NB: The following index entries deliberately avoid ``old'', +@c an adjective that does not come to mind for those who grew up +@c on ‘defadvice’ et al. For those folks, that way is ``current''. +@c They discover its oldness reading this node. +@cindex advices, porting from @code{defadvice} +@findex defadvice +@findex ad-activate A lot of code uses the old @code{defadvice} mechanism, which is largely made obsolete by the new @code{advice-add}, whose implementation and semantics is diff --git a/doc/lispref/hooks.texi b/doc/lispref/hooks.texi index 0ac5b08c87b..6443464f0ed 100644 --- a/doc/lispref/hooks.texi +++ b/doc/lispref/hooks.texi @@ -241,11 +241,6 @@ Redisplay}. @itemx window-scroll-functions @itemx window-size-change-functions @xref{Window Hooks}. - -@item window-text-change-functions -@vindex window-text-change-functions -Functions to call in redisplay when text in the window might change. - @end table @ignore diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi index 8eab2818f97..966d8f18b17 100644 --- a/doc/lispref/lists.texi +++ b/doc/lispref/lists.texi @@ -1511,12 +1511,12 @@ respects. A property list behaves like an association list in which each key can occur only once. @xref{Property Lists}, for a comparison of property lists and association lists. -@defun assoc key alist +@defun assoc key alist &optional testfn This function returns the first association for @var{key} in @var{alist}, comparing @var{key} against the alist elements using -@code{equal} (@pxref{Equality Predicates}). It returns @code{nil} if no -association in @var{alist} has a @sc{car} @code{equal} to @var{key}. -For example: +@var{testfn} if non-nil, or @code{equal} if nil (@pxref{Equality +Predicates}). It returns @code{nil} if no association in @var{alist} +has a @sc{car} equal to @var{key}. For example: @smallexample (setq trees '((pine . cones) (oak . acorns) (maple . seeds))) @@ -1561,11 +1561,11 @@ this as reverse @code{assoc}, finding the key for a given value. @defun assq key alist This function is like @code{assoc} in that it returns the first association for @var{key} in @var{alist}, but it makes the comparison -using @code{eq} instead of @code{equal}. @code{assq} returns @code{nil} -if no association in @var{alist} has a @sc{car} @code{eq} to @var{key}. -This function is used more often than @code{assoc}, since @code{eq} is -faster than @code{equal} and most alists use symbols as keys. -@xref{Equality Predicates}. +using @code{eq}. @code{assq} returns @code{nil} if no association in +@var{alist} has a @sc{car} @code{eq} to @var{key}. This function is +used more often than @code{assoc}, since @code{eq} is faster than +@code{equal} and most alists use symbols as keys. @xref{Equality +Predicates}. @smallexample (setq trees '((pine . cones) (oak . acorns) (maple . seeds))) diff --git a/doc/lispref/loading.texi b/doc/lispref/loading.texi index 1199cfaa0f0..d925c8c8f65 100644 --- a/doc/lispref/loading.texi +++ b/doc/lispref/loading.texi @@ -900,8 +900,7 @@ if loading the file fails. Normally, @code{require} returns @var{feature}. If loading the file succeeds but does not provide @var{feature}, -@code{require} signals an error, @samp{Required feature @var{feature} -was not provided}. +@code{require} signals an error about the missing feature. @end defun @defun featurep feature &optional subfeature diff --git a/doc/lispref/macros.texi b/doc/lispref/macros.texi index 5638dfaecf8..63a65a81304 100644 --- a/doc/lispref/macros.texi +++ b/doc/lispref/macros.texi @@ -255,10 +255,6 @@ of constants and nonconstant parts. To make this easier, use the @end example @end example - The body of a macro definition can include a @code{declare} form, -which specifies additional properties about the macro. @xref{Declare -Form}. - @node Problems with Macros @section Common Problems Using Macros @cindex macro caveats diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index 0913d7491f3..f7013da9433 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -7,11 +7,12 @@ @chapter Major and Minor Modes @cindex mode - A @dfn{mode} is a set of definitions that customize Emacs and can be -turned on and off while you edit. There are two varieties of modes: -@dfn{major modes}, which are mutually exclusive and used for editing -particular kinds of text, and @dfn{minor modes}, which provide features -that users can enable individually. + A @dfn{mode} is a set of definitions that customize Emacs behavior +in useful ways. There are two varieties of modes: @dfn{minor modes}, +which provide features that users can turn on and off while editing; +and @dfn{major modes}, which are used for editing or interacting with +a particular kind of text. Each buffer has exactly one @dfn{major +mode} at a time. This chapter describes how to write both major and minor modes, how to indicate them in the mode line, and how they run hooks supplied by the @@ -196,12 +197,15 @@ from the buffer-local hook list instead of from the global hook list. @cindex major mode @cindex major mode command - Major modes specialize Emacs for editing particular kinds of text. -Each buffer has one major mode at a time. Every major mode is -associated with a @dfn{major mode command}, whose name should end in -@samp{-mode}. This command takes care of switching to that mode in the -current buffer, by setting various buffer-local variables such as a -local keymap. @xref{Major Mode Conventions}. + Major modes specialize Emacs for editing or interacting with +particular kinds of text. Each buffer has exactly one major mode at a +time. Every major mode is associated with a @dfn{major mode command}, +whose name should end in @samp{-mode}. This command takes care of +switching to that mode in the current buffer, by setting various +buffer-local variables such as a local keymap. @xref{Major Mode +Conventions}. Note that unlike minor modes there is no way to ``turn +off'' a major mode, instead the buffer must be switched to a different +one. The least specialized major mode is called @dfn{Fundamental mode}, which has no mode-specific definitions or variable settings. @@ -816,14 +820,15 @@ which in turn may have been changed in a mode hook. Here is a hypothetical example: @example +(defvar hypertext-mode-map + (let ((map (make-sparse-keymap))) + (define-key map [down-mouse-3] 'do-hyper-link) + map)) + (define-derived-mode hypertext-mode text-mode "Hypertext" - "Major mode for hypertext. -\\@{hypertext-mode-map@}" - (setq case-fold-search nil)) - -(define-key hypertext-mode-map - [down-mouse-3] 'do-hyper-link) + "Major mode for hypertext." + (setq-local case-fold-search nil)) @end example Do not write an @code{interactive} spec in the definition; @@ -1732,7 +1737,9 @@ holds a @dfn{mode line construct}: a template that controls what is displayed on the buffer's mode line. The value of @code{header-line-format} specifies the buffer's header line in the same way. All windows for the same buffer use the same -@code{mode-line-format} and @code{header-line-format}. +@code{mode-line-format} and @code{header-line-format} unless a +@code{mode-line-format} or @code{header-line-format} parameter has been +specified for that window (@pxref{Window Parameters}). For efficiency, Emacs does not continuously recompute each window's mode line and header line. It does so when circumstances appear to call @@ -1967,6 +1974,14 @@ displays the buffer percentage and, optionally, the buffer size, the line number and the column number. @end defvar +@defopt mode-line-percent-position +This option is used in @code{mode-line-position}. Its value specifies +both the buffer percentage to display (one of @code{nil}, @code{"%o"}, +@code{"%p"}, @code{"%P"} or @code{"%q"}, @pxref{%-Constructs}) and a +width to space-fill or truncate to. You are recommended to set this +option with the @code{customize-variable} facility. +@end defopt + @defvar vc-mode The variable @code{vc-mode}, buffer-local in each buffer, records whether the buffer's visited file is maintained with version control, @@ -2106,7 +2121,12 @@ The current buffer name, obtained with the @code{buffer-name} function. @xref{Buffer Names}. @item %c -The current column number of point. +The current column number of point, counting from zero starting at the +left margin of the window. + +@item %C +The current column number of point, counting from one starting at the +left margin of the window. @item %e When Emacs is nearly out of memory for Lisp objects, a brief message @@ -2137,6 +2157,12 @@ of the buffer. @samp{Narrow} when narrowing is in effect; nothing otherwise (see @code{narrow-to-region} in @ref{Narrowing}). +@item %o +The degree of @dfn{travel} of the window through (the visible portion +of) the buffer, i.e. the size of the text above the top of the window +expressed as a percentage of all the text outside the window, or +@samp{Top}, @samp{Bottom} or @samp{All}. + @item %p The percentage of the buffer text above the @strong{top} of window, or @samp{Top}, @samp{Bottom} or @samp{All}. Note that the default mode @@ -2148,6 +2174,10 @@ the window (which includes the text visible in the window, as well as the text above the top), plus @samp{Top} if the top of the buffer is visible on screen; or @samp{Bottom} or @samp{All}. +@item %q +The percentages of text above both the @strong{top} and the +@strong{bottom} of the window, separated by @samp{-}, or @samp{All}. + @item %s The status of the subprocess belonging to the current buffer, obtained with @code{process-status}. @xref{Process Information}. diff --git a/doc/lispref/nonascii.texi b/doc/lispref/nonascii.texi index 29930c5312d..039201feca1 100644 --- a/doc/lispref/nonascii.texi +++ b/doc/lispref/nonascii.texi @@ -142,7 +142,7 @@ be one of the following: @table @code @item exact The result must be accurate. The function may need to encode and -decode a large part of the buffer. +decode a large part of the buffer, which is expensive and can be slow. @item approximate The value can be an approximation. The function may avoid expensive processing and return an inexact result. @@ -619,6 +619,29 @@ Corresponds to the Unicode @code{Simple_Titlecase_Mapping} property. character of a word needs to be capitalized. The value of this property is a single character. For unassigned codepoints, the value is @code{nil}, which means the character itself. + +@item special-uppercase +Corresponds to Unicode language- and context-independent special upper-casing +rules. The value of this property is a string (which may be empty). For +example mapping for @code{U+00DF} (@sc{latin small letter sharp s}) is +@code{"SS"}. For characters with no special mapping, the value is @code{nil} +which means @code{uppercase} property needs to be consulted instead. + +@item special-lowercase +Corresponds to Unicode language- and context-independent special lower-casing +rules. The value of this property is a string (which may be empty). For +example mapping for @code{U+0130} (@sc{latin capital letter i with dot above}) +the value is @code{"i\u0307"} (i.e. 2-character string consisting of @sc{latin +small letter i} followed by @sc{combining dot above}). For characters with no +special mapping, the value is @code{nil} which means @code{lowercase} property +needs to be consulted instead. + +@item special-titlecase +Corresponds to Unicode unconditional special title-casing rules. The value of +this property is a string (which may be empty). For example mapping for +@code{U+FB01} (@sc{latin small ligature fi}) the value is @code{"Fi"}. For +characters with no special mapping, the value is @code{nil} which means +@code{titlecase} property needs to be consulted instead. @end table @defun get-char-code-property char propname @@ -1017,10 +1040,14 @@ alternative encodings for the same characters; for example, there are three coding systems for the Cyrillic (Russian) alphabet: ISO, Alternativnyj, and KOI8. +@vindex undecided@r{ coding system} +@vindex prefer-utf-8@r{ coding system} Every coding system specifies a particular set of character code conversions, but the coding system @code{undecided} is special: it leaves the choice unspecified, to be chosen heuristically for each -file, based on the file's data. +file, based on the file's data. The coding system @code{prefer-utf-8} +is like @code{undecided}, but it prefers to choose @code{utf-8} when +possible. In general, a coding system doesn't guarantee roundtrip identity: decoding a byte sequence using coding system, then encoding the @@ -1124,7 +1151,7 @@ encode the buffer contents. (@pxref{Specifying Coding Systems}), or implicitly using a default mechanism (@pxref{Default Coding Systems}). But these methods may not completely specify what to do. For example, they may choose a coding -system such as @code{undefined} which leaves the character code +system such as @code{undecided} which leaves the character code conversion to be determined from the data. In these cases, the I/O operation finishes the job of choosing a coding system. Very often you will want to find out afterwards which coding system was chosen. @@ -1426,19 +1453,21 @@ Otherwise, it asks the user to choose from a list of coding systems which can encode all the text, and returns the user's choice. @var{default-coding-system} can also be a list whose first element is -t and whose other elements are coding systems. Then, if no coding +@code{t} and whose other elements are coding systems. Then, if no coding system in the list can handle the text, @code{select-safe-coding-system} queries the user immediately, without trying any of the three -alternatives described above. - -The optional argument @var{accept-default-p}, if non-@code{nil}, -should be a function to determine whether a coding system selected -without user interaction is acceptable. @code{select-safe-coding-system} -calls this function with one argument, the base coding system of the -selected coding system. If @var{accept-default-p} returns @code{nil}, -@code{select-safe-coding-system} rejects the silently selected coding -system, and asks the user to select a coding system from a list of -possible candidates. +alternatives described above. This is handy for checking only the +coding systems in the list. + +The optional argument @var{accept-default-p} determines whether a +coding system selected without user interaction is acceptable. If +it's omitted or @code{nil}, such a silent selection is always +acceptable. If it is non-@code{nil}, it should be a function; +@code{select-safe-coding-system} calls this function with one +argument, the base coding system of the selected coding system. If +the function returns @code{nil}, @code{select-safe-coding-system} +rejects the silently selected coding system, and asks the user to +select a coding system from a list of possible candidates. @vindex select-safe-coding-system-accept-default-p If the variable @code{select-safe-coding-system-accept-default-p} is @@ -1459,6 +1488,18 @@ similar functions). If it detects an apparent inconsistency, coding system. @end defun +@defvar select-safe-coding-system-function +This variable names the function to be called to request the user to +select a proper coding system for encoding text when the default +coding system for an output operation cannot safely encode that text. +The default value of this variable is @code{select-safe-coding-system}. +Emacs primitives that write text to files, such as +@code{write-region}, or send text to other processes, such as +@code{process-send-region}, normally call the value of this variable, +unless @code{coding-system-for-write} is bound to a non-@code{nil} +value (@pxref{Specifying Coding Systems}). +@end defvar + Here are two functions you can use to let the user specify a coding system, with completion. @xref{Completion}. @@ -1719,7 +1760,9 @@ including @code{file-coding-system-alist}, @defvar coding-system-for-write This works much like @code{coding-system-for-read}, except that it applies to output rather than input. It affects writing to files, -as well as sending output to subprocesses and net connections. +as well as sending output to subprocesses and net connections. It +also applies to encoding command-line arguments with which Emacs +invokes subprocesses. When a single operation does both input and output, as do @code{call-process-region} and @code{start-process}, both @@ -1727,6 +1770,23 @@ When a single operation does both input and output, as do affect it. @end defvar +@defvar coding-system-require-warning +Binding @code{coding-system-for-write} to a non-@code{nil} value +prevents output primitives from calling the function specified by +@code{select-safe-coding-system-function} (@pxref{User-Chosen Coding +Systems}). This is because @kbd{C-x RET c} +(@code{universal-coding-system-argument}) works by binding +@code{coding-system-for-write}, and Emacs should obey user selection. +If a Lisp program binds @code{coding-system-for-write} to a value that +might not be safe for encoding the text to be written, it can also bind +@code{coding-system-require-warning} to a non-@code{nil} value, which +will force the output primitives to check the encoding by calling the +value of @code{select-safe-coding-system-function} even though +@code{coding-system-for-write} is non-@code{nil}. Alternatively, call +@code{select-safe-coding-system} explicitly before using the specified +encoding. +@end defvar + @defopt inhibit-eol-conversion When this variable is non-@code{nil}, no end-of-line conversion is done, no matter which coding system is specified. This applies to all the diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi index deae5fd85dc..3fdc94169bd 100644 --- a/doc/lispref/numbers.texi +++ b/doc/lispref/numbers.texi @@ -427,8 +427,6 @@ the following argument. It returns @code{t} if so, @code{nil} otherwise. @defun max number-or-marker &rest numbers-or-markers This function returns the largest of its arguments. -If any of the arguments is floating point, the value is returned -as floating point, even if it was given as an integer. @example (max 20) @@ -436,14 +434,12 @@ as floating point, even if it was given as an integer. (max 1 2.5) @result{} 2.5 (max 1 3 2.5) - @result{} 3.0 + @result{} 3 @end example @end defun @defun min number-or-marker &rest numbers-or-markers This function returns the smallest of its arguments. -If any of the arguments is floating point, the value is returned -as floating point, even if it was given as an integer. @example (min -4 1) diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi index 56049af60a1..daa397175c3 100644 --- a/doc/lispref/objects.texi +++ b/doc/lispref/objects.texi @@ -25,9 +25,10 @@ but not for @emph{the} type of an object. which all other types are constructed, are called @dfn{primitive types}. Each object belongs to one and only one primitive type. These types include @dfn{integer}, @dfn{float}, @dfn{cons}, @dfn{symbol}, -@dfn{string}, @dfn{vector}, @dfn{hash-table}, @dfn{subr}, and -@dfn{byte-code function}, plus several special types, such as -@dfn{buffer}, that are related to editing. (@xref{Editing Types}.) +@dfn{string}, @dfn{vector}, @dfn{hash-table}, @dfn{subr}, +@dfn{byte-code function}, and @dfn{record}, plus several special +types, such as @dfn{buffer}, that are related to editing. +(@xref{Editing Types}.) Each primitive type has a corresponding Lisp function that checks whether an object is a member of that type. @@ -154,6 +155,8 @@ latter are unique to Emacs Lisp. expression, more fundamental but less pretty. * Primitive Function Type:: A function written in C, callable from Lisp. * Byte-Code Type:: A function written in Lisp, then compiled. +* Record Type:: Compound objects with programmer-defined types. +* Type Descriptors:: Objects holding information about types. * Autoload Type:: A type used for automatically loading seldom-used functions. * Finalizer Type:: Runs code when no longer reachable. @@ -280,11 +283,11 @@ character @kbd{a}. ?Q @result{} 81 ?q @result{} 113 @end example - You can use the same syntax for punctuation characters, but it is -often a good idea to add a @samp{\} so that the Emacs commands for -editing Lisp code don't get confused. For example, @samp{?\(} is the -way to write the open-paren character. If the character is @samp{\}, -you @emph{must} use a second @samp{\} to quote it: @samp{?\\}. + You can use the same syntax for punctuation characters. However, if +the punctuation character has a special syntactic meaning in Lisp, you +must quote it with a @samp{\}. For example, @samp{?\(} is the way to +write the open-paren character. Likewise, if the character is +@samp{\}, you must use a second @samp{\} to quote it: @samp{?\\}. @cindex whitespace @cindex bell character @@ -333,18 +336,19 @@ escape character; this has nothing to do with the character @key{ESC}. @samp{\s} is meant for use in character constants; in string constants, just write the space. - A backslash is allowed, and harmless, preceding any character without -a special escape meaning; thus, @samp{?\+} is equivalent to @samp{?+}. -There is no reason to add a backslash before most characters. However, -you should add a backslash before any of the characters -@samp{()\|;'`"#.,} to avoid confusing the Emacs commands for editing -Lisp code. You can also add a backslash before whitespace characters such as -space, tab, newline and formfeed. However, it is cleaner to use one of -the easily readable escape sequences, such as @samp{\t} or @samp{\s}, -instead of an actual whitespace character such as a tab or a space. -(If you do write backslash followed by a space, you should write -an extra space after the character constant to separate it from the -following text.) + A backslash is allowed, and harmless, preceding any character +without a special escape meaning; thus, @samp{?\+} is equivalent to +@samp{?+}. There is no reason to add a backslash before most +characters. However, you must add a backslash before any of the +characters @samp{()[]\;"}, and you should add a backslash before any +of the characters @samp{|'`#.,} to avoid confusing the Emacs commands +for editing Lisp code. You can also add a backslash before whitespace +characters such as space, tab, newline and formfeed. However, it is +cleaner to use one of the easily readable escape sequences, such as +@samp{\t} or @samp{\s}, instead of an actual whitespace character such +as a tab or a space. (If you do write backslash followed by a space, +you should write an extra space after the character constant to +separate it from the following text.) @node General Escape Syntax @subsubsection General Escape Syntax @@ -1347,6 +1351,28 @@ The printed representation and read syntax for a byte-code function object is like that for a vector, with an additional @samp{#} before the opening @samp{[}. +@node Record Type +@subsection Record Type + + A @dfn{record} is much like a @code{vector}. However, the first +element is used to hold its type as returned by @code{type-of}. The +purpose of records is to allow programmers to create objects with new +types that are not built into Emacs. + + @xref{Records}, for functions that work with records. + +@node Type Descriptors +@subsection Type Descriptors + + A @dfn{type descriptor} is a @code{record} which holds information +about a type. Slot 1 in the record must be a symbol naming the type, and +@code{type-of} relies on this to return the type of @code{record} +objects. No other type descriptor slot is used by Emacs; they are +free for use by Lisp extensions. + +An example of a type descriptor is any instance of +@code{cl-structure-class}. + @node Autoload Type @subsection Autoload Type @@ -1959,6 +1985,9 @@ with references to further information. @item processp @xref{Processes, processp}. +@item recordp +@xref{Record Type, recordp}. + @item sequencep @xref{Sequence Functions, sequencep}. @@ -2022,6 +2051,8 @@ This function returns a symbol naming the primitive type of @code{marker}, @code{mutex}, @code{overlay}, @code{process}, @code{string}, @code{subr}, @code{symbol}, @code{thread}, @code{vector}, @code{window}, or @code{window-configuration}. +However, if @var{object} is a record, the type specified by its first +slot is returned; @ref{Records}. @example (type-of 1) @@ -2033,6 +2064,8 @@ This function returns a symbol naming the primitive type of @result{} symbol (type-of '(x)) @result{} cons +(type-of (record 'foo)) + @result{} foo @end group @end example @end defun diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index f2f74adb67d..53744b52396 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -337,10 +337,10 @@ Do not display a splash screen. Run without an interactive terminal. @xref{Batch Mode}. @item --daemon -@itemx --old-daemon -@itemx --new-daemon +@itemx --bg-daemon +@itemx --fg-daemon Do not initialize any display; just start a server. -(An ``old-style'' daemon automatically runs in the background.) +(A ``background'' daemon automatically runs in the background.) @item --no-init-file @itemx -q @@ -2701,7 +2701,10 @@ This does not depend on one of the libraries linked to Emacs. Since all these libraries emit different events on notified file changes, there is the Emacs library @code{filenotify} which provides a -unique interface. +unified interface. Lisp programs that want to receive file +notifications should always use this library in preference to the +native ones. + @defun file-notify-add-watch file flags callback Add a watch for filesystem events pertaining to @var{file}. This diff --git a/doc/lispref/package.texi b/doc/lispref/package.texi index 6066ea9a936..af05d1ef58c 100644 --- a/doc/lispref/package.texi +++ b/doc/lispref/package.texi @@ -54,7 +54,8 @@ prefix used in the program (@pxref{Coding Conventions}). @item Version A version number, in a form that the function @code{version-to-list} understands (e.g., @samp{11.86}). Each release of a package should be -accompanied by an increase in the version number. +accompanied by an increase in the version number so that it will be +recognized as an upgrade by users querying the package archive. @item Brief description This is shown when the package is listed in the Package Menu. It @@ -71,8 +72,9 @@ once it is installed. A list of other packages (possibly including minimal acceptable version numbers) on which this package depends. The list may be empty, meaning this package has no dependencies. Otherwise, -installing this package also automatically installs its dependencies; -if any dependency cannot be found, the package cannot be installed. +installing this package also automatically installs its dependencies, +recursively; if any dependency cannot be found, the package cannot be +installed. @end table @cindex content directory, package @@ -212,8 +214,8 @@ subdirectories of the content directory. One of the files in the content directory must be named @file{@var{name}-pkg.el}. It must contain a single Lisp form, consisting of a call to the function @code{define-package}, described -below. This defines the package's version, brief description, and -requirements. +below. This defines the package's attributes: version, brief +description, and requirements. For example, if we distribute version 1.3 of the superfrobnicator as a multi-file package, the tar file would be @@ -286,9 +288,9 @@ form @code{(@var{id} . @var{location})}, where @var{id} is the name of the archive (a string) and @var{location} is its @dfn{base location} (a string). -If the base location starts with @samp{http:}, it is treated as a HTTP -URL, and packages are downloaded from this archive via HTTP (as is the -case for the default GNU archive). +If the base location starts with @samp{http:} or @samp{https:}, it +is treated as an HTTP(S) URL, and packages are downloaded from this +archive via HTTP(S) (as is the case for the default GNU archive). Otherwise, the base location should be a directory name. In this case, Emacs retrieves packages from this archive via ordinary file diff --git a/doc/lispref/positions.texi b/doc/lispref/positions.texi index 7c30fe977ca..9fd4bd8fe8e 100644 --- a/doc/lispref/positions.texi +++ b/doc/lispref/positions.texi @@ -432,11 +432,16 @@ prints a message reporting the number of lines, words, and characters in the buffer, or in the region if the region is active. @end deffn -@defun line-number-at-pos &optional pos +@defun line-number-at-pos &optional pos absolute @cindex line number This function returns the line number in the current buffer -corresponding to the buffer position @var{pos}. If @var{pos} is @code{nil} -or omitted, the current buffer position is used. +corresponding to the buffer position @var{pos}. If @var{pos} is +@code{nil} or omitted, the current buffer position is used. If +@var{absolute} is @code{nil}, the default, counting starts at +@code{(point-min)}, so the value refers to the contents of the +accessible portion of the (potentially narrowed) buffer. If +@var{absolute} is non-@code{nil}, ignore any narrowing and return +the absolute line number. @end defun @ignore diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index c47c447e1b5..7746a3268b7 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -299,8 +299,11 @@ system, much like text written into a file. @xref{Coding Systems}. @defun call-process program &optional infile destination display &rest args This function calls @var{program} and waits for it to finish. -The current working directory of the subprocess is -@code{default-directory}. +The current working directory of the subprocess is set to the current +buffer's value of @code{default-directory} if that is local (as +determined by @code{unhandled-file-name-directory}), or "~" otherwise. +If you want to run a process in a remote directory use +@code{process-file}. The standard input for the new process comes from file @var{infile} if @var{infile} is not @code{nil}, and from the null device otherwise. @@ -678,6 +681,12 @@ created with @code{make-pipe-process}, described below. The original argument list, modified with the actual connection information, is available via the @code{process-contact} function. + +The current working directory of the subprocess is set to the current +buffer's value of @code{default-directory} if that is local (as +determined by `unhandled-file-name-directory'), or "~" otherwise. If +you want to run a process in a remote directory use +@code{start-file-process}. @end defun @defun make-pipe-process &rest args @@ -3333,90 +3342,34 @@ dotted notation. @node Bindat Examples @subsection Examples of Byte Unpacking and Packing @c FIXME? This seems a very long example for something that is not used -@c very often. As of 24.1, gdb-mi.el is the only user of bindat.el in Emacs. +@c very often. As of 25.2, gdb-mi.el is the only user of bindat.el in Emacs. @c Maybe one or both of these examples should just be moved to the @c commentary of bindat.el. - Here is a complete example of byte unpacking and packing: + Here are two complete examples that use bindat.el. +The first shows simple byte packing: @lisp (require 'bindat) -(defvar fcookie-index-spec - '((:version u32) - (:count u32) - (:longest u32) - (:shortest u32) - (:flags u32) - (:delim u8) - (:ignored fill 3) - (:offset repeat (:count) (:foo u32))) - "Description of a fortune cookie index file's contents.") - -(defun fcookie (cookies &optional index) - "Display a random fortune cookie from file COOKIES. -Optional second arg INDEX specifies the associated index -filename, by default \"COOKIES.dat\". Display cookie text -in buffer \"*Fortune Cookie: BASENAME*\", where BASENAME -is COOKIES without the directory part." - (interactive "fCookies file: ") - (let* ((info (with-temp-buffer - (insert-file-contents-literally - (or index (concat cookies ".dat"))) - (bindat-unpack fcookie-index-spec - (buffer-string)))) - (sel (random (bindat-get-field info :count))) - (beg (cdar (bindat-get-field info :offset sel))) - (end (or (cdar (bindat-get-field info - :offset (1+ sel))) - (nth 7 (file-attributes cookies))))) - (switch-to-buffer - (get-buffer-create - (format "*Fortune Cookie: %s*" - (file-name-nondirectory cookies)))) - (erase-buffer) - (insert-file-contents-literally - cookies nil beg (- end 3)))) - -(defun fcookie-create-index (cookies &optional index delim) - "Scan file COOKIES, and write out its index file. -Optional arg INDEX specifies the index filename, which by -default is \"COOKIES.dat\". Optional arg DELIM specifies the -unibyte character that, when found on a line of its own in -COOKIES, indicates the border between entries." - (interactive "fCookies file: ") - (setq delim (or delim ?%)) - (let ((delim-line (format "\n%c\n" delim)) - (count 0) - (max 0) - min p q len offsets) - (unless (= 3 (string-bytes delim-line)) - (error "Delimiter cannot be represented in one byte")) - (with-temp-buffer - (insert-file-contents-literally cookies) - (while (and (setq p (point)) - (search-forward delim-line (point-max) t) - (setq len (- (point) 3 p))) - (setq count (1+ count) - max (max max len) - min (min (or min max) len) - offsets (cons (1- p) offsets)))) - (with-temp-buffer - (set-buffer-multibyte nil) - (insert - (bindat-pack - fcookie-index-spec - `((:version . 2) - (:count . ,count) - (:longest . ,max) - (:shortest . ,min) - (:flags . 0) - (:delim . ,delim) - (:offset . ,(mapcar (lambda (o) - (list (cons :foo o))) - (nreverse offsets)))))) - (let ((coding-system-for-write 'raw-text-unix)) - (write-file (or index (concat cookies ".dat"))))))) +(defun rfc868-payload () + (bindat-pack + '((now-hi u16) + (now-lo u16)) + ;; Emacs uses Unix epoch, while RFC868 epoch + ;; is 1900-01-01 00:00:00, which is 2208988800 + ;; (or #x83aa7e80) seconds more. + (let ((now (time-add nil '(#x83aa #x7e80)))) + `((now-hi . ,(car now)) + (now-lo . ,(cadr now)))))) + +(let ((s (rfc868-payload))) + (list (multibyte-string-p s) + (mapconcat (lambda (byte) + (format "%02x" byte)) + s " ") + (current-time-string))) + @result{} (nil "dc 6d 17 01" "Fri Mar 10 13:13:53 2017") @end lisp The following is an example of defining and unpacking a complex diff --git a/doc/lispref/records.texi b/doc/lispref/records.texi new file mode 100644 index 00000000000..7cc36f14068 --- /dev/null +++ b/doc/lispref/records.texi @@ -0,0 +1,90 @@ +@c -*-texinfo-*- +@c This is part of the GNU Emacs Lisp Reference Manual. +@c Copyright (C) 2017 Free Software +@c Foundation, Inc. +@c See the file elisp.texi for copying conditions. +@node Records +@chapter Records +@cindex record + + The purpose of records is to allow programmers to create objects +with new types that are not built into Emacs. They are used as the +underlying representation of @code{cl-defstruct} and @code{defclass} +instances. + + Internally, a record object is much like a vector; its slots can be +accessed using @code{aref} and it can be copied using +@code{copy-sequence}. However, the first slot is used to hold its +type as returned by @code{type-of}. Also, in the current +implementation records can have at most 4096 slots, whereas vectors +can be much larger. Like arrays, records use zero-origin indexing: +the first slot has index 0. + + The type slot should be a symbol or a type descriptor. If it's a +type descriptor, the symbol naming its type will be returned; +@ref{Type Descriptors}. Any other kind of object is returned as-is. + + The printed representation of records is @samp{#s} followed by a +list specifying the contents. The first list element must be the +record type. The following elements are the record slots. + + A record is considered a constant for evaluation: the result of +evaluating it is the same record. This does not evaluate or even +examine the slots. @xref{Self-Evaluating Forms}. + +@menu +* Record Functions:: Functions for records. +* Backward Compatibility:: Compatibility for cl-defstruct. +@end menu + +@node Record Functions +@section Record Functions + +@defun recordp object +This function returns @code{t} if @var{object} is a record. + +@example +@group +(recordp #s(a)) + @result{} t +@end group +@end example +@end defun + +@defun record type &rest objects +This function creates and returns a record whose type is @var{type} +and remaining slots are the rest of the arguments, @var{objects}. + +@example +@group +(record 'foo 23 [bar baz] "rats") + @result{} #s(foo 23 [bar baz] "rats") +@end group +@end example +@end defun + +@defun make-record type length object +This function returns a new record with type @var{type} and +@var{length} more slots, each initialized to @var{object}. + +@example +@group +(setq sleepy (make-record 'foo 9 'Z)) + @result{} #s(foo Z Z Z Z Z Z Z Z Z) +@end group +@end example +@end defun + +@node Backward Compatibility +@section Backward Compatibility + + Code compiled with older versions of @code{cl-defstruct} that +doesn't use records may run into problems when used in a new Emacs. +To alleviate this, Emacs detects when an old @code{cl-defstruct} is +used, and enables a mode in which @code{type-of} handles old struct +objects as if they were records. + +@defun cl-old-struct-compat-mode arg +If @var{arg} is positive, enable backward compatibility with old-style +structs. +@end defun diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi index 2c88ee38cb1..c7cf9f5e1af 100644 --- a/doc/lispref/sequences.texi +++ b/doc/lispref/sequences.texi @@ -151,20 +151,19 @@ This function generalizes @code{aref} (@pxref{Array Functions}) and @code{nth} (@pxref{Definition of nth}). @end defun -@defun copy-sequence sequence +@defun copy-sequence seqr @cindex copying sequences -This function returns a copy of @var{sequence}. The copy is the same -type of object as the original sequence, and it has the same elements -in the same order. +This function returns a copy of @var{seqr}, which should be either a +sequence or a record. The copy is the same type of object as the +original, and it has the same elements in the same order. Storing a new element into the copy does not affect the original -@var{sequence}, and vice versa. However, the elements of the new -sequence are not copies; they are identical (@code{eq}) to the elements +@var{seqr}, and vice versa. However, the elements of the copy +are not copies; they are identical (@code{eq}) to the elements of the original. Therefore, changes made within these elements, as -found via the copied sequence, are also visible in the original -sequence. +found via the copy, are also visible in the original. -If the sequence is a string with text properties, the property list in +If the argument is a string with text properties, the property list in the copy is itself a copy, not shared with the original's property list. However, the actual values of the properties are shared. @xref{Text Properties}. @@ -793,6 +792,33 @@ it is a function of two arguments to use instead of the default @code{equal}. @end defun +@defun seq-set-equal-p sequence1 sequence2 &optional testfn +This function checks whether @var{sequence1} and @var{sequence2} +contain the same elements, regardless of the order. If the optional +argument @var{testfn} is non-@code{nil}, it is a function of two +arguments to use instead of the default @code{equal}. + +@example +@group +(seq-set-equal-p '(a b c) '(c b a)) +@result{} t +@end group +@group +(seq-set-equal-p '(a b c) '(c b)) +@result{} nil +@end group +@group +(seq-set-equal-p '("a" "b" "c") '("c" "b" "a")) +@result{} t +@end group +@group +(seq-set-equal-p '("a" "b" "c") '("c" "b" "a") #'eq) +@result{} nil +@end group +@end example + +@end defun + @defun seq-position sequence elt &optional function This function returns the index of the first element in @var{sequence} that is equal to @var{elt}. If the optional argument @@ -1148,10 +1174,10 @@ vector, a string, a bool-vector or a char-table). @end example @end defun -@defun aref array index +@defun aref arr index @cindex array elements -This function returns the @var{index}th element of @var{array}. The -first element is at index zero. +This function returns the @var{index}th element of the array or record +@var{arr}. The first element is at index zero. @example @group diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi index cf47db4a814..23961f99efd 100644 --- a/doc/lispref/strings.texi +++ b/doc/lispref/strings.texi @@ -279,17 +279,26 @@ expression @var{separators} (@pxref{Regular Expressions}). Each match for @var{separators} defines a splitting point; the substrings between splitting points are made into a list, which is returned. +If @var{separators} is @code{nil} (or omitted), the default is the +value of @code{split-string-default-separators} and the function +behaves as if @var{omit-nulls} were @code{t}. + If @var{omit-nulls} is @code{nil} (or omitted), the result contains null strings whenever there are two consecutive matches for @var{separators}, or a match is adjacent to the beginning or end of @var{string}. If @var{omit-nulls} is @code{t}, these null strings are omitted from the result. -If @var{separators} is @code{nil} (or omitted), the default is the -value of @code{split-string-default-separators}. +If the optional argument @var{trim} is non-@code{nil}, it should be a +regular expression to match text to trim from the beginning and end of +each substring. If trimming makes the substring empty, it is treated +as null. -As a special case, when @var{separators} is @code{nil} (or omitted), -null strings are always omitted from the result. Thus: +If you need to split a string into a list of individual command-line +arguments suitable for @code{call-process} or @code{start-process}, +see @ref{Shell Arguments, split-string-and-unquote}. + +Examples: @example (split-string " two words ") @@ -306,8 +315,6 @@ useful. If you need such a result, use an explicit value for @result{} ("" "two" "words" "") @end example -More examples: - @example (split-string "Soup is good food" "o") @result{} ("S" "up is g" "" "d f" "" "d") @@ -354,15 +361,6 @@ practice: (split-string "ooo" "\\|o+" t) @result{} ("o" "o" "o") @end example - -If the optional argument @var{trim} is non-@code{nil}, it should be a -regular expression to match text to trim from the beginning and end of -each substring. If trimming makes the substring empty, it is treated -as null. - -If you need to split a string into a list of individual command-line -arguments suitable for @code{call-process} or @code{start-process}, -see @ref{Shell Arguments, split-string-and-unquote}. @end defun @defvar split-string-default-separators @@ -866,14 +864,6 @@ below, as the first argument, and the string as the second, like this: (format "%s" @var{arbitrary-string}) @end example - If @var{string} contains more than one format specification, the -format specifications correspond to successive values from -@var{objects}. Thus, the first format specification in @var{string} -uses the first such value, the second format specification uses the -second such value, and so on. Any extra format specifications (those -for which there are no corresponding values) cause an error. Any -extra values to be formatted are ignored. - Certain format specifications require values of particular types. If you supply a value that doesn't fit the requirements, an error is signaled. @@ -901,17 +891,18 @@ Functions}). Thus, strings are enclosed in @samp{"} characters, and @item %o @cindex integer to octal Replace the specification with the base-eight representation of an -integer. +unsigned integer. @item %d -Replace the specification with the base-ten representation of an +Replace the specification with the base-ten representation of a signed integer. @item %x @itemx %X @cindex integer to hexadecimal Replace the specification with the base-sixteen representation of an -integer. @samp{%x} uses lower case and @samp{%X} uses upper case. +unsigned integer. @samp{%x} uses lower case and @samp{%X} uses upper +case. @item %c Replace the specification with the character which is the value given. @@ -926,12 +917,17 @@ floating-point number. @item %g Replace the specification with notation for a floating-point number, -using either exponential notation or decimal-point notation, whichever -is shorter. +using either exponential notation or decimal-point notation. The +exponential notation is used if the exponent would be less than -4 or +greater than or equal to the precision (default: 6). By default, +trailing zeros are removed from the fractional portion of the result +and a decimal-point character appears only if it is followed by a +digit. @item %% Replace the specification with a single @samp{%}. This format -specification is unusual in that it does not use a value. For example, +specification is unusual in that its only form is plain +@samp{%%} and that it does not use a value. For example, @code{(format "%% %d" 30)} returns @code{"% 30"}. @end table @@ -958,44 +954,30 @@ operation} error. @end group @end example -@cindex field width -@cindex padding - A specification can have a @dfn{width}, which is a decimal number -between the @samp{%} and the specification character. If the printed -representation of the object contains fewer characters than this -width, @code{format} extends it with padding. The width specifier is -ignored for the @samp{%%} specification. Any padding introduced by -the width specifier normally consists of spaces inserted on the left: + By default, format specifications correspond to successive values from +@var{objects}. Thus, the first format specification in @var{string} +uses the first such value, the second format specification uses the +second such value, and so on. Any extra format specifications (those +for which there are no corresponding values) cause an error. Any +extra values to be formatted are ignored. -@example -(format "%5d is padded on the left with spaces" 123) - @result{} " 123 is padded on the left with spaces" -@end example - -@noindent -If the width is too small, @code{format} does not truncate the -object's printed representation. Thus, you can use a width to specify -a minimum spacing between columns with no risk of losing information. -In the following two examples, @samp{%7s} specifies a minimum width -of 7. In the first case, the string inserted in place of @samp{%7s} -has only 3 letters, and needs 4 blank spaces as padding. In the -second case, the string @code{"specification"} is 13 letters wide but -is not truncated. +@cindex field numbers in format spec + A format specification can have a @dfn{field number}, which is a +decimal number immediately after the initial @samp{%}, followed by a +literal dollar sign @samp{$}. It causes the format specification to +convert the argument with the given number instead of the next +argument. Field numbers start at 1. A format can contain either +numbered or unnumbered format specifications but not both, except that +@samp{%%} can be mixed with numbered specifications. @example -@group -(format "The word '%7s' has %d letters in it." - "foo" (length "foo")) - @result{} "The word ' foo' has 3 letters in it." -(format "The word '%7s' has %d letters in it." - "specification" (length "specification")) - @result{} "The word 'specification' has 13 letters in it." -@end group +(format "%2$s, %3$s, %%, %1$s" "x" "y" "z") + @result{} "y, z, %, x" @end example @cindex flags in format specifications - Immediately after the @samp{%} and before the optional width -specifier, you can also put certain @dfn{flag characters}. + After the @samp{%} and any field number, you can put certain +@dfn{flag characters}. The flag @samp{+} inserts a plus sign before a positive number, so that it always has a sign. A space character as flag inserts a space @@ -1008,9 +990,11 @@ both flags are used, @samp{+} takes precedence. The flag @samp{#} specifies an alternate form which depends on the format in use. For @samp{%o}, it ensures that the result begins with a @samp{0}. For @samp{%x} and @samp{%X}, it prefixes the result -with @samp{0x} or @samp{0X}. For @samp{%e}, @samp{%f}, and @samp{%g}, -the @samp{#} flag means include a decimal point even if the precision -is zero. +with @samp{0x} or @samp{0X}. For @samp{%e} and @samp{%f}, the +@samp{#} flag means include a decimal point even if the precision is +zero. For @samp{%g}, it always includes a decimal point, and also +forces any trailing zeros after the decimal point to be left in place +where they would otherwise be removed. The flag @samp{0} ensures that the padding consists of @samp{0} characters instead of spaces. This flag is ignored for non-numerical @@ -1018,8 +1002,8 @@ specification characters like @samp{%s}, @samp{%S} and @samp{%c}. These specification characters accept the @samp{0} flag, but still pad with @emph{spaces}. - The flag @samp{-} causes the padding inserted by the width -specifier, if any, to be inserted on the right rather than the left. + The flag @samp{-} causes any padding inserted by the width, +if specified, to be inserted on the right rather than the left. If both @samp{-} and @samp{0} are present, the @samp{0} flag is ignored. @@ -1037,14 +1021,52 @@ ignored. @end group @end example +@cindex field width +@cindex padding + A specification can have a @dfn{width}, which is a decimal number +that appears after any field number and flags. If the printed +representation of the object contains fewer characters than this +width, @code{format} extends it with padding. Any padding introduced by +the width normally consists of spaces inserted on the left: + +@example +(format "%5d is padded on the left with spaces" 123) + @result{} " 123 is padded on the left with spaces" +@end example + +@noindent +If the width is too small, @code{format} does not truncate the +object's printed representation. Thus, you can use a width to specify +a minimum spacing between columns with no risk of losing information. +In the following two examples, @samp{%7s} specifies a minimum width +of 7. In the first case, the string inserted in place of @samp{%7s} +has only 3 letters, and needs 4 blank spaces as padding. In the +second case, the string @code{"specification"} is 13 letters wide but +is not truncated. + +@example +@group +(format "The word '%7s' has %d letters in it." + "foo" (length "foo")) + @result{} "The word ' foo' has 3 letters in it." +(format "The word '%7s' has %d letters in it." + "specification" (length "specification")) + @result{} "The word 'specification' has 13 letters in it." +@end group +@end example + @cindex precision in format specifications All the specification characters allow an optional @dfn{precision} -before the character (after the width, if present). The precision is +after the field number, flags and width, if present. The precision is a decimal-point @samp{.} followed by a digit-string. For the -floating-point specifications (@samp{%e}, @samp{%f}, @samp{%g}), the -precision specifies how many decimal places to show; if zero, the -decimal-point itself is also omitted. For @samp{%s} and @samp{%S}, -the precision truncates the string to the given width, so @samp{%.3s} +floating-point specifications (@samp{%e} and @samp{%f}), the +precision specifies how many digits following the decimal point to +show; if zero, the decimal-point itself is also omitted. For +@samp{%g}, the precision specifies how many significant digits to show +(significant digits are the first digit before the decimal point and +all the digits after it). If the precision of %g is zero or +unspecified, it is treated as 1. For @samp{%s} and @samp{%S}, the +precision truncates the string to the given width, so @samp{%.3s} shows only the first three characters of the representation for @var{object}. For other specification characters, the effect of precision is what the local library functions of the @code{printf} @@ -1166,6 +1188,33 @@ When the argument to @code{upcase-initials} is a character, @end example @end defun + Note that case conversion is not a one-to-one mapping of codepoints +and length of the result may differ from length of the argument. +Furthermore, because passing a character forces return type to be +a character, functions are unable to perform proper substitution and +result may differ compared to treating a one-character string. For +example: + +@example +@group +(upcase "fi") ; note: single character, ligature "fi" + @result{} "FI" +@end group +@group +(upcase ?fi) + @result{} 64257 ; i.e. ?fi +@end group +@end example + + To avoid this, a character must first be converted into a string, +using @code{string} function, before being passed to one of the casing +functions. Of course, no assumptions on the length of the result may +be made. + + Mapping for such special cases are taken from +@code{special-uppercase}, @code{special-lowercase} and +@code{special-titlecase} @xref{Character Properties}. + @xref{Text Comparison}, for functions that compare strings; some of them ignore case differences, or can optionally ignore case differences. diff --git a/doc/lispref/tips.texi b/doc/lispref/tips.texi index 4e2a0fad1fa..35abd8e79db 100644 --- a/doc/lispref/tips.texi +++ b/doc/lispref/tips.texi @@ -1046,12 +1046,15 @@ package manager both at download time (to ensure that a complete set of packages is downloaded) and at activation time (to ensure that a package is only activated if all its dependencies have been). -Its format is a list of lists. The @code{car} of each sub-list is the -name of a package, as a symbol. The @code{cadr} of each sub-list is -the minimum acceptable version number, as a string. For instance: +Its format is a list of lists on a single line. The @code{car} of +each sub-list is the name of a package, as a symbol. The @code{cadr} +of each sub-list is the minimum acceptable version number, as a string +that can be parse by @code{version-to-list}. An entry that lacks a +version (i.e., an entry which is just a symbol, or a sub-list of one +element) is equivalent to entry with version "0". For instance: @smallexample -;; Package-Requires: ((gnus "1.0") (bubbles "2.7.2")) +;; Package-Requires: ((gnus "1.0") (bubbles "2.7.2") cl-lib (seq)) @end smallexample The package code automatically defines a package named @samp{emacs} diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index affa28c9202..eb5c2fc46be 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -42,6 +42,7 @@ is displayed in windows. * Vertical Scrolling:: Moving the contents up and down on the window. * Horizontal Scrolling:: Moving the contents sideways on the window. * Coordinates and Windows:: Converting coordinates to windows. +* Mouse Window Auto-selection:: Automatically selecting windows with the mouse. * Window Configurations:: Saving and restoring the state of the screen. * Window Parameters:: Associating additional information with windows. * Window Hooks:: Hooks for scrolling, window size changes, @@ -751,6 +752,7 @@ The optional argument @var{pixelwise} non-@code{nil} means to return the minimum size of @var{window} counted in pixels. @end defun + @node Resizing Windows @section Resizing Windows @cindex window resizing @@ -763,7 +765,7 @@ changing the size of its frame. Because live windows do not overlap, these functions are meaningful only on frames that contain two or more windows: resizing a window also changes the size of a neighboring window. If there is just one window on a frame, its size cannot be -changed except by resizing the frame (@pxref{Size and Position}). +changed except by resizing the frame (@pxref{Frame Size}). Except where noted, these functions also accept internal windows as arguments. Resizing an internal window causes its child windows to be @@ -942,7 +944,8 @@ help of the two options listed next. @defopt fit-frame-to-buffer-margins This option can be used to specify margins around frames to be fit by @code{fit-frame-to-buffer}. Such margins can be useful to avoid, for -example, that such frames overlap the taskbar. +example, that the resized frame overlaps the taskbar or parts of its +parent frame. It specifies the numbers of pixels to be left free on the left, above, the right, and below a frame that shall be fit. The default specifies @@ -1016,7 +1019,7 @@ A window can get resized explicitly by using one of the functions from the preceding section or implicitly, for example, when resizing an adjacent window, when splitting or deleting a window (@pxref{Splitting Windows}, @pxref{Deleting Windows}) or when resizing the window's frame -(@pxref{Size and Position}). +(@pxref{Frame Size}). It is possible to avoid implicit resizing of a specific window when there are one or more other resizable windows on the same frame. For @@ -1515,26 +1518,37 @@ direction as the existing window combination (otherwise, a new internal window is created anyway). @item window-size -In this case @code{display-buffer} makes a new parent window if it is -passed a @code{window-height} or @code{window-width} entry in the -@var{alist} argument (@pxref{Display Action Functions}). +This means that @code{display-buffer} makes a new parent window when it +splits a window and is passed a @code{window-height} or +@code{window-width} entry in the @var{alist} argument (@pxref{Display +Action Functions}). Otherwise, window splitting behaves as for a value +of @code{nil}. + +@item temp-buffer-resize +In this case @code{with-temp-buffer-window} makes a new parent window +when it splits a window and @code{temp-buffer-resize-mode} is enabled +(@pxref{Temporary Displays}). Otherwise, window splitting behaves as +for @code{nil}. @item temp-buffer -This value causes the creation of a new parent window when a window is -split for showing a temporary buffer (@pxref{Temporary Displays}) only. +In this case @code{with-temp-buffer-window} always makes a new parent +window when it splits an existing window (@pxref{Temporary Displays}). +Otherwise, window splitting behaves as for @code{nil}. @item display-buffer This means that when @code{display-buffer} (@pxref{Choosing Window}) -splits a window it always makes a new parent window. +splits a window it always makes a new parent window. Otherwise, window +splitting behaves as for @code{nil}. @item t -In this case a new parent window is always created when splitting a -window. Thus, if the value of this variable is at all times @code{t}, -then at all times every window tree is a binary tree (a tree where each -window except the root window has exactly one sibling). +This means that splitting a window always creates a new parent window. +Thus, if the value of this variable is at all times @code{t}, then at +all times every window tree is a binary tree (a tree where each window +except the root window has exactly one sibling). @end table -The default is @code{nil}. Other values are reserved for future use. +The default is @code{window-size}. Other values are reserved for future +use. If, as a consequence of this variable's setting, @code{split-window} makes a new parent window, it also calls @@ -1716,23 +1730,47 @@ value of @code{window-point} (@pxref{Window Point}) in @var{window}. @var{window} must be a live window. The return value is @var{window}. By default, this function also moves @var{window}'s buffer to the front -of the buffer list (@pxref{Buffer List}), and makes @var{window} the -most recently selected window. However, if the optional argument -@var{norecord} is non-@code{nil}, these additional actions are omitted. - -This function runs @code{buffer-list-update-hook} (@pxref{Buffer List}) -unless @var{norecord} is non-@code{nil}. Note that applications and -internal routines often temporarily select a window in order to simplify -coding. As a rule, such selections (including those made by the macros -@code{save-selected-window} and @code{with-selected-window} below) are -not recorded thus avoiding to pollute @code{buffer-list-update-hook}. -Selections that really count are those causing a visible change in -the next redisplay of @var{window}'s frame and should be always -recorded. This also means that to run a function each time a window -gets selected, putting it on @code{buffer-list-update-hook} should be -the right choice. +of the buffer list (@pxref{Buffer List}) and makes @var{window} the most +recently selected window. If the optional argument @var{norecord} is +non-@code{nil}, these additional actions are omitted. + +In addition, this function by default also tells the display engine to +update the display of @var{window} when its frame gets redisplayed the +next time. If @var{norecord} is non-@code{nil}, such updates are +usually not performed. If, however, @var{norecord} equals the special +symbol @code{mark-for-redisplay}, the additional actions mentioned above +are omitted but @var{window} will be nevertheless updated. @end defun +@cindex select window hook +@cindex running a hook when a windows gets selected +For historical reasons, Emacs does not run a separate hook whenever a +window gets selected. Applications and internal routines often +temporarily select a window to perform a few actions on it. They do +that either to simplify coding---because many functions by default +operate on the selected window when no @var{window} argument is +specified---or because some functions did not (and still do not) take a +window as argument and always operate(d) on the selected window instead. +Running a hook every time a window gets selected for a short time and +once more when the previously selected window gets restored is not +useful. + + However, when its @var{norecord} argument is @code{nil}, +@code{select-window} updates the buffer list and thus indirectly runs +the normal hook @code{buffer-list-update-hook} (@pxref{Buffer List}). +Consequently, that hook provides a reasonable way to run a function +whenever a window gets selected more ``permanently''. + + Since @code{buffer-list-update-hook} is also run by functions that are +not related to window management, it will usually make sense to save the +value of the selected window somewhere and compare it with the value of +@code{selected-window} while running that hook. Also, to avoid false +positives when using @code{buffer-list-update-hook}, it is good practice +that every @code{select-window} call supposed to select a window only +temporarily passes a non-@code{nil} @var{norecord} argument. If +possible, the macro @code{with-selected-window} (see below) should be +used in such cases. + @cindex most recently selected windows The sequence of calls to @code{select-window} with a non-@code{nil} @var{norecord} argument determines an ordering of windows by their @@ -1761,13 +1799,13 @@ the buffer list. @defmac with-selected-window window forms@dots{} This macro selects @var{window}, executes @var{forms} in sequence, then -restores the previously selected window and current buffer. The ordering -of recently selected windows and the buffer list remain unchanged unless -you deliberately change them within @var{forms}; for example, by calling -@code{select-window} with argument @var{norecord} @code{nil}. - -This macro does not change the order of recently selected windows or -the buffer list. +restores the previously selected window and current buffer. The +ordering of recently selected windows and the buffer list remain +unchanged unless you deliberately change them within @var{forms}; for +example, by calling @code{select-window} with argument @var{norecord} +@code{nil}. Hence, this macro is the preferred way to temporarily work +with @var{window} as the selected window without needlessly running +@code{buffer-list-update-hook}. @end defmac @defun frame-selected-window &optional frame @@ -2013,8 +2051,8 @@ signals an error. @xref{Dedicated Windows}. By default, this function resets @var{window}'s position, display margins, fringe widths, and scroll bar settings, based on the local variables in the specified buffer. However, if the optional argument -@var{keep-margins} is non-@code{nil}, it leaves the display margins -and fringe widths unchanged. +@var{keep-margins} is non-@code{nil}, it leaves @var{window}'s display +margins, fringes and scroll bar settings alone. When writing an application, you should normally use the higher-level functions described in @ref{Switching Buffers}, instead of calling @@ -2448,6 +2486,25 @@ the function specified in @code{pop-up-frame-function} is added to the newly created frame's parameters. @end defun +@defun display-buffer-in-child-frame buffer alist +This function tries to display @var{buffer} in a child frame +(@pxref{Child Frames}) of the selected frame, either reusing an existing +child frame or by making a new one. If @var{alist} has a non-@code{nil} +@code{child-frame-parameters} entry, the corresponding value is an alist +of frame parameters to give the new frame. A @code{parent-frame} +parameter specifying the selected frame is provided by default. If the +child frame should be or become the child of another frame, a +corresponding entry must be added to @var{alist}. + +The appearance of child frames is largely dependent on the parameters +provided via @var{alist}. It is advisable to use at least ratios to +specify the size (@pxref{Size Parameters}) and the position +(@pxref{Position Parameters}) of the child frame and to add the +@code{keep-ratio} in order to make sure that the child frame remains +visible. For other parameters that should be considered see @ref{Child +Frames}. +@end defun + @defun display-buffer-use-some-frame buffer alist This function tries to display @var{buffer} by trying to find a frame that meets a predicate (by default any frame other than the @@ -2803,12 +2860,13 @@ put it in the selected window. @section Window History @cindex window history -Each window remembers in a list the buffers it has previously displayed, -and the order in which these buffers were removed from it. This history -is used, for example, by @code{replace-buffer-in-windows} -(@pxref{Buffers and Windows}). The list is automatically maintained by -Emacs, but you can use the following functions to explicitly inspect or -alter it: +Each window remembers in a list the buffers it has previously +displayed, and the order in which these buffers were removed from it. +This history is used, for example, by @code{replace-buffer-in-windows} +(@pxref{Buffers and Windows}), and when quitting windows +(@pxref{Quitting Windows}). The list is automatically maintained by +Emacs, but you can use the following functions to explicitly inspect +or alter it: @defun window-prev-buffers &optional window This function returns a list specifying the previous contents of @@ -2994,33 +3052,35 @@ described next to deal with the window and its buffer. @end deffn @defun quit-restore-window &optional window bury-or-kill -This function tries to restore the state of @var{window} that existed -before its buffer was displayed in it. The optional argument -@var{window} must be a live window and defaults to the selected one. +This function handles @var{window} and its buffer after quitting. The +optional argument @var{window} must be a live window and defaults to +the selected one. The function's behavior is determined by the four +elements of the @code{quit-restore} window parameter (@pxref{Window +Parameters}), which is set to nil afterwards. + +The window is deleted entirely if: 1) the first element of the +@code{quit-restore} parameter is one of 'window or 'frame, 2) the +window has no history of previously-displayed buffers, and 3) the +displayed buffer matches the one in the fourth element of the +@code{quit-restore} parameter. If @var{window} is the +only window on its frame and there are other frames on the frame's +terminal, the value of the optional argument @var{bury-or-kill} +determines how to proceed with the window. If @var{bury-or-kill} +equals @code{kill}, the frame is deleted unconditionally. Otherwise, +the fate of the frame is determined by calling +@code{frame-auto-hide-function} (see below) with that frame as sole +argument. -If @var{window} was created specially for displaying its buffer, this -function deletes @var{window} provided its frame contains at least one -other live window. If @var{window} is the only window on its frame and -there are other frames on the frame's terminal, the value of the -optional argument @var{bury-or-kill} determines how to proceed with the -window. If @var{bury-or-kill} equals @code{kill}, the frame is deleted -unconditionally. Otherwise, the fate of the frame is determined by -calling @code{frame-auto-hide-function} (see below) with that frame as -sole argument. - -Otherwise, this function tries to redisplay the buffer previously shown -in @var{window}. It also tries to restore the window start -(@pxref{Window Start and End}) and point (@pxref{Window Point}) -positions of the previously shown buffer. If, in addition, +If the third element of the @code{quit-restore} parameter is a list of +buffer, window start (@pxref{Window Start and End}), and point +(@pxref{Window Point}), and that buffer is still live, the buffer will +be displayed, and start and point set accordingly. If, in addition, @var{window}'s buffer was temporarily resized, this function will also try to restore the original height of @var{window}. -The cases described so far require that the buffer shown in @var{window} -is still the buffer displayed by the last buffer display function for -this window. If another buffer has been shown in the meantime, or the -buffer previously shown no longer exists, this function calls -@code{switch-to-prev-buffer} (@pxref{Window History}) to show some other -buffer instead. +Otherwise, if @var{window} was previously used for displaying other +buffers (@pxref{Window History}), the most recent buffer in that +history will be displayed. The optional argument @var{bury-or-kill} specifies how to deal with @var{window}'s buffer. The following values are handled: @@ -3048,9 +3108,24 @@ buffer again without killing the buffer. This means to kill @var{window}'s buffer. @end table -@code{quit-restore-window} bases its decisions on information stored in -@var{window}'s @code{quit-restore} window parameter (@pxref{Window -Parameters}), and resets that parameter to @code{nil} after it's done. +Typically, the display routines run by @code{display-buffer} will set +the @code{quit-restore} window parameter correctly. It's also +possible to set it manually, using the following code for displaying +@var{buffer} in @var{window}: + +@example +@group +(display-buffer-record-window type window buffer) + +(set-window-buffer window buffer) + +(set-window-prev-buffers window nil) +@end group +@end example + +Setting the window history to nil ensures that a future call to +@code{quit-window} can delete the window altogether. + @end defun The following option specifies how to deal with a frame containing just @@ -3070,12 +3145,17 @@ killed. The default is to call @code{iconify-frame} (@pxref{Visibility of Frames}). Alternatively, you may specify either @code{delete-frame} (@pxref{Deleting Frames}) to remove the frame from its display, -@code{ignore} to leave the frame unchanged, or any other function that -can take a frame as its sole argument. +@code{make-frame-invisible} to make the frame invisible, @code{ignore} +to leave the frame unchanged, or any other function that can take a +frame as its sole argument. Note that the function specified by this option is called only if the specified frame contains just one live window and there is at least one other frame on the same terminal. + +For a particular frame, the value specified here may be overridden by +that frame's @code{auto-hide-function} frame parameter (@pxref{Frame +Interaction Parameters}). @end defopt @@ -3532,9 +3612,13 @@ point and the buffer's point always move together; they remain equal. @end itemize @cindex cursor - As far as the user is concerned, point is where the cursor is, and -when the user switches to another buffer, the cursor jumps to the -position of point in that buffer. + Emacs displays the cursor, by default as a rectangular block, in +each window at the position of that window's point. When the user +switches to another buffer in a window, Emacs moves that window's +cursor to where point is in that buffer. If the exact position of +point is hidden behind some display element, such as a display string +or an image, Emacs displays the cursor immediately before or after +that display element. @defun window-point &optional window This function returns the current position of point in @var{window}. @@ -4191,6 +4275,13 @@ scrolling value explicitly. The value you specify serves as a lower bound for automatic scrolling, i.e., automatic scrolling will not scroll a window to a column less than the specified one. + The default value of @code{auto-hscroll-mode} is @code{t}; setting +it to @code{current-line} activates a variant of automatic horizontal +scrolling whereby only the line showing the cursor is horizontally +scrolled to make point visible, the rest of the window is left either +unscrolled, or at the minimum scroll amount set by @code{scroll-left} +and @code{scroll-right}, see below. + @deffn Command scroll-left &optional count set-minimum This function scrolls the selected window @var{count} columns to the left (or to the right if @var{count} is negative). The default @@ -4299,13 +4390,12 @@ is off the screen due to horizontal scrolling: @cindex coordinate, relative to frame @cindex window position -This section describes functions that report the position of a window. -Most of these functions report positions relative to an origin at the -native position of the window's frame (@pxref{Frame Geometry}). Some -functions report positions relative to the origin of the display of the -window's frame. In any case, the origin has the coordinates (0, 0) and -X and Y coordinates increase rightward and downward -respectively. +This section describes functions that report positions of and within a +window. Most of these functions report positions relative to an origin +at the native position of the window's frame (@pxref{Frame Geometry}). +Some functions report positions relative to the origin of the display of +the window's frame. In any case, the origin has the coordinates (0, 0) +and X and Y coordinates increase rightward and downward respectively. For the following functions, X and Y coordinates are reported in integer character units, i.e., numbers of lines and columns @@ -4543,6 +4633,98 @@ point in the selected window, it's sufficient to write: @end example @end defun +The following function returns the largest rectangle that can be +inscribed in a window without covering text displayed in that window. + +@defun window-largest-empty-rectangle &optional window count min-width min-height positions left +This function calculates the dimensions of the largest empty rectangle +that can be inscribed in the specified @var{window}'s text area. +@var{window} must be a live window and defaults to the selected one. + +The return value is a triple of the width and the start and end +y-coordinates of the largest rectangle that can be inscribed into the +empty space (space not displaying any text) of the text area of +@var{window}. No x-coordinates are returned by this function---any such +rectangle is assumed to end at the right edge of @var{window}'s text +area. If no empty space can be found, the return value is @code{nil}. + +The optional argument @var{count}, if non-@code{nil}, specifies a +maximum number of rectangles to return. This means that the return +value is a list of triples specifying rectangles with the largest +rectangle first. @var{count} can be also a cons cell whose car +specifies the number of rectangles to return and whose @sc{cdr}, if +non-@code{nil}, states that all rectangles returned must be disjoint. + +The optional arguments @var{min-width} and @var{min-height}, if +non-@code{nil}, specify the minimum width and height of any rectangle +returned. + +The optional argument @var{positions}, if non-@code{nil}, is a cons cell +whose @sc{car} specifies the uppermost and whose @sc{cdr} specifies the +lowermost pixel position that must be covered by any rectangle returned. +These positions measure from the start of the text area of @var{window}. + +The optional argument @var{left}, if non-@code{nil}, means to return +values suitable for buffers displaying right to left text. In that +case, any rectangle returned is assumed to start at the left edge of +@var{window}'s text area. + +Note that this function has to retrieve the dimensions of each line of +@var{window}'s glyph matrix via @code{window-lines-pixel-dimensions} +(@pxref{Size of Displayed Text}). Hence, this function may also return +@code{nil} when the current glyph matrix of @var{window} is not +up-to-date. +@end defun + + +@node Mouse Window Auto-selection +@section Mouse Window Auto-selection +@cindex window auto-selection +@cindex auto-selection of window +The following option allows to automatically select the window under the +mouse pointer. This accomplishes a policy similar to that of window +managers that give focus to a frame (and thus trigger its subsequent +selection) whenever the mouse pointer enters its window-system window +(@pxref{Input Focus}). + +@defvar mouse-autoselect-window +If this variable is non-@code{nil}, Emacs will try to automatically +select the window under the mouse pointer. The following values are +meaningful: + +@table @asis +@item A positive number +This specifies a delay in seconds after which auto-selection triggers. +The window under the mouse pointer is selected after the mouse has +remained in it for the entire duration of the delay. + +@item A negative number +A negative number has a similar effect as a positive number, but selects +the window under the mouse pointer only after the mouse pointer has +remained in it for the entire duration of the absolute value of that +number and in addition has stopped moving. + +@item Other value +Any other non-@code{nil} value means to select a window instantaneously +as soon as the mouse pointer enters it. +@end table + +In either case, the mouse pointer must enter the text area of a window in +order to trigger its selection. Dragging the scroll bar slider or the +mode line of a window conceptually should not cause its auto-selection. + +Mouse auto-selection selects the minibuffer window only if it is active, +and never deselects the active minibuffer window. +@end defvar + +Mouse auto-selection can be used to emulate a focus follows mouse policy +for child frames (@pxref{Child Frames}) which usually are not tracked by +the window manager. This requires to set the value of +@code{focus-follows-mouse} (@pxref{Input Focus}) to a non-@code{nil} +value. If the value of @code{focus-follows-mouse} is @code{auto-raise}, +entering a child frame with the mouse will raise it automatically above +all other child frames of that frame's parent frame. + @node Window Configurations @section Window Configurations @@ -4797,37 +4979,45 @@ windows when exiting that function. The following parameters are currently used by the window management code: -@table @asis -@item @code{delete-window} +@table @code +@item delete-window +@vindex delete-window, a window parameter This parameter affects the execution of @code{delete-window} (@pxref{Deleting Windows}). -@item @code{delete-other-windows} +@item delete-other-windows +@vindex delete-other-windows, a window parameter This parameter affects the execution of @code{delete-other-windows} (@pxref{Deleting Windows}). -@item @code{no-delete-other-window} +@item no-delete-other-window +@vindex no-delete-other-window, a window parameter This parameter marks the window as not deletable by @code{delete-other-windows} (@pxref{Deleting Windows}). -@item @code{split-window} +@item split-window +@vindex split-window, a window parameter This parameter affects the execution of @code{split-window} (@pxref{Splitting Windows}). -@item @code{other-window} +@item other-window +@vindex other-window, a window parameter This parameter affects the execution of @code{other-window} (@pxref{Cyclic Window Ordering}). -@item @code{no-other-window} +@item no-other-window +@vindex no-other-window, a window parameter This parameter marks the window as not selectable by @code{other-window} (@pxref{Cyclic Window Ordering}). -@item @code{clone-of} +@item clone-of +@vindex clone-of, a window parameter This parameter specifies the window that this one has been cloned from. It is installed by @code{window-state-get} (@pxref{Window Configurations}). -@item @code{preserved-size} +@item preserved-size +@vindex preserved-size, a window parameter This parameter specifies a buffer, a direction where @code{nil} means vertical and @code{t} horizontal, and a size in pixels. If this window displays the specified buffer and its size in the indicated direction @@ -4836,39 +5026,69 @@ preserve the size of this window in the indicated direction. This parameter is installed and updated by the function @code{window-preserve-size} (@pxref{Preserving Window Sizes}). -@item @code{quit-restore} +@item quit-restore +@vindex quit-restore, a window parameter This parameter is installed by the buffer display functions (@pxref{Choosing Window}) and consulted by @code{quit-restore-window} (@pxref{Quitting Windows}). It contains four elements: -The first element is one of the symbols @code{window}, meaning that the -window has been specially created by @code{display-buffer}; @code{frame}, -a separate frame has been created; @code{same}, the window has -displayed the same buffer before; or @code{other}, the window showed -another buffer before. +The first element is one of the symbols @code{window}, meaning that +the window has been specially created by @code{display-buffer}; +@code{frame}, a separate frame has been created; @code{same}, the +window has only ever displayed this buffer; or @code{other}, the +window showed another buffer before. @code{frame} and @code{window} +affect how the window is quit, while @code{same} and @code{other} +affect the redisplay of buffers previously shown in this window. The second element is either one of the symbols @code{window} or @code{frame}, or a list whose elements are the buffer shown in the window before, that buffer's window start and window point positions, -and the window's height at that time. +and the window's height at that time. If that buffer is still live +when the window is quit, then the function @code{quit-restore-window} +reuses the window to display the buffer. The third element is the window selected at the time the parameter was -created. The function @code{quit-restore-window} tries to reselect that -window when it deletes the window passed to it as argument. +created. If @code{quit-restore-window} deletes the window passed to +it as argument, it then tries to reselect this window. The fourth element is the buffer whose display caused the creation of this parameter. @code{quit-restore-window} deletes the specified window only if it still shows that buffer. -@item @code{window-side} @code{window-slot} +See the description of @code{quit-restore-window} in @ref{Quitting +Windows} for details. + +@item window-side window-slot +@vindex window-side, a window parameter +@vindex window-slot, a window parameter These parameters are used for implementing side windows (@pxref{Side Windows}). -@item @code{window-atom} +@item window-atom +@vindex window-atom, a window parameter This parameter is used for implementing atomic windows, see @ref{Atomic Windows}. -@item @code{min-margins} +@item mode-line-format +@vindex mode-line-format, a window parameter +This parameter replaces the value of the buffer-local variable +@code{mode-line-format} (@pxref{Mode Line Basics}) of this window's +buffer whenever this window is displayed. The symbol @code{none} means +to suppress display of a mode line for this window. Display and +contents of the mode line on other windows showing this buffer are not +affected. + +@item header-line-format +@vindex header-line-format, a window parameter +This parameter replaces the value of the buffer-local variable +@code{header-line-format} (@pxref{Mode Line Basics}) of this window's +buffer whenever this window is displayed. The symbol @code{none} means +to suppress display of a header line for this window. Display and +contents of the header line on other windows showing this buffer are not +affected. + +@item min-margins +@vindex min-margins, a window parameter The value of this parameter is a cons cell whose @sc{car} and @sc{cdr}, if non-@code{nil}, specify the minimum values (in columns) for the left and right margin of this window. When present, Emacs will use these @@ -4890,9 +5110,6 @@ applications. It might be replaced by an improved solution in future versions of Emacs. @end table -The @code{window-atom} parameter is used for implementing atomic windows. - - @node Window Hooks @section Hooks for Window Scrolling and Changes @cindex hooks for window operations diff --git a/doc/man/emacs.1.in b/doc/man/emacs.1.in index 6807e866526..5d0948f51b3 100644 --- a/doc/man/emacs.1.in +++ b/doc/man/emacs.1.in @@ -3,7 +3,7 @@ . . .SH NAME -emacs \- GNU project Emacs +emacs \- GNU project Emacs editor . . .SH SYNOPSIS diff --git a/doc/misc/ada-mode.texi b/doc/misc/ada-mode.texi index 127a009417e..2ea4c7f36b2 100644 --- a/doc/misc/ada-mode.texi +++ b/doc/misc/ada-mode.texi @@ -540,7 +540,7 @@ Lisp variable: @code{ada-prj-default-bind-opt}. @item @code{build_dir} [default: @code{"."}] The compile commands will be issued in this directory. -@item @code{casing} [default: @code{("~/.emacs_case_exceptions")} +@item @code{casing} [default: @code{("~/.emacs_case_exceptions")}] List of files containing casing exceptions. See the help on @code{ada-case-exception-file} for more info. @c FIXME: section on case exceptions diff --git a/doc/misc/auth.texi b/doc/misc/auth.texi index 29e55eda52c..cfc62a9f922 100644 --- a/doc/misc/auth.texi +++ b/doc/misc/auth.texi @@ -61,6 +61,7 @@ It is a way for multiple applications to share a single configuration * Help for users:: * Multiple GMail accounts with Gnus:: * Secret Service API:: +* The Unix password store:: * Help for developers:: * GnuPG and EasyPG Assistant Configuration:: * GNU Free Documentation License:: The license for this documentation. @@ -85,8 +86,9 @@ password (known as the secret). Similarly, the auth-source library supports multiple storage backend, currently either the classic ``netrc'' backend, examples of which you -can see later in this document, or the Secret Service API@. This is -done with EIEIO-based backends and you can write your own if you want. +can see later in this document, the Secret Service API, and pass, the +standard unix password manager. This is done with EIEIO-based +backends and you can write your own if you want. @node Help for users @chapter Help for users @@ -150,9 +152,9 @@ auth-source library is not loaded for some other reason. @defvar auth-sources The @code{auth-sources} variable tells the auth-source library where -your netrc files or Secret Service API collection items live for a -particular host and protocol. While you can get fancy, the default -and simplest configuration is: +your netrc files, Secret Service API collection items, or your +password store live for a particular host and protocol. While you can +get fancy, the default and simplest configuration is: @lisp ;;; old default: required :host and :port, not needed anymore @@ -164,6 +166,9 @@ and simplest configuration is: ;;; use the Secrets API @var{Login} collection ;;; (@pxref{Secret Service API}) (setq auth-sources '("secrets:Login")) +;;; use pass (@file{~/.password-store}) +;;; (@pxref{The Unix password store}) +(setq auth-sources '(password-store)) @end lisp By adding multiple entries to @code{auth-sources} with a particular @@ -402,6 +407,34 @@ then fall back to @file{~/.authinfo.gpg}. "~/.authinfo.gpg")) @end example +@node The Unix password store +@chapter The Unix password store + +@uref{http://www.passwordstore.org,,The standard unix password +manager} (or just @code{pass}) stores your passwords in +@code{gpg}-protected files following the Unix philosophy. + +Emacs integration of @code{pass} follows the first approach suggested +by the pass project itself for data organization to find data. This +means that the filename of the file containing the password for a user +on a particular host must contain the host name. The file itself must +contain the password on the first line, as well as a @code{username} +field containing the username on a subsequent line. A @code{port} +field can be used to differentiate the authentication data for several +services with the same username on the same host. + +Users of @code{pass} may also be interested in functionality provided +by other Emacs packages dealing with pass: + +@itemize +@item +@uref{https://git.zx2c4.com/password-store/tree/contrib/emacs/password-store.el,,password-store}: library wrapping @code{pass}; +@item +@uref{https://github.com/NicolasPetton/pass,,pass}: major mode to manipulate the store and edit entries; +@item +@uref{https://github.com/jabranham/helm-pass,,helm-pass}: helm interface for pass. +@end itemize + @node Help for developers @chapter Help for developers @@ -517,14 +550,14 @@ or EasyPG Assistant To quick start, here are some questions: -@enumerate +@itemize @item Do you use GnuPG version 2 instead of GnuPG version 1? @item Do you use symmetric encryption rather than public key encryption? @item Do you want to use gpg-agent? -@end enumerate +@end itemize Here are configurations depending on your answers: diff --git a/doc/misc/cc-mode.texi b/doc/misc/cc-mode.texi index 14981c9c58b..f9ba5cc3921 100644 --- a/doc/misc/cc-mode.texi +++ b/doc/misc/cc-mode.texi @@ -274,6 +274,7 @@ Font Locking * Font Locking Preliminaries:: * Faces:: * Doc Comments:: +* Misc Font Locking:: * AWK Mode Font Locking:: Configuration Basics @@ -811,6 +812,10 @@ often (in seconds) progress messages are to be displayed. @cindex comments (insertion of) @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +When the commands in this section add comment delimiters, they use +either line comments or block comments depending on the setting of the +comment style (@pxref{Minor Modes}). + @table @asis @item @kbd{C-c C-c} (@code{comment-region}) @kindex C-c C-c @@ -1132,6 +1137,9 @@ line break. find useful while writing new code or editing old code: @table @asis +@item comment style +This specifies whether comment commands (such as @kbd{M-;}) insert +block comments or line comments. @item electric mode When this is enabled, certain visible characters cause reformatting as they are typed. This is normally helpful, but can be a nuisance when @@ -1167,20 +1175,32 @@ and @ref{Indentation Engine Basics}. You can toggle each of these minor modes on and off, and you can configure @ccmode{} so that it starts up with your favorite combination of them (@pxref{Sample Init File}). By default, when -you initialize a buffer, electric mode and syntactic-indentation mode -are enabled but the other three modes are disabled. - -@ccmode{} displays the current state of the first four of these minor -modes on the modeline by appending letters to the major mode's name, -one letter for each enabled minor mode: @samp{l} for electric mode, -@samp{a} for auto-newline mode, @samp{h} for hungry delete mode, and -@samp{w} for subword mode. If all these modes were enabled, you'd see -@samp{C/lahw}@footnote{The @samp{C} would be replaced with the name of -the language in question for the other languages @ccmode{} supports.}. +you initialize a buffer, the comment style is set to the default for +the major mode, electric mode and syntactic-indentation mode are +enabled, but the other three modes are disabled. + +@ccmode{} displays the current state of the first five of these minor +modes on the mode line by appending characters to the major mode's +name: @samp{/} or @samp{*} to indicate the comment style (respectively +line or block), and one letter for each of the other minor modes which +is enabled - @samp{l} for electric mode, @samp{a} for auto-newline +mode, @samp{h} for hungry delete mode, and @samp{w} for subword mode. +If the comment style was block and all the other modes were enabled, +you'd see @samp{C/*lahw}@footnote{The @samp{C} would be replaced with +the name of the language in question for the other languages @ccmode{} +supports.}. Here are the commands to toggle these modes: @table @asis +@item @kbd{C-c C-k} (@code{c-toggle-comment-style}) +@kindex C-c C-k +@findex c-toggle-comment-style +@findex toggle-comment-style (c-) +Toggle the comment style between line style and block style. In modes +(such as AWK Mode) which only have one of these styles, this function +does nothing. + @item @kbd{C-c C-l} (@code{c-toggle-electric-state}) @kindex C-c C-l @findex c-toggle-electric-state @@ -1217,10 +1237,12 @@ Toggle syntactic-indentation mode. @end table Common to all the toggle functions above is that if they are called -programmatically, they take an optional numerical argument. A -positive value will turn on the minor mode (or both of them in the -case of @code{c-toggle-auto-hungry-state}) and a negative value will -turn it (or them) off. +programmatically, they take an optional numerical argument. For +@code{c-toggle-comment style}, a positive value will select block +comments, a negative value will select line comments. For the other +functions, a positive value will turn on the minor mode (or both of +them in the case of @code{c-toggle-auto-hungry-state}) and a negative +value will turn it (or them) off. @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -1821,6 +1843,7 @@ sections apply to the other languages. * Font Locking Preliminaries:: * Faces:: * Doc Comments:: +* Misc Font Locking:: * AWK Mode Font Locking:: @end menu @@ -2023,7 +2046,7 @@ since those aren't syntactic errors in themselves. @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Doc Comments, AWK Mode Font Locking, Faces, Font Locking +@node Doc Comments, Misc Font Locking, Faces, Font Locking @comment node-name, next, previous, up @section Documentation Comments @cindex documentation comments @@ -2099,9 +2122,63 @@ initialization and the result is prepended. For an example, see If you add support for another doc comment style, please consider contributing it: send a note to @email{bug-cc-mode@@gnu.org}. +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Misc Font Locking, AWK Mode Font Locking, Doc Comments, Font Locking +@comment node-name, next, previous, up +@section Miscellaneous Font Locking +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +In some languages, particularly in C++, there are constructs which are +syntactically ambiguous---they could be either declarations or +expressions, and @ccmode{} cannot tell for sure which. Often such a +construct is one of the operators @samp{*} or @samp{&} surrounded by +two identifiers. + +Experience shows that very often when such a construct is a +declaration it will be written with the operator touching exactly one +of the identifiers, like: + +@example +foo *bar +@end example +or +@example +foo& bar +@end example + +. Whether such code is fontified depends on the setting of +@code{c-asymmetry-fontification-flag}. + +@defvar c-asymmetry-fontification-flag +@vindex asymmetry-fontification-flag (c-) +When @code{c-asymmetry-fontification-flag} is non-nil (which it is by +default), code like the above, with white space either before or after +the operator, but not both, is fontified as a declaration. When the +variable is nil, such a construct gets the default face. +@end defvar + +When the construct is an expression there will often be white space +both before and after the operator or there will be no white space +around it at all, like: + +@example +foo * bar +@end example +or +@example +foo&bar +@end example +. + +Such code is not fontified as a declaration. (Typically, the +identifiers don't get a non-default face.) + +For clarity's sake, we emphasize that the ``asymmetry'' rule in this +section only applies when CC Mode cannot disambiguate a construct in +any other way. @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node AWK Mode Font Locking, , Doc Comments, Font Locking +@node AWK Mode Font Locking, , Misc Font Locking, Font Locking @comment node-name, next, previous, up @section AWK Mode Font Locking @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -4255,8 +4332,8 @@ Analogous to the above, but for CORBA CIDL @code{composition} blocks. C++ template argument list continuations. @ref{Class Symbols}. @item inlambda Analogous to @code{inclass} syntactic symbol, but used inside lambda -(i.e., anonymous) functions. Only used in Pike mode. @ref{Statement -Block Symbols}. +(i.e., anonymous) functions. Used in C++ and Pike modes. +@ref{Statement Block Symbols}. @item lambda-intro-cont Lines continuing the header of a lambda function, i.e., between the @code{lambda} keyword and the function body. Only used in Pike mode. @@ -4993,6 +5070,21 @@ symbols they'd get in a normal block. Therefore, the indentation put on indentation. An @code{inexpr-statement} syntactic element doesn't contain an anchor position. +C++11's lambda expressions involve a block inside a statement. For +example: + +@example + 1: std::for_each(someList.begin(), someList.end(), [&total](int x) @{ + 2: total += x; + 3: @}); +@end example + +Here a lambda expressions begins at the open bracket on line 1 and +ends at the closing brace on line 3. Line 2, in addition to the +familiar @code{defun-block-intro} syntactic element, is also prefixed +by an @code{inlambda} element, which is typically used to indent the +entire lambda expression to under the opening bracket. + In Pike code, there are a few other situations where blocks occur inside statements, as illustrated here: @@ -7160,6 +7252,38 @@ too, add this to your @code{c-initialization-hook}: @xref{Getting Started}. This was a very common question. +@item +@emph{How do I get block comments in my C++ files?} + +Interactively, change the comment style with @kbd{C-c C-k}. +@xref{Minor Modes}. + +To configure this setting, say, for files within the gdb project, you +could amend your C++ Mode hook like this: + +@example +(defun my-c++-mode-hook () + (if (string-match "/gdb/" (buffer-file-name)) + (c-toggle-comment-style 1))) +(add-hook 'c++-mode-hook 'my-c++-mode-hook) +@end example + +@item +@emph{How do I stop my C++ lambda expressions being indented way over +to the right?} + +Change the offset associated with @code{inlambda} from its default, +the function @code{c-lineup-inexpr-block}, to 0. For example, if you +are setting offsets in a hook function you might include the following +line: + +@example +(c-set-offset 'inlambda 0) +@end example + +For details of the different ways you can make this setting, +@ref{Config Basics}. + @item @emph{How do I stop my code jumping all over the place when I type?} diff --git a/doc/misc/cl.texi b/doc/misc/cl.texi index 8baa0bd88c6..33b4858a45b 100644 --- a/doc/misc/cl.texi +++ b/doc/misc/cl.texi @@ -77,6 +77,7 @@ Appendices Indexes * Function Index:: An entry for each documented function. * Variable Index:: An entry for each documented variable. +* Concept Index:: An entry for each concept. @end menu @node Overview @@ -888,6 +889,7 @@ provides an even more convenient way to swap two variables; @node Generalized Variables @section Generalized Variables +@cindex generalized variable A @dfn{generalized variable} or @dfn{place form} is one of the many places in Lisp memory where values can be stored. The simplest place @@ -1252,6 +1254,7 @@ of symbol macros; @pxref{Macro Bindings}. @node Variable Bindings @section Variable Bindings +@cindex variable binding @noindent These Lisp forms make bindings to variables and function names, @@ -1268,6 +1271,7 @@ are also related to variable bindings. @node Dynamic Bindings @subsection Dynamic Bindings +@cindex dynamic binding @noindent The standard @code{let} form binds variables whose names are known @@ -1288,6 +1292,7 @@ are ignored. @node Function Bindings @subsection Function Bindings +@cindex function binding @noindent These forms make @code{let}-like bindings to functions instead @@ -1341,6 +1346,7 @@ differently. @xref{Obsolete Macros}. @node Macro Bindings @subsection Macro Bindings +@cindex macro binding @noindent These forms create local macros and ``symbol macros''. @@ -1434,6 +1440,7 @@ works much like @code{my-dolist}. @node Conditionals @section Conditionals +@cindex conditionals @noindent These conditional forms augment Emacs Lisp's simple @code{if}, @@ -1509,6 +1516,7 @@ simply returning @code{nil}. @node Blocks and Exits @section Blocks and Exits @cindex block +@cindex exit @noindent Common Lisp @dfn{blocks} provide a non-local exit mechanism very @@ -1588,6 +1596,7 @@ Labels have lexical scope and dynamic extent. @node Iteration @section Iteration +@cindex iteration @noindent The macros described here provide more sophisticated, high-level @@ -1728,6 +1737,7 @@ iterating over vectors or lists. @node Loop Facility @section Loop Facility +@cindex loop facility @noindent A common complaint with Lisp's traditional looping constructs was @@ -1966,18 +1976,6 @@ This clause iterates @var{var} over all the cons cells of @var{list}. @result{} ((1 2 3 4) (2 3 4) (3 4) (4)) @end example -With @code{by}, there is no real reason that the @code{on} expression -must be a list. For example: - -@example -(cl-loop for x on first-animal by 'next-animal collect x) -@end example - -@noindent -where @code{(next-animal x)} takes an ``animal'' @var{x} and returns -the next in the (assumed) sequence of animals, or @code{nil} if -@var{x} was the last animal in the sequence. - @item for @var{var} in-ref @var{list} by @var{function} This is like a regular @code{in} clause, but @var{var} becomes a @code{setf}-able ``reference'' onto the elements of the list @@ -2242,8 +2240,8 @@ were non-@code{nil}, the loop returns @code{t}: @example (if (cl-loop for size in size-list always (> size 10)) - (some-big-sizes) - (no-big-sizes)) + (only-big-sizes) + (some-small-sizes)) @end example @item never @var{condition} @@ -2482,6 +2480,7 @@ buffers are Emacs-specific extensions. @node Multiple Values @section Multiple Values +@cindex multiple values @noindent Common Lisp functions can return zero or more results. Emacs Lisp @@ -4001,10 +4000,7 @@ Given a @code{person}, @code{(copy-person @var{p})} makes a new object of the same type whose slots are @code{eq} to those of @var{p}. Given any Lisp object @var{x}, @code{(person-p @var{x})} returns -true if @var{x} looks like a @code{person}, and false otherwise. (Again, -in Common Lisp this predicate would be exact; in Emacs Lisp the -best it can do is verify that @var{x} is a vector of the correct -length that starts with the correct tag symbol.) +true if @var{x} is a @code{person}, and false otherwise. Accessors like @code{person-name} normally check their arguments (effectively using @code{person-p}) and signal an error if the @@ -4210,16 +4206,16 @@ allow for such a feature, so this package simply ignores @code{:print-function}. @item :type -The argument should be one of the symbols @code{vector} or @code{list}. -This tells which underlying Lisp data type should be used to implement -the new structure type. Vectors are used by default, but -@code{(:type list)} will cause structure objects to be stored as -lists instead. +The argument should be one of the symbols @code{vector} or +@code{list}. This tells which underlying Lisp data type should be +used to implement the new structure type. Records are used by +default, but @code{(:type vector)} will cause structure objects to be +stored as vectors and @code{(:type list)} lists instead. -The vector representation for structure objects has the advantage -that all structure slots can be accessed quickly, although creating -vectors is a bit slower in Emacs Lisp. Lists are easier to create, -but take a relatively long time accessing the later slots. +The record and vector representations for structure objects have the +advantage that all structure slots can be accessed quickly, although +creating them are a bit slower in Emacs Lisp. Lists are easier to +create, but take a relatively long time accessing the later slots. @item :named This option, which takes no arguments, causes a characteristic ``tag'' @@ -4228,21 +4224,24 @@ symbol to be stored at the front of the structure object. Using structure type stored as plain vectors or lists with no identifying features. -The default, if you don't specify @code{:type} explicitly, is to -use named vectors. Therefore, @code{:named} is only useful in -conjunction with @code{:type}. +The default, if you don't specify @code{:type} explicitly, is to use +records, which are always tagged. Therefore, @code{:named} is only +useful in conjunction with @code{:type}. @example (cl-defstruct (person1) name age sex) (cl-defstruct (person2 (:type list) :named) name age sex) (cl-defstruct (person3 (:type list)) name age sex) +(cl-defstruct (person4 (:type vector)) name age sex) (setq p1 (make-person1)) - @result{} [cl-struct-person1 nil nil nil] + @result{} #s(person1 nil nil nil) (setq p2 (make-person2)) @result{} (person2 nil nil nil) (setq p3 (make-person3)) @result{} (nil nil nil) +(setq p4 (make-person4)) + @result{} [nil nil nil] (person1-p p1) @result{} t @@ -4282,9 +4281,9 @@ introspection functions. @defun cl-struct-sequence-type struct-type This function returns the underlying data structure for -@code{struct-type}, which is a symbol. It returns @code{vector} or -@code{list}, or @code{nil} if @code{struct-type} is not actually a -structure. +@code{struct-type}, which is a symbol. It returns @code{record}, +@code{vector} or @code{list}, or @code{nil} if @code{struct-type} is +not actually a structure. @end defun @defun cl-struct-slot-info struct-type @@ -4551,9 +4550,8 @@ set down in Steele's book. The variable @code{cl--gensym-counter} starts out with zero. -The @code{cl-defstruct} facility is compatible, except that structures -are of type @code{:type vector :named} by default rather than some -special, distinct type. Also, the @code{:type} slot option is ignored. +The @code{cl-defstruct} facility is compatible, except that the +@code{:type} slot option is ignored. The second argument of @code{cl-check-type} is treated differently. @@ -4702,9 +4700,9 @@ Lisp. Rational numbers and complex numbers are not present, nor are large integers (all integers are ``fixnums''). All arrays are one-dimensional. There are no readtables or pathnames; streams are a set of existing data types rather than a new data -type of their own. Hash tables, random-states, structures, and -packages (obarrays) are built from Lisp vectors or lists rather -than being distinct types. +type of their own. Hash tables, random-states, and packages +(obarrays) are built from Lisp vectors or lists rather than being +distinct types. @item The Common Lisp Object System (CLOS) is not implemented, @@ -5199,12 +5197,14 @@ that called @code{get-setf-method}. @node Function Index @unnumbered Function Index - @printindex fn @node Variable Index @unnumbered Variable Index - @printindex vr +@node Concept Index +@unnumbered Concept Index +@printindex cp + @bye diff --git a/doc/misc/dired-x.texi b/doc/misc/dired-x.texi index 1e6f4b03bb0..bf103256f29 100644 --- a/doc/misc/dired-x.texi +++ b/doc/misc/dired-x.texi @@ -721,15 +721,27 @@ variable @code{window-min-height}. @item dired-mark-extension @findex dired-mark-extension Mark all files with a certain extension for use in later commands. A @samp{.} -is not automatically prepended to the string entered, you must type it -explicitly. -If invoked with prefix argument @kbd{C-u}, this command unmark files instead. +is automatically prepended to the string entered when not present. +If invoked with prefix argument @kbd{C-u}, this command unmarks files instead. If called with the @kbd{C-u C-u} prefix, asks for a character to use as the marker, and marks files with it. When called from Lisp, @var{extension} may also be a list of extensions and an optional argument @var{marker-char} specifies the marker used. +@item dired-mark-suffix +@findex dired-mark-suffix +Mark all files with a certain suffix for use in later commands. A @samp{.} +is not automatically prepended to the string entered, you must type it +explicitly. This is different from @var{dired-mark-extension} which prepends +a @samp{.} if not present. +If invoked with prefix argument @kbd{C-u}, this command unmarks files instead. +If called with the @kbd{C-u C-u} prefix, asks for a character to use +as the marker, and marks files with it. + +When called from Lisp, @var{suffix} may also be a list of suffixes +and an optional argument @var{marker-char} specifies the marker used. + @item dired-flag-extension @findex dired-flag-extension Flag all files with a certain extension for deletion. A @samp{.} is diff --git a/doc/misc/ediff.texi b/doc/misc/ediff.texi index 19b7adbd668..87d3dfd6ed9 100644 --- a/doc/misc/ediff.texi +++ b/doc/misc/ediff.texi @@ -99,7 +99,8 @@ through them. You can also copy difference regions from one buffer to another (and recover old differences if you change your mind). Another powerful feature is the ability to merge a pair of files into a -third buffer. Merging with an ancestor file is also supported. +third buffer. Merging with an ancestor file, (a.k.a. 3way merges) +is also supported. Furthermore, Ediff is equipped with directory-level capabilities that allow the user to conveniently launch browsing or merging sessions on groups of files in two (or three) different directories. @@ -828,7 +829,10 @@ region in buffer A, etc. @item / @kindex / -Displays the ancestor file during merges. +@vindex ediff-show-ancestor +Toggle to display the ancestor file in 3way merges. +You can enable permanently this setting customizing the variable +@code{ediff-show-ancestor}. @item & @kindex & In some situations, such as when one of the files agrees with the ancestor file diff --git a/doc/misc/eieio.texi b/doc/misc/eieio.texi index ce31bc84b4e..7076c244222 100644 --- a/doc/misc/eieio.texi +++ b/doc/misc/eieio.texi @@ -479,31 +479,31 @@ Name of a generic function which can be used to fetch the value of this slot. You can call this function later on your object and retrieve the value of the slot. -This options is in the CLOS spec, but is not fully compliant in @eieio{}. +This option is in the CLOS spec, but is not fully compliant in @eieio{}. @item :writer Name of a generic function which will write this slot. -This options is in the CLOS spec, but is not fully compliant in @eieio{}. +This option is in the CLOS spec, but is not fully compliant in @eieio{}. @item :reader Name of a generic function which will read this slot. -This options is in the CLOS spec, but is not fully compliant in @eieio{}. +This option is in the CLOS spec, but is not fully compliant in @eieio{}. @item :custom A custom :type specifier used when editing an object of this type. See documentation for @code{defcustom} for details. This specifier is equivalent to the :type spec of a @code{defcustom} call. -This options is specific to Emacs, and is not in the CLOS spec. +This option is specific to Emacs, and is not in the CLOS spec. @item :label When customizing an object, the value of :label will be used instead of the slot name. This enables better descriptions of the data than would usually be afforded. -This options is specific to Emacs, and is not in the CLOS spec. +This option is specific to Emacs, and is not in the CLOS spec. @item :group Similar to @code{defcustom}'s :group command, this organizes different @@ -511,7 +511,7 @@ slots in an object into groups. When customizing an object, only the slots belonging to a specific group need be worked with, simplifying the size of the display. -This options is specific to Emacs, and is not in the CLOS spec. +This option is specific to Emacs, and is not in the CLOS spec. @item :printer This routine takes a symbol which is a function name. The function @@ -546,7 +546,7 @@ Access this slot only from methods of the same class or a child class. Access this slot only from methods of the same class. @end table -This options is specific to Emacs, and is not in the CLOS spec. +This option is specific to Emacs, and is not in the CLOS spec. @end table @@ -571,7 +571,7 @@ the @code{:type} is specifies something such as @code{string} then allow this to pass. The default is to have this option be off. This is implemented as an alternative to unbound slots. -This options is specific to Emacs, and is not in the CLOS spec. +This option is specific to Emacs, and is not in the CLOS spec. @item :abstract A class which is @code{:abstract} cannot be instantiated, and instead @@ -1017,7 +1017,7 @@ If @var{errorp} is non-@code{nil}, @code{wrong-argument-type} is signaled. @defun class-p class @anchor{class-p} -Return @code{t} if @var{class} is a valid class vector. +Return @code{t} if @var{class} is a valid class object. @var{class} is a symbol. @end defun @@ -1055,7 +1055,7 @@ Will fetch the documentation string for @code{eieio-default-superclass}. Return a string of the form @samp{#<object-class myobjname>} for @var{obj}. This should look like Lisp symbols from other parts of Emacs such as buffers and processes, and is shorter and cleaner than printing the -object's vector. It is more useful to use @code{object-print} to get +object's record. It is more useful to use @code{object-print} to get and object's print form, as this allows the object to add extra display information into the symbol. @end defun @@ -1212,7 +1212,7 @@ items defined in this second slot. Introspection permits a programmer to peek at the contents of a class without any previous knowledge of that class. While @eieio{} implements -objects on top of vectors, and thus everything is technically visible, +objects on top of records, and thus everything is technically visible, some functions have been provided. None of these functions are a part of CLOS. @@ -1525,7 +1525,7 @@ Currently, the default superclass is defined as follows: nil "Default parent class for classes with no specified parent class. Its slots are automatically adopted by classes with no specified -parents. This class is not stored in the `parent' slot of a class vector." +parents. This class is not stored in the `parent' slot of a class object." :abstract t) @end example diff --git a/doc/misc/emacs-mime.texi b/doc/misc/emacs-mime.texi index b0cfbc9d3c0..069d6b3389b 100644 --- a/doc/misc/emacs-mime.texi +++ b/doc/misc/emacs-mime.texi @@ -405,7 +405,7 @@ variable will cause @samp{text/html} parts to be treated as attachments. @item mm-text-html-renderer @vindex mm-text-html-renderer This selects the function used to render @acronym{HTML}. The predefined -renderers are selected by the symbols @code{gnus-article-html}, +renderers are selected by the symbols @code{shr}, @code{gnus-w3m}, @code{w3m}@footnote{See @uref{http://emacs-w3m.namazu.org/} for more information about emacs-w3m}, @code{links}, @code{lynx}, @code{w3m-standalone} or @code{html2text}. If @code{nil} use an diff --git a/doc/misc/ert.texi b/doc/misc/ert.texi index b07cb0be490..4a2c29dcb9f 100644 --- a/doc/misc/ert.texi +++ b/doc/misc/ert.texi @@ -551,15 +551,15 @@ on their environment is easy. Such tests often look like this: @lisp (ert-deftest ert-test-mismatch () - (should (eql (ert--mismatch "" "") nil)) - (should (eql (ert--mismatch "" "a") 0)) - (should (eql (ert--mismatch "a" "a") nil)) - (should (eql (ert--mismatch "ab" "a") 1)) - (should (eql (ert--mismatch "Aa" "aA") 0)) - (should (eql (ert--mismatch '(a b c) '(a b d)) 2))) + (should (eql (cl-mismatch "" "") nil)) + (should (eql (cl-mismatch "" "a") 0)) + (should (eql (cl-mismatch "a" "a") nil)) + (should (eql (cl-mismatch "ab" "a") 1)) + (should (eql (cl-mismatch "Aa" "aA") 0)) + (should (eql (cl-mismatch '(a b c) '(a b d)) 2))) @end lisp -This test calls the function @code{ert--mismatch} several times with +This test calls the function @code{cl-mismatch} several times with various combinations of arguments and compares the return value to the expected return value. (Some programmers prefer @code{(should (eql EXPECTED ACTUAL))} over the @code{(should (eql ACTUAL EXPECTED))} diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi index bd89b9c5bf2..a7651b21d61 100644 --- a/doc/misc/eshell.texi +++ b/doc/misc/eshell.texi @@ -493,7 +493,7 @@ History I-search. @itemx M-n Previous and next history line. If there is anything on the input line when you run these commands, they will instead jump to the -precious or next line that begins with that string. +previous or next line that begins with that string. @end table @node Completion diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi index ceeb42b9182..e00e173bc18 100644 --- a/doc/misc/gnus.texi +++ b/doc/misc/gnus.texi @@ -13871,6 +13871,7 @@ installed. You then define a server as follows: (nntp-address "snews.bar.com")) @end lisp +@c FIXME openssl s_client should be deprecated in favor of gnutls. @findex nntp-open-ssl-stream @item nntp-open-ssl-stream Opens a connection to a server over a @dfn{secure} channel. To use @@ -26378,7 +26379,7 @@ read when doing the operation described above. @cindex characters in file names This is an alist that says how to translate characters in file names. For instance, if @samp{:} is invalid as a file character in file names -on your system (you OS/2 user you), you could say something like: +on your system (you MS Windows user you), you could say something like: @lisp @group @@ -26387,7 +26388,7 @@ on your system (you OS/2 user you), you could say something like: @end group @end lisp -In fact, this is the default value for this variable on OS/2 and MS +In fact, this is (part of) the default value for this variable on MS Windows (phooey) systems. @item gnus-hidden-properties diff --git a/doc/misc/info.texi b/doc/misc/info.texi index 6f2e53aa739..3db8e8e90f1 100644 --- a/doc/misc/info.texi +++ b/doc/misc/info.texi @@ -1108,6 +1108,7 @@ other file with @kbd{g(@var{filename})*@key{RET}}. @kindex 1 @r{through} 9 @r{(Info mode)} @findex Info-nth-menu-item @cindex select @var{n}'th menu item +@cindex menu items, select by their numbers If you begrudge each character of type-in which your system requires, you might like to use the commands @kbd{1}, @kbd{2}, @kbd{3}, @kbd{4}, @dots{}, @kbd{9}. They are short for the @kbd{m} command together @@ -1116,6 +1117,11 @@ in the current node's menu; @kbd{2} goes through the second item, etc. In the stand-alone reader, @kbd{0} goes through the last menu item; this is so you need not count how many entries are there. +@cindex 3rd menu item +@cindex third menu item +@cindex 6th menu item +@cindex sixth menu item +@cindex star @samp{*} before menu item If your display supports multiple fonts, colors or underlining, and you are using Emacs's Info mode to read Info files, the third, sixth and ninth menu items have a @samp{*} that stands out, either in color diff --git a/doc/misc/mh-e.texi b/doc/misc/mh-e.texi index a113272e494..3aa04caf865 100644 --- a/doc/misc/mh-e.texi +++ b/doc/misc/mh-e.texi @@ -7644,10 +7644,10 @@ Whitelisted message face @end vtable @cindex SpamProbe -@cindex Spamassassin +@cindex SpamAssassin @cindex bogofilter @cindex spam filters, SpamProbe -@cindex spam filters, Spamassassin +@cindex spam filters, SpamAssassin @cindex spam filters, bogofilter MH-E depends on @uref{http://spamassassin.apache.org/, SpamAssassin}, @@ -7720,8 +7720,8 @@ MH-E can work with. @subheading SpamAssassin -@cindex Spamassassin -@cindex spam filters, Spamassassin +@cindex SpamAssassin +@cindex spam filters, SpamAssassin SpamAssassin is one of the more popular spam filtering programs. Get it from your local distribution or from the diff --git a/doc/misc/org.texi b/doc/misc/org.texi index 596300e5ed8..e1de3087311 100644 --- a/doc/misc/org.texi +++ b/doc/misc/org.texi @@ -4,7 +4,7 @@ @settitle The Org Manual @include docstyle.texi -@set VERSION 8.2.9 +@set VERSION 9.0.9 @c Version and Contact Info @set MAINTAINERSITE @uref{http://orgmode.org,maintainers web page} @@ -284,8 +284,8 @@ modify this GNU manual.'' @subtitle Release @value{VERSION} @author by Carsten Dominik -with contributions by David O'Toole, Bastien Guerry, Philip Rooke, Dan -Davison, Eric Schulte, Thomas Dye, Jambunathan K and Nicolas Goaziou. +with contributions by Bastien Guerry, Nicolas Goaziou, Eric Schulte, +Jambunathan K, Dan Davison, Thomas Dye, David O'Toole, and Philip Rooke. @c The following two commands start the copyright page. @page @@ -293,13 +293,14 @@ Davison, Eric Schulte, Thomas Dye, Jambunathan K and Nicolas Goaziou. @insertcopying @end titlepage +@c Output the short table of contents at the beginning. +@shortcontents + @c Output the table of contents at the beginning. @contents @ifnottex -@c FIXME These hand-written next,prev,up node pointers make editing a lot -@c harder. There should be no need for them, makeinfo can do it -@c automatically for any document with a normal structure. + @node Top, Introduction, (dir), (dir) @top Org Mode Manual @@ -308,23 +309,23 @@ Davison, Eric Schulte, Thomas Dye, Jambunathan K and Nicolas Goaziou. @menu * Introduction:: Getting started -* Document Structure:: A tree works like your brain +* Document structure:: A tree works like your brain * Tables:: Pure magic for quick formatting * Hyperlinks:: Notes in context -* TODO Items:: Every tree branch can be a TODO item +* TODO items:: Every tree branch can be a TODO item * Tags:: Tagging headlines and matching sets of tags -* Properties and Columns:: Storing information about an entry -* Dates and Times:: Making items useful for planning +* Properties and columns:: Storing information about an entry +* Dates and times:: Making items useful for planning * Capture - Refile - Archive:: The ins and outs for projects -* Agenda Views:: Collecting information into views +* Agenda views:: Collecting information into views * Markup:: Prepare text for rich export * Exporting:: Sharing and publishing notes * Publishing:: Create a web site of linked Org files -* Working With Source Code:: Export, evaluate, and tangle code blocks +* Working with source code:: Export, evaluate, and tangle code blocks * Miscellaneous:: All the rest which did not fit elsewhere * Hacking:: How to hack your way around * MobileOrg:: Viewing and capture on a mobile device -* History and Acknowledgments:: How Org came into being +* History and acknowledgments:: How Org came into being * GNU Free Documentation License:: The license for this documentation. * Main Index:: An index of Org's concepts and features * Key Index:: Key bindings and where they are described @@ -363,11 +364,6 @@ Visibility cycling * Initial visibility:: Setting the initial visibility state * Catching invisible edits:: Preventing mistakes when editing invisible parts -Global and local cycling - -* Initial visibility:: Setting the initial visibility state -* Catching invisible edits:: Preventing mistakes when editing invisible parts - Tables * Built-in table editor:: Simple tables @@ -434,7 +430,7 @@ Tags * Tag inheritance:: Tags use the tree structure of the outline * Setting tags:: How to assign tags to a headline -* Tag groups:: Use one tag to search for several tags +* Tag hierarchy:: Create a hierarchy of tags * Tag searches:: Searching for combinations of tags Properties and columns @@ -464,8 +460,7 @@ Dates and times * Deadlines and scheduling:: Planning your work * Clocking work time:: Tracking how long you spend on a task * Effort estimates:: Planning work effort in advance -* Relative timer:: Notes with a running timer -* Countdown timer:: Starting a countdown timer for a task +* Timers:: Notes with a running timer Creating timestamps @@ -487,7 +482,7 @@ Capture - Refile - Archive * Capture:: Capturing new stuff * Attachments:: Add files to tasks -* RSS Feeds:: Getting input from RSS feeds +* RSS feeds:: Getting input from RSS feeds * Protocols:: External (e.g., Browser) access to Emacs and Org * Refile and copy:: Moving/copying a tree from one place to another * Archiving:: What to do with finished projects @@ -517,7 +512,7 @@ Agenda views * Presentation and sorting:: How agenda items are prepared for display * Agenda commands:: Remote editing of Org trees * Custom agenda views:: Defining special searches and views -* Exporting Agenda Views:: Writing a view to a file +* Exporting agenda views:: Writing a view to a file * Agenda column view:: Using column view for collected entries The built-in agenda views @@ -540,114 +535,127 @@ Custom agenda views * Storing searches:: Type once, use often * Block agenda:: All the stuff you need in a single buffer -* Setting Options:: Changing the rules +* Setting options:: Changing the rules Markup for rich export -* Structural markup elements:: The basic structure as seen by the exporter +* Paragraphs:: The basic unit of text +* Emphasis and monospace:: Bold, italic, etc. +* Horizontal rules:: Make a line * Images and tables:: Images, tables and caption mechanism * Literal examples:: Source code examples with special formatting -* Include files:: Include additional files into a document -* Index entries:: Making an index -* Macro replacement:: Use macros to create templates +* Special symbols:: Greek letters and other symbols +* Subscripts and superscripts:: Simple syntax for raising/lowering text * Embedded @LaTeX{}:: LaTeX can be freely used inside Org documents -* Special blocks:: Containers targeted at export back-ends - -Structural markup elements - -* Document title:: Where the title is taken from -* Headings and sections:: The document structure as seen by the exporter -* Table of contents:: The if and where of the table of contents -* Lists:: Lists -* Paragraphs:: Paragraphs -* Footnote markup:: Footnotes -* Emphasis and monospace:: Bold, italic, etc. -* Horizontal rules:: Make a line -* Comment lines:: What will *not* be exported Embedded @LaTeX{} -* Special symbols:: Greek letters and other symbols -* Subscripts and superscripts:: Simple syntax for raising/lowering text * @LaTeX{} fragments:: Complex formulas made easy * Previewing @LaTeX{} fragments:: What will this snippet look like? * CDLaTeX mode:: Speed up entering of formulas Exporting -* The Export Dispatcher:: The main exporter interface -* Export back-ends:: Built-in export formats -* Export settings:: Generic export settings +* The export dispatcher:: The main interface +* Export settings:: Common export settings +* Table of contents:: The if and where of the table of contents +* Include files:: Include additional files into a document +* Macro replacement:: Use macros to create templates +* Comment lines:: What will not be exported * ASCII/Latin-1/UTF-8 export:: Exporting to flat files with encoding * Beamer export:: Exporting as a Beamer presentation * HTML export:: Exporting to HTML -* @LaTeX{} and PDF export:: Exporting to @LaTeX{}, and processing to PDF +* @LaTeX{} export:: Exporting to @LaTeX{}, and processing to PDF * Markdown export:: Exporting to Markdown * OpenDocument Text export:: Exporting to OpenDocument Text * Org export:: Exporting to Org * Texinfo export:: Exporting to Texinfo * iCalendar export:: Exporting to iCalendar * Other built-in back-ends:: Exporting to a man page -* Export in foreign buffers:: Author tables and lists in Org syntax * Advanced configuration:: Fine-tuning the export output +* Export in foreign buffers:: Author tables and lists in Org syntax + +Beamer export + +* Beamer export commands:: For creating Beamer documents. +* Beamer specific export settings:: For customizing Beamer export. +* Sectioning Frames and Blocks in Beamer:: For composing Beamer slides. +* Beamer specific syntax:: For using in Org documents. +* Editing support:: For using helper functions. +* A Beamer example:: A complete presentation. HTML export -* HTML Export commands:: How to invoke HTML export -* HTML doctypes:: Org can export to various (X)HTML flavors -* HTML preamble and postamble:: How to insert a preamble and a postamble -* Quoting HTML tags:: Using direct HTML in Org mode -* Links in HTML export:: How links will be interpreted and formatted -* Tables in HTML export:: How to modify the formatting of tables -* Images in HTML export:: How to insert figures into HTML output -* Math formatting in HTML export:: Beautiful math also on the web -* Text areas in HTML export:: An alternative way to show an example -* CSS support:: Changing the appearance of the output -* JavaScript support:: Info and Folding in a web browser - -@LaTeX{} and PDF export - -* @LaTeX{} export commands:: How to export to LaTeX and PDF -* Header and sectioning:: Setting up the export file structure -* Quoting @LaTeX{} code:: Incorporating literal @LaTeX{} code -* @LaTeX{} specific attributes:: Controlling @LaTeX{} output +* HTML Export commands:: Invoking HTML export +* HTML Specific export settings:: Settings for HTML export +* HTML doctypes:: Exporting various (X)HTML flavors +* HTML preamble and postamble:: Inserting preamble and postamble +* Quoting HTML tags:: Using direct HTML in Org files +* Links in HTML export:: Interpreting and formatting links +* Tables in HTML export:: Formatting and modifying tables +* Images in HTML export:: Inserting figures with HTML output +* Math formatting in HTML export:: Handling math equations +* Text areas in HTML export:: Showing an alternate approach, an example +* CSS support:: Styling HTML output +* JavaScript support:: Folding scripting in the web browser + +@LaTeX{} export + +* @LaTeX{} export commands:: For producing @LaTeX{} and PDF documents. +* @LaTeX{} specific export settings:: Unique to this @LaTeX{} back-end. +* @LaTeX{} header and sectioning:: For file structure. +* Quoting @LaTeX{} code:: Directly in the Org document. +* Tables in @LaTeX{} export:: Attributes specific to tables. +* Images in @LaTeX{} export:: Attributes specific to images. +* Plain lists in @LaTeX{} export:: Attributes specific to lists. +* Source blocks in @LaTeX{} export:: Attributes specific to source code blocks. +* Example blocks in @LaTeX{} export:: Attributes specific to example blocks. +* Special blocks in @LaTeX{} export:: Attributes specific to special blocks. +* Horizontal rules in @LaTeX{} export:: Attributes specific to horizontal rules. OpenDocument Text export -* Pre-requisites for ODT export:: What packages ODT exporter relies on -* ODT export commands:: How to invoke ODT export -* Extending ODT export:: How to produce @samp{doc}, @samp{pdf} files -* Applying custom styles:: How to apply custom styles to the output -* Links in ODT export:: How links will be interpreted and formatted -* Tables in ODT export:: How Tables are exported -* Images in ODT export:: How to insert images -* Math formatting in ODT export:: How @LaTeX{} fragments are formatted -* Labels and captions in ODT export:: How captions are rendered -* Literal examples in ODT export:: How source and example blocks are formatted -* Advanced topics in ODT export:: Read this if you are a power user +* Pre-requisites for ODT export:: Required packages. +* ODT export commands:: Invoking export. +* ODT specific export settings:: Configuration options. +* Extending ODT export:: Producing @file{.doc}, @file{.pdf} files. +* Applying custom styles:: Styling the output. +* Links in ODT export:: Handling and formatting links. +* Tables in ODT export:: Org table conversions. +* Images in ODT export:: Inserting images. +* Math formatting in ODT export:: Formatting @LaTeX{} fragments. +* Labels and captions in ODT export:: Rendering objects. +* Literal examples in ODT export:: For source code and example blocks. +* Advanced topics in ODT export:: For power users. Math formatting in ODT export -* Working with @LaTeX{} math snippets:: How to embed @LaTeX{} math fragments -* Working with MathML or OpenDocument formula files:: How to embed equations in native format +* Working with @LaTeX{} math snippets:: Embedding in @LaTeX{} format. +* Working with MathML or OpenDocument formula files:: Embedding in native format. Advanced topics in ODT export -* Configuring a document converter:: How to register a document converter -* Working with OpenDocument style files:: Explore the internals -* Creating one-off styles:: How to produce custom highlighting etc -* Customizing tables in ODT export:: How to define and use Table templates -* Validating OpenDocument XML:: How to debug corrupt OpenDocument files +* Configuring a document converter:: Registering a document converter. +* Working with OpenDocument style files:: Exploring internals. +* Creating one-off styles:: Customizing styles, highlighting. +* Customizing tables in ODT export:: Defining table templates. +* Validating OpenDocument XML:: Debugging corrupted OpenDocument files. Texinfo export -* Texinfo export commands:: How to invoke Texinfo export -* Document preamble:: File header, title and copyright page -* Headings and sectioning structure:: Building document structure -* Indices:: Creating indices -* Quoting Texinfo code:: Incorporating literal Texinfo code -* Texinfo specific attributes:: Controlling Texinfo output -* An example:: +* Texinfo export commands:: Invoking commands. +* Texinfo specific export settings:: Setting the environment. +* Texinfo file header:: Generating the header. +* Texinfo title and copyright page:: Creating preamble pages. +* Info directory file:: Installing a manual in Info file hierarchy. +* Headings and sectioning structure:: Building document structure. +* Indices:: Creating indices. +* Quoting Texinfo code:: Incorporating literal Texinfo code. +* Plain lists in Texinfo export:: List attributes. +* Tables in Texinfo export:: Table attributes. +* Images in Texinfo export:: Image attributes. +* Special blocks in Texinfo export:: Special block attributes. +* A Texinfo example:: Processing Org to Texinfo. Publishing @@ -694,36 +702,32 @@ Header arguments Using header arguments -* System-wide header arguments:: Set global default values -* Language-specific header arguments:: Set default values by language -* Header arguments in Org mode properties:: Set default values for a buffer or heading -* Language-specific header arguments in Org mode properties:: Set language-specific default values for a buffer or heading -* Code block specific header arguments:: The most common way to set values -* Header arguments in function calls:: The most specific level +* System-wide header arguments:: Set globally, language-specific +* Language-specific header arguments:: Set in the Org file's headers +* Header arguments in Org mode properties:: Set in the Org file +* Language-specific mode properties:: +* Code block specific header arguments:: The most commonly used method +* Arguments in function calls:: The most specific level, takes highest priority Specific header arguments -* var:: Pass arguments to code blocks -* results:: Specify the type of results and how they will - be collected and handled -* file:: Specify a path for file output +* var:: Pass arguments to @samp{src} code blocks +* results:: Specify results type; how to collect +* file:: Specify a path for output file * file-desc:: Specify a description for file results -* dir:: Specify the default (possibly remote) - directory for code block execution -* exports:: Export code and/or results -* tangle:: Toggle tangling and specify file name -* mkdirp:: Toggle creation of parent directories of target - files during tangling -* comments:: Toggle insertion of comments in tangled - code files -* padline:: Control insertion of padding lines in tangled - code files -* no-expand:: Turn off variable assignment and noweb - expansion during tangling +* file-ext:: Specify an extension for file output +* output-dir:: Specify a directory for output file +* dir:: Specify the default directory for code block execution +* exports:: Specify exporting code, results, both, none +* tangle:: Toggle tangling; or specify file name +* mkdirp:: Toggle for parent directory creation for target files during tangling +* comments:: Toggle insertion of comments in tangled code files +* padline:: Control insertion of padding lines in tangled code files +* no-expand:: Turn off variable assignment and noweb expansion during tangling * session:: Preserve the state of code evaluation * noweb:: Toggle expansion of noweb references * noweb-ref:: Specify block's noweb reference resolution target -* noweb-sep:: String used to separate noweb references +* noweb-sep:: String to separate noweb references * cache:: Avoid re-evaluating unchanged code blocks * sep:: Delimiter for writing tabular results outside Org * hlines:: Handle horizontal lines in tables @@ -733,22 +737,22 @@ Specific header arguments * tangle-mode:: Set permission of tangled files * eval:: Limit evaluation of specific code blocks * wrap:: Mark source block evaluation results -* post:: Post processing of code block results -* prologue:: Text to prepend to code block body -* epilogue:: Text to append to code block body +* post:: Post processing of results of code block evaluation +* prologue:: Text to prepend to body of code block +* epilogue:: Text to append to body of code block Miscellaneous -* Completion:: M-TAB knows what you need -* Easy Templates:: Quick insertion of structural elements +* Completion:: M-TAB guesses completions +* Easy templates:: Quick insertion of structural elements * Speed keys:: Electric commands at the beginning of a headline * Code evaluation security:: Org mode files evaluate inline code -* Customization:: Adapting Org to your taste +* Customization:: Adapting Org to changing tastes * In-buffer settings:: Overview of the #+KEYWORDS * The very busy C-c C-c key:: When in doubt, press C-c C-c * Clean view:: Getting rid of leading stars in the outline * TTY keys:: Using Org on a tty -* Interaction:: Other Emacs packages +* Interaction:: With other Emacs packages * org-crypt:: Encrypting Org files Interaction with other packages @@ -780,14 +784,14 @@ Tables and lists in arbitrary syntax MobileOrg -* Setting up the staging area:: Where to interact with the mobile device +* Setting up the staging area:: For the mobile device * Pushing to MobileOrg:: Uploading Org files and agendas * Pulling from MobileOrg:: Integrating captured and flagged items @end detailmenu @end menu -@node Introduction, Document Structure, Top, Top +@node Introduction @chapter Introduction @cindex introduction @@ -799,79 +803,65 @@ MobileOrg * Conventions:: Typesetting conventions in the manual @end menu -@node Summary, Installation, Introduction, Introduction +@node Summary @section Summary @cindex summary -Org is a mode for keeping notes, maintaining TODO lists, and doing -project planning with a fast and effective plain-text system. - -Org develops organizational tasks around NOTES files that contain -lists or information about projects as plain text. Org is -implemented on top of Outline mode, which makes it possible to keep the -content of large files well structured. Visibility cycling and -structure editing help to work with the tree. Tables are easily created -with a built-in table editor. Org supports TODO items, deadlines, -timestamps, and scheduling. It dynamically compiles entries into an -agenda that utilizes and smoothly integrates much of the Emacs calendar -and diary. Plain text URL-like links connect to websites, emails, -Usenet messages, BBDB entries, and any files related to the projects. -For printing and sharing notes, an Org file can be exported as a -structured ASCII file, as HTML, or (TODO and agenda items only) as an -iCalendar file. It can also serve as a publishing tool for a set of -linked web pages. - -As a project planning environment, Org works by adding metadata to outline -nodes. Based on this data, specific entries can be extracted in queries and -create dynamic @i{agenda views}. - -Org mode contains the Org Babel environment which allows you to work with -embedded source code blocks in a file, to facilitate code evaluation, -documentation, and literate programming techniques. - -Org's automatic, context-sensitive table editor with spreadsheet -capabilities can be integrated into any major mode by activating the -minor Orgtbl mode. Using a translation step, it can be used to maintain -tables in arbitrary file types, for example in @LaTeX{}. The structure -editing and list creation capabilities can be used outside Org with -the minor Orgstruct mode. - -Org keeps simple things simple. When first fired up, it should -feel like a straightforward, easy to use outliner. Complexity is not -imposed, but a large amount of functionality is available when you need -it. Org is a toolbox and can be used in different ways and for different -ends, for example: - -@example -@r{@bullet{} an outline extension with visibility cycling and structure editing} -@r{@bullet{} an ASCII system and table editor for taking structured notes} -@r{@bullet{} a TODO list editor} -@r{@bullet{} a full agenda and planner with deadlines and work scheduling} -@pindex GTD, Getting Things Done -@r{@bullet{} an environment in which to implement David Allen's GTD system} -@r{@bullet{} a simple hypertext system, with HTML and @LaTeX{} export} -@r{@bullet{} a publishing tool to create a set of interlinked web pages} -@r{@bullet{} an environment for literate programming} -@end example +Org is a mode for keeping notes, maintaining TODO lists, and project planning +with a fast and effective plain-text system. It also is an authoring system +with unique support for literate programming and reproducible research. + +Org is implemented on top of Outline mode, which makes it possible to keep +the content of large files well structured. Visibility cycling and structure +editing help to work with the tree. Tables are easily created with a +built-in table editor. Plain text URL-like links connect to websites, +emails, Usenet messages, BBDB entries, and any files related to the projects. + +Org develops organizational tasks around notes files that contain lists or +information about projects as plain text. Project planning and task +management makes use of metadata which is part of an outline node. Based on +this data, specific entries can be extracted in queries and create dynamic +@i{agenda views} that also integrate the Emacs calendar and diary. Org can +be used to implement many different project planning schemes, such as David +Allen's GTD system. + +Org files can serve as a single source authoring system with export to many +different formats such as HTML, @LaTeX{}, Open Document, and Markdown. New +export backends can be derived from existing ones, or defined from scratch. + +Org files can include source code blocks, which makes Org uniquely suited for +authoring technical documents with code examples. Org source code blocks are +fully functional; they can be evaluated in place and their results can be +captured in the file. This makes it possible to create a single file +reproducible research compendium. + +Org keeps simple things simple. When first fired up, it should feel like a +straightforward, easy to use outliner. Complexity is not imposed, but a +large amount of functionality is available when needed. Org is a toolbox. +Many users actually run only a (very personal) fraction of Org's capabilities, and +know that there is more whenever they need it. + +All of this is achieved with strictly plain text files, the most portable and +future-proof file format. Org runs in Emacs. Emacs is one of the most +widely ported programs, so that Org mode is available on every major +platform. @cindex FAQ There is a website for Org which provides links to the newest version of Org, as well as additional information, frequently asked questions (FAQ), links to tutorials, etc. This page is located at @uref{http://orgmode.org}. - @cindex print edition -The version 7.3 of this manual is available as a -@uref{http://www.network-theory.co.uk/org/manual/, paperback book from Network -Theory Ltd.} -@page +An earlier version (7.3) of this manual is available as a +@uref{http://www.network-theory.co.uk/org/manual/, paperback book from +Network Theory Ltd.} +@page -@node Installation, Activation, Summary, Introduction +@node Installation @section Installation @cindex installation -@cindex XEmacs Org is part of recent distributions of GNU Emacs, so you normally don't need to install it. If, for one reason or another, you want to install Org on top @@ -895,7 +885,7 @@ been visited, i.e., where no Org built-in function have been loaded. Otherwise autoload Org functions will mess up the installation. Then, to make sure your Org configuration is taken into account, initialize -the package system with @code{(package-initialize)} in your @file{.emacs} +the package system with @code{(package-initialize)} in your Emacs init file before setting any Org option. If you want to use Org's package repository, check out the @uref{http://orgmode.org/elpa.html, Org ELPA page}. @@ -903,7 +893,7 @@ check out the @uref{http://orgmode.org/elpa.html, Org ELPA page}. You can download Org latest release from @uref{http://orgmode.org/, Org's website}. In this case, make sure you set the load-path correctly in your -@file{.emacs}: +Emacs init file: @lisp (add-to-list 'load-path "~/path/to/orgdir/lisp") @@ -945,7 +935,7 @@ For more detailed explanations on Org's build system, please check the Org Build System page on @uref{http://orgmode.org/worg/dev/org-build-system.html, Worg}. -@node Activation, Feedback, Installation, Introduction +@node Activation @section Activation @cindex activation @cindex autoload @@ -957,14 +947,6 @@ Worg}. @findex org-store-link @findex org-iswitchb -Since Emacs 22.2, files with the @file{.org} extension use Org mode by -default. If you are using an earlier version of Emacs, add this line to your -@file{.emacs} file: - -@lisp -(add-to-list 'auto-mode-alist '("\\.org\\'" . org-mode)) -@end lisp - Org mode buffers need font-lock to be turned on: this is the default in Emacs@footnote{If you don't use font-lock globally, turn it on in Org buffer with @code{(add-hook 'org-mode-hook 'turn-on-font-lock)}}. @@ -979,15 +961,15 @@ suggested bindings for these keys, please modify the keys to your own liking. @lisp (global-set-key "\C-cl" 'org-store-link) -(global-set-key "\C-cc" 'org-capture) (global-set-key "\C-ca" 'org-agenda) +(global-set-key "\C-cc" 'org-capture) (global-set-key "\C-cb" 'org-iswitchb) @end lisp @cindex Org mode, turning on -With this setup, all files with extension @samp{.org} will be put -into Org mode. As an alternative, make the first line of a file look -like this: +Files with the @file{.org} extension use Org mode by default. To turn on Org +mode in a file that does not have the extension @file{.org}, make the first +line of a file look like this: @example MY PROJECTS -*- mode: org; -*- @@ -999,17 +981,12 @@ the file's name is. See also the variable @code{org-insert-mode-line-in-empty-file}. Many commands in Org work on the region if the region is @i{active}. To make -use of this, you need to have @code{transient-mark-mode} -(@code{zmacs-regions} in XEmacs) turned on. In Emacs 23 this is the default, -in Emacs 22 you need to do this yourself with -@lisp -(transient-mark-mode 1) -@end lisp -@noindent If you do not like @code{transient-mark-mode}, you can create an -active region by using the mouse to select a region, or pressing +use of this, you need to have @code{transient-mark-mode} turned on, which is +the default. If you do not like @code{transient-mark-mode}, you can create +an active region by using the mouse to select a region, or pressing @kbd{C-@key{SPC}} twice before moving the cursor. -@node Feedback, Conventions, Activation, Introduction +@node Feedback @section Feedback @cindex feedback @cindex bug reports @@ -1018,6 +995,8 @@ active region by using the mouse to select a region, or pressing If you find problems with Org, or if you have questions, remarks, or ideas about it, please mail to the Org mailing list @email{emacs-orgmode@@gnu.org}. +You can subscribe to the list +@uref{https://lists.gnu.org/mailman/listinfo/emacs-orgmode, on this web page}. If you are not a member of the mailing list, your mail will be passed to the list after a moderator has approved it@footnote{Please consider subscribing to the mailing list, in order to minimize the work the mailing list @@ -1028,13 +1007,13 @@ version of Org available---if you are running an outdated version, it is quite possible that the bug has been fixed already. If the bug persists, prepare a report and provide as much information as possible, including the version information of Emacs (@kbd{M-x emacs-version @key{RET}}) and Org -(@kbd{M-x org-version RET}), as well as the Org related setup in -@file{.emacs}. The easiest way to do this is to use the command +(@kbd{M-x org-version RET}), as well as the Org related setup in the Emacs +init file. The easiest way to do this is to use the command @example @kbd{M-x org-submit-bug-report RET} @end example @noindent which will put all this information into an Emacs mail buffer so -that you only need to add your description. If you re not sending the Email +that you only need to add your description. If you are not sending the Email from within Emacs, please copy and paste the content into your Email program. Sometimes you might face a problem due to an error in your Emacs or Org mode @@ -1097,8 +1076,7 @@ To do this, use or select @code{Org -> Refresh/Reload -> Reload Org uncompiled} from the menu. @item -Go to the @code{Options} menu and select @code{Enter Debugger on Error} -(XEmacs has this option in the @code{Troubleshooting} sub-menu). +Go to the @code{Options} menu and select @code{Enter Debugger on Error}. @item Do whatever you have to do to hit the error. Don't forget to document the steps you take. @@ -1108,7 +1086,7 @@ screen. Save this buffer to a file (for example using @kbd{C-x C-w}) and attach it to your bug report. @end enumerate -@node Conventions, , Feedback, Introduction +@node Conventions @section Typesetting conventions used in this manual @subsubheading TODO keywords, tags, properties, etc. @@ -1132,21 +1110,20 @@ special meaning are written with all capitals. @end table Moreover, Org uses @i{option keywords} (like @code{#+TITLE} to set the title) -and @i{environment keywords} (like @code{#+BEGIN_HTML} to start a @code{HTML} -environment). They are written in uppercase in the manual to enhance its -readability, but you can use lowercase in your Org files@footnote{Easy -templates insert lowercase keywords and Babel dynamically inserts -@code{#+results}.}. +and @i{environment keywords} (like @code{#+BEGIN_EXPORT html} to start +a @code{HTML} environment). They are written in uppercase in the manual to +enhance its readability, but you can use lowercase in your Org file. -@subsubheading Keybindings and commands +@subsubheading Key bindings and commands @kindex C-c a @findex org-agenda @kindex C-c c @findex org-capture -The manual suggests two global keybindings: @kbd{C-c a} for @code{org-agenda} -and @kbd{C-c c} for @code{org-capture}. These are only suggestions, but the -rest of the manual assumes that you are using these keybindings. +The manual suggests a few global key bindings, in particular @kbd{C-c a} for +@code{org-agenda} and @kbd{C-c c} for @code{org-capture}. These are only +suggestions, but the rest of the manual assumes that these key bindings are in +place in order to list commands by key access. Also, the manual lists both the keys and the corresponding commands for accessing a functionality. Org mode often uses the same key for different @@ -1159,7 +1136,7 @@ will be listed to call @code{org-table-move-column-right}. If you prefer, you can compile the manual without the command names by unsetting the flag @code{cmdnames} in @file{org.texi}. -@node Document Structure, Tables, Introduction, Top +@node Document structure @chapter Document structure @cindex document structure @cindex structure of document @@ -1182,7 +1159,7 @@ edit the structure of the document. * Org syntax:: Formal description of Org's syntax @end menu -@node Outlines, Headlines, Document Structure, Document Structure +@node Outlines @section Outlines @cindex outlines @cindex Outline mode @@ -1196,7 +1173,7 @@ currently being worked on. Org greatly simplifies the use of outlines by compressing the entire show/hide functionality into a single command, @command{org-cycle}, which is bound to the @key{TAB} key. -@node Headlines, Visibility cycling, Outlines, Document Structure +@node Headlines @section Headlines @cindex headlines @cindex outline tree @@ -1209,7 +1186,7 @@ start with one or more stars, on the left margin@footnote{See the variables @code{org-special-ctrl-a/e}, @code{org-special-ctrl-k}, and @code{org-ctrl-k-protect-subtree} to configure special behavior of @kbd{C-a}, @kbd{C-e}, and @kbd{C-k} in headlines.} @footnote{Clocking only works with -headings indented less then 30 stars.}. For example: +headings indented less than 30 stars.}. For example: @example * Top level headline @@ -1222,7 +1199,12 @@ headings indented less then 30 stars.}. For example: * Another top level headline @end example -@noindent Some people find the many stars too noisy and would prefer an +@vindex org-footnote-section +@noindent Note that a headline named after @code{org-footnote-section}, +which defaults to @samp{Footnotes}, is considered as special. A subtree with +this headline will be silently ignored by exporting functions. + +Some people find the many stars too noisy and would prefer an outline that has whitespace followed by a single star as headline starters. @ref{Clean view}, describes a setup to realize this. @@ -1233,7 +1215,7 @@ least two empty lines, one empty line will remain visible after folding the subtree, in order to structure the collapsed view. See the variable @code{org-cycle-separator-lines} to modify this behavior. -@node Visibility cycling, Motion, Headlines, Document Structure +@node Visibility cycling @section Visibility cycling @cindex cycling, visibility @cindex visibility cycling @@ -1247,7 +1229,7 @@ variable @code{org-cycle-separator-lines} to modify this behavior. * Catching invisible edits:: Preventing mistakes when editing invisible parts @end menu -@node Global and local cycling, Initial visibility, Visibility cycling, Visibility cycling +@node Global and local cycling @subsection Global and local cycling Outlines make it possible to hide parts of the text in the buffer. @@ -1299,7 +1281,7 @@ tables, @kbd{S-@key{TAB}} jumps to the previous field. @orgcmd{C-u C-u @key{TAB},org-set-startup-visibility} Switch back to the startup visibility of the buffer (@pxref{Initial visibility}). @cindex show all, command -@orgcmd{C-u C-u C-u @key{TAB},show-all} +@orgcmd{C-u C-u C-u @key{TAB},outline-show-all} Show all, including drawers. @cindex revealing context @orgcmd{C-c C-r,org-reveal} @@ -1310,37 +1292,25 @@ exposed by a sparse tree command (@pxref{Sparse trees}) or an agenda command level, all sibling headings. With a double prefix argument, also show the entire subtree of the parent. @cindex show branches, command -@orgcmd{C-c C-k,show-branches} +@orgcmd{C-c C-k,outline-show-branches} Expose all the headings of the subtree, CONTENT view for just one subtree. @cindex show children, command -@orgcmd{C-c @key{TAB},show-children} +@orgcmd{C-c @key{TAB},outline-show-children} Expose all direct children of the subtree. With a numeric prefix argument N, expose all children down to level N@. @orgcmd{C-c C-x b,org-tree-to-indirect-buffer} -Show the current subtree in an indirect buffer@footnote{The indirect -buffer -@ifinfo -(@pxref{Indirect Buffers,,,emacs,GNU Emacs Manual}) -@end ifinfo -@ifnotinfo -(see the Emacs manual for more information about indirect buffers) -@end ifnotinfo -will contain the entire buffer, but will be narrowed to the current -tree. Editing the indirect buffer will also change the original buffer, -but without affecting visibility in that buffer.}. With a numeric -prefix argument N, go up to level N and then take that tree. If N is -negative then go up that many levels. With a @kbd{C-u} prefix, do not remove -the previously used indirect buffer. +Show the current subtree in an indirect buffer@footnote{The indirect buffer +(@pxref{Indirect Buffers,,,emacs,GNU Emacs Manual}) will contain the entire +buffer, but will be narrowed to the current tree. Editing the indirect +buffer will also change the original buffer, but without affecting visibility +in that buffer.}. With a numeric prefix argument N, go up to level N and +then take that tree. If N is negative then go up that many levels. With a +@kbd{C-u} prefix, do not remove the previously used indirect buffer. @orgcmd{C-c C-x v,org-copy-visible} Copy the @i{visible} text in the region into the kill ring. @end table -@menu -* Initial visibility:: Setting the initial visibility state -* Catching invisible edits:: Preventing mistakes when editing invisible parts -@end menu - -@node Initial visibility, Catching invisible edits, Global and local cycling, Visibility cycling +@node Initial visibility @subsection Initial visibility @cindex visibility, initialize @@ -1366,14 +1336,10 @@ following lines anywhere in the buffer: #+STARTUP: showeverything @end example -The startup visibility options are ignored when the file is open for the -first time during the agenda generation: if you want the agenda to honor -the startup visibility, set @code{org-agenda-inhibit-startup} to @code{nil}. - @cindex property, VISIBILITY @noindent Furthermore, any entries with a @samp{VISIBILITY} property (@pxref{Properties -and Columns}) will get their visibility adapted accordingly. Allowed values +and columns}) will get their visibility adapted accordingly. Allowed values for this property are @code{folded}, @code{children}, @code{content}, and @code{all}. @@ -1384,7 +1350,7 @@ requested by startup options and @samp{VISIBILITY} properties in individual entries. @end table -@node Catching invisible edits, , Initial visibility, Visibility cycling +@node Catching invisible edits @subsection Catching invisible edits @vindex org-catch-invisible-edits @@ -1395,7 +1361,7 @@ confused on what has been edited and how to undo the mistake. Setting docstring of this option on how Org should catch invisible edits and process them. -@node Motion, Structure editing, Visibility cycling, Document Structure +@node Motion @section Motion @cindex motion, between headlines @cindex jumping, to headlines @@ -1403,9 +1369,9 @@ them. The following commands jump to other headlines in the buffer. @table @asis -@orgcmd{C-c C-n,outline-next-visible-heading} +@orgcmd{C-c C-n,org-next-visible-heading} Next heading. -@orgcmd{C-c C-p,outline-previous-visible-heading} +@orgcmd{C-c C-p,org-previous-visible-heading} Previous heading. @orgcmd{C-c C-f,org-forward-same-level} Next heading same level. @@ -1435,7 +1401,7 @@ q @r{Quit} See also the option @code{org-goto-interface}. @end table -@node Structure editing, Sparse trees, Motion, Document Structure +@node Structure editing @section Structure editing @cindex structure editing @cindex headline, promotion and demotion @@ -1451,24 +1417,23 @@ See also the option @code{org-goto-interface}. @table @asis @orgcmd{M-@key{RET},org-insert-heading} @vindex org-M-RET-may-split-line -Insert a new heading/item with the same level than the one at point. -If the cursor is in a plain list item, a new item is created -(@pxref{Plain lists}). To prevent this behavior in lists, call the -command with a prefix argument. When this command is used in the -middle of a line, the line is split and the rest of the line becomes -the new item or headline@footnote{If you do not want the line to be -split, customize the variable @code{org-M-RET-may-split-line}.}. If -the command is used at the @emph{beginning} of a headline, the new -headline is created before the current line. If the command is used -at the @emph{end} of a folded subtree (i.e., behind the ellipses at -the end of a headline), then a headline will be -inserted after the end of the subtree. Calling this command with -@kbd{C-u C-u} will unconditionally respect the headline's content and -create a new item at the end of the parent subtree. +Insert a new heading/item with the same level as the one at point. + +If the command is used at the @emph{beginning} of a line, and if there is +a heading or a plain list item (@pxref{Plain lists}) at point, the new +heading/item is created @emph{before} the current line. When used at the +beginning of a regular line of text, turn that line into a heading. + +When this command is used in the middle of a line, the line is split and the +rest of the line becomes the new item or headline. If you do not want the +line to be split, customize @code{org-M-RET-may-split-line}. + +Calling the command with a @kbd{C-u} prefix unconditionally inserts a new +heading at the end of the current subtree, thus preserving its contents. +With a double @kbd{C-u C-u} prefix, the new heading is created at the end of +the parent subtree instead. @orgcmd{C-@key{RET},org-insert-heading-respect-content} -Just like @kbd{M-@key{RET}}, except when adding a new heading below the -current heading, the new heading is placed after the body instead of before -it. This command works from anywhere in the entry. +Insert a new heading at the end of the current subtree. @orgcmd{M-S-@key{RET},org-insert-todo-heading} @vindex org-treat-insert-todo-heading-as-state-change Insert new TODO entry with same level as current heading. See also the @@ -1572,33 +1537,29 @@ inside a table (@pxref{Tables}), the Meta-Cursor keys have different functionality. -@node Sparse trees, Plain lists, Structure editing, Document Structure +@node Sparse trees @section Sparse trees @cindex sparse trees @cindex trees, sparse @cindex folding, sparse trees @cindex occur, command -@vindex org-show-hierarchy-above -@vindex org-show-following-heading -@vindex org-show-siblings -@vindex org-show-entry-below +@vindex org-show-context-detail An important feature of Org mode is the ability to construct @emph{sparse trees} for selected information in an outline tree, so that the entire document is folded as much as possible, but the selected information is made visible along with the headline structure above it@footnote{See also the -variables @code{org-show-hierarchy-above}, @code{org-show-following-heading}, -@code{org-show-siblings}, and @code{org-show-entry-below} for detailed -control on how much context is shown around each match.}. Just try it out -and you will see immediately how it works. +variable @code{org-show-context-detail} to decide how much context is shown +around each match.}. Just try it out and you will see immediately how it +works. -Org mode contains several commands creating such trees, all these +Org mode contains several commands for creating such trees, all these commands can be accessed through a dispatcher: @table @asis @orgcmd{C-c /,org-sparse-tree} This prompts for an extra key to select a sparse-tree creating command. -@orgcmd{C-c / r,org-occur} +@orgcmdkkc{C-c / r,C-c / /,org-occur} @vindex org-remove-highlights-with-change Prompts for a regexp and shows a sparse tree with all matches. If the match is in a headline, the headline is made visible. If the match is in @@ -1639,13 +1600,11 @@ tags, or properties and will be discussed later in this manual. @cindex printing sparse trees @cindex visible text, printing To print a sparse tree, you can use the Emacs command -@code{ps-print-buffer-with-faces} which does not print invisible parts -of the document @footnote{This does not work under XEmacs, because -XEmacs uses selective display for outlining, not text properties.}. -Or you can use @kbd{C-c C-e C-v} to export only the visible part of -the document and print the resulting file. +@code{ps-print-buffer-with-faces} which does not print invisible parts of the +document. Or you can use @kbd{C-c C-e C-v} to export only the visible part +of the document and print the resulting file. -@node Plain lists, Drawers, Sparse trees, Document Structure +@node Plain lists @section Plain lists @cindex plain lists @cindex lists, plain @@ -1714,25 +1673,23 @@ In that case, all items are closed. Here is an example: But in the end, no individual scenes matter but the film as a whole. Important actors in this film are: - @b{Elijah Wood} :: He plays Frodo - - @b{Sean Austin} :: He plays Sam, Frodo's friend. I still remember + - @b{Sean Astin} :: He plays Sam, Frodo's friend. I still remember him very well from his role as Mikey Walsh in @i{The Goonies}. @end group @end example Org supports these lists by tuning filling and wrapping commands to deal with -them correctly@footnote{Org only changes the filling settings for Emacs. For -XEmacs, you should use Kyle E. Jones' @file{filladapt.el}. To turn this on, -put into @file{.emacs}: @code{(require 'filladapt)}}, and by exporting them -properly (@pxref{Exporting}). Since indentation is what governs the -structure of these lists, many structural constructs like @code{#+BEGIN_...} -blocks can be indented to signal that they belong to a particular item. +them correctly, and by exporting them properly (@pxref{Exporting}). Since +indentation is what governs the structure of these lists, many structural +constructs like @code{#+BEGIN_...} blocks can be indented to signal that they +belong to a particular item. @vindex org-list-demote-modify-bullet @vindex org-list-indent-offset If you find that using a different bullet for a sub-list (than that used for the current list-level) improves readability, customize the variable @code{org-list-demote-modify-bullet}. To get a greater difference of -indentation between items and theirs sub-items, customize +indentation between items and their sub-items, customize @code{org-list-indent-offset}. @vindex org-list-automatic-rules @@ -1824,10 +1781,10 @@ Cycle the entire list level through the different itemize/enumerate bullets (@samp{-}, @samp{+}, @samp{*}, @samp{1.}, @samp{1)}) or a subset of them, depending on @code{org-plain-list-ordered-item-terminator}, the type of list, and its indentation. With a numeric prefix argument N, select the Nth bullet -from this list. If there is an active region when calling this, selected -text will be changed into an item. With a prefix argument, all lines will be -converted to list items. If the first line already was a list item, any item -marker will be removed from the list. Finally, even without an active +from this list. If there is an active region when calling this, all selected +lines are converted to list items. With a prefix argument, selected text is +changed into a single item. If the first line already was a list item, any +item marker will be removed from the list. Finally, even without an active region, a normal line will be converted into a list item. @kindex C-c * @item C-c * @@ -1853,20 +1810,17 @@ numerically, alphabetically, by time, by checked status for check lists, or by a custom function. @end table -@node Drawers, Blocks, Plain lists, Document Structure +@node Drawers @section Drawers @cindex drawers -@cindex #+DRAWERS @cindex visibility cycling, drawers -@vindex org-drawers @cindex org-insert-drawer @kindex C-c C-x d Sometimes you want to keep information associated with an entry, but you -normally don't want to see it. For this, Org mode has @emph{drawers}. -Drawers need to be configured with the option @code{org-drawers}@footnote{You -can define additional drawers on a per-file basis with a line like -@code{#+DRAWERS: HIDDEN STATE}}. Drawers look like this: +normally don't want to see it. For this, Org mode has @emph{drawers}. They +can contain anything but a headline and another drawer. Drawers look like +this: @example ** This is a headline @@ -1880,18 +1834,21 @@ can define additional drawers on a per-file basis with a line like You can interactively insert drawers at point by calling @code{org-insert-drawer}, which is bound to @key{C-c C-x d}. With an active region, this command will put the region inside the drawer. With a prefix -argument, this command calls @code{org-insert-property-drawer} and add a -property drawer right below the current headline. Completion over drawer -keywords is also possible using @key{M-TAB}. +argument, this command calls @code{org-insert-property-drawer} and add +a property drawer right below the current headline. Completion over drawer +keywords is also possible using @kbd{M-@key{TAB}}@footnote{Many desktops +intercept @kbd{M-@key{TAB}} to switch windows. Use @kbd{C-M-i} or +@kbd{@key{ESC} @key{TAB}} instead for completion (@pxref{Completion}).}. Visibility cycling (@pxref{Visibility cycling}) on the headline will hide and show the entry, but keep the drawer collapsed to a single line. In order to look inside the drawer, you need to move the cursor to the drawer line and press @key{TAB} there. Org mode uses the @code{PROPERTIES} drawer for -storing properties (@pxref{Properties and Columns}), and you can also arrange +storing properties (@pxref{Properties and columns}), and you can also arrange for state change notes (@pxref{Tracking TODO state changes}) and clock times (@pxref{Clocking work time}) to be stored in a drawer @code{LOGBOOK}. If you -want to store a quick note in the LOGBOOK drawer, in a similar way to state changes, use +want to store a quick note in the LOGBOOK drawer, in a similar way to state +changes, use @table @kbd @kindex C-c C-z @@ -1900,12 +1857,13 @@ Add a time-stamped note to the LOGBOOK drawer. @end table @vindex org-export-with-drawers +@vindex org-export-with-properties You can select the name of the drawers which should be exported with @code{org-export-with-drawers}. In that case, drawer contents will appear in -export output. Property drawers are not affected by this variable and are -never exported. +export output. Property drawers are not affected by this variable: configure +@code{org-export-with-properties} instead. -@node Blocks, Footnotes, Drawers, Document Structure +@node Blocks @section Blocks @vindex org-hide-block-startup @@ -1924,18 +1882,17 @@ or on a per-file basis by using #+STARTUP: nohideblocks @end example -@node Footnotes, Orgstruct mode, Blocks, Document Structure +@node Footnotes @section Footnotes @cindex footnotes -Org mode supports the creation of footnotes. In contrast to the -@file{footnote.el} package, Org mode's footnotes are designed for work on -a larger document, not only for one-off documents like emails. +Org mode supports the creation of footnotes. A footnote is started by a footnote marker in square brackets in column 0, no indentation allowed. It ends at the next footnote definition, headline, or after two consecutive empty lines. The footnote reference is simply the -marker in square brackets, inside text. For example: +marker in square brackets, inside text. Markers always start with +@code{fn:}. For example: @example The Org homepage[fn:1] now looks a lot better than it used to. @@ -1944,23 +1901,16 @@ The Org homepage[fn:1] now looks a lot better than it used to. @end example Org mode extends the number-based syntax to @emph{named} footnotes and -optional inline definition. Using plain numbers as markers (as -@file{footnote.el} does) is supported for backward compatibility, but not -encouraged because of possible conflicts with @LaTeX{} snippets (@pxref{Embedded -@LaTeX{}}). Here are the valid references: +optional inline definition. Here are the valid references: @table @code -@item [1] -A plain numeric footnote marker. Compatible with @file{footnote.el}, but not -recommended because something like @samp{[1]} could easily be part of a code -snippet. @item [fn:name] A named footnote reference, where @code{name} is a unique label word, or, for simplicity of automatic creation, a number. -@item [fn:: This is the inline definition of this footnote] +@item [fn::This is the inline definition of this footnote] A @LaTeX{}-like anonymous footnote where the definition is given directly at the reference point. -@item [fn:name: a definition] +@item [fn:name:a definition] An inline definition of a footnote, which also specifies a name for the note. Since Org allows multiple references to the same note, you can then use @code{[fn:name]} to create additional references. @@ -2007,9 +1957,7 @@ r @r{Renumber the simple @code{fn:N} footnotes. Automatic renumbering} S @r{Short for first @code{r}, then @code{s} action.} n @r{Normalize the footnotes by collecting all definitions (including} @r{inline definitions) into a special section, and then numbering them} - @r{in sequence. The references will then also be numbers. This is} - @r{meant to be the final step before finishing a document (e.g., sending} - @r{off an email).} + @r{in sequence. The references will then also be numbers.} d @r{Delete the footnote at point, and all definitions of and references} @r{to it.} @end example @@ -2029,9 +1977,17 @@ location with a prefix argument, offer the same menu as @kbd{C-c C-x f}. @item C-c C-o @r{or} mouse-1/2 Footnote labels are also links to the corresponding definition/reference, and you can use the usual commands to follow these links. + +@vindex org-edit-footnote-reference +@kindex C-c ' +@item C-c ' +@item C-c ' +Edit the footnote definition corresponding to the reference at point in +a separate window. The window can be closed by pressing @kbd{C-c '}. + @end table -@node Orgstruct mode, Org syntax, Footnotes, Document Structure +@node Orgstruct mode @section The Orgstruct minor mode @cindex Orgstruct mode @cindex minor mode for structure editing @@ -2066,7 +2022,7 @@ Lisp files, you will be able to fold and unfold headlines in Emacs Lisp commented lines. Some commands like @code{org-demote} are disabled when the prefix is set, but folding/unfolding will work correctly. -@node Org syntax, , Orgstruct mode, Document Structure +@node Org syntax @section Org syntax @cindex Org syntax @@ -2088,7 +2044,11 @@ abstract structure. The export engine relies on the information stored in this list. Most interactive commands (e.g., for structure editing) also rely on the syntactic meaning of the surrounding context. -@node Tables, Hyperlinks, Document Structure, Top +@cindex syntax checker +@cindex linter +You can check syntax in your documents using @code{org-lint} command. + +@node Tables @chapter Tables @cindex tables @cindex editing tables @@ -2106,7 +2066,7 @@ calculations are supported using the Emacs @file{calc} package * Org-Plot:: Plotting from org tables @end menu -@node Built-in table editor, Column width and alignment, Tables, Tables +@node Built-in table editor @section The built-in table editor @cindex table editor, built-in @@ -2155,12 +2115,13 @@ unpredictable for you, configure the options @table @kbd @tsubheading{Creation and conversion} @orgcmd{C-c |,org-table-create-or-convert-from-region} -Convert the active region to table. If every line contains at least one +Convert the active region to a table. If every line contains at least one TAB character, the function assumes that the material is tab separated. If every line contains a comma, comma-separated values (CSV) are assumed. If not, lines are split at whitespace into fields. You can use a prefix argument to force a specific separator: @kbd{C-u} forces CSV, @kbd{C-u -C-u} forces TAB, and a numeric argument N indicates that at least N +C-u} forces TAB, @kbd{C-u C-u C-u} will prompt for a regular expression to +match the separator, and a numeric argument N indicates that at least N consecutive spaces, or alternatively a TAB will be the separator. @* If there is no active region, this command creates an empty Org @@ -2171,7 +2132,10 @@ table. But it is easier just to start typing, like @orgcmd{C-c C-c,org-table-align} Re-align the table and don't move to another field. @c -@orgcmd{<TAB>,org-table-next-field} +@orgcmd{C-c SPC,org-table-blank-field} +Blank the field at point. +@c +@orgcmd{TAB,org-table-next-field} Re-align the table, move to the next field. Creates a new row if necessary. @c @@ -2224,8 +2188,10 @@ point is before the first column, you will be prompted for the sorting column. If there is an active region, the mark specifies the first line and the sorting column, while point should be in the last line to be included into the sorting. The command prompts for the sorting type -(alphabetically, numerically, or by time). When called with a prefix -argument, alphabetic sorting will be case-sensitive. +(alphabetically, numerically, or by time). You can sort in normal or +reverse order. You can also supply your own key extraction and comparison +functions. When called with a prefix argument, alphabetic sorting will be +case-sensitive. @tsubheading{Regions} @orgcmd{C-c C-x M-w,org-table-copy-region} @@ -2322,7 +2288,7 @@ it off with @noindent Then the only table command that still works is @kbd{C-c C-c} to do a manual re-align. -@node Column width and alignment, Column groups, Built-in table editor, Tables +@node Column width and alignment @section Column width and alignment @cindex narrow columns in tables @cindex alignment in tables @@ -2333,11 +2299,11 @@ of number-like versus non-number fields in the column. Sometimes a single field or a few fields need to carry more text, leading to inconveniently wide columns. Or maybe you want to make a table with several -columns having a fixed width, regardless of content. To set@footnote{This -feature does not work on XEmacs.} the width of a column, one field anywhere -in the column may contain just the string @samp{<N>} where @samp{N} is an -integer specifying the width of the column in characters. The next re-align -will then set the width of this column to this value. +columns having a fixed width, regardless of content. To set the width of +a column, one field anywhere in the column may contain just the string +@samp{<N>} where @samp{N} is an integer specifying the width of the column in +characters. The next re-align will then set the width of this column to this +value. @example @group @@ -2374,7 +2340,7 @@ on a per-file basis with: @end example If you would like to overrule the automatic alignment of number-rich columns -to the right and of string-rich column to the left, you can use @samp{<r>}, +to the right and of string-rich columns to the left, you can use @samp{<r>}, @samp{<c>}@footnote{Centering does not work inside Emacs, but it does have an effect when exporting to HTML.} or @samp{<l>} in a similar fashion. You may also combine alignment and field width like this: @samp{<r10>}. @@ -2382,30 +2348,29 @@ also combine alignment and field width like this: @samp{<r10>}. Lines which only contain these formatting cookies will be removed automatically when exporting the document. -@node Column groups, Orgtbl mode, Column width and alignment, Tables +@node Column groups @section Column groups @cindex grouping columns in tables -When Org exports tables, it does so by default without vertical -lines because that is visually more satisfying in general. Occasionally -however, vertical lines can be useful to structure a table into groups -of columns, much like horizontal lines can do for groups of rows. In -order to specify column groups, you can use a special row where the -first field contains only @samp{/}. The further fields can either -contain @samp{<} to indicate that this column should start a group, -@samp{>} to indicate the end of a column, or @samp{<>} (no space between @samp{<} -and @samp{>}) to make a column -a group of its own. Boundaries between column groups will upon export be -marked with vertical lines. Here is an example: - -@example -| N | N^2 | N^3 | N^4 | sqrt(n) | sqrt[4](N) | -|---+-----+-----+-----+---------+------------| -| / | < | | > | < | > | -| 1 | 1 | 1 | 1 | 1 | 1 | -| 2 | 4 | 8 | 16 | 1.4142 | 1.1892 | -| 3 | 9 | 27 | 81 | 1.7321 | 1.3161 | -|---+-----+-----+-----+---------+------------| +When Org exports tables, it does so by default without vertical lines because +that is visually more satisfying in general. Occasionally however, vertical +lines can be useful to structure a table into groups of columns, much like +horizontal lines can do for groups of rows. In order to specify column +groups, you can use a special row where the first field contains only +@samp{/}. The further fields can either contain @samp{<} to indicate that +this column should start a group, @samp{>} to indicate the end of a group, or +@samp{<>} (no space between @samp{<} and @samp{>}) to make a column a group +of its own. Boundaries between column groups will upon export be marked with +vertical lines. Here is an example: + +@example +| N | N^2 | N^3 | N^4 | ~sqrt(n)~ | ~sqrt[4](N)~ | +|---+-----+-----+-----+-----------+--------------| +| / | < | | > | < | > | +| 1 | 1 | 1 | 1 | 1 | 1 | +| 2 | 4 | 8 | 16 | 1.4142 | 1.1892 | +| 3 | 9 | 27 | 81 | 1.7321 | 1.3161 | +|---+-----+-----+-----+-----------+--------------| #+TBLFM: $2=$1^2::$3=$1^3::$4=$1^4::$5=sqrt($1)::$6=sqrt(sqrt(($1))) @end example @@ -2418,7 +2383,7 @@ every vertical line you would like to have: | / | < | | | < | | @end example -@node Orgtbl mode, The spreadsheet, Column groups, Tables +@node Orgtbl mode @section The Orgtbl minor mode @cindex Orgtbl mode @cindex minor mode for tables @@ -2439,7 +2404,7 @@ construct @LaTeX{} tables with the underlying ease and power of Orgtbl mode, including spreadsheet capabilities. For details, see @ref{Tables in arbitrary syntax}. -@node The spreadsheet, Org-Plot, Orgtbl mode, Tables +@node The spreadsheet @section The spreadsheet @cindex calculations, in tables @cindex spreadsheet capabilities @@ -2468,7 +2433,7 @@ formula, moving these references by arrow keys * Advanced features:: Field and column names, parameters and automatic recalc @end menu -@node References, Formula syntax for Calc, The spreadsheet, The spreadsheet +@node References @subsection References @cindex references @@ -2554,7 +2519,7 @@ format at least for the first field (i.e the reference must start with @example $1..$3 @r{first three fields in the current row} $P..$Q @r{range, using column names (see under Advanced)} -$<<<..$>> @r{start in third column, continue to the one but last} +$<<<..$>> @r{start in third column, continue to the last but one} @@2$1..@@4$3 @r{6 fields between these two fields (same as @code{A2..C4})} @@-1$-2..@@-1 @r{3 fields in the row above, starting from 2 columns on the left} @@I..II @r{between first and second hline, short for @code{@@I..@@II}} @@ -2572,21 +2537,28 @@ for Calc}. @cindex row, of field coordinates @cindex column, of field coordinates -For Calc formulas and Lisp formulas @code{@@#} and @code{$#} can be used to -get the row or column number of the field where the formula result goes. -The traditional Lisp formula equivalents are @code{org-table-current-dline} -and @code{org-table-current-column}. Examples: +One of the very first actions during evaluation of Calc formulas and Lisp +formulas is to substitute @code{@@#} and @code{$#} in the formula with the +row or column number of the field where the current result will go to. The +traditional Lisp formula equivalents are @code{org-table-current-dline} and +@code{org-table-current-column}. Examples: -@example -if(@@# % 2, $#, string("")) @r{column number on odd lines only} -$3 = remote(FOO, @@@@#$2) @r{copy column 2 from table FOO into} - @r{column 3 of the current table} -@end example +@table @code +@item if(@@# % 2, $#, string("")) +Insert column number on odd rows, set field to empty on even rows. +@item $2 = '(identity remote(FOO, @@@@#$1)) +Copy text or values of each row of column 1 of the table named @code{FOO} +into column 2 of the current table. +@item @@3 = 2 * remote(FOO, @@1$$#) +Insert the doubled value of each column of row 1 of the table named +@code{FOO} into row 3 of the current table. +@end table -@noindent For the second example, table FOO must have at least as many rows -as the current table. Note that this is inefficient@footnote{The computation time scales as -O(N^2) because table FOO is parsed for each field to be copied.} for large -number of rows. +@noindent For the second/third example, the table named @code{FOO} must have +at least as many rows/columns as the current table. Note that this is +inefficient@footnote{The computation time scales as O(N^2) because the table +named @code{FOO} is parsed for each field to be read.} for large number of +rows/columns. @subsubheading Named references @cindex named references @@ -2608,7 +2580,7 @@ line like @noindent @vindex constants-unit-system @pindex constants.el -Also properties (@pxref{Properties and Columns}) can be used as +Also properties (@pxref{Properties and columns}) can be used as constants in table formulas: for a property @samp{:Xyz:} use the name @samp{$PROP_Xyz}, and the property will be searched in the current outline entry and in the hierarchy above it. If you have the @@ -2647,7 +2619,13 @@ table in that entry. REF is an absolute field or range reference as described above for example @code{@@3$3} or @code{$somename}, valid in the referenced table. -@node Formula syntax for Calc, Formula syntax for Lisp, References, The spreadsheet +Indirection of NAME-OR-ID: When NAME-OR-ID has the format @code{@@ROW$COLUMN} +it will be substituted with the name or ID found in this field of the current +table. For example @code{remote($1, @@>$2)} => @code{remote(year_2013, +@@>$1)}. The format @code{B3} is not supported because it can not be +distinguished from a plain table name or ID. + +@node Formula syntax for Calc @subsection Formula syntax for Calc @cindex formula syntax, Calc @cindex syntax, of formulas @@ -2762,7 +2740,7 @@ should be padded with 0 to the full size. You can add your own Calc functions defined in Emacs Lisp with @code{defmath} and use them in formula syntax for Calc. -@node Formula syntax for Lisp, Durations and time values, Formula syntax for Calc, The spreadsheet +@node Formula syntax for Lisp @subsection Emacs Lisp forms as formulas @cindex Lisp forms, as table formulas @@ -2798,7 +2776,7 @@ Add columns 1 and 2, equivalent to Calc's @code{$1+$2}. Compute the sum of columns 1 to 4, like Calc's @code{vsum($1..$4)}. @end table -@node Durations and time values, Field and range formulas, Formula syntax for Lisp, The spreadsheet +@node Durations and time values @subsection Durations and time values @cindex Duration, computing @cindex Time, computing @@ -2817,7 +2795,7 @@ formulas or Elisp formulas: @end group @end example -Input duration values must be of the form @code{[HH:MM[:SS]}, where seconds +Input duration values must be of the form @code{HH:MM[:SS]}, where seconds are optional. With the @code{T} flag, computed durations will be displayed as @code{HH:MM:SS} (see the first formula above). With the @code{t} flag, computed durations will be displayed according to the value of the option @@ -2828,7 +2806,7 @@ example above). Negative duration values can be manipulated as well, and integers will be considered as seconds in addition and subtraction. -@node Field and range formulas, Column formulas, Durations and time values, The spreadsheet +@node Field and range formulas @subsection Field and range formulas @cindex field formula @cindex range formula @@ -2845,13 +2823,13 @@ current field will be replaced with the result. Formulas are stored in a special line starting with @samp{#+TBLFM:} directly below the table. If you type the equation in the 4th field of the 3rd data line in the table, the formula will look like @samp{@@3$4=$1+$2}. When -inserting/deleting/swapping column and rows with the appropriate commands, +inserting/deleting/swapping columns and rows with the appropriate commands, @i{absolute references} (but not relative ones) in stored formulas are -modified in order to still reference the same field. To avoid this from -happening, in particular in range references, anchor ranges at the table -borders (using @code{@@<}, @code{@@>}, @code{$<}, @code{$>}), or at hlines -using the @code{@@I} notation. Automatic adaptation of field references does -of course not happen if you edit the table structure with normal editing +modified in order to still reference the same field. To avoid this, in +particular in range references, anchor ranges at the table borders (using +@code{@@<}, @code{@@>}, @code{$<}, @code{$>}), or at hlines using the +@code{@@I} notation. Automatic adaptation of field references does of course +not happen if you edit the table structure with normal editing commands---then you must fix the equations yourself. Instead of typing an equation into the field, you may also use the following @@ -2884,7 +2862,7 @@ can also be used to assign a formula to some but not all fields in a row. Named field, see @ref{Advanced features}. @end table -@node Column formulas, Lookup functions, Field and range formulas, The spreadsheet +@node Column formulas @subsection Column formulas @cindex column formula @cindex formula, for table column @@ -2908,7 +2886,7 @@ and the current field replaced with the result. If the field contains only @samp{=}, the previously stored formula for this column is used. For each column, Org will only remember the most recently used formula. In the @samp{#+TBLFM:} line, column formulas will look like @samp{$4=$1+$2}. The -left-hand side of a column formula can not be the name of column, it must be +left-hand side of a column formula cannot be the name of column, it must be the numeric column reference or @code{$>}. Instead of typing an equation into the field, you may also use the @@ -2923,7 +2901,7 @@ stores it. With a numeric prefix argument(e.g., @kbd{C-5 C-c =}) the command will apply it to that many consecutive fields in the current column. @end table -@node Lookup functions, Editing and debugging formulas, Column formulas, The spreadsheet +@node Lookup functions @subsection Lookup functions @cindex lookup functions in tables @cindex table lookup functions @@ -2967,7 +2945,7 @@ matching cells, rank results, group data etc. For practical examples see @uref{http://orgmode.org/worg/org-tutorials/org-lookups.html, this tutorial on Worg}. -@node Editing and debugging formulas, Updating the table, Lookup functions, The spreadsheet +@node Editing and debugging formulas @subsection Editing and debugging formulas @cindex formula editing @cindex editing, of table formulas @@ -3026,7 +3004,9 @@ a Lisp formula, format the formula according to Emacs Lisp rules. Another @key{TAB} collapses the formula back again. In the open formula, @key{TAB} re-indents just like in Emacs Lisp mode. @orgcmd{M-@key{TAB},lisp-complete-symbol} -Complete Lisp symbols, just like in Emacs Lisp mode. +Complete Lisp symbols, just like in Emacs Lisp mode.@footnote{Many desktops +intercept @kbd{M-@key{TAB}} to switch windows. Use @kbd{C-M-i} or +@kbd{@key{ESC} @key{TAB}} instead for completion (@pxref{Completion}).} @kindex S-@key{up} @kindex S-@key{down} @kindex S-@key{left} @@ -3118,7 +3098,7 @@ turn on formula debugging in the @code{Tbl} menu and repeat the calculation, for example by pressing @kbd{C-u C-u C-c = @key{RET}} in a field. Detailed information will be displayed. -@node Updating the table, Advanced features, Editing and debugging formulas, The spreadsheet +@node Updating the table @subsection Updating the table @cindex recomputing table fields @cindex updating, table @@ -3155,7 +3135,7 @@ Iterate all tables in the current buffer, in order to converge table-to-table dependencies. @end table -@node Advanced features, , Updating the table, The spreadsheet +@node Advanced features @subsection Advanced features If you want the recalculation of fields to happen automatically, or if you @@ -3260,17 +3240,23 @@ functions. @end group @end example -@node Org-Plot, , The spreadsheet, Tables +@node Org-Plot @section Org-Plot @cindex graph, in tables @cindex plot tables using Gnuplot @cindex #+PLOT -Org-Plot can produce 2D and 3D graphs of information stored in org tables -using @file{Gnuplot} @uref{http://www.gnuplot.info/} and @file{gnuplot-mode} +Org-Plot can produce graphs of information stored in org tables, either +graphically or in ASCII-art. + +@subheading Graphical plots using @file{Gnuplot} + +Org-Plot produces 2D and 3D graphs using @file{Gnuplot} +@uref{http://www.gnuplot.info/} and @file{gnuplot-mode} @uref{http://xafs.org/BruceRavel/GnuplotMode}. To see this in action, ensure that you have both Gnuplot and Gnuplot mode installed on your system, then -call @code{org-plot/gnuplot} on the following table. +call @kbd{C-c " g} or @kbd{M-x org-plot/gnuplot @key{RET}} on the following +table. @example @group @@ -3288,8 +3274,8 @@ call @code{org-plot/gnuplot} on the following table. Notice that Org Plot is smart enough to apply the table's headers as labels. Further control over the labels, type, content, and appearance of plots can be exercised through the @code{#+PLOT:} lines preceding a table. See below -for a complete list of Org-plot options. For more information and examples -see the Org-plot tutorial at +for a complete list of Org-plot options. The @code{#+PLOT:} lines are +optional. For more information and examples see the Org-plot tutorial at @uref{http://orgmode.org/worg/org-tutorials/org-plot.html}. @subsubheading Plot Options @@ -3345,7 +3331,48 @@ may still want to specify the plot type, as that can impact the content of the data file. @end table -@node Hyperlinks, TODO Items, Tables, Top +@subheading ASCII bar plots + +While the cursor is on a column, typing @kbd{C-c " a} or +@kbd{M-x orgtbl-ascii-plot @key{RET}} create a new column containing an +ASCII-art bars plot. The plot is implemented through a regular column +formula. When the source column changes, the bar plot may be updated by +refreshing the table, for example typing @kbd{C-u C-c *}. + +@example +@group +| Sede | Max cites | | +|---------------+-----------+--------------| +| Chile | 257.72 | WWWWWWWWWWWW | +| Leeds | 165.77 | WWWWWWWh | +| Sao Paolo | 71.00 | WWW; | +| Stockholm | 134.19 | WWWWWW: | +| Morelia | 257.56 | WWWWWWWWWWWH | +| Rochefourchat | 0.00 | | +#+TBLFM: $3='(orgtbl-ascii-draw $2 0.0 257.72 12) +@end group +@end example + +The formula is an elisp call: +@lisp +(orgtbl-ascii-draw COLUMN MIN MAX WIDTH) +@end lisp + +@table @code +@item COLUMN + is a reference to the source column. + +@item MIN MAX + are the minimal and maximal values displayed. Sources values + outside this range are displayed as @samp{too small} + or @samp{too large}. + +@item WIDTH + is the width in characters of the bar-plot. It defaults to @samp{12}. + +@end table + +@node Hyperlinks @chapter Hyperlinks @cindex hyperlinks @@ -3363,7 +3390,7 @@ other files, Usenet articles, emails, and much more. * Custom searches:: When the default search is not enough @end menu -@node Link format, Internal links, Hyperlinks, Hyperlinks +@node Link format @section Link format @cindex link format @cindex format, of links @@ -3394,7 +3421,7 @@ missing bracket hides the link internals again. To show the internal structure of all links, use the menu entry @code{Org->Hyperlinks->Literal links}. -@node Internal links, External links, Link format, Hyperlinks +@node Internal links @section Internal links @cindex internal links @cindex links, internal @@ -3419,8 +3446,8 @@ a @i{dedicated target}: the same string in double angular brackets, like @cindex #+NAME If no dedicated target exists, the link will then try to match the exact name of an element within the buffer. Naming is done with the @code{#+NAME} -keyword, which has to be put the line before the element it refers to, as in -the following example +keyword, which has to be put in the line before the element it refers to, as +in the following example @example #+NAME: My Target @@ -3465,7 +3492,7 @@ earlier. * Radio targets:: Make targets trigger links in plain text @end menu -@node Radio targets, , Internal links, Internal links +@node Radio targets @subsection Radio targets @cindex radio targets @cindex targets, radio @@ -3481,7 +3508,7 @@ for radio targets only when the file is first loaded into Emacs. To update the target list during editing, press @kbd{C-c C-c} with the cursor on or at a target. -@node External links, Handling links, Internal links, Hyperlinks +@node External links @section External links @cindex links, external @cindex external links @@ -3504,42 +3531,44 @@ string followed by a colon. There can be no space after the colon. The following list shows examples for each link type. @example -http://www.astro.uva.nl/~dominik @r{on the web} -doi:10.1000/182 @r{DOI for an electronic resource} -file:/home/dominik/images/jupiter.jpg @r{file, absolute path} -/home/dominik/images/jupiter.jpg @r{same as above} -file:papers/last.pdf @r{file, relative path} -./papers/last.pdf @r{same as above} -file:/myself@@some.where:papers/last.pdf @r{file, path on remote machine} -/myself@@some.where:papers/last.pdf @r{same as above} -file:sometextfile::NNN @r{file, jump to line number} -file:projects.org @r{another Org file} -file:projects.org::some words @r{text search in Org file}@footnote{ +http://www.astro.uva.nl/~dominik @r{on the web} +doi:10.1000/182 @r{DOI for an electronic resource} +file:/home/dominik/images/jupiter.jpg @r{file, absolute path} +/home/dominik/images/jupiter.jpg @r{same as above} +file:papers/last.pdf @r{file, relative path} +./papers/last.pdf @r{same as above} +file:/ssh:myself@@some.where:papers/last.pdf @r{file, path on remote machine} +/ssh:myself@@some.where:papers/last.pdf @r{same as above} +file:sometextfile::NNN @r{file, jump to line number} +file:projects.org @r{another Org file} +file:projects.org::some words @r{text search in Org file}@footnote{ The actual behavior of the search will depend on the value of the option @code{org-link-search-must-match-exact-headline}. If its value -is @code{nil}, then a fuzzy text search will be done. If it is t, then only the -exact headline will be matched. If the value is @code{'query-to-create}, -then an exact headline will be searched; if it is not found, then the user -will be queried to create it.} -file:projects.org::*task title @r{heading search in Org file} -file+sys:/path/to/file @r{open via OS, like double-click} -file+emacs:/path/to/file @r{force opening by Emacs} -docview:papers/last.pdf::NNN @r{open in doc-view mode at page} -id:B7423F4D-2E8A-471B-8810-C40F074717E9 @r{Link to heading by ID} -news:comp.emacs @r{Usenet link} -mailto:adent@@galaxy.net @r{Mail link} -mhe:folder @r{MH-E folder link} -mhe:folder#id @r{MH-E message link} -rmail:folder @r{RMAIL folder link} -rmail:folder#id @r{RMAIL message link} -gnus:group @r{Gnus group link} -gnus:group#id @r{Gnus article link} -bbdb:R.*Stallman @r{BBDB link (with regexp)} -irc:/irc.com/#emacs/bob @r{IRC link} -info:org#External links @r{Info node link} -shell:ls *.org @r{A shell command} -elisp:org-agenda @r{Interactive Elisp command} -elisp:(find-file-other-frame "Elisp.org") @r{Elisp form to evaluate} +is @code{nil}, then a fuzzy text search will be done. If it is @code{t}, then only +the exact headline will be matched, ignoring spaces and cookies. If the +value is @code{query-to-create}, then an exact headline will be searched; if +it is not found, then the user will be queried to create it.} +file:projects.org::*task title @r{heading search in Org file}@footnote{ +Headline searches always match the exact headline, ignoring +spaces and cookies. If the headline is not found and the value of the option +@code{org-link-search-must-match-exact-headline} is @code{query-to-create}, +then the user will be queried to create it.} +docview:papers/last.pdf::NNN @r{open in doc-view mode at page} +id:B7423F4D-2E8A-471B-8810-C40F074717E9 @r{Link to heading by ID} +news:comp.emacs @r{Usenet link} +mailto:adent@@galaxy.net @r{Mail link} +mhe:folder @r{MH-E folder link} +mhe:folder#id @r{MH-E message link} +rmail:folder @r{RMAIL folder link} +rmail:folder#id @r{RMAIL message link} +gnus:group @r{Gnus group link} +gnus:group#id @r{Gnus article link} +bbdb:R.*Stallman @r{BBDB link (with regexp)} +irc:/irc.com/#emacs/bob @r{IRC link} +info:org#External links @r{Info node or index link} +shell:ls *.org @r{A shell command} +elisp:org-agenda @r{Interactive Elisp command} +elisp:(find-file-other-frame "Elisp.org") @r{Elisp form to evaluate} @end example @cindex VM links @@ -3550,13 +3579,13 @@ to VM or Wanderlust messages are available when you load the corresponding libraries from the @code{contrib/} directory: @example -vm:folder @r{VM folder link} -vm:folder#id @r{VM message link} -vm://myself@@some.where.org/folder#id @r{VM on remote machine} -vm-imap:account:folder @r{VM IMAP folder link} -vm-imap:account:folder#id @r{VM IMAP message link} -wl:folder @r{WANDERLUST folder link} -wl:folder#id @r{WANDERLUST message link} +vm:folder @r{VM folder link} +vm:folder#id @r{VM message link} +vm://myself@@some.where.org/folder#id @r{VM on remote machine} +vm-imap:account:folder @r{VM IMAP folder link} +vm-imap:account:folder#id @r{VM IMAP message link} +wl:folder @r{WANDERLUST folder link} +wl:folder#id @r{WANDERLUST message link} @end example For customizing Org to add new link types @ref{Adding hyperlink types}. @@ -3582,7 +3611,7 @@ as links. If spaces must be part of the link (for example in @samp{bbdb:Richard Stallman}), or if you need to remove ambiguities about the end of the link, enclose them in square brackets. -@node Handling links, Using links outside Org, External links, Hyperlinks +@node Handling links @section Handling links @cindex links, handling @@ -3614,9 +3643,9 @@ will be stored. In addition or alternatively (depending on the value of be created and/or used to construct a link@footnote{The library @file{org-id.el} must first be loaded, either through @code{org-customize} by enabling @code{org-id} in @code{org-modules}, or by adding @code{(require -'org-id)} in your @file{.emacs}.}. So using this command in Org buffers will -potentially create two links: a human-readable from the custom ID, and one -that is globally unique and works even if the entry is moved from file to +'org-id)} in your Emacs init file.}. So using this command in Org buffers +will potentially create two links: a human-readable from the custom ID, and +one that is globally unique and works even if the entry is moved from file to file. Later, when inserting the link, you need to decide which one to use. @b{Email/News clients: VM, Rmail, Wanderlust, MH-E, Gnus}@* @@ -3624,7 +3653,7 @@ Pretty much all Emacs mail clients are supported. The link will point to the current article, or, in some GNUS buffers, to the group. The description is constructed from the author and the subject. -@b{Web browsers: W3 and W3M}@* +@b{Web browsers: Eww, W3 and W3M}@* Here the link will be the current URL, with the page title as description. @b{Contacts: BBDB}@* @@ -3656,7 +3685,8 @@ entry referenced by the current line. @cindex completion, of links @cindex inserting links @vindex org-keep-stored-link-after-insertion -Insert a link@footnote{ Note that you don't have to use this command to +@vindex org-link-parameters +Insert a link@footnote{Note that you don't have to use this command to insert a link. Links in Org are plain text, and you can type or paste them straight into the buffer. By using this command, the links are automatically enclosed in double brackets, and you will be asked for the optional @@ -3679,11 +3709,12 @@ them with @key{up} and @key{down} (or @kbd{M-p/n}). valid link prefixes like @samp{http:} or @samp{ftp:}, including the prefixes defined through link abbreviations (@pxref{Link abbreviations}). If you press @key{RET} after inserting only the @var{prefix}, Org will offer -specific completion support for some link types@footnote{This works by -calling a special function @code{org-PREFIX-complete-link}.} For -example, if you type @kbd{file @key{RET}}, file name completion (alternative -access: @kbd{C-u C-c C-l}, see below) will be offered, and after @kbd{bbdb -@key{RET}} you can complete contact names. +specific completion support for some link types@footnote{This works if +a completion function is defined in the @samp{:complete} property of a link +in @code{org-link-parameters}.} For example, if you type @kbd{file +@key{RET}}, file name completion (alternative access: @kbd{C-u C-c C-l}, see +below) will be offered, and after @kbd{bbdb @key{RET}} you can complete +contact names. @orgkey C-u C-c C-l @cindex file name completion @cindex completion, of file names @@ -3729,8 +3760,8 @@ the link at point. @kindex mouse-1 @item mouse-2 @itemx mouse-1 -On links, @kbd{mouse-2} will open the link just as @kbd{C-c C-o} -would. Under Emacs 22 and later, @kbd{mouse-1} will also follow a link. +On links, @kbd{mouse-1} and @kbd{mouse-2} will open the link just as @kbd{C-c +C-o} would. @c @kindex mouse-3 @item mouse-3 @@ -3778,7 +3809,7 @@ to @kbd{C-n} and @kbd{C-p} @end lisp @end table -@node Using links outside Org, Link abbreviations, Handling links, Hyperlinks +@node Using links outside Org @section Using links outside Org You can insert and follow links that have Org syntax not only in @@ -3791,7 +3822,7 @@ yourself): (global-set-key "\C-c o" 'org-open-at-point-global) @end lisp -@node Link abbreviations, Search options, Using links outside Org, Hyperlinks +@node Link abbreviations @section Link abbreviations @cindex link abbreviations @cindex abbreviation, links @@ -3830,8 +3861,8 @@ url-encode the tag (see the example above, where we need to encode the URL parameter.) Using @samp{%(my-function)} will pass the tag to a custom function, and replace it by the resulting string. -If the replacement text don't contain any specifier, it will simply -be appended to the string in order to create the link. +If the replacement text doesn't contain any specifier, the tag will simply be +appended in order to create the link. Instead of a string, you may also specify a function that will be called with the tag as the only argument to create the link. @@ -3855,12 +3886,17 @@ can define them in the file with @noindent In-buffer completion (@pxref{Completion}) can be used after @samp{[} to -complete link abbreviations. You may also define a function -@code{org-PREFIX-complete-link} that implements special (e.g., completion) -support for inserting such a link with @kbd{C-c C-l}. Such a function should -not accept any arguments, and return the full link with prefix. +complete link abbreviations. You may also define a function that implements +special (e.g., completion) support for inserting such a link with @kbd{C-c +C-l}. Such a function should not accept any arguments, and return the full +link with prefix. You can add a completion function to a link like this: + +@lisp +(org-link-set-parameters ``type'' :complete #'some-function) +@end lisp + -@node Search options, Custom searches, Link abbreviations, Hyperlinks +@node Search options @section Search options in file links @cindex search option in file links @cindex file links, searching @@ -3912,7 +3948,7 @@ to search the current file. For example, @code{[[file:::find me]]} does a search for @samp{find me} in the current file, just as @samp{[[find me]]} would. -@node Custom searches, , Search options, Hyperlinks +@node Custom searches @section Custom Searches @cindex custom search strings @cindex search strings, custom @@ -3936,7 +3972,7 @@ variables for more information. Org actually uses this mechanism for Bib@TeX{} database files, and you can use the corresponding code as an implementation example. See the file @file{org-bibtex.el}. -@node TODO Items, Tags, Hyperlinks, Top +@node TODO items @chapter TODO items @cindex TODO items @@ -3961,7 +3997,7 @@ methods to give you an overview of all the things that you have to do. * Checkboxes:: Tick-off lists @end menu -@node TODO basics, TODO extensions, TODO Items, TODO Items +@node TODO basics @section Basic TODO functionality Any headline becomes a TODO item when it starts with the word @@ -4022,7 +4058,7 @@ N, show the tree for the Nth keyword in the option @code{org-todo-keywords}. With two prefix arguments, find all TODO states, both un-done and done. @orgcmd{C-c a t,org-todo-list} Show the global TODO list. Collects the TODO items (with not-DONE states) -from all agenda files (@pxref{Agenda Views}) into a single buffer. The new +from all agenda files (@pxref{Agenda views}) into a single buffer. The new buffer will be in @code{agenda-mode}, which provides commands to examine and manipulate the TODO entries from the new buffer (@pxref{Agenda commands}). @xref{Global TODO list}, for more information. @@ -4035,7 +4071,7 @@ Insert a new TODO entry below the current one. Changing a TODO state can also trigger tag changes. See the docstring of the option @code{org-todo-state-tags-triggers} for details. -@node TODO extensions, Progress logging, TODO basics, TODO Items +@node TODO extensions @section Extended use of TODO keywords @cindex extended TODO keywords @@ -4059,7 +4095,7 @@ TODO items in particular (@pxref{Tags}). * TODO dependencies:: When one task needs to wait for others @end menu -@node Workflow states, TODO types, TODO extensions, TODO extensions +@node Workflow states @subsection TODO keywords as workflow states @cindex TODO workflow @cindex workflow states as TODO keywords @@ -4090,7 +4126,7 @@ define many keywords, you can use in-buffer completion buffer. Changing a TODO state can be logged with a timestamp, see @ref{Tracking TODO state changes}, for more information. -@node TODO types, Multiple sets in one file, Workflow states, TODO extensions +@node TODO types @subsection TODO keywords as types @cindex TODO types @cindex names as TODO keywords @@ -4122,7 +4158,7 @@ Lucy has to do, you would use @kbd{C-3 C-c / t}. To collect Lucy's items from all agenda files into a single buffer, you would use the numeric prefix argument as well when creating the global TODO list: @kbd{C-3 C-c a t}. -@node Multiple sets in one file, Fast access to TODO states, TODO types, TODO extensions +@node Multiple sets in one file @subsection Multiple keyword sets in one file @cindex TODO keyword sets @@ -4164,14 +4200,14 @@ These keys jump from one TODO subset to the next. In the above example, @kindex S-@key{left} @item S-@key{right} @itemx S-@key{left} -@kbd{S-@key{<left>}} and @kbd{S-@key{<right>}} and walk through @emph{all} -keywords from all sets, so for example @kbd{S-@key{<right>}} would switch +@kbd{S-@key{left}} and @kbd{S-@key{right}} and walk through @emph{all} +keywords from all sets, so for example @kbd{S-@key{right}} would switch from @code{DONE} to @code{REPORT} in the example above. See also @ref{Conflicts}, for a discussion of the interaction with @code{shift-selection-mode}. @end table -@node Fast access to TODO states, Per-file keywords, Multiple sets in one file, TODO extensions +@node Fast access to TODO states @subsection Fast access to TODO states If you would like to quickly change an entry to an arbitrary TODO state @@ -4196,7 +4232,7 @@ state through the tags interface (@pxref{Setting tags}), in case you like to mingle the two concepts. Note that this means you need to come up with unique keys across both sets of keywords.} -@node Per-file keywords, Faces for TODO keywords, Fast access to TODO states, TODO extensions +@node Per-file keywords @subsection Setting up keywords for individual files @cindex keyword options @cindex per-file keywords @@ -4205,11 +4241,10 @@ unique keys across both sets of keywords.} @cindex #+SEQ_TODO It can be very useful to use different aspects of the TODO mechanism in -different files. For file-local settings, you need to add special lines -to the file which set the keywords and interpretation for that file -only. For example, to set one of the two examples discussed above, you -need one of the following lines, starting in column zero anywhere in the -file: +different files. For file-local settings, you need to add special lines to +the file which set the keywords and interpretation for that file only. For +example, to set one of the two examples discussed above, you need one of the +following lines anywhere in the file: @example #+TODO: TODO FEEDBACK VERIFY | DONE CANCELED @@ -4243,7 +4278,7 @@ Org mode is activated after visiting a file. @kbd{C-c C-c} with the cursor in a line starting with @samp{#+} is simply restarting Org mode for the current buffer.}. -@node Faces for TODO keywords, TODO dependencies, Per-file keywords, TODO extensions +@node Faces for TODO keywords @subsection Faces for TODO keywords @cindex faces, for TODO keywords @@ -4271,10 +4306,11 @@ special face and use that. A string is interpreted as a color. The option @code{org-faces-easy-properties} determines if that color is interpreted as a foreground or a background color. -@node TODO dependencies, , Faces for TODO keywords, TODO extensions +@node TODO dependencies @subsection TODO dependencies @cindex TODO dependencies @cindex dependencies, of TODO states +@cindex TODO dependencies, NOBLOCKING @vindex org-enforce-todo-dependencies @cindex property, ORDERED @@ -4303,6 +4339,16 @@ example: ** TODO c, needs to wait for (a) and (b) @end example +You can ensure an entry is never blocked by using the @code{NOBLOCKING} +property: + +@example +* This entry is never blocked + :PROPERTIES: + :NOBLOCKING: t + :END: +@end example + @table @kbd @orgcmd{C-c C-x o,org-toggle-ordered-property} @vindex org-track-ordered-property-with-tag @@ -4319,7 +4365,7 @@ Change TODO state, circumventing any state blocking. @vindex org-agenda-dim-blocked-tasks If you set the option @code{org-agenda-dim-blocked-tasks}, TODO entries that cannot be closed because of such dependencies will be shown in a dimmed -font or even made invisible in agenda views (@pxref{Agenda Views}). +font or even made invisible in agenda views (@pxref{Agenda views}). @cindex checkboxes and TODO dependencies @vindex org-enforce-todo-dependencies @@ -4333,7 +4379,7 @@ between entries in different trees or files, check out the contributed module @file{org-depend.el}. @page -@node Progress logging, Priorities, TODO extensions, TODO Items +@node Progress logging @section Progress logging @cindex progress logging @cindex logging, of progress @@ -4351,7 +4397,7 @@ work time}. * Tracking your habits:: How consistent have you been? @end menu -@node Closing items, Tracking TODO state changes, Progress logging, Progress logging +@node Closing items @subsection Closing items The most basic logging is to keep track of @emph{when} a certain TODO @@ -4387,7 +4433,7 @@ In the timeline (@pxref{Timeline}) and in the agenda display the TODO items with a @samp{CLOSED} timestamp on each day, giving you an overview of what has been done. -@node Tracking TODO state changes, Tracking your habits, Closing items, Progress logging +@node Tracking TODO state changes @subsection Tracking TODO state changes @cindex drawer, for state change recording @@ -4470,7 +4516,7 @@ settings like @code{TODO(!)}. For example :END: @end example -@node Tracking your habits, , Tracking TODO state changes, Progress logging +@node Tracking your habits @subsection Tracking your habits @cindex habits @@ -4506,6 +4552,10 @@ actual habit with some history: @example ** TODO Shave SCHEDULED: <2009-10-17 Sat .+2d/4d> + :PROPERTIES: + :STYLE: habit + :LAST_REPEAT: [2009-10-19 Mon 00:36] + :END: - State "DONE" from "TODO" [2009-10-15 Thu] - State "DONE" from "TODO" [2009-10-12 Mon] - State "DONE" from "TODO" [2009-10-10 Sat] @@ -4516,10 +4566,6 @@ actual habit with some history: - State "DONE" from "TODO" [2009-09-19 Sat] - State "DONE" from "TODO" [2009-09-16 Wed] - State "DONE" from "TODO" [2009-09-12 Sat] - :PROPERTIES: - :STYLE: habit - :LAST_REPEAT: [2009-10-19 Mon 00:36] - :END: @end example What this habit says is: I want to shave at most every 2 days (given by the @@ -4570,7 +4616,7 @@ temporarily be disabled and they won't appear at all. Press @kbd{K} again to bring them back. They are also subject to tag filtering, if you have habits which should only be done in certain contexts, for example. -@node Priorities, Breaking down tasks, Progress logging, TODO Items +@node Priorities @section Priorities @cindex priorities @@ -4628,7 +4674,7 @@ priority): #+PRIORITIES: A C B @end example -@node Breaking down tasks, Checkboxes, Priorities, TODO Items +@node Breaking down tasks @section Breaking tasks down into subtasks @cindex tasks, breaking down @cindex statistics, for TODO items @@ -4689,7 +4735,7 @@ Another possibility is the use of checkboxes to identify (a hierarchy of) a large number of subtasks (@pxref{Checkboxes}). -@node Checkboxes, , Breaking down tasks, TODO Items +@node Checkboxes @section Checkboxes @cindex checkboxes @@ -4698,7 +4744,7 @@ Every item in a plain list@footnote{With the exception of description lists. But you can allow it by modifying @code{org-list-automatic-rules} accordingly.} (@pxref{Plain lists}) can be made into a checkbox by starting it with the string @samp{[ ]}. This feature is similar to TODO items -(@pxref{TODO Items}), but is more lightweight. Checkboxes are not included +(@pxref{TODO items}), but is more lightweight. Checkboxes are not included in the global TODO list, so they are often great to split a task into a number of simple steps. Or you can use them in a shopping list. To toggle a checkbox, use @kbd{C-c C-c}, or use the mouse (thanks to Piotr Zielinski's @@ -4755,11 +4801,12 @@ off a box while there are unchecked boxes above it. @table @kbd @orgcmd{C-c C-c,org-toggle-checkbox} -Toggle checkbox status or (with prefix arg) checkbox presence at point. -With a single prefix argument, add an empty checkbox or remove the current -one@footnote{@kbd{C-u C-c C-c} on the @emph{first} item of a list with no checkbox -will add checkboxes to the rest of the list.}. With a double prefix argument, set it to @samp{[-]}, which is -considered to be an intermediate state. +Toggle checkbox status or (with prefix arg) checkbox presence at point. With +a single prefix argument, add an empty checkbox or remove the current +one@footnote{@kbd{C-u C-c C-c} before the @emph{first} bullet in a list with +no checkbox will add checkboxes to the rest of the list.}. With a double +prefix argument, set it to @samp{[-]}, which is considered to be an +intermediate state. @orgcmd{C-c C-x C-b,org-toggle-checkbox} Toggle checkbox status or (with prefix arg) checkbox presence at point. With double prefix argument, set it to @samp{[-]}, which is considered to be an @@ -4770,8 +4817,10 @@ If there is an active region, toggle the first checkbox in the region and set all remaining boxes to the same status as the first. With a prefix arg, add or remove the checkbox for all items in the region. @item -If the cursor is in a headline, toggle checkboxes in the region between -this headline and the next (so @emph{not} the entire subtree). +If the cursor is in a headline, toggle the state of the first checkbox in the +region between this headline and the next---so @emph{not} the entire +subtree---and propagate this new state to all other checkboxes in the same +area. @item If there is no active region, just toggle the checkbox at point. @end itemize @@ -4795,7 +4844,7 @@ changing TODO states. If you delete boxes/entries or add/change them by hand, use this command to get things back into sync. @end table -@node Tags, Properties and Columns, TODO Items, Top +@node Tags @chapter Tags @cindex tags @cindex headline tagging @@ -4819,11 +4868,11 @@ You may specify special faces for specific tags using the option @menu * Tag inheritance:: Tags use the tree structure of the outline * Setting tags:: How to assign tags to a headline -* Tag groups:: Use one tag to search for several tags +* Tag hierarchy:: Create a hierarchy of tags * Tag searches:: Searching for combinations of tags @end menu -@node Tag inheritance, Setting tags, Tags, Tags +@node Tag inheritance @section Tag inheritance @cindex tag inheritance @cindex inheritance, of tags @@ -4842,11 +4891,11 @@ well. For example, in the list @noindent the final heading will have the tags @samp{:work:}, @samp{:boss:}, @samp{:notes:}, and @samp{:action:} even though the final heading is not -explicitly marked with those tags. You can also set tags that all entries in -a file should inherit just as if these tags were defined in a hypothetical -level zero that surrounds the entire file. Use a line like this@footnote{As -with all these in-buffer settings, pressing @kbd{C-c C-c} activates any -changes in the line.}: +explicitly marked with all those tags. You can also set tags that all +entries in a file should inherit just as if these tags were defined in +a hypothetical level zero that surrounds the entire file. Use a line like +this@footnote{As with all these in-buffer settings, pressing @kbd{C-c C-c} +activates any changes in the line.}: @cindex #+FILETAGS @example @@ -4877,7 +4926,7 @@ with inherited tags. Set @code{org-agenda-use-tag-inheritance} to control this: the default value includes all agenda types, but setting this to @code{nil} can really speed up agenda generation. -@node Setting tags, Tag groups, Tag inheritance, Tags +@node Setting tags @section Setting tags @cindex setting tags @cindex tags, setting @@ -4939,10 +4988,10 @@ By default Org mode uses the standard minibuffer completion facilities for entering tags. However, it also implements another, quicker, tag selection method called @emph{fast tag selection}. This allows you to select and deselect tags with just a single key press. For this to work well you should -assign unique letters to most of your commonly used tags. You can do this -globally by configuring the variable @code{org-tag-alist} in your -@file{.emacs} file. For example, you may find the need to tag many items in -different files with @samp{:@@home:}. In this case you can set something +assign unique, case-sensitive, letters to most of your commonly used tags. +You can do this globally by configuring the variable @code{org-tag-alist} in +your Emacs init file. For example, you may find the need to tag many items +in different files with @samp{:@@home:}. In this case you can set something like: @lisp @@ -5004,14 +5053,15 @@ If at least one tag has a selection key then pressing @kbd{C-c C-c} will automatically present you with a special interface, listing inherited tags, the tags of the current headline, and a list of all valid tags with corresponding keys@footnote{Keys will automatically be assigned to tags which -have no configured keys.}. In this interface, you can use the following -keys: +have no configured keys.}. + +Pressing keys assigned to tags will add or remove them from the list of tags +in the current line. Selecting a tag in a group of mutually exclusive tags +will turn off any other tags from that group. + +In this interface, you can also use the following special keys: @table @kbd -@item a-z... -Pressing keys assigned to tags will add or remove them from the list of -tags in the current line. Selecting a tag in a group of mutually -exclusive tags will turn off any other tags from that group. @kindex @key{TAB} @item @key{TAB} Enter a tag in the minibuffer, even if the tag is not in the predefined @@ -5021,16 +5071,21 @@ You can also add several tags: just separate them with a comma. @kindex @key{SPC} @item @key{SPC} Clear all tags for this line. + @kindex @key{RET} @item @key{RET} Accept the modified set. + @item C-g Abort without installing changes. + @item q If @kbd{q} is not assigned to a tag, it aborts like @kbd{C-g}. + @item ! Turn off groups of mutually exclusive tags. Use this to (as an exception) assign several tags from such a group. + @item C-c Toggle auto-exit after the next change (see below). If you are using expert mode, the first @kbd{C-c} will display the @@ -5058,41 +5113,104 @@ instead of @kbd{C-c C-c}). If you set the variable to the value @code{expert}, the special window is not even shown for single-key tag selection, it comes up only when you press an extra @kbd{C-c}. -@node Tag groups, Tag searches, Setting tags, Tags -@section Tag groups +@node Tag hierarchy +@section Tag hierarchy @cindex group tags @cindex tags, groups -In a set of mutually exclusive tags, the first tag can be defined as a -@emph{group tag}. When you search for a group tag, it will return matches -for all members in the group. In an agenda view, filtering by a group tag -will display headlines tagged with at least one of the members of the -group. This makes tag searches and filters even more flexible. +@cindex tag hierarchy +Tags can be defined in hierarchies. A tag can be defined as a @emph{group +tag} for a set of other tags. The group tag can be seen as the ``broader +term'' for its set of tags. Defining multiple @emph{group tags} and nesting +them creates a tag hierarchy. + +One use-case is to create a taxonomy of terms (tags) that can be used to +classify nodes in a document or set of documents. + +When you search for a group tag, it will return matches for all members in +the group and its subgroups. In an agenda view, filtering by a group tag +will display or hide headlines tagged with at least one of the members of the +group or any of its subgroups. This makes tag searches and filters even more +flexible. + +You can set group tags by using brackets and inserting a colon between the +group tag and its related tags---beware that all whitespaces are mandatory so +that Org can parse this line correctly: -You can set group tags by inserting a colon between the group tag and other -tags---beware that all whitespaces are mandatory so that Org can parse this -line correctly: +@example +#+TAGS: [ GTD : Control Persp ] +@end example + +In this example, @samp{GTD} is the @emph{group tag} and it is related to two +other tags: @samp{Control}, @samp{Persp}. Defining @samp{Control} and +@samp{Persp} as group tags creates an hierarchy of tags: @example -#+TAGS: @{ @@read : @@read_book @@read_ebook @} +#+TAGS: [ Control : Context Task ] +#+TAGS: [ Persp : Vision Goal AOF Project ] @end example -In this example, @samp{@@read} is a @emph{group tag} for a set of three -tags: @samp{@@read}, @samp{@@read_book} and @samp{@@read_ebook}. +That can conceptually be seen as a hierarchy of tags: + +@example +- GTD + - Persp + - Vision + - Goal + - AOF + - Project + - Control + - Context + - Task +@end example -You can also use the @code{:grouptags} keyword directly when setting -@code{org-tag-alist}: +You can use the @code{:startgrouptag}, @code{:grouptags} and +@code{:endgrouptag} keyword directly when setting @code{org-tag-alist} +directly: @lisp -(setq org-tag-alist '((:startgroup . nil) - ("@@read" . nil) - (:grouptags . nil) - ("@@read_book" . nil) - ("@@read_ebook" . nil) - (:endgroup . nil))) +(setq org-tag-alist '((:startgrouptag) + ("GTD") + (:grouptags) + ("Control") + ("Persp") + (:endgrouptag) + (:startgrouptag) + ("Control") + (:grouptags) + ("Context") + ("Task") + (:endgrouptag))) @end lisp -You cannot nest group tags or use a group tag as a tag in another group. +The tags in a group can be mutually exclusive if using the same group syntax +as is used for grouping mutually exclusive tags together; using curly +brackets. + +@example +#+TAGS: @{ Context : @@Home @@Work @@Call @} +@end example + +When setting @code{org-tag-alist} you can use @code{:startgroup} & +@code{:endgroup} instead of @code{:startgrouptag} & @code{:endgrouptag} to +make the tags mutually exclusive. + +Furthermore, the members of a @emph{group tag} can also be regular +expressions, creating the possibility of a more dynamic and rule-based +tag structure. The regular expressions in the group must be specified +within @{ @}. Here is an expanded example: + +@example +#+TAGS: [ Vision : @{V@@@.+@} ] +#+TAGS: [ Goal : @{G@@@.+@} ] +#+TAGS: [ AOF : @{AOF@@@.+@} ] +#+TAGS: [ Project : @{P@@@.+@} ] +@end example + +Searching for the tag @samp{Project} will now list all tags also including +regular expression matches for @samp{P@@@.+}, and similarly for tag searches on +@samp{Vision}, @samp{Goal} and @samp{AOF}. For example, this would work well +for a project tagged with a common project-identifier, e.g. @samp{P@@2014_OrgTags}. @kindex C-c C-x q @vindex org-group-tags @@ -5100,7 +5218,7 @@ If you want to ignore group tags temporarily, toggle group tags support with @command{org-toggle-tags-groups}, bound to @kbd{C-c C-x q}. If you want to disable tag groups completely, set @code{org-group-tags} to @code{nil}. -@node Tag searches, , Tag groups, Tags +@node Tag searches @section Tag searches @cindex tag searches @cindex searching for tags @@ -5126,13 +5244,13 @@ only TODO items and force checking subitems (see the option These commands all prompt for a match string which allows basic Boolean logic like @samp{+boss+urgent-project1}, to find entries with tags @samp{boss} and @samp{urgent}, but not @samp{project1}, or @samp{Kathy|Sally} to find entries -which are tagged, like @samp{Kathy} or @samp{Sally}. The full syntax of the search -string is rich and allows also matching against TODO keywords, entry levels -and properties. For a complete description with many examples, see -@ref{Matching tags and properties}. +tagged as @samp{Kathy} or @samp{Sally}. The full syntax of the search string +is rich and allows also matching against TODO keywords, entry levels and +properties. For a complete description with many examples, see @ref{Matching +tags and properties}. -@node Properties and Columns, Dates and Times, Tags, Top +@node Properties and columns @chapter Properties and columns @cindex properties @@ -5162,16 +5280,18 @@ Properties can be conveniently edited and viewed in column view * Property API:: Properties for Lisp programmers @end menu -@node Property syntax, Special properties, Properties and Columns, Properties and Columns +@node Property syntax @section Property syntax @cindex property syntax @cindex drawer, for properties Properties are key-value pairs. When they are associated with a single entry -or with a tree they need to be inserted into a special -drawer (@pxref{Drawers}) with the name @code{PROPERTIES}. Each property -is specified on a single line, with the key (surrounded by colons) -first, and the value after it. Here is an example: +or with a tree they need to be inserted into a special drawer +(@pxref{Drawers}) with the name @code{PROPERTIES}, which has to be located +right below a headline, and its planning line (@pxref{Deadlines and +scheduling}) when applicable. Each property is specified on a single line, +with the key (surrounded by colons) first, and the value after it. Keys are +case-insensitive. Here is an example: @example * CD collection @@ -5187,7 +5307,7 @@ first, and the value after it. Here is an example: @end example Depending on the value of @code{org-use-property-inheritance}, a property set -this way will either be associated with a single entry, or the sub-tree +this way will either be associated with a single entry, or the subtree defined by the entry, see @ref{Property inheritance}. You may define the allowed values for a particular property @samp{:Xyz:} @@ -5215,7 +5335,7 @@ file, use a line like @end example Contrary to properties set from a special drawer, you have to refresh the -buffer with @kbd{C-c C-c} to activate this changes. +buffer with @kbd{C-c C-c} to activate this change. If you want to add to the value of an existing property, append a @code{+} to the property name. The following results in the property @code{var} having @@ -5284,58 +5404,52 @@ Compute the property at point, using the operator and scope from the nearest column format definition. @end table -@node Special properties, Property searches, Property syntax, Properties and Columns +@node Special properties @section Special properties @cindex properties, special Special properties provide an alternative access method to Org mode features, like the TODO state or the priority of an entry, discussed in the previous -chapters. This interface exists so that you can include these states in a -column view (@pxref{Column view}), or to use them in queries. The following -property names are special and (except for @code{:CATEGORY:}) should not be -used as keys in the properties drawer: +chapters. This interface exists so that you can include these states in +a column view (@pxref{Column view}), or to use them in queries. The +following property names are special and should not be used as keys in the +properties drawer: -@cindex property, special, ID -@cindex property, special, TODO -@cindex property, special, TAGS @cindex property, special, ALLTAGS -@cindex property, special, CATEGORY -@cindex property, special, PRIORITY +@cindex property, special, BLOCKED +@cindex property, special, CLOCKSUM +@cindex property, special, CLOCKSUM_T +@cindex property, special, CLOSED @cindex property, special, DEADLINE +@cindex property, special, FILE +@cindex property, special, ITEM +@cindex property, special, PRIORITY @cindex property, special, SCHEDULED -@cindex property, special, CLOSED +@cindex property, special, TAGS @cindex property, special, TIMESTAMP @cindex property, special, TIMESTAMP_IA -@cindex property, special, CLOCKSUM -@cindex property, special, CLOCKSUM_T -@cindex property, special, BLOCKED -@c guessing that ITEM is needed in this area; also, should this list be sorted? -@cindex property, special, ITEM -@cindex property, special, FILE +@cindex property, special, TODO @example -ID @r{A globally unique ID used for synchronization during} - @r{iCalendar or MobileOrg export.} -TODO @r{The TODO keyword of the entry.} -TAGS @r{The tags defined directly in the headline.} ALLTAGS @r{All tags, including inherited ones.} -CATEGORY @r{The category of an entry.} -PRIORITY @r{The priority of the entry, a string with a single letter.} -DEADLINE @r{The deadline time string, without the angular brackets.} -SCHEDULED @r{The scheduling timestamp, without the angular brackets.} -CLOSED @r{When was this entry closed?} -TIMESTAMP @r{The first keyword-less timestamp in the entry.} -TIMESTAMP_IA @r{The first inactive timestamp in the entry.} +BLOCKED @r{"t" if task is currently blocked by children or siblings.} CLOCKSUM @r{The sum of CLOCK intervals in the subtree. @code{org-clock-sum}} @r{must be run first to compute the values in the current buffer.} CLOCKSUM_T @r{The sum of CLOCK intervals in the subtree for today.} @r{@code{org-clock-sum-today} must be run first to compute the} @r{values in the current buffer.} -BLOCKED @r{"t" if task is currently blocked by children or siblings} -ITEM @r{The headline of the entry.} +CLOSED @r{When was this entry closed?} +DEADLINE @r{The deadline time string, without the angular brackets.} FILE @r{The filename the entry is located in.} +ITEM @r{The headline of the entry.} +PRIORITY @r{The priority of the entry, a string with a single letter.} +SCHEDULED @r{The scheduling timestamp, without the angular brackets.} +TAGS @r{The tags defined directly in the headline.} +TIMESTAMP @r{The first keyword-less timestamp in the entry.} +TIMESTAMP_IA @r{The first inactive timestamp in the entry.} +TODO @r{The TODO keyword of the entry.} @end example -@node Property searches, Property inheritance, Special properties, Properties and Columns +@node Property searches @section Property searches @cindex properties, searching @cindex searching, of properties @@ -5372,7 +5486,7 @@ value. If you enclose the value in curly braces, it is interpreted as a regular expression and matched against the property values. @end table -@node Property inheritance, Column view, Property searches, Properties and Columns +@node Property inheritance @section Property Inheritance @cindex properties, inheritance @cindex inheritance, of properties @@ -5416,7 +5530,7 @@ The LOGGING property may define logging settings for an entry or a subtree (@pxref{Tracking TODO state changes}). @end table -@node Column view, Property API, Property inheritance, Properties and Columns +@node Column view @section Column view A great way to view and edit properties in an outline tree is @@ -5430,7 +5544,7 @@ view (@kbd{S-@key{TAB} S-@key{TAB}}, or simply @kbd{c} while column view is active), but you can still open, read, and edit the entry below each headline. Or, you can switch to column view after executing a sparse tree command and in this way get a table only for the selected items. -Column view also works in agenda buffers (@pxref{Agenda Views}) where +Column view also works in agenda buffers (@pxref{Agenda views}) where queries have collected selected items, possibly from a number of files. @menu @@ -5439,7 +5553,7 @@ queries have collected selected items, possibly from a number of files. * Capturing column view:: A dynamic block for column view @end menu -@node Defining columns, Using column view, Column view, Column view +@node Defining columns @subsection Defining columns @cindex column view, for properties @cindex properties, column view @@ -5452,7 +5566,7 @@ done by defining a column format line. * Column attributes:: Appearance and content of a column @end menu -@node Scope of column definitions, Column attributes, Defining columns, Defining columns +@node Scope of column definitions @subsubsection Scope of column definitions To define a column format for an entire file, use a line like @@ -5479,7 +5593,7 @@ you can define columns on level 1 that are general enough for all sublevels, and more specific columns further down, when you edit a deeper part of the tree. -@node Column attributes, , Scope of column definitions, Defining columns +@node Column attributes @subsubsection Column attributes A column definition sets the attributes of a column. The general definition looks like this: @@ -5501,38 +5615,45 @@ optional. The individual parts have the following meaning: @var{title} @r{The header text for the column. If omitted, the property} @r{name is used.} @{@var{summary-type}@} @r{The summary type. If specified, the column values for} - @r{parent nodes are computed from the children.} + @r{parent nodes are computed from the children@footnote{If + more than one summary type apply to the property, the parent + values are computed according to the first of them.}.} @r{Supported summary types are:} @{+@} @r{Sum numbers in this column.} @{+;%.1f@} @r{Like @samp{+}, but format result with @samp{%.1f}.} @{$@} @r{Currency, short for @samp{+;%.2f}.} - @{:@} @r{Sum times, HH:MM, plain numbers are hours.} - @{X@} @r{Checkbox status, @samp{[X]} if all children are @samp{[X]}.} - @{X/@} @r{Checkbox status, @samp{[n/m]}.} - @{X%@} @r{Checkbox status, @samp{[n%]}.} @{min@} @r{Smallest number in column.} @{max@} @r{Largest number.} @{mean@} @r{Arithmetic mean of numbers.} + @{X@} @r{Checkbox status, @samp{[X]} if all children are @samp{[X]}.} + @{X/@} @r{Checkbox status, @samp{[n/m]}.} + @{X%@} @r{Checkbox status, @samp{[n%]}.} + @{:@} @r{Sum times, HH:MM, plain numbers are + hours@footnote{A time can also be a duration, using effort + modifiers defined in @code{org-effort-durations}, e.g., + @samp{3d 1h}. If any value in the column is as such, the + summary will also be an effort duration.}.} @{:min@} @r{Smallest time value in column.} @{:max@} @r{Largest time value.} @{:mean@} @r{Arithmetic mean of time values.} - @{@@min@} @r{Minimum age (in days/hours/mins/seconds).} + @{@@min@} @r{Minimum age@footnote{An age is defined as + a duration since a given time-stamp (@pxref{Timestamps}). It + can also be expressed as days, hours, minutes and seconds, + identified by @samp{d}, @samp{h}, @samp{m} and @samp{s} + suffixes, all mandatory, e.g., @samp{0d 13h 0m 10s}.} (in + days/hours/mins/seconds).} @{@@max@} @r{Maximum age (in days/hours/mins/seconds).} @{@@mean@} @r{Arithmetic mean of ages (in days/hours/mins/seconds).} - @{est+@} @r{Add low-high estimates.} + @{est+@} @r{Add @samp{low-high} estimates.} @end example -@noindent -Be aware that you can only have one summary type for any property you -include. Subsequent columns referencing the same property will all display the -same summary information. - The @code{est+} summary type requires further explanation. It is used for -combining estimates, expressed as low-high ranges. For example, instead -of estimating a particular task will take 5 days, you might estimate it as -5--6 days if you're fairly confident you know how much work is required, or -1--10 days if you don't really know what needs to be done. Both ranges -average at 5.5 days, but the first represents a more predictable delivery. +combining estimates, expressed as @samp{low-high} ranges or plain numbers. +For example, instead of estimating a particular task will take 5 days, you +might estimate it as 5--6 days if you're fairly confident you know how much +work is required, or 1--10 days if you don't really know what needs to be +done. Both ranges average at 5.5 days, but the first represents a more +predictable delivery. When combining a set of such estimates, simply adding the lows and highs produces an unrealistically wide result. Instead, @code{est+} adds the @@ -5546,6 +5667,10 @@ full job more realistically, at 10--15 days. Numbers are right-aligned when a format specifier with an explicit width like @code{%5d} or @code{%5.1f} is used. +@vindex org-columns-summary-types +You can also define custom summary types by setting +@code{org-columns-summary-types}, which see. + Here is an example for a complete columns definition, along with allowed values. @@ -5574,7 +5699,7 @@ an @samp{[X]} status if all children have been checked. The sums of CLOCK intervals in the subtree, either for all clocks or just for today. -@node Using column view, Capturing column view, Defining columns, Column view +@node Using column view @subsection Using column view @table @kbd @@ -5582,14 +5707,15 @@ today. @orgcmd{C-c C-x C-c,org-columns} @vindex org-columns-default-format Turn on column view. If the cursor is before the first headline in the file, -column view is turned on for the entire file, using the @code{#+COLUMNS} -definition. If the cursor is somewhere inside the outline, this command -searches the hierarchy, up from point, for a @code{:COLUMNS:} property that -defines a format. When one is found, the column view table is established -for the tree starting at the entry that contains the @code{:COLUMNS:} -property. If no such property is found, the format is taken from the -@code{#+COLUMNS} line or from the variable @code{org-columns-default-format}, -and column view is established for the current entry and its subtree. +or the function called with the universal prefix argument, column view is +turned on for the entire file, using the @code{#+COLUMNS} definition. If the +cursor is somewhere inside the outline, this command searches the hierarchy, +up from point, for a @code{:COLUMNS:} property that defines a format. When +one is found, the column view table is established for the tree starting at +the entry that contains the @code{:COLUMNS:} property. If no such property +is found, the format is taken from the @code{#+COLUMNS} line or from the +variable @code{org-columns-default-format}, and column view is established +for the current entry and its subtree. @orgcmd{r,org-columns-redo} Recreate the column view, to include recent changes made in the buffer. @orgcmd{g,org-columns-redo} @@ -5620,7 +5746,7 @@ View the full value of this property. This is useful if the width of the column is smaller than that of the value. @orgcmd{a,org-columns-edit-allowed} Edit the list of allowed values for this property. If the list is found -in the hierarchy, the modified values is stored there. If no list is +in the hierarchy, the modified value is stored there. If no list is found, the new value is stored in the first entry that is part of the current column view. @tsubheading{Modifying the table structure} @@ -5632,7 +5758,7 @@ Insert a new column, to the left of the current column. Delete the current column. @end table -@node Capturing column view, , Using column view, Column view +@node Capturing column view @subsection Capturing column view Since column view is just an overlay over a buffer, it cannot be @@ -5677,6 +5803,8 @@ When set to a number, don't capture entries below this level. @item :skip-empty-rows When set to @code{t}, skip rows where the only non-empty specifier of the column view is @code{ITEM}. +@item :indent +When non-@code{nil}, indent each @code{ITEM} field according to its level. @end table @@ -5709,7 +5837,7 @@ distributed with the main distribution of Org (visit properties from entries in a certain scope, and arbitrary Lisp expressions to process these values before inserting them into a table or a dynamic block. -@node Property API, , Column view, Properties and Columns +@node Property API @section The Property API @cindex properties, API @cindex API, for properties @@ -5719,7 +5847,7 @@ be used by Emacs Lisp programs to work with properties and to implement features based on them. For more information see @ref{Using the property API}. -@node Dates and Times, Capture - Refile - Archive, Properties and Columns, Top +@node Dates and times @chapter Dates and times @cindex dates @cindex times @@ -5729,7 +5857,7 @@ property API}. To assist project planning, TODO items can be labeled with a date and/or a time. The specially formatted string carrying the date and time information is called a @emph{timestamp} in Org mode. This may be a -little confusing because timestamp is often used as indicating when +little confusing because timestamp is often used to indicate when something was created or last changed. However, in Org mode this term is used in a much wider sense. @@ -5739,12 +5867,11 @@ is used in a much wider sense. * Deadlines and scheduling:: Planning your work * Clocking work time:: Tracking how long you spend on a task * Effort estimates:: Planning work effort in advance -* Relative timer:: Notes with a running timer -* Countdown timer:: Starting a countdown timer for a task +* Timers:: Notes with a running timer @end menu -@node Timestamps, Creating timestamps, Dates and Times, Dates and Times +@node Timestamps @section Timestamps, deadlines, and scheduling @cindex timestamps @cindex ranges, time @@ -5795,10 +5922,10 @@ following will show up in the agenda every Wednesday: For more complex date specifications, Org mode supports using the special sexp diary entries implemented in the Emacs calendar/diary package@footnote{When working with the standard diary sexp functions, you -need to be very careful with the order of the arguments. That order depend +need to be very careful with the order of the arguments. That order depends evilly on the variable @code{calendar-date-style} (or, for older Emacs versions, @code{european-calendar-style}). For example, to specify a date -December 12, 2005, the call might look like @code{(diary-date 12 1 2005)} or +December 1, 2005, the call might look like @code{(diary-date 12 1 2005)} or @code{(diary-date 1 12 2005)} or @code{(diary-date 2005 12 1)}, depending on the settings. This has been the source of much confusion. Org mode users can resort to special versions of these functions like @code{org-date} or @@ -5838,7 +5965,7 @@ angular ones. These timestamps are inactive in the sense that they do @end table -@node Creating timestamps, Deadlines and scheduling, Timestamps, Dates and Times +@node Creating timestamps @section Creating timestamps @cindex creating timestamps @cindex timestamps, creating @@ -5909,7 +6036,7 @@ the following column). * Custom time format:: Making dates look different @end menu -@node The date/time prompt, Custom time format, Creating timestamps, Creating timestamps +@node The date/time prompt @subsection The date/time prompt @cindex date, reading in minibuffer @cindex time, reading in minibuffer @@ -5948,7 +6075,7 @@ feb 15 @result{} @b{2007}-02-15 sep 12 9 @result{} 2009-09-12 12:45 @result{} @b{2006}-@b{06}-@b{13} 12:45 22 sept 0:34 @result{} @b{2006}-09-22 00:34 -w4 @result{} ISO week for of the current year @b{2006} +w4 @result{} ISO week four of the current year @b{2006} 2012 w4 fri @result{} Friday of ISO week 4 in 2012 2012-w04-5 @result{} Same as above @end example @@ -6017,14 +6144,18 @@ from the minibuffer: @kindex M-S-@key{right} @kindex M-S-@key{left} @kindex @key{RET} +@kindex M-S-@key{down} +@kindex M-S-@key{up} + @example -@key{RET} @r{Choose date at cursor in calendar.} -mouse-1 @r{Select date by clicking on it.} -S-@key{right}/@key{left} @r{One day forward/backward.} -S-@key{down}/@key{up} @r{One week forward/backward.} -M-S-@key{right}/@key{left} @r{One month forward/backward.} -> / < @r{Scroll calendar forward/backward by one month.} -M-v / C-v @r{Scroll calendar forward/backward by 3 months.} +@key{RET} @r{Choose date at cursor in calendar.} +mouse-1 @r{Select date by clicking on it.} +S-@key{right}/@key{left} @r{One day forward/backward.} +S-@key{down}/@key{up} @r{One week forward/backward.} +M-S-@key{right}/@key{left} @r{One month forward/backward.} +> / < @r{Scroll calendar forward/backward by one month.} +M-v / C-v @r{Scroll calendar forward/backward by 3 months.} +M-S-@key{down}/@key{up} @r{Scroll calendar forward/backward by one year.} @end example @vindex org-read-date-display-live @@ -6035,7 +6166,7 @@ on, the current interpretation of your input will be displayed live in the minibuffer@footnote{If you find this distracting, turn the display off with @code{org-read-date-display-live}.}. -@node Custom time format, , The date/time prompt, Creating timestamps +@node Custom time format @subsection Custom time format @cindex custom date/time format @cindex time format, custom @@ -6083,10 +6214,12 @@ format is shorter, things do work as expected. @end itemize -@node Deadlines and scheduling, Clocking work time, Creating timestamps, Dates and Times +@node Deadlines and scheduling @section Deadlines and scheduling -A timestamp may be preceded by special keywords to facilitate planning: +A timestamp may be preceded by special keywords to facilitate planning. Both +the timestamp and the keyword have to be positioned immediately after the task +they refer to. @table @var @item DEADLINE @@ -6110,9 +6243,9 @@ until the entry is marked DONE@. An example: @end example You can specify a different lead time for warnings for a specific -deadlines using the following syntax. Here is an example with a warning +deadline using the following syntax. Here is an example with a warning period of 5 days @code{DEADLINE: <2004-02-29 Sun -5d>}. This warning is -deactivated if the task get scheduled and you set +deactivated if the task gets scheduled and you set @code{org-agenda-skip-deadline-prewarning-if-scheduled} to @code{t}. @item SCHEDULED @@ -6172,28 +6305,25 @@ sexp entry matches. * Repeated tasks:: Items that show up again and again @end menu -@node Inserting deadline/schedule, Repeated tasks, Deadlines and scheduling, Deadlines and scheduling +@node Inserting deadline/schedule @subsection Inserting deadlines or schedules -The following commands allow you to quickly insert@footnote{The @samp{SCHEDULED} and -@samp{DEADLINE} dates are inserted on the line right below the headline. Don't put -any text between this line and the headline.} a deadline or to schedule +The following commands allow you to quickly insert a deadline or to schedule an item: @table @kbd @c @orgcmd{C-c C-d,org-deadline} -Insert @samp{DEADLINE} keyword along with a stamp. The insertion will happen -in the line directly following the headline. Any CLOSED timestamp will be -removed. When called with a prefix arg, an existing deadline will be removed -from the entry. Depending on the variable @code{org-log-redeadline}@footnote{with corresponding -@code{#+STARTUP} keywords @code{logredeadline}, @code{lognoteredeadline}, -and @code{nologredeadline}}, a note will be taken when changing an existing +Insert @samp{DEADLINE} keyword along with a stamp. Any CLOSED timestamp will +be removed. When called with a prefix arg, an existing deadline will be +removed from the entry. Depending on the variable +@code{org-log-redeadline}@footnote{with corresponding @code{#+STARTUP} +keywords @code{logredeadline}, @code{lognoteredeadline}, and +@code{nologredeadline}}, a note will be taken when changing an existing deadline. @orgcmd{C-c C-s,org-schedule} -Insert @samp{SCHEDULED} keyword along with a stamp. The insertion will -happen in the line directly following the headline. Any CLOSED timestamp +Insert @samp{SCHEDULED} keyword along with a stamp. Any CLOSED timestamp will be removed. When called with a prefix argument, remove the scheduling date from the entry. Depending on the variable @code{org-log-reschedule}@footnote{with corresponding @code{#+STARTUP} @@ -6201,14 +6331,6 @@ keywords @code{logreschedule}, @code{lognotereschedule}, and @code{nologreschedule}}, a note will be taken when changing an existing scheduling time. @c -@orgcmd{C-c C-x C-k,org-mark-entry-for-agenda-action} -@kindex k a -@kindex k s -Mark the current entry for agenda action. After you have marked the entry -like this, you can open the agenda or the calendar to find an appropriate -date. With the cursor on the selected date, press @kbd{k s} or @kbd{k d} to -schedule the marked item. -@c @orgcmd{C-c / d,org-check-deadlines} @cindex sparse tree, for deadlines @vindex org-deadline-warning-days @@ -6230,7 +6352,7 @@ setting the date by indicating a relative time: e.g., +1d will set the date to the next day after today, and --1w will set the date to the previous week before any current timestamp. -@node Repeated tasks, , Inserting deadline/schedule, Deadlines and scheduling +@node Repeated tasks @subsection Repeated tasks @cindex tasks, repeated @cindex repeated tasks @@ -6271,6 +6393,9 @@ switch the date like this: DEADLINE: <2005-11-01 Tue +1m> @end example +To mark a task with a repeater as @code{DONE}, use @kbd{C-- 1 C-c C-t} +(i.e., @code{org-todo} with a numeric prefix argument of -1.) + @vindex org-log-repeat A timestamp@footnote{You can change this using the option @code{org-log-repeat}, or the @code{#+STARTUP} options @code{logrepeat}, @@ -6299,6 +6424,13 @@ special repeaters @samp{++} and @samp{.+}. For example: but also by as many weeks as it takes to get this date into the future. However, it stays on a Sunday, even if you called and marked it done on Saturday. +** TODO Empty kitchen trash + DEADLINE: <2008-02-08 Fri 20:00 ++1d> + Marking this DONE will shift the date by at least one day, and + also by as many days as it takes to get the timestamp into the + future. Since there is a time in the timestamp, the next + deadline in the future will be on today's date if you + complete the task before 20:00. ** TODO Check the batteries in the smoke detectors DEADLINE: <2005-11-01 Tue .+1m> Marking this DONE will shift the date to one month after @@ -6310,7 +6442,9 @@ You may have both scheduling and deadline information for a specific task. If the repeater is set for the scheduling information only, you probably want the repeater to be ignored after the deadline. If so, set the variable @code{org-agenda-skip-scheduled-if-deadline-is-shown} to -@code{repeated-after-deadline}. If you want both scheduling and deadline +@code{repeated-after-deadline}. However, any scheduling information without +a repeater is no longer relevant once the task is done, and thus, removed +upon repeating the task. If you want both scheduling and deadline information to repeat after the same interval, set the same repeater for both timestamps. @@ -6319,7 +6453,7 @@ subtree, with dates shifted in each copy. The command @kbd{C-c C-x c} was created for this purpose, it is described in @ref{Structure editing}. -@node Clocking work time, Effort estimates, Deadlines and scheduling, Dates and Times +@node Clocking work time @section Clocking work time @cindex clocking time @cindex time clocking @@ -6330,10 +6464,9 @@ you stop working on that task, or when you mark the task done, the clock is stopped and the corresponding time interval is recorded. It also computes the total time spent on each subtree@footnote{Clocking only works if all headings are indented with less than 30 stars. This is a hardcoded -limitation of @code{lmax} in @code{org-clock-sum}.} of a project. And it -remembers a -history or tasks recently clocked, to that you can jump quickly between a -number of tasks absorbing your time. +limitation of @code{lmax} in @code{org-clock-sum}.} of a project. +And it remembers a history or tasks recently clocked, so that you can jump +quickly between a number of tasks absorbing your time. To save the clock history across Emacs sessions, use @lisp @@ -6352,7 +6485,7 @@ what to do with it. * Resolving idle time:: Resolving time when you've been idle @end menu -@node Clocking commands, The clock table, Clocking work time, Clocking work time +@node Clocking commands @subsection Clocking commands @table @kbd @@ -6387,7 +6520,7 @@ reset of the task @footnote{as recorded by the @code{LAST_REPEAT} property} will be shown. More control over what time is shown can be exercised with the @code{CLOCK_MODELINE_TOTAL} property. It may have the values @code{current} to show only the current clocking instance, @code{today} to -show all time clocked on this tasks today (see also the variable +show all time clocked on this task today (see also the variable @code{org-extend-today-until}), @code{all} to include all time, or @code{auto} which is the default@footnote{See also the variable @code{org-clock-modeline-total}.}.@* Clicking with @kbd{mouse-1} onto the @@ -6397,7 +6530,7 @@ mode line entry will pop up a menu with clocking options. @vindex org-log-note-clock-out Stop the clock (clock-out). This inserts another timestamp at the same location where the clock was last started. It also directly computes -the resulting time in inserts it after the time range as @samp{=> +the resulting time and inserts it after the time range as @samp{=> HH:MM}. See the variable @code{org-log-note-clock-out} for the possibility to record an additional note together with the clock-out timestamp@footnote{The corresponding in-buffer setting is: @@ -6449,10 +6582,10 @@ the agenda (@pxref{Weekly/daily agenda}) to show which tasks have been worked on or closed during a day. @strong{Important:} note that both @code{org-clock-out} and -@code{org-clock-in-last} can have a global keybinding and will not +@code{org-clock-in-last} can have a global key binding and will not modify the window disposition. -@node The clock table, Resolving idle time, Clocking commands, Clocking work time +@node The clock table @subsection The clock table @cindex clocktable, dynamic block @cindex report, of clocked time @@ -6492,7 +6625,7 @@ buffer with the @kbd{C-c C-x C-r} command: @end example @noindent @vindex org-clocktable-defaults -The @samp{BEGIN} line and specify a number of options to define the scope, +The @samp{BEGIN} line specifies a number of options to define the scope, structure, and formatting of the report. Defaults for all these options can be configured in the variable @code{org-clocktable-defaults}. @@ -6512,7 +6645,7 @@ be selected: file-with-archives @r{current file and its archives} agenda-with-archives @r{all agenda files, including archives} :block @r{The time block to consider. This block is specified either} - @r{absolute, or relative to the current time and may be any of} + @r{absolutely, or relative to the current time and may be any of} @r{these formats:} 2007-12-31 @r{New year eve 2007} 2007-12 @r{December 2007} @@ -6523,6 +6656,7 @@ be selected: thisweek, lastweek, thisweek-@var{N} @r{a relative week} thismonth, lastmonth, thismonth-@var{N} @r{a relative month} thisyear, lastyear, thisyear-@var{N} @r{a relative year} + untilnow @r{Use @kbd{S-@key{left}/@key{right}} keys to shift the time interval.} :tstart @r{A time string specifying when to start considering times.} @r{Relative times like @code{"<-2w>"} can also be used. See} @@ -6541,7 +6675,7 @@ be selected: @r{@ref{Matching tags and properties} for the match syntax.} @end example -Then there are options which determine the formatting of the table. There +Then there are options which determine the formatting of the table. These options are interpreted by the function @code{org-clocktable-write-default}, but you can specify your own function using the @code{:formatter} parameter. @example @@ -6555,6 +6689,8 @@ but you can specify your own function using the @code{:formatter} parameter. :tcolumns @r{Number of columns to be used for times. If this is smaller} @r{than @code{:maxlevel}, lower levels will be lumped into one column.} :level @r{Should a level number column be included?} +:sort @r{A cons cell like containing the column to sort and a sorting type.} + @r{E.g., @code{:sort (1 . ?a)} sorts the first column alphabetically.} :compact @r{Abbreviation for @code{:level nil :indent t :narrow 40! :tcolumns 1}} @r{All are overwritten except if there is an explicit @code{:narrow}} :timestamp @r{A timestamp for the entry, when available. Look for SCHEDULED,} @@ -6600,7 +6736,7 @@ would be #+END: clocktable @end example -@node Resolving idle time, , The clock table, Clocking work time +@node Resolving idle time @subsection Resolving idle time and continuous clocking @subsubheading Resolving idle time @@ -6616,7 +6752,7 @@ applying it to another one. @vindex org-clock-idle-time By customizing the variable @code{org-clock-idle-time} to some integer, such as 10 or 15, Emacs can alert you when you get back to your computer after -being idle for that many minutes@footnote{On computers using macOS, +being idle for that many minutes@footnote{On computers using Mac OS X, idleness is based on actual user idleness, not just Emacs' idle time. For X11, you can install a utility program @file{x11idle.c}, available in the @code{contrib/scripts} directory of the Org git distribution, or install the @@ -6685,20 +6821,18 @@ last clocked entry for this session, and start the new clock from there. If you only want this from time to time, use three universal prefix arguments with @code{org-clock-in} and two @kbd{C-u C-u} with @code{org-clock-in-last}. -@node Effort estimates, Relative timer, Clocking work time, Dates and Times +@node Effort estimates @section Effort estimates @cindex effort estimates @cindex property, Effort -@vindex org-effort-property If you want to plan your work in a very detailed way, or if you need to produce offers with quotations of the estimated work effort, you may want to assign effort estimates to entries. If you are also clocking your work, you -may later want to compare the planned effort with the actual working time, a -great way to improve planning estimates. Effort estimates are stored in a -special property @samp{Effort}@footnote{You may change the property being -used with the variable @code{org-effort-property}.}. You can set the effort -for an entry with the following commands: +may later want to compare the planned effort with the actual working time, +a great way to improve planning estimates. Effort estimates are stored in +a special property @code{EFFORT}. You can set the effort for an entry with +the following commands: @table @kbd @orgcmd{C-c C-x e,org-set-effort} @@ -6748,61 +6882,57 @@ with the @kbd{/} key in the agenda (@pxref{Agenda commands}). If you have these estimates defined consistently, two or three key presses will narrow down the list to stuff that fits into an available time slot. -@node Relative timer, Countdown timer, Effort estimates, Dates and Times -@section Taking notes with a relative timer +@node Timers +@section Taking notes with a timer @cindex relative timer +@cindex countdown timer +@kindex ; + +Org provides two types of timers. There is a relative timer that counts up, +which can be useful when taking notes during, for example, a meeting or +a video viewing. There is also a countdown timer. + +The relative and countdown are started with separate commands. -When taking notes during, for example, a meeting or a video viewing, it can -be useful to have access to times relative to a starting time. Org provides -such a relative timer and make it easy to create timed notes. +@table @kbd +@orgcmd{C-c C-x 0,org-timer-start} +Start or reset the relative timer. By default, the timer is set to 0. When +called with a @kbd{C-u} prefix, prompt the user for a starting offset. If +there is a timer string at point, this is taken as the default, providing a +convenient way to restart taking notes after a break in the process. When +called with a double prefix argument @kbd{C-u C-u}, change all timer strings +in the active region by a certain amount. This can be used to fix timer +strings if the timer was not started at exactly the right moment. +@orgcmd{C-c C-x ;,org-timer-set-timer} +Start a countdown timer. The user is prompted for a duration. +@code{org-timer-default-timer} sets the default countdown value. Giving +a numeric prefix argument overrides this default value. This command is +available as @kbd{;} in agenda buffers. +@end table + +Once started, relative and countdown timers are controlled with the same +commands. @table @kbd @orgcmd{C-c C-x .,org-timer} -Insert a relative time into the buffer. The first time you use this, the -timer will be started. When called with a prefix argument, the timer is -restarted. +Insert the value of the current relative or countdown timer into the buffer. +If no timer is running, the relative timer will be started. When called with +a prefix argument, the relative timer is restarted. @orgcmd{C-c C-x -,org-timer-item} -Insert a description list item with the current relative time. With a prefix -argument, first reset the timer to 0. +Insert a description list item with the value of the current relative or +countdown timer. With a prefix argument, first reset the relative timer to +0. @orgcmd{M-@key{RET},org-insert-heading} Once the timer list is started, you can also use @kbd{M-@key{RET}} to insert new timer items. -@c for key sequences with a comma, command name macros fail :( -@kindex C-c C-x , -@item C-c C-x , -Pause the timer, or continue it if it is already paused -(@command{org-timer-pause-or-continue}). -@c removed the sentence because it is redundant to the following item -@kindex C-u C-c C-x , -@item C-u C-c C-x , +@orgcmd{C-c C-x @comma{},org-timer-pause-or-continue} +Pause the timer, or continue it if it is already paused. +@orgcmd{C-c C-x _,org-timer-stop} Stop the timer. After this, you can only start a new timer, not continue the old one. This command also removes the timer from the mode line. -@orgcmd{C-c C-x 0,org-timer-start} -Reset the timer without inserting anything into the buffer. By default, the -timer is reset to 0. When called with a @kbd{C-u} prefix, reset the timer to -specific starting offset. The user is prompted for the offset, with a -default taken from a timer string at point, if any, So this can be used to -restart taking notes after a break in the process. When called with a double -prefix argument @kbd{C-u C-u}, change all timer strings in the active region -by a certain amount. This can be used to fix timer strings if the timer was -not started at exactly the right moment. @end table -@node Countdown timer, , Relative timer, Dates and Times -@section Countdown timer -@cindex Countdown timer -@kindex C-c C-x ; -@kindex ; - -Calling @code{org-timer-set-timer} from an Org mode buffer runs a countdown -timer. Use @kbd{;} from agenda buffers, @key{C-c C-x ;} everywhere else. - -@code{org-timer-set-timer} prompts the user for a duration and displays a -countdown timer in the modeline. @code{org-timer-default-timer} sets the -default countdown value. Giving a prefix numeric argument overrides this -default value. - -@node Capture - Refile - Archive, Agenda Views, Dates and Times, Top +@node Capture - Refile - Archive @chapter Capture - Refile - Archive @cindex capture @@ -6816,13 +6946,13 @@ trees to an archive file keeps the system compact and fast. @menu * Capture:: Capturing new stuff * Attachments:: Add files to tasks -* RSS Feeds:: Getting input from RSS feeds +* RSS feeds:: Getting input from RSS feeds * Protocols:: External (e.g., Browser) access to Emacs and Org * Refile and copy:: Moving/copying a tree from one place to another * Archiving:: What to do with finished projects @end menu -@node Capture, Attachments, Capture - Refile - Archive, Capture - Refile - Archive +@node Capture @section Capture @cindex capture @@ -6849,7 +6979,7 @@ customization. * Capture templates:: Define the outline of different note types @end menu -@node Setting up capture, Using capture, Capture, Capture +@node Setting up capture @subsection Setting up capture The following customization sets a default target file for notes, and defines @@ -6864,12 +6994,12 @@ suggestion.} for capturing new material. @end group @end smalllisp -@node Using capture, Capture templates, Setting up capture, Capture +@node Using capture @subsection Using capture @table @kbd @orgcmd{C-c c,org-capture} -Call the command @code{org-capture}. Note that this keybinding is global and +Call the command @code{org-capture}. Note that this key binding is global and not active by default: you need to install it. If you have templates @cindex date tree defined @pxref{Capture templates}, it will offer these templates for @@ -6921,7 +7051,7 @@ automatically be created unless you set @code{org-capture-bookmark} to To insert the capture at point in an Org buffer, call @code{org-capture} with a @code{C-0} prefix argument. -@node Capture templates, , Using capture, Capture +@node Capture templates @subsection Capture templates @cindex templates, for Capture @@ -6980,7 +7110,7 @@ like this: * Templates in contexts:: Only show a template in a specific context @end menu -@node Template elements, Template expansion, Capture templates, Capture templates +@node Template elements @subsubsection Template elements Now lets look at the elements of a template definition. Each entry in @@ -7032,7 +7162,9 @@ files, targets usually define a node. Entries will become children of this node. Other types will be added to the table or list in the body of this node. Most target specifications contain a file name. If that file name is the empty string, it defaults to @code{org-default-notes-file}. A file can -also be given as a variable, function, or Emacs Lisp form. +also be given as a variable or as a function called with no argument. When +an absolute path is not specified for a target, it is taken as relative to +@code{org-directory}. Valid values are: @@ -7061,6 +7193,13 @@ one matched.}. @item (file+datetree+prompt "path/to/file") Will create a heading in a date tree, but will prompt for the date. +@item (file+weektree "path/to/file") +Will create a heading in a week tree for today's date. Week trees are sorted +by week and not by month unlike datetrees. + +@item (file+weektree+prompt "path/to/file") +Will create a heading in a week tree, but will prompt for the date. + @item (file+function "path/to/file" function-finding-location) A function to find the right location in the file. @@ -7068,8 +7207,8 @@ A function to find the right location in the file. File to the entry that is currently being clocked. @item (function function-finding-location) -Most general way, write your own function to find both -file and location. +Most general way: write your own function which both visits +the file and moves point to the right location. @end table @item template @@ -7117,9 +7256,10 @@ narrow it so that you only see the new material. @item :table-line-pos Specification of the location in the table where the new line should be -inserted. It should be a string like @code{"II-3"} meaning that the new -line should become the third line before the second horizontal separator -line. +inserted. It can be a string, a variable holding a string or a function +returning a string. The string should look like @code{"II-3"} meaning that +the new line should become the third line before the second horizontal +separator line. @item :kill-buffer If the target file was not yet visited when capture was invoked, kill the @@ -7127,7 +7267,7 @@ buffer again after capture is completed. @end table @end table -@node Template expansion, Templates in contexts, Template elements, Capture templates +@node Template expansion @subsubsection Template expansion In the template itself, special @kbd{%}-escapes@footnote{If you need one of @@ -7169,7 +7309,7 @@ dynamic insertion of content. The templates are expanded in the order given her @r{You may specify a default value and a completion table with} @r{%^@{prompt|default|completion2|completion3...@}.} @r{The arrow keys access a prompt-specific history.} -%\n @r{Insert the text entered at the nth %^@{@var{prompt}@}, where @code{n} is} +%\1 @dots{} %\N @r{Insert the text entered at the Nth %^@{@var{prompt}@}, where @code{N} is} @r{a number, starting from 1.} %? @r{After completing the template, position cursor here.} @end smallexample @@ -7187,15 +7327,15 @@ Link type | Available keywords ---------------------------------+---------------------------------------------- bbdb | %:name %:company irc | %:server %:port %:nick -vm, vm-imap, wl, mh, mew, rmail | %:type %:subject %:message-id - | %:from %:fromname %:fromaddress +vm, vm-imap, wl, mh, mew, rmail, | %:type %:subject %:message-id +gnus, notmuch | %:from %:fromname %:fromaddress | %:to %:toname %:toaddress | %:date @r{(message date header field)} | %:date-timestamp @r{(date as active timestamp)} | %:date-timestamp-inactive @r{(date as inactive timestamp)} | %:fromto @r{(either "to NAME" or "from NAME")@footnote{This will always be the other, not the user. See the variable @code{org-from-is-user-regexp}.}} gnus | %:group, @r{for messages also all email fields} -w3, w3m | %:url +eww, w3, w3m | %:url info | %:file %:node calendar | %:date @end smallexample @@ -7207,7 +7347,7 @@ To place the cursor after template expansion use: %? @r{After completing the template, position cursor here.} @end smallexample -@node Templates in contexts, , Template expansion, Capture templates +@node Templates in contexts @subsubsection Templates in contexts @vindex org-capture-templates-contexts @@ -7231,7 +7371,7 @@ template. In that case, add this command key like this: See the docstring of the variable for more information. -@node Attachments, RSS Feeds, Capture, Capture - Refile - Archive +@node Attachments @section Attachments @cindex attachments @@ -7319,7 +7459,7 @@ same directory for attachments as the parent does. @end table @end table -@node RSS Feeds, Protocols, Attachments, Capture - Refile - Archive +@node RSS feeds @section RSS feeds @cindex RSS feeds @cindex Atom feeds @@ -7357,17 +7497,12 @@ Prompt for a feed name and go to the inbox configured for this feed. Under the same headline, Org will create a drawer @samp{FEEDSTATUS} in which it will store information about the status of items in the feed, to avoid -adding the same item several times. You should add @samp{FEEDSTATUS} to the -list of drawers in that file: - -@example -#+DRAWERS: LOGBOOK PROPERTIES FEEDSTATUS -@end example +adding the same item several times. For more information, including how to read atom feeds, see @file{org-feed.el} and the docstring of @code{org-feed-alist}. -@node Protocols, Refile and copy, RSS Feeds, Capture - Refile - Archive +@node Protocols @section Protocols for external access @cindex protocols, for external access @cindex emacsserver @@ -7381,7 +7516,7 @@ a remote website you are looking at with the browser. See @uref{http://orgmode.org/worg/org-contrib/org-protocol.php} for detailed documentation and setup instructions. -@node Refile and copy, Archiving, Protocols, Capture - Refile - Archive +@node Refile and copy @section Refile and copy @cindex refiling notes @cindex copying notes @@ -7438,7 +7573,7 @@ setting @code{org-refile-use-cache}. To make the command see new possible targets, you have to clear the cache with this command. @end table -@node Archiving, , Refile and copy, Capture - Refile - Archive +@node Archiving @section Archiving @cindex archiving @@ -7459,7 +7594,7 @@ Archive the current entry using the command specified in the variable * Internal archiving:: Switch off a tree but keep it in the file @end menu -@node Moving subtrees, Internal archiving, Archiving, Archiving +@node Moving subtrees @subsection Moving a tree to the archive file @cindex external archiving @@ -7477,6 +7612,10 @@ the archive. To do this, each subtree is checked for open TODO entries. If none are found, the command offers to move it to the archive location. If the cursor is @emph{not} on a headline when this command is invoked, the level 1 trees will be checked. +@orgkey{C-u C-u C-c C-x C-s} +As above, but check subtree for timestamps instead of TODO entries. The +command will offer to archive the subtree if it @emph{does} contain a +timestamp, and that timestamp is in the past. @end table @cindex archive locations @@ -7488,14 +7627,7 @@ For information and examples on how to specify the file and the heading, see the documentation string of the variable @code{org-archive-location}. -There is also an in-buffer option for setting this variable, for -example@footnote{For backward compatibility, the following also works: -If there are several such lines in a file, each specifies the archive -location for the text below it. The first such line also applies to any -text before its definition. However, using this method is -@emph{strongly} deprecated as it is incompatible with the outline -structure of the document. The correct method for setting multiple -archive locations in a buffer is using properties.}: +There is also an in-buffer option for setting this variable, for example: @cindex #+ARCHIVE @example @@ -7506,7 +7638,7 @@ archive locations in a buffer is using properties.}: @noindent If you would like to have a special ARCHIVE location for a single entry or a (sub)tree, give the entry an @code{:ARCHIVE:} property with the -location as the value (@pxref{Properties and Columns}). +location as the value (@pxref{Properties and columns}). @vindex org-archive-save-context-info When a subtree is moved, it receives a number of special properties that @@ -7516,14 +7648,15 @@ outline path the archiving time etc. Configure the variable added. -@node Internal archiving, , Moving subtrees, Archiving +@node Internal archiving @subsection Internal archiving -If you want to just switch off (for agenda views) certain subtrees without -moving them to a different file, you can use the @code{ARCHIVE tag}. +@cindex archive tag +If you want to just switch off---for agenda views---certain subtrees without +moving them to a different file, you can use the archive tag. -A headline that is marked with the ARCHIVE tag (@pxref{Tags}) stays at -its location in the outline tree, but behaves in the following way: +A headline that is marked with the @samp{:ARCHIVE:} tag (@pxref{Tags}) stays +at its location in the outline tree, but behaves in the following way: @itemize @minus @item @vindex org-cycle-open-archived-trees @@ -7539,7 +7672,7 @@ archived subtrees are not exposed, unless you configure the option @code{org-sparse-tree-open-archived-trees}. @item @vindex org-agenda-skip-archived-trees -During agenda view construction (@pxref{Agenda Views}), the content of +During agenda view construction (@pxref{Agenda views}), the content of archived trees is ignored unless you configure the option @code{org-agenda-skip-archived-trees}, in which case these trees will always be included. In the agenda you can press @kbd{v a} to get archives @@ -7579,7 +7712,7 @@ outline. @end table -@node Agenda Views, Markup, Capture - Refile - Archive, Top +@node Agenda views @chapter Agenda views @cindex agenda views @@ -7622,6 +7755,15 @@ buffer}. This buffer is read-only, but provides commands to visit the corresponding locations in the original Org files, and even to edit these files remotely. +@vindex org-agenda-skip-comment-trees +@vindex org-agenda-skip-archived-trees +@cindex commented entries, in agenda views +@cindex archived entries, in agenda views +By default, the report ignores commented (@pxref{Comment lines}) and archived +(@pxref{Internal archiving}) entries. You can override this by setting +@code{org-agenda-skip-comment-trees} and +@code{org-agenda-skip-archived-trees} to @code{nil}. + @vindex org-agenda-window-setup @vindex org-agenda-restore-windows-after-quit Two variables control how the agenda buffer is displayed and whether the @@ -7636,11 +7778,11 @@ window configuration is restored when the agenda exits: * Presentation and sorting:: How agenda items are prepared for display * Agenda commands:: Remote editing of Org trees * Custom agenda views:: Defining special searches and views -* Exporting Agenda Views:: Writing a view to a file +* Exporting agenda views:: Writing a view to a file * Agenda column view:: Using column view for collected entries @end menu -@node Agenda files, Agenda dispatcher, Agenda Views, Agenda Views +@node Agenda files @section Agenda files @cindex agenda files @cindex files for agenda @@ -7717,7 +7859,7 @@ effect immediately. Lift the restriction. @end table -@node Agenda dispatcher, Built-in agenda views, Agenda files, Agenda Views +@node Agenda dispatcher @section The agenda dispatcher @cindex agenda dispatcher @cindex dispatching agenda commands @@ -7763,15 +7905,17 @@ current region/subtree.}. After pressing @kbd{< <}, you still need to press the character selecting the command. @item * +@cindex agenda, sticky @vindex org-agenda-sticky Toggle sticky agenda views. By default, Org maintains only a single agenda buffer and rebuilds it each time you change the view, to make sure everything -is always up to date. If you switch between views often and the build time -bothers you, you can turn on sticky agenda buffers (make this the default by -customizing the variable @code{org-agenda-sticky}). With sticky agendas, the -dispatcher only switches to the selected view, you need to update it by hand -with @kbd{r} or @kbd{g}. You can toggle sticky agenda view any time with -@code{org-toggle-sticky-agenda}. +is always up to date. If you often switch between agenda views and the build +time bothers you, you can turn on sticky agenda buffers or make this the +default by customizing the variable @code{org-agenda-sticky}. With sticky +agendas, the agenda dispatcher will not recreate agenda views from scratch, +it will only switch to the selected one, and you need to update the agenda by +hand with @kbd{r} or @kbd{g} when needed. You can toggle sticky agenda view +any time with @code{org-toggle-sticky-agenda}. @end table You can also define custom commands that will be accessible through the @@ -7780,7 +7924,7 @@ possibility to create extended agenda buffers that contain several blocks together, for example the weekly agenda, the global TODO list and a number of special tags matches. @xref{Custom agenda views}. -@node Built-in agenda views, Presentation and sorting, Agenda dispatcher, Agenda Views +@node Built-in agenda views @section The built-in agenda views In this section we describe the built-in views. @@ -7794,7 +7938,7 @@ In this section we describe the built-in views. * Stuck projects:: Find projects you need to review @end menu -@node Weekly/daily agenda, Global TODO list, Built-in agenda views, Built-in agenda views +@node Weekly/daily agenda @subsection The weekly/daily agenda @cindex agenda @cindex weekly agenda @@ -7872,10 +8016,16 @@ the following segment of an Org file will be processed and entries will be made in the agenda: @example -* Birthdays and similar stuff -#+CATEGORY: Holiday +* Holidays + :PROPERTIES: + :CATEGORY: Holiday + :END: %%(org-calendar-holiday) ; special function for holiday names -#+CATEGORY: Ann + +* Birthdays + :PROPERTIES: + :CATEGORY: Ann + :END: %%(org-anniversary 1956 5 14)@footnote{@code{org-anniversary} is just like @code{diary-anniversary}, but the argument order is always according to ISO and therefore independent of the value of @code{calendar-date-style}.} Arthur Dent is %d years old %%(org-anniversary 1869 10 2) Mahatma Gandhi would be %d years old @end example @@ -7919,6 +8069,20 @@ hash with anniversaries. However, from then on things will be very fast---much faster in fact than a long list of @samp{%%(diary-anniversary)} entries in an Org or Diary file. +If you would like to see upcoming anniversaries with a bit of forewarning, +you can use the following instead: + +@example +* Anniversaries + :PROPERTIES: + :CATEGORY: Anniv + :END: +%%(org-bbdb-anniversaries-future 3) +@end example + +That will give you three days' warning: on the anniversary date itself and the +two days prior. The argument is optional: if omitted, it defaults to 7. + @subsubheading Appointment reminders @cindex @file{appt.el} @cindex appointment reminders @@ -7933,7 +8097,7 @@ It also reads a @code{APPT_WARNTIME} property which will then override the value of @code{appt-message-warning-time} for this appointment. See the docstring for details. -@node Global TODO list, Matching tags and properties, Weekly/daily agenda, Built-in agenda views +@node Global TODO list @subsection The global TODO list @cindex global TODO list @cindex TODO list, global @@ -7944,7 +8108,7 @@ collected into a single place. @table @kbd @orgcmd{C-c a t,org-todo-list} Show the global TODO list. This collects the TODO items from all agenda -files (@pxref{Agenda Views}) into a single buffer. By default, this lists +files (@pxref{Agenda views}) into a single buffer. By default, this lists items with a state the is not a DONE state. The buffer is in @code{agenda-mode}, so there are commands to examine and manipulate the TODO entries directly from that buffer (@pxref{Agenda commands}). @@ -7994,7 +8158,7 @@ and omit the sublevels from the global list. Configure the variable @code{org-agenda-todo-list-sublevels} to get this behavior. @end itemize -@node Matching tags and properties, Timeline, Global TODO list, Built-in agenda views +@node Matching tags and properties @subsection Matching tags and properties @cindex matching, of tags @cindex matching, of properties @@ -8002,7 +8166,7 @@ and omit the sublevels from the global list. Configure the variable @cindex match view If headlines in the agenda files are marked with @emph{tags} (@pxref{Tags}), -or have properties (@pxref{Properties and Columns}), you can select headlines +or have properties (@pxref{Properties and columns}), you can select headlines based on this metadata and collect them into an agenda buffer. The match syntax described here also applies when creating sparse trees with @kbd{C-c / m}. @@ -8063,31 +8227,29 @@ braces. For example, @samp{:work:} and any tag @i{starting} with @samp{boss}. @cindex group tags, as regular expressions -Group tags (@pxref{Tag groups}) are expanded as regular expressions. E.g., +Group tags (@pxref{Tag hierarchy}) are expanded as regular expressions. E.g., if @samp{:work:} is a group tag for the group @samp{:work:lab:conf:}, then searching for @samp{work} will search for @samp{@{\(?:work\|lab\|conf\)@}} and searching for @samp{-work} will search for all headlines but those with -one of the tag in the group (i.e., @samp{-@{\(?:work\|lab\|conf\)@}}). +one of the tags in the group (i.e., @samp{-@{\(?:work\|lab\|conf\)@}}). @cindex TODO keyword matching, with tags search @cindex level, require for tags/property match @cindex category, require for tags/property match @vindex org-odd-levels-only -You may also test for properties (@pxref{Properties and Columns}) at the same +You may also test for properties (@pxref{Properties and columns}) at the same time as matching tags. The properties may be real properties, or special properties that represent other metadata (@pxref{Special properties}). For example, the ``property'' @code{TODO} represents the TODO keyword of the entry and the ``property'' @code{PRIORITY} represents the PRIORITY keyword of -the entry. The ITEM special property cannot currently be used in tags/property -searches@footnote{But @pxref{x-agenda-skip-entry-regexp, -,skipping entries based on regexp}.}. +the entry. -Except the @pxref{Special properties}, one other ``property'' can also be -used. @code{LEVEL} represents the level of an entry. So a search -@samp{+LEVEL=3+boss-TODO="DONE"} lists all level three headlines that have -the tag @samp{boss} and are @emph{not} marked with the TODO keyword DONE@. -In buffers with @code{org-odd-levels-only} set, @samp{LEVEL} does not count -the number of stars, but @samp{LEVEL=2} will correspond to 3 stars etc. +In addition to the properties mentioned above, @code{LEVEL} represents the +level of an entry. So a search @samp{+LEVEL=3+boss-TODO="DONE"} lists all +level three headlines that have the tag @samp{boss} and are @emph{not} marked +with the TODO keyword DONE@. In buffers with @code{org-odd-levels-only} set, +@samp{LEVEL} does not count the number of stars, but @samp{LEVEL=2} will +correspond to 3 stars etc. Here are more examples: @@ -8141,11 +8303,6 @@ property that is numerically smaller than 2, a @samp{:With:} property that is matched by the regular expression @samp{Sarah\|Denny}, and that are scheduled on or after October 11, 2008. -Accessing TODO, LEVEL, and CATEGORY during a search is fast. Accessing any -other properties will slow down the search. However, once you have paid the -price by accessing one property, testing additional properties is cheap -again. - You can configure Org mode to use property inheritance during a search, but beware that this can slow down searches considerably. See @ref{Property inheritance}, for details. @@ -8174,7 +8331,7 @@ Select @samp{:work:}-tagged TODO lines that are either @samp{WAITING} or @samp{NEXT}. @end table -@node Timeline, Search view, Matching tags and properties, Built-in agenda views +@node Timeline @subsection Timeline for a single file @cindex timeline, single file @cindex time-sorted view @@ -8194,7 +8351,7 @@ When called with a @kbd{C-u} prefix, all unfinished TODO entries The commands available in the timeline buffer are listed in @ref{Agenda commands}. -@node Search view, Stuck projects, Timeline, Built-in agenda views +@node Search view @subsection Search view @cindex search view @cindex text search @@ -8224,7 +8381,7 @@ the docstring of the command @code{org-search-view}. Note that in addition to the agenda files, this command will also search the files listed in @code{org-agenda-text-search-extra-files}. -@node Stuck projects, , Search view, Built-in agenda views +@node Stuck projects @subsection Stuck projects @pindex GTD, Getting Things Done @@ -8272,7 +8429,7 @@ correct customization for this is Note that if a project is identified as non-stuck, the subtree of this entry will still be searched for stuck projects. -@node Presentation and sorting, Agenda commands, Built-in agenda views, Agenda Views +@node Presentation and sorting @section Presentation and sorting @cindex presentation, of agenda items @@ -8294,21 +8451,14 @@ associated with the item. * Filtering/limiting agenda items:: Dynamically narrow the agenda @end menu -@node Categories, Time-of-day specifications, Presentation and sorting, Presentation and sorting +@node Categories @subsection Categories @cindex category @cindex #+CATEGORY -The category is a broad label assigned to each agenda item. By default, -the category is simply derived from the file name, but you can also -specify it with a special line in the buffer, like this@footnote{For -backward compatibility, the following also works: if there are several -such lines in a file, each specifies the category for the text below it. -The first category also applies to any text before the first CATEGORY -line. However, using this method is @emph{strongly} deprecated as it is -incompatible with the outline structure of the document. The correct -method for setting multiple categories in a buffer is using a -property.}: +The category is a broad label assigned to each agenda item. By default, the +category is simply derived from the file name, but you can also specify it +with a special line in the buffer, like this: @example #+CATEGORY: Thesis @@ -8328,7 +8478,7 @@ longer than 10 characters. You can set up icons for category by customizing the @code{org-agenda-category-icon-alist} variable. -@node Time-of-day specifications, Sorting agenda items, Categories, Presentation and sorting +@node Time-of-day specifications @subsection Time-of-day specifications @cindex time-of-day specification @@ -8379,7 +8529,7 @@ The time grid can be turned on and off with the variable @code{org-agenda-use-time-grid}, and can be configured with @code{org-agenda-time-grid}. -@node Sorting agenda items, Filtering/limiting agenda items, Time-of-day specifications, Presentation and sorting +@node Sorting agenda items @subsection Sorting agenda items @cindex sorting, of agenda items @cindex priorities, of agenda items @@ -8413,14 +8563,14 @@ Sorting can be customized using the variable @code{org-agenda-sorting-strategy}, and may also include criteria based on the estimated effort of an entry (@pxref{Effort estimates}). -@node Filtering/limiting agenda items, , Sorting agenda items, Presentation and sorting +@node Filtering/limiting agenda items @subsection Filtering/limiting agenda items Agenda built-in or customized commands are statically defined. Agenda filters and limits provide two ways of dynamically narrowing down the list of -agenda entries: @emph{fitlers} and @emph{limits}. Filters only act on the +agenda entries: @emph{filters} and @emph{limits}. Filters only act on the display of the items, while limits take effect before the list of agenda -entries is built. Filter are more often used interactively, while limits are +entries is built. Filters are more often used interactively, while limits are mostly useful when defined as local variables within custom agenda commands. @subsubheading Filtering in the agenda @@ -8444,34 +8594,14 @@ refreshes and more secondary filtering. The filter is a global property of the entire agenda view---in a block agenda, you should only set this in the global options section, not in the section of an individual block.} -You will be prompted for a tag selection letter; @key{SPC} will mean any tag at -all. Pressing @key{TAB} at that prompt will offer use completion to select a -tag (including any tags that do not have a selection character). The command -then hides all entries that do not contain or inherit this tag. When called -with prefix arg, remove the entries that @emph{do} have the tag. A second -@kbd{/} at the prompt will turn off the filter and unhide any hidden entries. -If the first key you press is either @kbd{+} or @kbd{-}, the previous filter -will be narrowed by requiring or forbidding the selected additional tag. -Instead of pressing @kbd{+} or @kbd{-} after @kbd{/}, you can also -immediately use the @kbd{\} command. - -@vindex org-sort-agenda-noeffort-is-high -In order to filter for effort estimates, you should set up allowed -efforts globally, for example -@lisp -(setq org-global-properties - '(("Effort_ALL". "0 0:10 0:30 1:00 2:00 3:00 4:00"))) -@end lisp -You can then filter for an effort by first typing an operator, one of -@kbd{<}, @kbd{>}, and @kbd{=}, and then the one-digit index of an effort -estimate in your array of allowed values, where @kbd{0} means the 10th value. -The filter will then restrict to entries with effort smaller-or-equal, equal, -or larger-or-equal than the selected value. If the digits 0--9 are not used -as fast access keys to tags, you can also simply press the index digit -directly without an operator. In this case, @kbd{<} will be assumed. For -application of the operator, entries without a defined effort will be treated -according to the value of @code{org-sort-agenda-noeffort-is-high}. To filter -for tasks without effort definition, press @kbd{?} as the operator. +You will be prompted for a tag selection letter; @key{SPC} will mean any tag +at all. Pressing @key{TAB} at that prompt will offer use completion to +select a tag (including any tags that do not have a selection character). +The command then hides all entries that do not contain or inherit this tag. +When called with prefix arg, remove the entries that @emph{do} have the tag. +A second @kbd{/} at the prompt will turn off the filter and unhide any hidden +entries. Pressing @kbd{+} or @kbd{-} switches between filtering and +excluding the next tag. Org also supports automatic, context-aware tag filtering. If the variable @code{org-agenda-auto-exclude-function} is set to a user-defined function, @@ -8499,12 +8629,6 @@ Internet, and outside of business hours, with something like this: @end group @end smalllisp -@orgcmd{\\,org-agenda-filter-by-tag-refine} -Narrow the current agenda filter by an additional condition. When called with -prefix arg, remove the entries that @emph{do} have the tag, or that do match -the effort criterion. You can achieve the same effect by pressing @kbd{+} or -@kbd{-} as the first key after the @kbd{/} command. - @c @kindex [ @kindex ] @@ -8525,9 +8649,12 @@ selected. @vindex org-agenda-category-filter-preset Filter the current agenda view with respect to the category of the item at -point. Pressing @code{<} another time will remove this filter. You can add -a filter preset through the option @code{org-agenda-category-filter-preset} -(see below.) +point. Pressing @code{<} another time will remove this filter. When called +with a prefix argument exclude the category of the item at point from the +agenda. + +You can add a filter preset in custom agenda commands through the option +@code{org-agenda-category-filter-preset}. @xref{Setting options}. @orgcmd{^,org-agenda-filter-by-top-headline} Filter the current agenda view and only display the siblings and the parent @@ -8540,8 +8667,34 @@ Filter the agenda view by a regular expression: only show agenda entries matching the regular expression the user entered. When called with a prefix argument, it will filter @emph{out} entries matching the regexp. With two universal prefix arguments, it will remove all the regexp filters, which can -be accumulated. You can add a filter preset through the option -@code{org-agenda-category-filter-preset} (see below.) +be accumulated. + +You can add a filter preset in custom agenda commands through the option +@code{org-agenda-regexp-filter-preset}. @xref{Setting options}. + +@orgcmd{_,org-agenda-filter-by-effort} +@vindex org-agenda-effort-filter-preset +@vindex org-sort-agenda-noeffort-is-high +Filter the agenda view with respect to effort estimates. +You first need to set up allowed efforts globally, for example +@lisp +(setq org-global-properties + '(("Effort_ALL". "0 0:10 0:30 1:00 2:00 3:00 4:00"))) +@end lisp +You can then filter for an effort by first typing an operator, one of +@kbd{<}, @kbd{>}, and @kbd{=}, and then the one-digit index of an effort +estimate in your array of allowed values, where @kbd{0} means the 10th value. +The filter will then restrict to entries with effort smaller-or-equal, equal, +or larger-or-equal than the selected value. For application of the operator, +entries without a defined effort will be treated according to the value of +@code{org-sort-agenda-noeffort-is-high}. + +When called with a prefix argument, it will remove entries matching the +condition. With two universal prefix arguments, it will clear effort +filters, which can be accumulated. + +You can add a filter preset in custom agenda commands through the option +@code{org-agenda-effort-filter-preset}. @xref{Setting options}. @orgcmd{|,org-agenda-filter-remove-all} Remove all filters in the current agenda view. @@ -8555,9 +8708,9 @@ Remove all filters in the current agenda view. @vindex org-agenda-max-tags Here is a list of options that you can set, either globally, or locally in -your custom agenda views@pxref{Custom agenda views}. +your custom agenda views (@pxref{Custom agenda views}). -@table @var +@table @code @item org-agenda-max-entries Limit the number of entries. @item org-agenda-max-effort @@ -8570,7 +8723,7 @@ Limit the number of tagged entries. When set to a positive integer, each option will exclude entries from other categories: for example, @code{(setq org-agenda-max-effort 100)} will limit -the agenda to 100 minutes of effort and exclude any entry that as no effort +the agenda to 100 minutes of effort and exclude any entry that has no effort property. If you want to include entries with no effort property, use a negative value for @code{org-agenda-max-effort}. @@ -8588,15 +8741,15 @@ Once you mark one of these five entry as @code{DONE}, rebuilding the agenda will again the next five entries again, including the first entry that was excluded so far. -You can also dynamically set temporary limits@footnote{Those temporary limits -are lost when rebuilding the agenda.}: +You can also dynamically set temporary limits, which will be lost when +rebuilding the agenda: @table @kbd @orgcmd{~,org-agenda-limit-interactively} This prompts for the type of limit to apply and its value. @end table -@node Agenda commands, Custom agenda views, Presentation and sorting, Agenda Views +@node Agenda commands @section Commands in the agenda buffer @cindex commands, in agenda buffer @@ -8617,11 +8770,14 @@ the other commands, the cursor needs to be in the desired line. Next line (same as @key{down} and @kbd{C-n}). @orgcmd{p,org-agenda-previous-line} Previous line (same as @key{up} and @kbd{C-p}). +@orgcmd{N,org-agenda-next-item} +Next item: same as next line, but only consider items. +@orgcmd{P,org-agenda-previous-item} +Previous item: same as previous line, but only consider items. @tsubheading{View/Go to Org file} @orgcmdkkc{@key{SPC},mouse-3,org-agenda-show-and-scroll-up} -Display the original location of the item in another window. -With prefix arg, make sure that the entire entry is made visible in the -outline, not only the heading. +Display the original location of the item in another window. With prefix +arg, make sure that drawers stay folded. @c @orgcmd{L,org-agenda-recenter} Display original location and recenter that window. @@ -8719,6 +8875,7 @@ agenda and timeline views. @c @orgcmd{v a,org-agenda-archives-mode} @xorgcmd{v A,org-agenda-archives-mode 'files} +@cindex Archives mode Toggle Archives mode. In Archives mode, trees that are marked @code{ARCHIVED} are also scanned when producing the agenda. When you use the capital @kbd{A}, even all archive files are included. To exit archives mode, @@ -8789,35 +8946,25 @@ file or subtree (@pxref{Agenda files}). @tsubheading{Secondary filtering and query editing} -For a detailed description of these commands, see @pxref{Filtering/limiting +For a detailed description of these commands, @pxref{Filtering/limiting agenda items}. @orgcmd{/,org-agenda-filter-by-tag} -@vindex org-agenda-tag-filter-preset Filter the agenda view with respect to a tag and/or effort estimates. -@orgcmd{\\,org-agenda-filter-by-tag-refine} -Narrow the current agenda filter by an additional condition. - @orgcmd{<,org-agenda-filter-by-category} -@vindex org-agenda-category-filter-preset - Filter the current agenda view with respect to the category of the item at -point. Pressing @code{<} another time will remove this filter. +point. @orgcmd{^,org-agenda-filter-by-top-headline} Filter the current agenda view and only display the siblings and the parent headline of the one at point. @orgcmd{=,org-agenda-filter-by-regexp} -@vindex org-agenda-regexp-filter-preset +Filter the agenda view by a regular expression. -Filter the agenda view by a regular expression: only show agenda entries -matching the regular expression the user entered. When called with a prefix -argument, it will filter @emph{out} entries matching the regexp. With two -universal prefix arguments, it will remove all the regexp filters, which can -be accumulated. You can add a filter preset through the option -@code{org-agenda-category-filter-preset} (see below.) +@orgcmd{_,org-agenda-filter-by-effort} +Filter the agenda view with respect to effort estimates. @orgcmd{|,org-agenda-filter-remove-all} Remove all filters in the current agenda view. @@ -8996,8 +9143,8 @@ Bulk action: act on all marked entries in the agenda. This will prompt for another key to select the action to be applied. The prefix arg to @kbd{B} will be passed through to the @kbd{s} and @kbd{d} commands, to bulk-remove these special timestamps. By default, marks are removed after the bulk. If -you want them to persist, set @code{org-agenda-bulk-persistent-marks} to -@code{t} or hit @kbd{p} at the prompt. +you want them to persist, set @code{org-agenda-persistent-marks} to @code{t} +or hit @kbd{p} at the prompt. @table @kbd @item * @@ -9124,7 +9271,7 @@ visit Org files will not be removed. @end table -@node Custom agenda views, Exporting Agenda Views, Agenda commands, Agenda Views +@node Custom agenda views @section Custom agenda views @cindex custom agenda views @cindex agenda views, custom @@ -9137,10 +9284,10 @@ dispatcher (@pxref{Agenda dispatcher}), just like the default commands. @menu * Storing searches:: Type once, use often * Block agenda:: All the stuff you need in a single buffer -* Setting Options:: Changing the rules +* Setting options:: Changing the rules @end menu -@node Storing searches, Block agenda, Custom agenda views, Custom agenda views +@node Storing searches @subsection Storing searches The first application of custom searches is the definition of keyboard @@ -9162,7 +9309,7 @@ buffer). Custom commands are configured in the variable @code{org-agenda-custom-commands}. You can customize this variable, for example by pressing @kbd{C-c a C}. You can also directly set it with Emacs -Lisp in @file{.emacs}. The following example contains all valid agenda +Lisp in the Emacs init file. The following example contains all valid agenda views: @lisp @@ -9232,7 +9379,7 @@ Peter, or Kim) as additional tag to match. Note that the @code{*-tree} agenda views need to be called from an Org buffer as they operate on the current buffer only. -@node Block agenda, Setting Options, Storing searches, Custom agenda views +@node Block agenda @subsection Block agenda @cindex block agenda @cindex agenda, with block views @@ -9266,7 +9413,7 @@ your agenda for the current week, all TODO items that carry the tag @samp{home}, and also all lines tagged with @samp{garden}. Finally the command @kbd{C-c a o} provides a similar view for office tasks. -@node Setting Options, , Block agenda, Custom agenda views +@node Setting options @subsection Setting options for custom commands @cindex options, for custom agenda views @@ -9285,8 +9432,7 @@ right spot in @code{org-agenda-custom-commands}. For example: ((org-agenda-sorting-strategy '(priority-down)) (org-agenda-prefix-format " Mixed: "))) ("U" tags-tree "+boss-urgent" - ((org-show-following-heading nil) - (org-show-hierarchy-above nil))) + ((org-show-context-detail 'minimal))) ("N" search "" ((org-agenda-files '("~org/notes.org")) (org-agenda-text-search-extra-files nil))))) @@ -9340,7 +9486,7 @@ yourself. @vindex org-agenda-custom-commands-contexts To control whether an agenda command should be accessible from a specific context, you can customize @code{org-agenda-custom-commands-contexts}. Let's -say for example that you have an agenda commands @code{"o"} displaying a view +say for example that you have an agenda command @code{"o"} displaying a view that you only need when reading emails. Then you would configure this option like this: @@ -9359,8 +9505,8 @@ command key @code{"r"}. In that case, add this command key like this: See the docstring of the variable for more information. -@node Exporting Agenda Views, Agenda column view, Custom agenda views, Agenda Views -@section Exporting Agenda Views +@node Exporting agenda views +@section Exporting agenda views @cindex agenda views, exporting If you are away from your computer, it can be very useful to have a printed @@ -9498,7 +9644,7 @@ processing by other programs. See @ref{Extracting agenda information}, for more information. -@node Agenda column view, , Exporting Agenda Views, Agenda Views +@node Agenda column view @section Using column view in the agenda @cindex column view, in agenda @cindex agenda, column view @@ -9524,11 +9670,12 @@ This causes the following issues: Org needs to make a decision which @code{COLUMNS} format to use. Since the entries in the agenda are collected from different files, and different files may have different @code{COLUMNS} formats, this is a non-trivial problem. -Org first checks if the variable @code{org-agenda-overriding-columns-format} is -currently set, and if so, takes the format from there. Otherwise it takes +Org first checks if the variable @code{org-agenda-overriding-columns-format} +is currently set, and if so, takes the format from there. Otherwise it takes the format associated with the first item in the agenda, or, if that item -does not have a specific format (defined in a property, or in its file), it +does not have a specific format---defined in a property, or in its file---it uses @code{org-columns-default-format}. + @item @cindex property, special, CLOCKSUM If any of the columns has a summary type defined (@pxref{Column attributes}), @@ -9537,11 +9684,12 @@ make sure that the computations of this property are up to date. This is also true for the special @code{CLOCKSUM} property. Org will then sum the values displayed in the agenda. In the daily/weekly agenda, the sums will cover a single day; in all other views they cover the entire block. It is -vital to realize that the agenda may show the same entry @emph{twice} (for -example as scheduled and as a deadline), and it may show two entries from the -same hierarchy (for example a @emph{parent} and its @emph{child}). In these +vital to realize that the agenda may show the same entry @emph{twice}---for +example as scheduled and as a deadline---and it may show two entries from the +same hierarchy---for example a @emph{parent} and its @emph{child}. In these cases, the summation in the agenda will lead to incorrect results because some values will count double. + @item When the column view in the agenda shows the @code{CLOCKSUM}, that is always the entire clocked time for this item. So even in the daily/weekly agenda, @@ -9555,149 +9703,46 @@ the agenda). @item @cindex property, special, CLOCKSUM_T When the column view in the agenda shows the @code{CLOCKSUM_T}, that is -always today's clocked time for this item. So even in the weekly agenda, -the clocksum listed in column view only originates from today. This lets -you compare the time you spent on a task for today, with the time already -spent (via @code{CLOCKSUM}) and with the planned total effort for it. +always today's clocked time for this item. So even in the weekly agenda, the +clocksum listed in column view only originates from today. This lets you +compare the time you spent on a task for today, with the time already +spent ---via @code{CLOCKSUM}---and with the planned total effort for it. @end enumerate -@node Markup, Exporting, Agenda Views, Top +@node Markup @chapter Markup for rich export When exporting Org mode documents, the exporter tries to reflect the structure of the document as accurately as possible in the back-end. Since -export targets like HTML, @LaTeX{} allow much richer formatting, Org mode has +export targets like HTML and @LaTeX{} allow much richer formatting, Org mode has rules on how to prepare text for rich export. This section summarizes the markup rules used in an Org mode buffer. @menu -* Structural markup elements:: The basic structure as seen by the exporter +* Paragraphs:: The basic unit of text +* Emphasis and monospace:: Bold, italic, etc. +* Horizontal rules:: Make a line * Images and tables:: Images, tables and caption mechanism * Literal examples:: Source code examples with special formatting -* Include files:: Include additional files into a document -* Index entries:: Making an index -* Macro replacement:: Use macros to create templates +* Special symbols:: Greek letters and other symbols +* Subscripts and superscripts:: Simple syntax for raising/lowering text * Embedded @LaTeX{}:: LaTeX can be freely used inside Org documents -* Special blocks:: Containers targeted at export back-ends -@end menu - -@node Structural markup elements, Images and tables, Markup, Markup -@section Structural markup elements - -@menu -* Document title:: Where the title is taken from -* Headings and sections:: The document structure as seen by the exporter -* Table of contents:: The if and where of the table of contents -* Lists:: Lists -* Paragraphs:: Paragraphs -* Footnote markup:: Footnotes -* Emphasis and monospace:: Bold, italic, etc. -* Horizontal rules:: Make a line -* Comment lines:: What will *not* be exported @end menu -@node Document title, Headings and sections, Structural markup elements, Structural markup elements -@subheading Document title -@cindex document title, markup rules - -@noindent -The title of the exported document is taken from the special line - -@cindex #+TITLE -@example -#+TITLE: This is the title of the document -@end example - -@noindent -If this line does not exist, the title will be the name of the file -associated to buffer, without extension, or the buffer name. - -@cindex property, EXPORT_TITLE -If you are exporting only a subtree, its heading will become the title of the -document. If the subtree has a property @code{EXPORT_TITLE}, that will take -precedence. - -@node Headings and sections, Table of contents, Document title, Structural markup elements -@subheading Headings and sections -@cindex headings and sections, markup rules - -@vindex org-export-headline-levels -The outline structure of the document as described in @ref{Document -Structure}, forms the basis for defining sections of the exported document. -However, since the outline structure is also used for (for example) lists of -tasks, only the first three outline levels will be used as headings. Deeper -levels will become itemized lists. You can change the location of this -switch globally by setting the variable @code{org-export-headline-levels}, or on a -per-file basis with a line - -@cindex #+OPTIONS -@example -#+OPTIONS: H:4 -@end example - -@node Table of contents, Lists, Headings and sections, Structural markup elements -@subheading Table of contents -@cindex table of contents, markup rules - -@cindex #+TOC -@vindex org-export-with-toc -The table of contents is normally inserted directly before the first headline -of the file. The depth of the table is by default the same as the number of -headline levels, but you can choose a smaller number, or turn off the table -of contents entirely, by configuring the variable @code{org-export-with-toc}, -or on a per-file basis with a line like - -@example -#+OPTIONS: toc:2 (only to two levels in TOC) -#+OPTIONS: toc:nil (no default TOC at all) -@end example - -If you would like to move the table of contents to a different location, you -should turn off the default table using @code{org-export-with-toc} or -@code{#+OPTIONS} and insert @code{#+TOC: headlines N} at the desired -location(s). - -@example -#+OPTIONS: toc:nil (no default TOC) -... -#+TOC: headlines 2 (insert TOC here, with two headline levels) -@end example - -Multiple @code{#+TOC: headline} lines are allowed. The same @code{TOC} -keyword can also generate a list of all tables (resp.@: all listings) with a -caption in the buffer. - -@example -#+TOC: listings (build a list of listings) -#+TOC: tables (build a list of tables) -@end example - -@cindex property, ALT_TITLE -The headline's title usually determines its corresponding entry in a table of -contents. However, it is possible to specify an alternative title by -setting @code{ALT_TITLE} property accordingly. It will then be used when -building the table. - -@node Lists, Paragraphs, Table of contents, Structural markup elements -@subheading Lists -@cindex lists, markup rules - -Plain lists as described in @ref{Plain lists}, are translated to the back-end's -syntax for such lists. Most back-ends support unordered, ordered, and -description lists. - -@node Paragraphs, Footnote markup, Lists, Structural markup elements -@subheading Paragraphs, line breaks, and quoting +@node Paragraphs +@section Paragraphs, line breaks, and quoting @cindex paragraphs, markup rules Paragraphs are separated by at least one empty line. If you need to enforce a line break within a paragraph, use @samp{\\} at the end of a line. -To keep the line breaks in a region, but otherwise use normal formatting, you -can use this construct, which can also be used to format poetry. +To preserve the line breaks, indentation and blank lines in a region, but +otherwise use normal formatting, you can use this construct, which can also +be used to format poetry. @cindex #+BEGIN_VERSE +@cindex verse blocks @example #+BEGIN_VERSE Great clouds overhead @@ -9713,6 +9758,7 @@ as a paragraph that is indented on both the left and the right margin. You can include quotations in Org mode documents like this: @cindex #+BEGIN_QUOTE +@cindex quote blocks @example #+BEGIN_QUOTE Everything should be made as simple as possible, @@ -9722,6 +9768,7 @@ but not any simpler -- Albert Einstein If you would like to center some text, do it like this: @cindex #+BEGIN_CENTER +@cindex center blocks @example #+BEGIN_CENTER Everything should be made as simple as possible, \\ @@ -9729,18 +9776,8 @@ but not any simpler #+END_CENTER @end example - -@node Footnote markup, Emphasis and monospace, Paragraphs, Structural markup elements -@subheading Footnote markup -@cindex footnotes, markup rules -@cindex @file{footnote.el} - -Footnotes defined in the way described in @ref{Footnotes}, will be exported -by all back-ends. Org allows multiple references to the same note, and -multiple footnotes side by side. - -@node Emphasis and monospace, Horizontal rules, Footnote markup, Structural markup elements -@subheading Emphasis and monospace +@node Emphasis and monospace +@section Emphasis and monospace @cindex underlined text, markup rules @cindex bold text, markup rules @@ -9764,32 +9801,13 @@ can tweak @code{org-emphasis-regexp-components}. Beware that changing one of the above variables will no take effect until you reload Org, for which you may need to restart Emacs. -@node Horizontal rules, Comment lines, Emphasis and monospace, Structural markup elements -@subheading Horizontal rules +@node Horizontal rules +@section Horizontal rules @cindex horizontal rules, markup rules A line consisting of only dashes, and at least 5 of them, will be exported as a horizontal line. -@node Comment lines, , Horizontal rules, Structural markup elements -@subheading Comment lines -@cindex comment lines -@cindex exporting, not -@cindex #+BEGIN_COMMENT - -Lines starting with zero or more whitespace characters followed by one -@samp{#} and a whitespace are treated as comments and will never be exported. -Also entire subtrees starting with the word @samp{COMMENT} will never be -exported. Finally, regions surrounded by @samp{#+BEGIN_COMMENT} -... @samp{#+END_COMMENT} will not be exported. - -@table @kbd -@kindex C-c ; -@item C-c ; -Toggle the COMMENT keyword at the beginning of an entry. -@end table - - -@node Images and tables, Literal examples, Structural markup elements, Markup +@node Images and tables @section Images and Tables @cindex tables, markup rules @@ -9837,7 +9855,7 @@ the same caption mechanism can apply to many others (e.g., @LaTeX{} equations, source code blocks). Depending on the export back-end, those may or may not be handled. -@node Literal examples, Include files, Images and tables, Markup +@node Literal examples @section Literal examples @cindex literal examples, markup rules @cindex code line references, markup rules @@ -9865,20 +9883,25 @@ Here is an example @end example @cindex formatting source code, markup rules +@vindex org-latex-listings If the example is source code from a programming language, or any other text that can be marked up by font-lock in Emacs, you can ask for the example to look like the fontified Emacs buffer@footnote{This works automatically for the HTML back-end (it requires version 1.34 of the @file{htmlize.el} package, which is distributed with Org). Fontified code chunks in @LaTeX{} can be -achieved using either the listings or the -@url{http://code.google.com/p/minted, minted,} package. Refer to -@code{org-latex-listings} documentation for details.}. This is done -with the @samp{src} block, where you also need to specify the name of the -major mode that should be used to fontify the example@footnote{Code in -@samp{src} blocks may also be evaluated either interactively or on export. -See @pxref{Working With Source Code} for more information on evaluating code -blocks.}, see @ref{Easy Templates} for shortcuts to easily insert code -blocks. +achieved using either the +@url{https://www.ctan.org/tex-archive/macros/latex/contrib/listings/?lang=en, listings,} +or the +@url{https://github.com/gpoore/minted, minted,} package. +If you use minted or listing, you must load the packages manually, for +example by adding the desired package to +@code{org-latex-packages-alist}. Refer to @code{org-latex-listings} +for details.}. This is done with the @samp{src} block, where you also need +to specify the name of the major mode that should be used to fontify the +example@footnote{Code in @samp{src} blocks may also be evaluated either +interactively or on export. @xref{Working with source code}, for more +information on evaluating code blocks.}, see @ref{Easy templates} for +shortcuts to easily insert code blocks. @cindex #+BEGIN_SRC @example @@ -9891,13 +9914,29 @@ blocks. Both in @code{example} and in @code{src} snippets, you can add a @code{-n} switch to the end of the @code{BEGIN} line, to get the lines of the example -numbered. If you use a @code{+n} switch, the numbering from the previous -numbered snippet will be continued in the current one. In literal examples, -Org will interpret strings like @samp{(ref:name)} as labels, and use them as -targets for special hyperlinks like @code{[[(name)]]} (i.e., the reference name -enclosed in single parenthesis). In HTML, hovering the mouse over such a -link will remote-highlight the corresponding code line, which is kind of -cool. +numbered. The @code{-n} takes an optional numeric argument specifying the +starting line number of the block. If you use a @code{+n} switch, the +numbering from the previous numbered snippet will be continued in the current +one. The @code{+n} can also take a numeric argument. The value of the +argument will be added to the last line of the previous block to determine +the starting line number. + +@example +#+BEGIN_SRC emacs-lisp -n 20 + ;; this will export with line number 20 + (message "This is line 21") +#+END_SRC +#+BEGIN_SRC emacs-lisp +n 10 + ;; This will be listed as line 31 + (message "This is line 32") +#+END_SRC +@end example + +In literal examples, Org will interpret strings like @samp{(ref:name)} as +labels, and use them as targets for special hyperlinks like @code{[[(name)]]} +(i.e., the reference name enclosed in single parenthesis). In HTML, hovering +the mouse over such a link will remote-highlight the corresponding code line, +which is kind of cool. You can also add a @code{-r} switch which @i{removes} the labels from the source code@footnote{Adding @code{-k} to @code{-n -r} will @i{keep} the @@ -9916,6 +9955,10 @@ In line [[(sc)]] we remember the current position. [[(jump)][Line (jump)]] jumps to point-min. @end example +@cindex indentation, in source blocks +Finally, you can use @code{-i} to preserve the indentation of a specific code +block (@pxref{Editing source code}). + @vindex org-coderef-label-format If the syntax for the label format conflicts with the language syntax, use a @code{-l} switch to change the format, for example @samp{#+BEGIN_SRC pascal @@ -9925,8 +9968,8 @@ HTML export also allows examples to be published as text areas (@pxref{Text areas in HTML export}). Because the @code{#+BEGIN_...} and @code{#+END_...} patterns need to be added -so often, shortcuts are provided using the Easy Templates facility -(@pxref{Easy Templates}). +so often, shortcuts are provided using the Easy templates facility +(@pxref{Easy templates}). @table @kbd @kindex C-c ' @@ -9952,157 +9995,44 @@ formatting like @samp{(ref:label)} at the end of the current line. Then the label is stored as a link @samp{(label)}, for retrieval with @kbd{C-c C-l}. @end table - -@node Include files, Index entries, Literal examples, Markup -@section Include files -@cindex include files, markup rules - -During export, you can include the content of another file. For example, to -include your @file{.emacs} file, you could use: -@cindex #+INCLUDE - -@example -#+INCLUDE: "~/.emacs" src emacs-lisp -@end example - -@noindent -The optional second and third parameter are the markup (i.e., @samp{example} -or @samp{src}), and, if the markup is @samp{src}, the language for formatting -the contents. The markup is optional; if it is not given, the text will be -assumed to be in Org mode format and will be processed normally. - -Contents of the included file will belong to the same structure (headline, -item) containing the @code{INCLUDE} keyword. In particular, headlines within -the file will become children of the current section. That behavior can be -changed by providing an additional keyword parameter, @code{:minlevel}. In -that case, all headlines in the included file will be shifted so the one with -the lowest level reaches that specified level. For example, to make a file -become a sibling of the current top-level headline, use - -@example -#+INCLUDE: "~/my-book/chapter2.org" :minlevel 1 -@end example - -You can also include a portion of a file by specifying a lines range using -the @code{:lines} parameter. The line at the upper end of the range will not -be included. The start and/or the end of the range may be omitted to use the -obvious defaults. - -@example -#+INCLUDE: "~/.emacs" :lines "5-10" @r{Include lines 5 to 10, 10 excluded} -#+INCLUDE: "~/.emacs" :lines "-10" @r{Include lines 1 to 10, 10 excluded} -#+INCLUDE: "~/.emacs" :lines "10-" @r{Include lines from 10 to EOF} -@end example - -@table @kbd -@kindex C-c ' -@item C-c ' -Visit the include file at point. -@end table - -@node Index entries, Macro replacement, Include files, Markup -@section Index entries -@cindex index entries, for publishing - -You can specify entries that will be used for generating an index during -publishing. This is done by lines starting with @code{#+INDEX}. An entry -the contains an exclamation mark will create a sub item. See @ref{Generating -an index} for more information. - -@example -* Curriculum Vitae -#+INDEX: CV -#+INDEX: Application!CV -@end example - - - - -@node Macro replacement, Embedded @LaTeX{}, Index entries, Markup -@section Macro replacement -@cindex macro replacement, during export -@cindex #+MACRO - -You can define text snippets with - -@example -#+MACRO: name replacement text $1, $2 are arguments -@end example - -@noindent which can be referenced in -paragraphs, verse blocks, table cells and some keywords with -@code{@{@{@{name(arg1,arg2)@}@}@}}@footnote{Since commas separate arguments, -commas within arguments have to be escaped with a backslash character. -Conversely, backslash characters before a comma, and only them, need to be -escaped with another backslash character.}. In addition to defined macros, -@code{@{@{@{title@}@}@}}, @code{@{@{@{author@}@}@}}, etc., will reference -information set by the @code{#+TITLE:}, @code{#+AUTHOR:}, and similar lines. -Also, @code{@{@{@{time(@var{FORMAT})@}@}@}} and -@code{@{@{@{modification-time(@var{FORMAT})@}@}@}} refer to current date time -and to the modification time of the file being exported, respectively. -@var{FORMAT} should be a format string understood by -@code{format-time-string}. - -Macro expansion takes place during export. - - -@node Embedded @LaTeX{}, Special blocks, Macro replacement, Markup -@section Embedded @LaTeX{} -@cindex @TeX{} interpretation -@cindex @LaTeX{} interpretation - -Plain ASCII is normally sufficient for almost all note taking. Exceptions -include scientific notes, which often require mathematical symbols and the -occasional formula. @LaTeX{}@footnote{@LaTeX{} is a macro system based on -Donald E. Knuth's @TeX{} system. Many of the features described here as -``@LaTeX{}'' are really from @TeX{}, but for simplicity I am blurring this -distinction.} is widely used to typeset scientific documents. Org mode -supports embedding @LaTeX{} code into its files, because many academics are -used to writing and reading @LaTeX{} source code, and because it can be -readily processed to produce pretty output for a number of export back-ends. - -@menu -* Special symbols:: Greek letters and other symbols -* Subscripts and superscripts:: Simple syntax for raising/lowering text -* @LaTeX{} fragments:: Complex formulas made easy -* Previewing @LaTeX{} fragments:: What will this snippet look like? -* CDLaTeX mode:: Speed up entering of formulas -@end menu - -@node Special symbols, Subscripts and superscripts, Embedded @LaTeX{}, Embedded @LaTeX{} -@subsection Special symbols +@node Special symbols +@section Special symbols +@cindex Org entities @cindex math symbols @cindex special symbols -@cindex @TeX{} macros -@cindex @LaTeX{} fragments, markup rules @cindex HTML entities @cindex @LaTeX{} entities -You can use @LaTeX{}-like syntax to insert special symbols like @samp{\alpha} -to indicate the Greek letter, or @samp{\to} to indicate an arrow. Completion -for these symbols is available, just type @samp{\} and maybe a few letters, -and press @kbd{M-@key{TAB}} to see possible completions. Unlike @LaTeX{} -code, Org mode allows these symbols to be present without surrounding math -delimiters, for example: +You can use @LaTeX{}-like syntax to insert special symbols---named +entities---like @samp{\alpha} to indicate the Greek letter, or @samp{\to} to +indicate an arrow. Completion for these symbols is available, just type +@samp{\} and maybe a few letters, and press @kbd{M-@key{TAB}} to see possible +completions. If you need such a symbol inside a word, terminate it with +a pair of curly brackets. For example @example -Angles are written as Greek letters \alpha, \beta and \gamma. +Pro tip: Given a circle \Gamma of diameter d, the length of its circumference +is \pi@{@}d. @end example -@vindex org-entities -During export, these symbols will be transformed into the native format of -the exporter back-end. Strings like @code{\alpha} will be exported as -@code{α} in the HTML output, and as @code{$\alpha$} in the @LaTeX{} -output. Similarly, @code{\nbsp} will become @code{ } in HTML and -@code{~} in @LaTeX{}. If you need such a symbol inside a word, terminate it -like this: @samp{\Aacute@{@}stor}. - +@findex org-entities-help +@vindex org-entities-user A large number of entities is provided, with names taken from both HTML and -@LaTeX{}; see the variable @code{org-entities} for the complete list. -@samp{\-} is treated as a shy hyphen, and @samp{--}, @samp{---}, and -@samp{...} are all converted into special commands creating hyphens of -different lengths or a compact set of dots. +@LaTeX{}; you can comfortably browse the complete list from a dedicated +buffer using the command @code{org-entities-help}. It is also possible to +provide your own special symbols in the variable @code{org-entities-user}. +During export, these symbols are transformed into the native format of the +exporter back-end. Strings like @code{\alpha} are exported as @code{α} +in the HTML output, and as @code{\(\alpha\)} in the @LaTeX{} output. +Similarly, @code{\nbsp} becomes @code{ } in HTML and @code{~} in +@LaTeX{}. + +@cindex escaping characters +Entities may also be used as a may to escape markup in an Org document, e.g., +@samp{\under@{@}not underlined\under} exports as @samp{_not underlined_}. + +@cindex special symbols, in-buffer display If you would like to see entities displayed as UTF-8 characters, use the following command@footnote{You can turn this on by default by setting the variable @code{org-pretty-entities}, or on a per-file base with the @@ -10117,20 +10047,28 @@ buffer content which remains plain ASCII, but it overlays the UTF-8 character for display purposes only. @end table -@node Subscripts and superscripts, @LaTeX{} fragments, Special symbols, Embedded @LaTeX{} -@subsection Subscripts and superscripts +@cindex shy hyphen, special symbol +@cindex dash, special symbol +@cindex ellipsis, special symbol +In addition to regular entities defined above, Org exports in a special +way@footnote{This behaviour can be disabled with @code{-} export setting +(@pxref{Export settings}).} the following commonly used character +combinations: @samp{\-} is treated as a shy hyphen, @samp{--} and @samp{---} +are converted into dashes, and @samp{...} becomes a compact set of dots. + +@node Subscripts and superscripts +@section Subscripts and superscripts @cindex subscript @cindex superscript -Just like in @LaTeX{}, @samp{^} and @samp{_} are used to indicate super- and -subscripts. Again, these can be used without embedding them in math-mode -delimiters. To increase the readability of ASCII text, it is not necessary -(but OK) to surround multi-character sub- and superscripts with curly braces. -For example +@samp{^} and @samp{_} are used to indicate super- and subscripts. To +increase the readability of ASCII text, it is not necessary---but OK---to +surround multi-character sub- and superscripts with curly braces. Those are, +however, mandatory, when more than one word is involved. For example @example -The mass of the sun is M_sun = 1.989 x 10^30 kg. The radius of -the sun is R_@{sun@} = 6.96 x 10^8 m. +The radius of the sun is R_sun = 6.96 x 10^8 m. On the other hand, the +radius of Alpha Centauri is R_@{Alpha Centauri@} = 1.28 x R_@{sun@}. @end example @vindex org-use-sub-superscripts @@ -10147,46 +10085,58 @@ In addition to showing entities as UTF-8 characters, this command will also format sub- and superscripts in a WYSIWYM way. @end table -@node @LaTeX{} fragments, Previewing @LaTeX{} fragments, Subscripts and superscripts, Embedded @LaTeX{} +@node Embedded @LaTeX{} +@section Embedded @LaTeX{} +@cindex @TeX{} interpretation +@cindex @LaTeX{} interpretation + +Plain ASCII is normally sufficient for almost all note taking. Exceptions +include scientific notes, which often require mathematical symbols and the +occasional formula. @LaTeX{}@footnote{@LaTeX{} is a macro system based on +Donald E. Knuth's @TeX{} system. Many of the features described here as +``@LaTeX{}'' are really from @TeX{}, but for simplicity I am blurring this +distinction.} is widely used to typeset scientific documents. Org mode +supports embedding @LaTeX{} code into its files, because many academics are +used to writing and reading @LaTeX{} source code, and because it can be +readily processed to produce pretty output for a number of export back-ends. + +@menu +* @LaTeX{} fragments:: Complex formulas made easy +* Previewing @LaTeX{} fragments:: What will this snippet look like? +* CDLaTeX mode:: Speed up entering of formulas +@end menu + +@node @LaTeX{} fragments @subsection @LaTeX{} fragments @cindex @LaTeX{} fragments @vindex org-format-latex-header -Going beyond symbols and sub- and superscripts, a full formula language is -needed. Org mode can contain @LaTeX{} math fragments, and it supports ways -to process these for several export back-ends. When exporting to @LaTeX{}, -the code is obviously left as it is. When exporting to HTML, Org invokes the -@uref{http://www.mathjax.org, MathJax library} (@pxref{Math formatting in -HTML export}) to process and display the math@footnote{If you plan to use -this regularly or on pages with significant page views, you should install -@file{MathJax} on your own server in order to limit the load of our server.}. -Finally, it can also process the mathematical expressions into -images@footnote{For this to work you need to be on a system with a working -@LaTeX{} installation. You also need the @file{dvipng} program or the -@file{convert}, respectively available at -@url{http://sourceforge.net/projects/dvipng/} and from the @file{imagemagick} -suite. The @LaTeX{} header that will be used when processing a fragment can -be configured with the variable @code{org-format-latex-header}.} that can be -displayed in a browser. +Org mode can contain @LaTeX{} math fragments, and it supports ways to process +these for several export back-ends. When exporting to @LaTeX{}, the code is +left as it is. When exporting to HTML, Org can use either +@uref{http://www.mathjax.org, MathJax} (@pxref{Math formatting in HTML +export}) or transcode the math into images (see @pxref{Previewing @LaTeX{} +fragments}). @LaTeX{} fragments don't need any special marking at all. The following snippets will be identified as @LaTeX{} source code: @itemize @bullet @item -Environments of any kind@footnote{When @file{MathJax} is used, only the -environments recognized by @file{MathJax} will be processed. When -@file{dvipng} program or @file{imagemagick} suite is used to create images, -any @LaTeX{} environment will be handled.}. The only requirement is that the -@code{\begin} and @code{\end} statements appear on a new line, at the +Environments of any kind@footnote{When MathJax is used, only the +environments recognized by MathJax will be processed. When +@file{dvipng} program, @file{dvisvgm} program or @file{imagemagick} suite is +used to create images, any @LaTeX{} environment will be handled.}. The only +requirement is that the @code{\begin} statement appears on a new line, at the beginning of the line or after whitespaces only. @item Text within the usual @LaTeX{} math delimiters. To avoid conflicts with currency specifications, single @samp{$} characters are only recognized as math delimiters if the enclosed text contains at most two line breaks, is directly attached to the @samp{$} characters with no whitespace in between, -and if the closing @samp{$} is followed by whitespace, punctuation or a dash. -For the other delimiters, there is no such restriction, so when in doubt, use -@samp{\(...\)} as inline math delimiters. +and if the closing @samp{$} is followed by whitespace or punctuation +(parentheses and quotes are considered to be punctuation in this +context). For the other delimiters, there is no such restriction, so when in +doubt, use @samp{\(...\)} as inline math delimiters. @end itemize @noindent For example: @@ -10210,7 +10160,7 @@ either $$ a=+\sqrt@{2@} $$ or \[ a=-\sqrt@{2@} \]. @vindex org-export-with-latex @LaTeX{} processing can be configured with the variable @code{org-export-with-latex}. The default setting is @code{t} which means -@file{MathJax} for HTML, and no processing for ASCII and @LaTeX{} back-ends. +MathJax for HTML, and no processing for ASCII and @LaTeX{} back-ends. You can also set this variable on a per-file basis using one of these lines: @@ -10220,16 +10170,26 @@ lines: #+OPTIONS: tex:verbatim @r{Verbatim export, for jsMath or so} @end example -@node Previewing @LaTeX{} fragments, CDLaTeX mode, @LaTeX{} fragments, Embedded @LaTeX{} +@node Previewing @LaTeX{} fragments @subsection Previewing @LaTeX{} fragments @cindex @LaTeX{} fragments, preview -@vindex org-latex-create-formula-image-program -If you have @file{dvipng} or @file{imagemagick} installed@footnote{Choose the -converter by setting the variable -@code{org-latex-create-formula-image-program} accordingly.}, @LaTeX{} -fragments can be processed to produce preview images of the typeset -expressions: +@vindex org-preview-latex-default-process +If you have a working @LaTeX{} installation and @file{dvipng}, @file{dvisvgm} +or @file{convert} installed@footnote{These are respectively available at +@url{http://sourceforge.net/projects/dvipng/}, @url{http://dvisvgm.bplaced.net/} +and from the @file{imagemagick} suite. Choose the converter by setting the +variable @code{org-preview-latex-default-process} accordingly.}, @LaTeX{} +fragments can be processed to produce images of the typeset expressions to be +used for inclusion while exporting to HTML (see @pxref{@LaTeX{} fragments}), +or for inline previewing within Org mode. + +@vindex org-format-latex-options +@vindex org-format-latex-header +You can customize the variables @code{org-format-latex-options} and +@code{org-format-latex-header} to influence some aspects of the preview. In +particular, the @code{:scale} (and for HTML export, @code{:html-scale}) +property of the former can be used to adjust the size of the preview images. @table @kbd @kindex C-c C-x C-l @@ -10245,12 +10205,6 @@ process the entire buffer. Remove the overlay preview images. @end table -@vindex org-format-latex-options -You can customize the variable @code{org-format-latex-options} to influence -some aspects of the preview. In particular, the @code{:scale} (and for HTML -export, @code{:html-scale}) property can be used to adjust the size of the -preview images. - @vindex org-startup-with-latex-preview You can turn on the previewing of all @LaTeX{} fragments in a file with @@ -10264,7 +10218,7 @@ To disable it, simply use #+STARTUP: nolatexpreview @end example -@node CDLaTeX mode, , Previewing @LaTeX{} fragments, Embedded @LaTeX{} +@node CDLaTeX mode @subsection Using CD@LaTeX{} to enter math @cindex CD@LaTeX{} @@ -10325,252 +10279,233 @@ modification will work only inside @LaTeX{} fragments; outside the quote is normal. @end itemize -@node Special blocks, , Embedded @LaTeX{}, Markup -@section Special blocks -@cindex Special blocks +@node Exporting +@chapter Exporting +@cindex exporting -Org syntax includes pre-defined blocks (@pxref{Paragraphs} and @ref{Literal -examples}). It is also possible to create blocks containing raw code -targeted at a specific back-ends (e.g., @samp{#+BEGIN_LATEX}). +Sometimes, you may want to pretty print your notes, publish them on the web +or even share them with people not using Org. In these cases, the Org export +facilities can be used to convert your documents to a variety of other +formats, while retaining as much structure (@pxref{Document structure}) and +markup (@pxref{Markup}) as possible. -Any other block is a @emph{special block}. +@cindex export back-end +Libraries responsible for such translation are called back-ends. Org ships +with the following ones -For example, @samp{#+BEGIN_ABSTRACT} and @samp{#+BEGIN_VIDEO} are special -blocks. The first one is useful when exporting to @LaTeX{}, the second one -when exporting to HTML5. +@itemize +@item ascii (ASCII format) +@item beamer (@LaTeX{} Beamer format) +@item html (HTML format) +@item icalendar (iCalendar format) +@item latex (@LaTeX{} format) +@item md (Markdown format) +@item odt (OpenDocument Text format) +@item org (Org format) +@item texinfo (Texinfo format) +@item man (Man page format) +@end itemize -Each export back-end decides if they should be exported, and how. When the -block is ignored, its contents are still exported, as if the opening and -closing block lines were not there. For example, when exporting a -@samp{#+BEGIN_TEST} block, HTML back-end wraps its contents within a -@samp{<div name="test">} tag. +@noindent Org also uses additional libraries located in @code{contrib/} +directory (@pxref{Installation}). Users can install additional export +libraries for additional formats from the Emacs packaging system. For easy +discovery, these packages have a common naming scheme: @file{ox-NAME}, where +NAME is one of the formats. For example, @file{ox-koma-letter} for +@code{koma-letter} back-end. -Refer to back-end specific documentation for more information. +@vindex org-export-backends +Org loads back-ends for the following formats by default: @code{ascii}, +@code{html}, @code{icalendar}, @code{latex} and @code{odt}. -@node Exporting, Publishing, Markup, Top -@chapter Exporting -@cindex exporting +Org can load additional back-ends either of two ways: through the +@code{org-export-backends} variable configuration; or, by requiring the +library in the Emacs init file like this: -The Org mode export facilities can be used to export Org documents or parts -of Org documents to a variety of other formats. In addition, these -facilities can be used with @code{orgtbl-mode} and/or @code{orgstruct-mode} -in foreign buffers so you can author tables and lists in Org syntax and -convert them in place to the target language. - -ASCII export produces a readable and simple version of an Org file for -printing and sharing notes. HTML export allows you to easily publish notes -on the web, or to build full-fledged websites. @LaTeX{} export lets you use -Org mode and its structured editing functions to create arbitrarily complex -@LaTeX{} files for any kind of document. OpenDocument Text (ODT) export -allows seamless collaboration across organizational boundaries. Markdown -export lets you seamlessly collaborate with other developers. Finally, iCal -export can extract entries with deadlines or appointments to produce a file -in the iCalendar format. +@lisp +(require 'ox-md) +@end lisp @menu -* The Export Dispatcher:: The main exporter interface -* Export back-ends:: Built-in export formats -* Export settings:: Generic export settings +* The export dispatcher:: The main interface +* Export settings:: Common export settings +* Table of contents:: The if and where of the table of contents +* Include files:: Include additional files into a document +* Macro replacement:: Use macros to create templates +* Comment lines:: What will not be exported * ASCII/Latin-1/UTF-8 export:: Exporting to flat files with encoding * Beamer export:: Exporting as a Beamer presentation * HTML export:: Exporting to HTML -* @LaTeX{} and PDF export:: Exporting to @LaTeX{}, and processing to PDF +* @LaTeX{} export:: Exporting to @LaTeX{}, and processing to PDF * Markdown export:: Exporting to Markdown * OpenDocument Text export:: Exporting to OpenDocument Text * Org export:: Exporting to Org * Texinfo export:: Exporting to Texinfo * iCalendar export:: Exporting to iCalendar * Other built-in back-ends:: Exporting to a man page -* Export in foreign buffers:: Author tables and lists in Org syntax * Advanced configuration:: Fine-tuning the export output +* Export in foreign buffers:: Author tables and lists in Org syntax @end menu -@node The Export Dispatcher, Export back-ends, Exporting, Exporting -@section The Export Dispatcher +@node The export dispatcher +@section The export dispatcher @vindex org-export-dispatch-use-expert-ui @cindex Export, dispatcher -The main entry point for export related tasks is the dispatcher, a -hierarchical menu from which it is possible to select an export format and -toggle export options@footnote{It is also possible to use a less intrusive -interface by setting @code{org-export-dispatch-use-expert-ui} to a -non-@code{nil} value. In that case, only a prompt is visible from the -minibuffer. From there one can still switch back to regular menu by pressing -@key{?}.} from which it is possible to select an export format and to toggle -export options. +The export dispatcher is the main interface for Org's exports. A +hierarchical menu presents the currently configured export formats. Options +are shown as easy toggle switches on the same screen. + +Org also has a minimal prompt interface for the export dispatcher. When the +variable @code{org-export-dispatch-use-expert-ui} is set to a non-@code{nil} +value, Org prompts in the minibuffer. To switch back to the hierarchical +menu, press @key{?}. -@c @quotation @table @asis @orgcmd{C-c C-e,org-export-dispatch} -Dispatch for export and publishing commands. When called with a @kbd{C-u} -prefix argument, repeat the last export command on the current buffer while -preserving toggled options. If the current buffer hasn't changed and subtree -export was activated, the command will affect that same subtree. +Invokes the export dispatcher interface. The options show default settings. +The @kbd{C-u} prefix argument preserves options from the previous export, +including any sub-tree selections. + @end table -@c @end quotation -Normally the entire buffer is exported, but if there is an active region -only that part of the buffer will be exported. +Org exports the entire buffer by default. If the Org buffer has an active +region, then Org exports just that region. -Several export options (@pxref{Export settings}) can be toggled from the -export dispatcher with the following key combinations: +These are the export options, the key combinations that toggle them +(@pxref{Export settings}): @table @kbd @item C-a @vindex org-export-async-init-file -Toggle asynchronous export. Asynchronous export uses an external Emacs -process that is configured with a specified initialization file. +Toggles asynchronous export. Asynchronous export uses an external Emacs +process with a specially configured initialization file to complete the +exporting process in the background thereby releasing the current interface. +This is particularly useful when exporting long documents. -While exporting asynchronously, the output is not displayed, but stored in -a place called ``the export stack''. This stack can be displayed by calling -the dispatcher with a double @kbd{C-u} prefix argument, or with @kbd{&} key -from the dispatcher menu. +Output from an asynchronous export is saved on the ``the export stack''. To +view this stack, call the export dispatcher with a double @kbd{C-u} prefix +argument. If already in the export dispatcher menu, @kbd{&} displays the +stack. @vindex org-export-in-background -To make this behavior the default, customize the variable +To make the background export process the default, customize the variable, @code{org-export-in-background}. @item C-b -Toggle body-only export. Its effect depends on the back-end used. -Typically, if the back-end has a header section (like @code{<head>...</head>} -in the HTML back-end), a body-only export will not include this header. +Toggle body-only export. Useful for excluding headers and footers in the +export. Affects only those back-end formats that have such sections---like +@code{<head>...</head>} in HTML. @item C-s @vindex org-export-initial-scope -Toggle subtree export. The top heading becomes the document title. +Toggle sub-tree export. When turned on, Org exports only the sub-tree starting +from the cursor position at the time the export dispatcher was invoked. Org +uses the top heading of this sub-tree as the document's title. If the cursor +is not on a heading, Org uses the nearest enclosing header. If the cursor is +in the document preamble, Org signals an error and aborts export. -You can change the default state of this option by setting +To make the sub-tree export the default, customize the variable, @code{org-export-initial-scope}. @item C-v -Toggle visible-only export. Only export the text that is currently -visible, i.e., not hidden by outline visibility in the buffer. - +Toggle visible-only export. Useful for exporting only visible parts of an +Org document by adjusting outline visibility settings. @end table -@vindex org-export-copy-to-kill-ring -With the exception of asynchronous export, a successful export process writes -its output to the kill-ring. You can configure this behavior by altering the -option @code{org-export-copy-to-kill-ring}. - -@node Export back-ends, Export settings, The Export Dispatcher, Exporting -@section Export back-ends -@cindex Export, back-ends - -An export back-end is a library that translates Org syntax into a foreign -format. An export format is not available until the proper back-end has been -loaded. - -@vindex org-export-backends -By default, the following four back-ends are loaded: @code{ascii}, -@code{html}, @code{icalendar} and @code{latex}. It is possible to add more -(or remove some) by customizing @code{org-export-backends}. - -Built-in back-ends include: - -@itemize -@item ascii (ASCII format) -@item beamer (@LaTeX{} Beamer format) -@item html (HTML format) -@item icalendar (iCalendar format) -@item latex (@LaTeX{} format) -@item man (Man page format) -@item md (Markdown format) -@item odt (OpenDocument Text format) -@item org (Org format) -@item texinfo (Texinfo format) -@end itemize - -Other back-ends might be found in the @code{contrib/} directory -(@pxref{Installation}). - -@node Export settings, ASCII/Latin-1/UTF-8 export, Export back-ends, Exporting +@node Export settings @section Export settings @cindex Export, settings +@cindex #+OPTIONS Export options can be set: globally with variables; for an individual file by making variables buffer-local with in-buffer settings (@pxref{In-buffer settings}), by setting individual keywords, or by specifying them in a compact form with the @code{#+OPTIONS} keyword; or for a tree by setting -properties (@pxref{Properties and Columns}). Options set at a specific level +properties (@pxref{Properties and columns}). Options set at a specific level override options set at a more general level. @cindex #+SETUPFILE In-buffer settings may appear anywhere in the file, either directly or indirectly through a file included using @samp{#+SETUPFILE: filename} syntax. Option keyword sets tailored to a particular back-end can be inserted from -the export dispatcher (@pxref{The Export Dispatcher}) using the @code{Insert +the export dispatcher (@pxref{The export dispatcher}) using the @code{Insert template} command by pressing @key{#}. To insert keywords individually, a good way to make sure the keyword is correct is to type @code{#+} and then -to use @kbd{M-<TAB>} for completion. +to use @kbd{M-@key{TAB}}@footnote{Many desktops intercept @kbd{M-TAB} to +switch windows. Use @kbd{C-M-i} or @kbd{@key{ESC} @key{TAB}} instead.} for +completion. The export keywords available for every back-end, and their equivalent global variables, include: @table @samp @item AUTHOR +@cindex #+AUTHOR @vindex user-full-name The document author (@code{user-full-name}). @item CREATOR +@cindex #+CREATOR @vindex org-export-creator-string Entity responsible for output generation (@code{org-export-creator-string}). @item DATE +@cindex #+DATE @vindex org-export-date-timestamp-format A date or a time-stamp@footnote{The variable @code{org-export-date-timestamp-format} defines how this time-stamp will be exported.}. -@item DESCRIPTION -The document description. Back-ends handle it as they see fit (e.g., for the -XHTML meta tag), if at all. You can use several such keywords for long -descriptions. - @item EMAIL +@cindex #+EMAIL @vindex user-mail-address The email address (@code{user-mail-address}). -@item KEYWORDS -The keywords defining the contents of the document. Back-ends handle it as -they see fit (e.g., for the XHTML meta tag), if at all. You can use several -such keywords if the list is long. - @item LANGUAGE +@cindex #+LANGUAGE @vindex org-export-default-language -The language used for translating some strings -(@code{org-export-default-language}). E.g., @samp{#+LANGUAGE: fr} will tell -Org to translate @emph{File} (english) into @emph{Fichier} (french) in the -clocktable. +Language to use for translating certain strings +(@code{org-export-default-language}). With @samp{#+LANGUAGE: fr}, for +example, Org translates @emph{Table of contents} to the French @emph{Table +des matières}. @item SELECT_TAGS +@cindex #+SELECT_TAGS @vindex org-export-select-tags -The tags that select a tree for export (@code{org-export-select-tags}). The -default value is @code{:export:}. Within a subtree tagged with -@code{:export:}, you can still exclude entries with @code{:noexport:} (see -below). When headlines are selectively exported with @code{:export:} -anywhere in a file, text before the first headline is ignored. +The default value is @code{:export:}. When a tree is tagged with +@code{:export:} (@code{org-export-select-tags}), Org selects that tree and +its sub-trees for export. Org excludes trees with @code{:noexport:} tags, +see below. When selectively exporting files with @code{:export:} tags set, +Org does not export any text that appears before the first headline. @item EXCLUDE_TAGS -The tags that exclude a tree from export (@code{org-export-exclude-tags}). -The default value is @code{:noexport:}. Entries with the @code{:noexport:} -tag will be unconditionally excluded from the export, even if they have an -@code{:export:} tag. +@cindex #+EXCLUDE_TAGS +@vindex org-export-exclude-tags +The default value is @code{:noexport:}. When a tree is tagged with +@code{:noexport:} (@code{org-export-exclude-tags}), Org excludes that tree +and its sub-trees from export. Entries tagged with @code{:noexport:} will be +unconditionally excluded from the export, even if they have an +@code{:export:} tag. Even if a sub-tree is not exported, Org will execute any +code blocks contained in them. @item TITLE -The title to be shown (otherwise derived from buffer's name). You can use -several such keywords for long titles. +@cindex #+TITLE +@cindex document title +Org displays this title. For long titles, use multiple @code{#+TITLE} lines. @end table -The @code{#+OPTIONS} keyword is a compact@footnote{If you want to configure -many options this way, you can use several @code{#+OPTIONS} lines.} form that -recognizes the following arguments: +The @code{#+OPTIONS} keyword is a compact form. To configure multiple +options, use several @code{#+OPTIONS} lines. @code{#+OPTIONS} recognizes the +following arguments. @table @code @item ': @vindex org-export-with-smart-quotes -Toggle smart quotes (@code{org-export-with-smart-quotes}). +Toggle smart quotes (@code{org-export-with-smart-quotes}). Depending on the +language used, when activated, Org treats pairs of double quotes as primary +quotes, pairs of single quotes as secondary quotes, and single quote marks as +apostrophes. @item *: Toggle emphasized text (@code{org-export-with-emphasize}). @@ -10587,12 +10522,12 @@ Toggle fixed-width sections @item <: @vindex org-export-with-timestamps -Toggle inclusion of any time/date active/inactive stamps +Toggle inclusion of time/date active/inactive stamps (@code{org-export-with-timestamps}). -@item : +@item \n: @vindex org-export-preserve-breaks -Toggle line-break-preservation (@code{org-export-preserve-breaks}). +Toggles whether to preserve line breaks (@code{org-export-preserve-breaks}). @item ^: @vindex org-export-with-sub-superscripts @@ -10602,8 +10537,8 @@ it is (@code{org-export-with-sub-superscripts}). @item arch: @vindex org-export-with-archived-trees -Configure export of archived trees. Can be set to @code{headline} to only -process the headline, skipping its contents +Configure how archived trees are exported. When set to @code{headline}, the +export process skips the contents and processes only the headlines (@code{org-export-with-archived-trees}). @item author: @@ -10611,19 +10546,29 @@ process the headline, skipping its contents Toggle inclusion of author name into exported file (@code{org-export-with-author}). +@item broken-links: +@vindex org-export-with-broken-links +Toggles if Org should continue exporting upon finding a broken internal link. +When set to @code{mark}, Org clearly marks the problem link in the output +(@code{org-export-with-broken-links}). + @item c: @vindex org-export-with-clocks Toggle inclusion of CLOCK keywords (@code{org-export-with-clocks}). @item creator: @vindex org-export-with-creator -Configure inclusion of creator info into exported file. It may be set to -@code{comment} (@code{org-export-with-creator}). +Toggle inclusion of creator information in the exported file +(@code{org-export-with-creator}). @item d: @vindex org-export-with-drawers -Toggle inclusion of drawers, or list drawers to include -(@code{org-export-with-drawers}). +Toggles inclusion of drawers, or list of drawers to include, or list of +drawers to exclude (@code{org-export-with-drawers}). + +@item date: +@vindex org-export-with-date +Toggle inclusion of a date into exported file (@code{org-export-with-date}). @item e: @vindex org-export-with-entities @@ -10650,20 +10595,28 @@ Toggle inclusion of inlinetasks (@code{org-export-with-inlinetasks}). @item num: @vindex org-export-with-section-numbers -Toggle section-numbers (@code{org-export-with-section-numbers}). It can also -be set to a number @samp{n}, so only headlines at that level or above will be -numbered. +@cindex property, UNNUMBERED +Toggle section-numbers (@code{org-export-with-section-numbers}). When set to +number @samp{n}, Org numbers only those headlines at level @samp{n} or above. +Set @code{UNNUMBERED} property to non-@code{nil} to disable numbering of +heading and subheadings entirely. @item p: @vindex org-export-with-planning Toggle export of planning information (@code{org-export-with-planning}). -``Planning information'' is the line containing the @code{SCHEDULED:}, the -@code{DEADLINE:} or the @code{CLOSED:} cookies or a combination of them. +``Planning information'' comes from lines located right after the headline +and contain any combination of these cookies: @code{SCHEDULED:}, +@code{DEADLINE:}, or @code{CLOSED:}. @item pri: @vindex org-export-with-priority Toggle inclusion of priority cookies (@code{org-export-with-priority}). +@item prop: +@vindex org-export-with-properties +Toggle inclusion of property drawers, or list the properties to include +(@code{org-export-with-properties}). + @item stat: @vindex org-export-with-statistics-cookies Toggle inclusion of statistics cookies @@ -10676,20 +10629,24 @@ Toggle inclusion of tags, may also be @code{not-in-toc} @item tasks: @vindex org-export-with-tasks -Toggle inclusion of tasks (TODO items), can be @code{nil} to remove all -tasks, @code{todo} to remove DONE tasks, or a list of keywords to keep +Toggle inclusion of tasks (TODO items); or @code{nil} to remove all tasks; or +@code{todo} to remove DONE tasks; or list the keywords to keep (@code{org-export-with-tasks}). @item tex: @vindex org-export-with-latex -Configure export of @LaTeX{} fragments and environments. It may be set to -@code{verbatim} (@code{org-export-with-latex}). +@code{nil} does not export; @code{t} exports; @code{verbatim} keeps +everything in verbatim (@code{org-export-with-latex}). @item timestamp: @vindex org-export-time-stamp-file -Toggle inclusion of the creation time into exported file +Toggle inclusion of the creation time in the exported file (@code{org-export-time-stamp-file}). +@item title: +@vindex org-export-with-title +Toggle inclusion of title (@code{org-export-with-title}). + @item toc: @vindex org-export-with-toc Toggle inclusion of the table of contents, or set the level limit @@ -10703,255 +10660,589 @@ Toggle inclusion of TODO keywords into exported text @item |: @vindex org-export-with-tables Toggle inclusion of tables (@code{org-export-with-tables}). + @end table -When exporting only a subtree, each of the previous keywords@footnote{With -the exception of @samp{SETUPFILE}.} can be overridden locally by special node -properties. These begin with @samp{EXPORT_}, followed by the name of the -keyword they supplant. For example, @samp{DATE} and @samp{OPTIONS} keywords -become, respectively, @samp{EXPORT_DATE} and @samp{EXPORT_OPTIONS} -properties. +When exporting sub-trees, special node properties in them can override the +above keywords. They are special because they have an @samp{EXPORT_} prefix. +For example, @samp{DATE} and @samp{OPTIONS} keywords become, respectively, +@samp{EXPORT_DATE} and @samp{EXPORT_OPTIONS}. Except for @samp{SETUPFILE}, +all other keywords listed above have an @samp{EXPORT_} equivalent. @cindex #+BIND @vindex org-export-allow-bind-keywords If @code{org-export-allow-bind-keywords} is non-@code{nil}, Emacs variables can become buffer-local during export by using the BIND keyword. Its syntax is @samp{#+BIND: variable value}. This is particularly useful for in-buffer -settings that cannot be changed using specific keywords. +settings that cannot be changed using keywords. @cindex property, EXPORT_FILE_NAME -The name of the output file to be generated is taken from the file associated -to the buffer, when possible, or asked to you otherwise. For subtree export, -you can also set @samp{EXPORT_FILE_NAME} property. In all cases, only the -base name of the file is retained, and a back-end specific extension is -added. +Normally Org generates the file name based on the buffer name and the +extension based on the back-end format. For sub-trees, Org can export to a +file name as specified in the @code{EXPORT_FILE_NAME} property. + +@node Table of contents +@section Table of contents +@cindex table of contents +@cindex list of tables +@cindex list of listings + +@cindex #+TOC +@vindex org-export-with-toc +Org normally inserts the table of contents directly before the first headline +of the file. Org sets the TOC depth the same as the headline levels in the +file. Use a lower number for lower TOC depth. To turn off TOC entirely, use +@code{nil}. This is configured in the @code{org-export-with-toc} variable or +as keywords in an Org file as: + +@example +#+OPTIONS: toc:2 @r{only include two levels in TOC} +#+OPTIONS: toc:nil @r{no default TOC at all} +@end example + +To move the table of contents to a different location, first turn off the +default with @code{org-export-with-toc} variable or with @code{#+OPTIONS: +toc:nil}. Then insert @code{#+TOC: headlines N} at the desired location(s). + +@example +#+OPTIONS: toc:nil @r{no default TOC} +... +#+TOC: headlines 2 @r{insert TOC here, with two headline levels} +@end example + +To adjust the TOC depth for a specific section of the Org document, append an +additional @samp{local} parameter. This parameter becomes a relative depth +for the current level. + +Note that for this feature to work properly in @LaTeX{} export, the Org file +requires the inclusion of the @code{titletoc} package. Because of +compatibility issues, @code{titletoc} has to be loaded @emph{before} +@code{hyperref}. Customize the @code{org-latex-default-packages-alist} +variable. + +@example +* Section #+TOC: headlines 1 local @r{insert local TOC, with direct children +only} +@end example + +Use the @code{TOC} keyword to generate list of tables (resp.@: all listings) +with captions. + +@example +#+TOC: listings @r{build a list of listings} +#+TOC: tables @r{build a list of tables} +@end example + +@cindex property, ALT_TITLE +Normally Org uses the headline for its entry in the table of contents. But +with @code{ALT_TITLE} property, a different entry can be specified for the +table of contents. + +@node Include files +@section Include files +@cindex include files, during export +Include other files during export. For example, to include your @file{.emacs} +file, you could use: +@cindex #+INCLUDE + +@example +#+INCLUDE: "~/.emacs" src emacs-lisp +@end example + +@noindent +The first parameter is the file name to include. The optional second +parameter specifies the block type: @samp{example}, @samp{export} or +@samp{src}. The optional third parameter specifies the source code language +to use for formatting the contents. This is relevant to both @samp{export} +and @samp{src} block types. + +If an include file is specified as having a markup language, Org neither +checks for valid syntax nor changes the contents in any way. For +@samp{example} and @samp{src} blocks, Org code-escapes the contents before +inclusion. + +If an include file is not specified as having any markup language, Org +assumes it be in Org format and proceeds as usual with a few exceptions. Org +makes the footnote labels (@pxref{Footnotes}) in the included file local to +that file. The contents of the included file will belong to the same +structure---headline, item---containing the @code{INCLUDE} keyword. In +particular, headlines within the file will become children of the current +section. That behavior can be changed by providing an additional keyword +parameter, @code{:minlevel}. It shifts the headlines in the included file to +become the lowest level. For example, this syntax makes the included file +a sibling of the current top-level headline: + +@example +#+INCLUDE: "~/my-book/chapter2.org" :minlevel 1 +@end example + +Inclusion of only portions of files are specified using ranges parameter with +@code{:lines} keyword. The line at the upper end of the range will not be +included. The start and/or the end of the range may be omitted to use the +obvious defaults. + +@example +#+INCLUDE: "~/.emacs" :lines "5-10" @r{Include lines 5 to 10, 10 excluded} +#+INCLUDE: "~/.emacs" :lines "-10" @r{Include lines 1 to 10, 10 excluded} +#+INCLUDE: "~/.emacs" :lines "10-" @r{Include lines from 10 to EOF} +@end example + +Inclusions may specify a file-link to extract an object matched by +@code{org-link-search}@footnote{Note that +@code{org-link-search-must-match-exact-headline} is locally bound to +non-@code{nil}. Therefore, @code{org-link-search} only matches headlines and +named elements.} (@pxref{Search options}). + +To extract only the contents of the matched object, set @code{:only-contents} +property to non-@code{nil}. This will omit any planning lines or property +drawers. The ranges for @code{:lines} keyword are relative to the requested +element. Some examples: + +@example +#+INCLUDE: "./paper.org::#theory" :only-contents t + @r{Include the body of the heading with the custom id @samp{theory}} +#+INCLUDE: "./paper.org::mytable" @r{Include named element.} +#+INCLUDE: "./paper.org::*conclusion" :lines 1-20 + @r{Include the first 20 lines of the headline named @samp{conclusion}.} +@end example + +@table @kbd +@kindex C-c ' +@item C-c ' +Visit the include file at point. +@end table + +@node Macro replacement +@section Macro replacement +@cindex macro replacement, during export +@cindex #+MACRO + +Macros replace text snippets during export. This is a macro definition in +Org: + +@example +#+MACRO: name replacement text $1, $2 are arguments +@end example + +@noindent which can be referenced using +@code{@{@{@{name(arg1, arg2)@}@}@}}@footnote{Since commas separate the +arguments, commas within arguments have to be escaped with the backslash +character. So only those backslash characters before a comma need escaping +with another backslash character.}. + +Org recognizes macro references in following Org markup areas: paragraphs, +headlines, verse blocks, tables cells and lists. Org also recognizes macro +references in keywords, such as @code{#+CAPTION}, @code{#+TITLE}, +@code{#+AUTHOR}, @code{#+DATE}, and for some back-end specific export +options. + +Org comes with following pre-defined macros: + +@table @code +@item @{@{@{title@}@}@} +@itemx @{@{@{author@}@}@} +@itemx @{@{@{email@}@}@} +@cindex title, macro +@cindex author, macro +@cindex email, macro +Org replaces these macro references with available information at the time of +export. + +@item @{@{@{date@}@}@} +@itemx @{@{@{date(@var{FORMAT})@}@}@} +@cindex date, macro +This macro refers to the @code{#+DATE} keyword. @var{FORMAT} is an optional +argument to the @code{@{@{@{date@}@}@}} macro that will be used only if +@code{#+DATE} is a single timestamp. @var{FORMAT} should be a format string +understood by @code{format-time-string}. + +@item @{@{@{time(@var{FORMAT})@}@}@} +@itemx @{@{@{modification-time(@var{FORMAT}, @var{VC})@}@}@} +@cindex time, macro +@cindex modification time, macro +These macros refer to the document's date and time of export and date and +time of modification. @var{FORMAT} is a string understood by +@code{format-time-string}. If the second argument to the +@code{modification-time} macro is non-@code{nil}, Org uses @file{vc.el} to +retrieve the document's modification time from the version control +system. Otherwise Org reads the file attributes. + +@item @{@{@{input-file@}@}@} +@cindex input file, macro +This macro refers to the filename of the exported file. + +@item @{@{@{property(@var{PROPERTY-NAME})@}@}@} +@itemx @{@{@{property(@var{PROPERTY-NAME},@var{SEARCH-OPTION})@}@}@} +@cindex property, macro +This macro returns the value of property @var{PROPERTY-NAME} in the current +entry. If @var{SEARCH-OPTION} (@pxref{Search options}) refers to a remote +entry, that will be used instead. +@end table + +The surrounding brackets can be made invisible by setting +@code{org-hide-macro-markers} non-@code{nil}. + +Org expands macros at the very beginning of the export process. + +@node Comment lines +@section Comment lines +@cindex exporting, not -@node ASCII/Latin-1/UTF-8 export, Beamer export, Export settings, Exporting +@cindex comment lines +Lines starting with zero or more whitespace characters followed by one +@samp{#} and a whitespace are treated as comments and, as such, are not +exported. + +@cindex #+BEGIN_COMMENT +Likewise, regions surrounded by @samp{#+BEGIN_COMMENT} +... @samp{#+END_COMMENT} are not exported. + +@cindex comment trees +Finally, a @samp{COMMENT} keyword at the beginning of an entry, but after any +other keyword or priority cookie, comments out the entire subtree. In this +case, the subtree is not exported and no code block within it is executed +either@footnote{For a less drastic behavior, consider using a select tag +(@pxref{Export settings}) instead.}. The command below helps changing the +comment status of a headline. + +@table @kbd +@kindex C-c ; +@item C-c ; +Toggle the @samp{COMMENT} keyword at the beginning of an entry. +@end table + +@node ASCII/Latin-1/UTF-8 export @section ASCII/Latin-1/UTF-8 export @cindex ASCII export @cindex Latin-1 export @cindex UTF-8 export -ASCII export produces a simple and very readable version of an Org mode -file, containing only plain ASCII@. Latin-1 and UTF-8 export augment the file -with special characters and symbols available in these encodings. +ASCII export produces an output file containing only plain ASCII characters. +This is the most simplest and direct text output. It does not contain any +Org markup either. Latin-1 and UTF-8 export use additional characters and +symbols available in these encoding standards. All three of these export +formats offer the most basic of text output for maximum portability. + +@vindex org-ascii-text-width +On export, Org fills and justifies text according to the text width set in +@code{org-ascii-text-width}. @vindex org-ascii-links-to-notes -Links are exported in a footnote-like style, with the descriptive part in the -text and the link in a note before the next heading. See the variable -@code{org-ascii-links-to-notes} for details and other options. +Org exports links using a footnote-like style where the descriptive part is +in the text and the link is in a note before the next heading. See the +variable @code{org-ascii-links-to-notes} for details. @subheading ASCII export commands @table @kbd @orgcmd{C-c C-e t a/l/u,org-ascii-export-to-ascii} -Export as an ASCII file. For an Org file, @file{myfile.org}, the ASCII file -will be @file{myfile.txt}. The file will be overwritten without warning. -When the original file is @file{myfile.txt}, the resulting file becomes -@file{myfile.txt.txt} in order to prevent data loss. +Export as an ASCII file with a @file{.txt} extension. For @file{myfile.org}, +Org exports to @file{myfile.txt}, overwriting without warning. For +@file{myfile.txt}, Org exports to @file{myfile.txt.txt} in order to prevent +data loss. @orgcmd{C-c C-e t A/L/U,org-ascii-export-as-ascii} -Export to a temporary buffer. Do not create a file. +Export to a temporary buffer. Does not create a file. +@end table + +@subheading ASCII specific export settings +The ASCII export back-end has one extra keyword for customizing ASCII output. +Setting this keyword works similar to the general options (@pxref{Export +settings}). + +@table @samp +@item SUBTITLE +@cindex #+SUBTITLE (ASCII) +The document subtitle. For long subtitles, use multiple @code{#+SUBTITLE} +lines in the Org file. Org prints them on one continuous line, wrapping into +multiple lines if necessary. @end table @subheading Header and sectioning structure -In the exported version, the first three outline levels become headlines, -defining a general document structure. Additional levels are exported as -lists. The transition can also occur at a different level (@pxref{Export -settings}). +Org converts the first three outline levels into headlines for ASCII export. +The remaining levels are turned into lists. To change this cut-off point +where levels become lists, @pxref{Export settings}. @subheading Quoting ASCII text -You can insert text that will only appear when using @code{ASCII} back-end -with the following constructs: +To insert text within the Org file by the ASCII back-end, use one the +following constructs, inline, keyword, or export block: @cindex #+ASCII -@cindex #+BEGIN_ASCII +@cindex #+BEGIN_EXPORT ascii @example -Text @@@@ascii:and additional text@@@@ within a paragraph. +Inline text @@@@ascii:and additional text@@@@ within a paragraph. #+ASCII: Some text -#+BEGIN_ASCII -All lines in this block will appear only when using this back-end. -#+END_ASCII +#+BEGIN_EXPORT ascii +Org exports text in this block only when using ASCII back-end. +#+END_EXPORT @end example @subheading ASCII specific attributes @cindex #+ATTR_ASCII @cindex horizontal rules, in ASCII export -@code{ASCII} back-end only understands one attribute, @code{:width}, which -specifies the length, in characters, of a given horizontal rule. It must be -specified using an @code{ATTR_ASCII} line, directly preceding the rule. +ASCII back-end recognizes only one attribute, @code{:width}, which specifies +the width of an horizontal rule in number of characters. The keyword and +syntax for specifying widths is: @example #+ATTR_ASCII: :width 10 ----- @end example -@node Beamer export, HTML export, ASCII/Latin-1/UTF-8 export, Exporting +@subheading ASCII special blocks +@cindex special blocks, in ASCII export +@cindex #+BEGIN_JUSTIFYLEFT +@cindex #+BEGIN_JUSTIFYRIGHT + +Besides @code{#+BEGIN_CENTER} blocks (@pxref{Paragraphs}), ASCII back-end has +these two left and right justification blocks: + +@example +#+BEGIN_JUSTIFYLEFT +It's just a jump to the left... +#+END_JUSTIFYLEFT + +#+BEGIN_JUSTIFYRIGHT +...and then a step to the right. +#+END_JUSTIFYRIGHT +@end example + +@node Beamer export @section Beamer export @cindex Beamer export -The @LaTeX{} class @emph{Beamer} allows production of high quality -presentations using @LaTeX{} and pdf processing. Org mode has special -support for turning an Org mode file or tree into a Beamer presentation. +Org uses @emph{Beamer} export to convert an Org file tree structure into a +high-quality interactive slides for presentations. @emph{Beamer} is a +@LaTeX{} document class for creating presentations in PDF, HTML, and other +popular display formats. + +@menu +* Beamer export commands:: For creating Beamer documents. +* Beamer specific export settings:: For customizing Beamer export. +* Sectioning Frames and Blocks in Beamer:: For composing Beamer slides. +* Beamer specific syntax:: For using in Org documents. +* Editing support:: For using helper functions. +* A Beamer example:: A complete presentation. +@end menu -@subheading Beamer export commands +@node Beamer export commands +@subsection Beamer export commands @table @kbd @orgcmd{C-c C-e l b,org-beamer-export-to-latex} -Export as a @LaTeX{} file. For an Org file @file{myfile.org}, the @LaTeX{} -file will be @file{myfile.tex}. The file will be overwritten without -warning. +Export as @LaTeX{} file with a @file{.tex} extension. For @file{myfile.org}, +Org exports to @file{myfile.tex}, overwriting without warning. @orgcmd{C-c C-e l B,org-beamer-export-as-latex} -Export to a temporary buffer. Do not create a file. +Export to a temporary buffer. Does not create a file. @orgcmd{C-c C-e l P,org-beamer-export-to-pdf} -Export as @LaTeX{} and then process to PDF. +Export as @LaTeX{} file and then convert it to PDF format. @item C-c C-e l O -Export as @LaTeX{} and then process to PDF, then open the resulting PDF file. +Export as @LaTeX{} file, convert it to PDF format, and then open the PDF +file. @end table -@subheading Sectioning, Frames and Blocks +@node Beamer specific export settings +@subsection Beamer specific export settings + +Beamer export back-end has several additional keywords for customizing Beamer +output. These keywords work similar to the general options settings +(@pxref{Export settings}). + +@table @samp +@item BEAMER_THEME +@cindex #+BEAMER_THEME +@vindex org-beamer-theme +The Beamer layout theme (@code{org-beamer-theme}). Use square brackets for +options. For example: +@smallexample +#+BEAMER_THEME: Rochester [height=20pt] +@end smallexample + +@item BEAMER_FONT_THEME +@cindex #+BEAMER_FONT_THEME +The Beamer font theme. + +@item BEAMER_INNER_THEME +@cindex #+BEAMER_INNER_THEME +The Beamer inner theme. + +@item BEAMER_OUTER_THEME +@cindex #+BEAMER_OUTER_THEME +The Beamer outer theme. -Any tree with not-too-deep level nesting should in principle be exportable as -a Beamer presentation. Headlines fall into three categories: sectioning -elements, frames and blocks. +@item BEAMER_HEADER +@cindex #+BEAMER_HEADER +Arbitrary lines inserted in the preamble, just before the @samp{hyperref} +settings. + +@item DESCRIPTION +@cindex #+DESCRIPTION (Beamer) +The document description. For long descriptions, use multiple +@code{#+DESCRIPTION} keywords. By default, @samp{hyperref} inserts +@code{#+DESCRIPTION} as metadata. Use @code{org-latex-hyperref-template} to +configure document metadata. Use @code{org-latex-title-command} to configure +typesetting of description as part of front matter. + +@item KEYWORDS +@cindex #+KEYWORDS (Beamer) +The keywords for defining the contents of the document. Use multiple +@code{#+KEYWORDS} lines if necessary. By default, @samp{hyperref} inserts +@code{#+KEYWORDS} as metadata. Use @code{org-latex-hyperref-template} to +configure document metadata. Use @code{org-latex-title-command} to configure +typesetting of keywords as part of front matter. + +@item SUBTITLE +@cindex #+SUBTITLE (Beamer) +@vindex org-beamer-subtitle-format +Document's subtitle. For typesetting, use @code{org-beamer-subtitle-format} +string. Use @code{org-latex-hyperref-template} to configure document +metadata. Use @code{org-latex-title-command} to configure typesetting of +subtitle as part of front matter. +@end table + +@node Sectioning Frames and Blocks in Beamer +@subsection Sectioning, Frames and Blocks in Beamer + +Org transforms heading levels into Beamer's sectioning elements, frames and +blocks. Any Org tree with a not-too-deep-level nesting should in principle +be exportable as a Beamer presentation. @itemize @minus @item @vindex org-beamer-frame-level -Headlines become frames when their level is equal to +Org headlines become Beamer frames when the heading level in Org is equal to @code{org-beamer-frame-level} or @code{H} value in an @code{OPTIONS} line (@pxref{Export settings}). @cindex property, BEAMER_ENV -Though, if a headline in the current tree has a @code{BEAMER_ENV} property -set to either to @code{frame} or @code{fullframe}, its level overrides the -variable. A @code{fullframe} is a frame with an empty (ignored) title. +Org overrides headlines to frames conversion for the current tree of an Org +file if it encounters the @code{BEAMER_ENV} property set to @code{frame} or +@code{fullframe}. Org ignores whatever @code{org-beamer-frame-level} happens +to be for that headline level in the Org tree. In Beamer terminology, a +@code{fullframe} is a frame without its title. @item @vindex org-beamer-environments-default @vindex org-beamer-environments-extra -All frame's children become @code{block} environments. Special block types -can be enforced by setting headline's @code{BEAMER_ENV} property@footnote{If -this property is set, the entry will also get a @code{:B_environment:} tag to -make this visible. This tag has no semantic meaning, it is only a visual -aid.} to an appropriate value (see @code{org-beamer-environments-default} for -supported values and @code{org-beamer-environments-extra} for adding more). +Org exports a Beamer frame's objects as @code{block} environments. Org can +enforce wrapping in special block types when @code{BEAMER_ENV} property is +set@footnote{If @code{BEAMER_ENV} is set, Org export adds +@code{:B_environment:} tag to make it visible. The tag serves as a visual +aid and has no semantic relevance.}. For valid values see +@code{org-beamer-environments-default}. To add more values, see +@code{org-beamer-environments-extra}. @item @cindex property, BEAMER_REF -As a special case, if the @code{BEAMER_ENV} property is set to either -@code{appendix}, @code{note}, @code{noteNH} or @code{againframe}, the -headline will become, respectively, an appendix, a note (within frame or -between frame, depending on its level), a note with its title ignored or an -@code{\againframe} command. In the latter case, a @code{BEAMER_REF} property -is mandatory in order to refer to the frame being resumed, and contents are -ignored. - -Also, a headline with an @code{ignoreheading} environment will have its -contents only inserted in the output. This special value is useful to have -data between frames, or to properly close a @code{column} environment. +If @code{BEAMER_ENV} is set to @code{appendix}, Org exports the entry as an +appendix. When set to @code{note}, Org exports the entry as a note within +the frame or between frames, depending on the entry's heading level. When +set to @code{noteNH}, Org exports the entry as a note without its title. +When set to @code{againframe}, Org exports the entry with @code{\againframe} +command, which makes setting the @code{BEAMER_REF} property mandatory because +@code{\againframe} needs frame to resume. + +When @code{ignoreheading} is set, Org export ignores the entry's headline but +not its content. This is useful for inserting content between frames. It is +also useful for properly closing a @code{column} environment. @end itemize @cindex property, BEAMER_ACT @cindex property, BEAMER_OPT -Headlines also support @code{BEAMER_ACT} and @code{BEAMER_OPT} properties. -The former is translated as an overlay/action specification, or a default -overlay specification when enclosed within square brackets. The latter -specifies options@footnote{The @code{fragile} option is added automatically -if it contains code that requires a verbatim environment, though.} for the -current frame or block. The export back-end will automatically wrap -properties within angular or square brackets when appropriate. +When @code{BEAMER_ACT} is set for a headline, Org export translates that +headline as an overlay or action specification. When enclosed in square +brackets, Org export makes the overlay specification a default. Use +@code{BEAMER_OPT} to set any options applicable to the current Beamer frame +or block. The Beamer export back-end wraps with appropriate angular or +square brackets. It also adds the @code{fragile} option for any code that may +require a verbatim block. @cindex property, BEAMER_COL -Moreover, headlines handle the @code{BEAMER_COL} property. Its value should -be a decimal number representing the width of the column as a fraction of the -total text width. If the headline has no specific environment, its title -will be ignored and its contents will fill the column created. Otherwise, -the block will fill the whole column and the title will be preserved. Two -contiguous headlines with a non-@code{nil} @code{BEAMER_COL} value share the same -@code{columns} @LaTeX{} environment. It will end before the next headline -without such a property. This environment is generated automatically. -Although, it can also be explicitly created, with a special @code{columns} -value for @code{BEAMER_ENV} property (if it needs to be set up with some -specific options, for example). - -@subheading Beamer specific syntax - -Beamer back-end is an extension of @LaTeX{} back-end. As such, all @LaTeX{} -specific syntax (e.g., @samp{#+LATEX:} or @samp{#+ATTR_LATEX:}) is -recognized. See @ref{@LaTeX{} and PDF export} for more information. - -@cindex #+BEAMER_THEME -@cindex #+BEAMER_COLOR_THEME -@cindex #+BEAMER_FONT_THEME -@cindex #+BEAMER_INNER_THEME -@cindex #+BEAMER_OUTER_THEME -Beamer export introduces a number of keywords to insert code in the -document's header. Four control appearance of the presentation: -@code{#+BEAMER_THEME}, @code{#+BEAMER_COLOR_THEME}, -@code{#+BEAMER_FONT_THEME}, @code{#+BEAMER_INNER_THEME} and -@code{#+BEAMER_OUTER_THEME}. All of them accept optional arguments -within square brackets. The last one, @code{#+BEAMER_HEADER}, is more -generic and allows you to append any line of code in the header. - -@example -#+BEAMER_THEME: Rochester [height=20pt] -#+BEAMER_COLOR_THEME: spruce -@end example - -Table of contents generated from @code{toc:t} @code{OPTION} keyword are -wrapped within a @code{frame} environment. Those generated from a @code{TOC} -keyword (@pxref{Table of contents}) are not. In that case, it is also -possible to specify options, enclosed within square brackets. +To create a column on the Beamer slide, use the @code{BEAMER_COL} property +for its headline in the Org file. Set the value of @code{BEAMER_COL} to a +decimal number representing the fraction of the total text width. Beamer +export uses this value to set the column's width and fills the column with +the contents of the Org entry. If the Org entry has no specific environment +defined, Beamer export ignores the heading. If the Org entry has a defined +environment, Beamer export uses the heading as title. Behind the scenes, +Beamer export automatically handles @LaTeX{} column separations for +contiguous headlines. To manually adjust them for any unique configurations +needs, use the @code{BEAMER_ENV} property. + +@node Beamer specific syntax +@subsection Beamer specific syntax +Since Org's Beamer export back-end is an extension of the @LaTeX{} back-end, +it recognizes other @LaTeX{} specific syntax---for example, @samp{#+LATEX:} +or @samp{#+ATTR_LATEX:}. @xref{@LaTeX{} export}, for details. + +Beamer export wraps the table of contents generated with @code{toc:t} +@code{OPTION} keyword in a @code{frame} environment. Beamer export does not +wrap the table of contents generated with @code{TOC} keyword (@pxref{Table of +contents}). Use square brackets for specifying options. @example #+TOC: headlines [currentsection] @end example -Beamer specific code can be inserted with the following constructs: +Insert Beamer-specific code using the following constructs: @cindex #+BEAMER -@cindex #+BEGIN_BEAMER +@cindex #+BEGIN_EXPORT beamer @example #+BEAMER: \pause -#+BEGIN_BEAMER -All lines in this block will appear only when using this back-end. +#+BEGIN_EXPORT beamer +Only Beamer export back-end will export this line. #+END_BEAMER Text @@@@beamer:some code@@@@ within a paragraph. @end example -In particular, this last example can be used to add overlay specifications to -objects whose type is among @code{bold}, @code{item}, @code{link}, -@code{radio-target} and @code{target}, when the value is enclosed within -angular brackets and put at the beginning the object. +Inline constructs, such as the last one above, are useful for adding overlay +specifications to objects with @code{bold}, @code{item}, @code{link}, +@code{radio-target} and @code{target} types. Enclose the value in angular +brackets and place the specification at the beginning the object as shown in +this example: @example A *@@@@beamer:<2->@@@@useful* feature @end example @cindex #+ATTR_BEAMER -Eventually, every plain list has support for @code{:environment}, -@code{:overlay} and @code{:options} attributes through -@code{ATTR_BEAMER} affiliated keyword. The first one allows the use -of a different environment, the second sets overlay specifications and -the last one inserts optional arguments in current list environment. +Beamer export recognizes the @code{ATTR_BEAMER} keyword with the following +attributes from Beamer configurations: @code{:environment} for changing local +Beamer environment, @code{:overlay} for specifying Beamer overlays in angular +or square brackets, and @code{:options} for inserting optional arguments. + +@example +#+ATTR_BEAMER: :environment nonindentlist +- item 1, not indented +- item 2, not indented +- item 3, not indented +@end example @example -#+ATTR_BEAMER: :overlay +- +#+ATTR_BEAMER: :overlay <+-> - item 1 - item 2 @end example -@subheading Editing support +@example +#+ATTR_BEAMER: :options [Lagrange] +Let $G$ be a finite group, and let $H$ be +a subgroup of $G$. Then the order of $H$ divides the order of $G$. +@end example + +@node Editing support +@subsection Editing support + -You can turn on a special minor mode @code{org-beamer-mode} for faster -editing with: +The @code{org-beamer-mode} is a special minor mode for faster editing of +Beamer documents. @example #+STARTUP: beamer @@ -10959,23 +11250,19 @@ editing with: @table @kbd @orgcmd{C-c C-b,org-beamer-select-environment} -In @code{org-beamer-mode}, this key offers fast selection of a Beamer -environment or the @code{BEAMER_COL} property. +The @code{org-beamer-mode} provides this key for quicker selections in Beamer +normal environments, and for selecting the @code{BEAMER_COL} property. @end table -Also, a template for useful in-buffer settings or properties can be inserted -into the buffer with @kbd{M-x org-beamer-insert-options-template}. Among -other things, this will install a column view format which is very handy for -editing special properties used by Beamer. +@node A Beamer example +@subsection A Beamer example -@subheading An example +Here is an example of an Org document ready for Beamer export. -Here is a simple example Org document that is intended for Beamer export. - -@smallexample +@example #+TITLE: Example Presentation #+AUTHOR: Carsten Dominik -#+OPTIONS: H:2 +#+OPTIONS: H:2 toc:t num:t #+LATEX_CLASS: beamer #+LATEX_CLASS_OPTIONS: [presentation] #+BEAMER_THEME: Madrid @@ -10984,91 +11271,148 @@ Here is a simple example Org document that is intended for Beamer export. * This is the first structural section ** Frame 1 -*** Thanks to Eric Fraga :B_block:BMCOL: +*** Thanks to Eric Fraga :B_block: :PROPERTIES: :BEAMER_COL: 0.48 :BEAMER_ENV: block :END: for the first viable Beamer setup in Org -*** Thanks to everyone else :B_block:BMCOL: +*** Thanks to everyone else :B_block: :PROPERTIES: :BEAMER_COL: 0.48 :BEAMER_ACT: <2-> :BEAMER_ENV: block :END: for contributing to the discussion -**** This will be formatted as a beamer note :B_note: +**** This will be formatted as a beamer note :B_note: :PROPERTIES: :BEAMER_env: note :END: ** Frame 2 (where we will not use columns) *** Request Please test this stuff! -@end smallexample +@end example -@node HTML export, @LaTeX{} and PDF export, Beamer export, Exporting +@node HTML export @section HTML export @cindex HTML export -Org mode contains an HTML (XHTML 1.0 strict) exporter with extensive -HTML formatting, in ways similar to John Gruber's @emph{markdown} -language, but with additional support for tables. +Org mode contains an HTML exporter with extensive HTML formatting compatible +with XHTML 1.0 strict standard. @menu -* HTML Export commands:: How to invoke HTML export -* HTML doctypes:: Org can export to various (X)HTML flavors -* HTML preamble and postamble:: How to insert a preamble and a postamble -* Quoting HTML tags:: Using direct HTML in Org mode -* Links in HTML export:: How links will be interpreted and formatted -* Tables in HTML export:: How to modify the formatting of tables -* Images in HTML export:: How to insert figures into HTML output -* Math formatting in HTML export:: Beautiful math also on the web -* Text areas in HTML export:: An alternative way to show an example -* CSS support:: Changing the appearance of the output -* JavaScript support:: Info and Folding in a web browser +* HTML Export commands:: Invoking HTML export +* HTML Specific export settings:: Settings for HTML export +* HTML doctypes:: Exporting various (X)HTML flavors +* HTML preamble and postamble:: Inserting preamble and postamble +* Quoting HTML tags:: Using direct HTML in Org files +* Links in HTML export:: Interpreting and formatting links +* Tables in HTML export:: Formatting and modifying tables +* Images in HTML export:: Inserting figures with HTML output +* Math formatting in HTML export:: Handling math equations +* Text areas in HTML export:: Showing an alternate approach, an example +* CSS support:: Styling HTML output +* JavaScript support:: Folding scripting in the web browser @end menu -@node HTML Export commands, HTML doctypes, HTML export, HTML export + +@node HTML Export commands @subsection HTML export commands @table @kbd @orgcmd{C-c C-e h h,org-html-export-to-html} -Export as an HTML file. For an Org file @file{myfile.org}, -the HTML file will be @file{myfile.html}. The file will be overwritten -without warning. -@kbd{C-c C-e h o} -Export as an HTML file and immediately open it with a browser. +Export as HTML file with a @file{.html} extension. For @file{myfile.org}, +Org exports to @file{myfile.html}, overwriting without warning. @kbd{C-c C-e +h o} Exports to HTML and opens it in a web browser. + @orgcmd{C-c C-e h H,org-html-export-as-html} -Export to a temporary buffer. Do not create a file. +Exports to a temporary buffer. Does not create a file. @end table -@c FIXME Exporting sublevels -@c @cindex headline levels, for exporting -@c In the exported version, the first 3 outline levels will become headlines, -@c defining a general document structure. Additional levels will be exported as -@c itemized lists. If you want that transition to occur at a different level, -@c specify it with a numeric prefix argument. For example, +@node HTML Specific export settings +@subsection HTML Specific export settings +HTML export has a number of keywords, similar to the general options settings +described in @ref{Export settings}. + +@table @samp +@item DESCRIPTION +@cindex #+DESCRIPTION (HTML) +This is the document's description, which the HTML exporter inserts it as a +HTML meta tag in the HTML file. For long descriptions, use multiple +@code{#+DESCRIPTION} lines. The exporter takes care of wrapping the lines +properly. + +@item HTML_DOCTYPE +@cindex #+HTML_DOCTYPE +@vindex org-html-doctype +Specify the document type, for example: HTML5 (@code{org-html-doctype}). + +@item HTML_CONTAINER +@cindex #+HTML_CONTAINER +@vindex org-html-container-element +Specify the HTML container, such as @samp{div}, for wrapping sections and +elements (@code{org-html-container-element}). + +@item HTML_LINK_HOME +@cindex #+HTML_LINK_HOME +@vindex org-html-link-home +The URL for home link (@code{org-html-link-home}). -@c @example -@c @kbd{C-2 C-c C-e b} -@c @end example +@item HTML_LINK_UP +@cindex #+HTML_LINK_UP +@vindex org-html-link-up +The URL for the up link of exported HTML pages (@code{org-html-link-up}). -@c @noindent -@c creates two levels of headings and does the rest as items. +@item HTML_MATHJAX +@cindex #+HTML_MATHJAX +@vindex org-html-mathjax-options +Options for MathJax (@code{org-html-mathjax-options}). MathJax is used to +typeset @LaTeX{} math in HTML documents. @xref{Math formatting in HTML +export}, for an example. -@node HTML doctypes, HTML preamble and postamble, HTML Export commands, HTML export +@item HTML_HEAD +@cindex #+HTML_HEAD +@vindex org-html-head +Arbitrary lines for appending to the HTML document's head +(@code{org-html-head}). + +@item HTML_HEAD_EXTRA +@cindex #+HTML_HEAD_EXTRA +@vindex org-html-head-extra +More arbitrary lines for appending to the HTML document's head +(@code{org-html-head-extra}). + +@item KEYWORDS +@cindex #+KEYWORDS (HTML) +Keywords to describe the document's content. HTML exporter inserts these +keywords as HTML meta tags. For long keywords, use multiple +@code{#+KEYWORDS} lines. + +@item LATEX_HEADER +@cindex #+LATEX_HEADER (HTML) +Arbitrary lines for appending to the preamble; HTML exporter appends when +transcoding @LaTeX{} fragments to images (@pxref{Math formatting in HTML +export}). + +@item SUBTITLE +@cindex #+SUBTITLE (HTML) +The document's subtitle. HTML exporter formats subtitle if document type is +@samp{HTML5} and the CSS has a @samp{subtitle} class. +@end table + +Some of these keywords are explained in more detail in the following sections +of the manual. + +@node HTML doctypes @subsection HTML doctypes -@vindex org-html-doctype -@vindex org-html-doctype-alist Org can export to various (X)HTML flavors. -Setting the variable @code{org-html-doctype} allows you to export to different -(X)HTML variants. The exported HTML will be adjusted according to the syntax -requirements of that variant. You can either set this variable to a doctype -string directly, in which case the exporter will try to adjust the syntax -automatically, or you can use a ready-made doctype. The ready-made options -are: +@vindex org-html-doctype +@vindex org-html-doctype-alist +Set the @code{org-html-doctype} variable for different (X)HTML variants. +Depending on the variant, the HTML exporter adjusts the syntax of HTML +conversion accordingly. Org includes the following ready-made variants: @itemize @item @@ -11091,23 +11435,21 @@ are: ``xhtml5'' @end itemize -See the variable @code{org-html-doctype-alist} for details. The default is -``xhtml-strict''. +@noindent See the variable @code{org-html-doctype-alist} for details. +The default is ``xhtml-strict''. -@subsubheading Fancy HTML5 export @vindex org-html-html5-fancy -@vindex org-html-html5-elements - -HTML5 introduces several new element types. By default, Org will not make -use of these element types, but you can set @code{org-html-html5-fancy} to -@code{t} (or set @code{html5-fancy} item in an @code{OPTIONS} line), to -enable a few new block-level elements. These are created using arbitrary -#+BEGIN and #+END blocks. For instance: +@cindex HTML5, export new elements +Org's HTML exporter does not by default enable new block elements introduced +with the HTML5 standard. To enable them, set @code{org-html-html5-fancy} to +non-@code{nil}. Or use an @code{OPTIONS} line in the file to set +@code{html5-fancy}. HTML5 documents can now have arbitrary #+BEGIN and #+END +blocks. For example: @example -#+BEGIN_ASIDE +#+BEGIN_aside Lorem ipsum -#+END_ASIDE +#+END_aside @end example Will export to: @@ -11122,14 +11464,14 @@ While this: @example #+ATTR_HTML: :controls controls :width 350 -#+BEGIN_VIDEO +#+BEGIN_video #+HTML: <source src="movie.mp4" type="video/mp4"> #+HTML: <source src="movie.ogg" type="video/ogg"> Your browser does not support the video tag. -#+END_VIDEO +#+END_video @end example -Becomes: +Exports to: @example <video controls="controls" width="350"> @@ -11139,15 +11481,17 @@ Becomes: </video> @end example -Special blocks that do not correspond to HTML5 elements (see -@code{org-html-html5-elements}) will revert to the usual behavior, i.e., -@code{#+BEGIN_LEDERHOSEN} will still export to @samp{<div class="lederhosen">}. +@vindex org-html-html5-elements +When special blocks do not have a corresponding HTML5 element, the HTML +exporter reverts to standard translation (see +@code{org-html-html5-elements}). For example, @code{#+BEGIN_lederhosen} +exports to @samp{<div class="lederhosen">}. -Headlines cannot appear within special blocks. To wrap a headline and its -contents in e.g., @samp{<section>} or @samp{<article>} tags, set the -@code{HTML_CONTAINER} property on the headline itself. +Special blocks cannot have headlines. For the HTML exporter to wrap the +headline and its contents in @samp{<section>} or @samp{<article>} tags, set +the @code{HTML_CONTAINER} property for the headline. -@node HTML preamble and postamble, Quoting HTML tags, HTML doctypes, HTML export +@node HTML preamble and postamble @subsection HTML preamble and postamble @vindex org-html-preamble @vindex org-html-postamble @@ -11157,69 +11501,77 @@ contents in e.g., @samp{<section>} or @samp{<article>} tags, set the @vindex org-export-creator-string @vindex org-export-time-stamp-file -The HTML exporter lets you define a preamble and a postamble. - -The default value for @code{org-html-preamble} is @code{t}, which means -that the preamble is inserted depending on the relevant format string in -@code{org-html-preamble-format}. - -Setting @code{org-html-preamble} to a string will override the default format -string. If you set it to a function, it will insert the output of the -function, which must be a string. Setting to @code{nil} will not insert any -preamble. - -The default value for @code{org-html-postamble} is @code{'auto}, which means -that the HTML exporter will look for information about the author, the email, -the creator and the date, and build the postamble from these values. Setting -@code{org-html-postamble} to @code{t} will insert the postamble from the -relevant format string found in @code{org-html-postamble-format}. Setting it -to @code{nil} will not insert any postamble. - -@node Quoting HTML tags, Links in HTML export, HTML preamble and postamble, HTML export +The HTML exporter has delineations for preamble and postamble. The default +value for @code{org-html-preamble} is @code{t}, which makes the HTML exporter +insert the preamble. See the variable @code{org-html-preamble-format} for +the format string. + +Set @code{org-html-preamble} to a string to override the default format +string. If the string is a function, the HTML exporter expects the function +to return a string upon execution. The HTML exporter inserts this string in +the preamble. The HTML exporter will not insert a preamble if +@code{org-html-preamble} is set @code{nil}. + +The default value for @code{org-html-postamble} is @code{auto}, which makes +the HTML exporter build a postamble from looking up author's name, email +address, creator's name, and date. Set @code{org-html-postamble} to @code{t} +to insert the postamble in the format specified in the +@code{org-html-postamble-format} variable. The HTML exporter will not insert +a postamble if @code{org-html-postamble} is set to @code{nil}. + +@node Quoting HTML tags @subsection Quoting HTML tags -Plain @samp{<} and @samp{>} are always transformed to @samp{<} and -@samp{>} in HTML export. If you want to include raw HTML code, which -should only appear in HTML export, mark it with @samp{@@@@html:} as in -@samp{@@@@html:<b>@@@@bold text@@@@html:</b>@@@@}. For more extensive HTML -that should be copied verbatim to the exported file use either +The HTML export back-end transforms @samp{<} and @samp{>} to @samp{<} and +@samp{>}. To include raw HTML code in the Org file so the HTML export +back-end can insert that HTML code in the output, use this inline syntax: +@samp{@@@@html:}. For example: @samp{@@@@html:<b>@@@@bold +text@@@@html:</b>@@@@}. For larger raw HTML code blocks, use these HTML +export code blocks: @cindex #+HTML -@cindex #+BEGIN_HTML +@cindex #+BEGIN_EXPORT html @example #+HTML: Literal HTML code for export @end example @noindent or -@cindex #+BEGIN_HTML +@cindex #+BEGIN_EXPORT html @example -#+BEGIN_HTML +#+BEGIN_EXPORT html All lines between these markers are exported literally -#+END_HTML +#+END_EXPORT @end example -@node Links in HTML export, Tables in HTML export, Quoting HTML tags, HTML export +@node Links in HTML export @subsection Links in HTML export @cindex links, in HTML export @cindex internal links, in HTML export @cindex external links, in HTML export -Internal links (@pxref{Internal links}) will continue to work in HTML@. This -includes automatic links created by radio targets (@pxref{Radio -targets}). Links to external files will still work if the target file is on -the same @i{relative} path as the published Org file. Links to other -@file{.org} files will be translated into HTML links under the assumption -that an HTML version also exists of the linked file, at the same relative -path. @samp{id:} links can then be used to jump to specific entries across -files. For information related to linking files while publishing them to a -publishing directory see @ref{Publishing links}. - -If you want to specify attributes for links, you can do so using a special -@code{#+ATTR_HTML} line to define attributes that will be added to the -@code{<a>} or @code{<img>} tags. Here is an example that sets @code{title} -and @code{style} attributes for a link: +@vindex org-html-link-org-files-as-html +The HTML export back-end transforms Org's internal links (@pxref{Internal +links}) to equivalent HTML links in the output. The back-end similarly +handles Org's automatic links created by radio targets (@pxref{Radio +targets}) similarly. For Org links to external files, the back-end +transforms the links to @emph{relative} paths. + +For Org links to other @file{.org} files, the back-end automatically changes +the file extension to @file{.html} and makes file paths relative. If the +@file{.org} files have an equivalent @file{.html} version at the same +location, then the converted links should work without any further manual +intervention. However, to disable this automatic path translation, set +@code{org-html-link-org-files-as-html} to @code{nil}. When disabled, the +HTML export back-end substitutes the @samp{id:}-based links in the HTML +output. For more about linking files when publishing to a directory, +@pxref{Publishing links}. + +Org files can also have special directives to the HTML export back-end. For +example, by using @code{#+ATTR_HTML} lines to specify new format attributes +to @code{<a>} or @code{<img>} tags. This example shows changing the link's +@code{title} and @code{style}: @cindex #+ATTR_HTML @example @@ -11227,15 +11579,15 @@ and @code{style} attributes for a link: [[http://orgmode.org]] @end example -@node Tables in HTML export, Images in HTML export, Links in HTML export, HTML export -@subsection Tables +@node Tables in HTML export +@subsection Tables in HTML export @cindex tables, in HTML @vindex org-html-table-default-attributes -Org mode tables are exported to HTML using the table attributes defined in -@code{org-html-table-default-attributes}. The default setting makes tables -without cell borders and frame. If you would like to change this for -individual tables, place something like the following before the table: +The HTML export back-end uses @code{org-html-table-default-attributes} when +exporting Org tables to HTML. By default, the exporter does not draw frames +and cell borders. To change for this for a table, use the following lines +before the table in the Org file: @cindex #+CAPTION @cindex #+ATTR_HTML @@ -11244,36 +11596,72 @@ individual tables, place something like the following before the table: #+ATTR_HTML: :border 2 :rules all :frame border @end example +The HTML export back-end preserves column groupings in Org tables +(@pxref{Column groups}) when exporting to HTML. + +Additional options for customizing tables for HTML export. + +@table @code +@vindex org-html-table-align-individual-fields +@item org-html-table-align-individual-fields +Non-@code{nil} attaches style attributes for alignment to each table field. + +@vindex org-html-table-caption-above +@item org-html-table-caption-above +Non-@code{nil} places caption string at the beginning of the table. + +@vindex org-html-table-data-tags +@item org-html-table-data-tags +Opening and ending tags for table data fields. + +@vindex org-html-table-default-attributes +@item org-html-table-default-attributes +Default attributes and values for table tags. + +@vindex org-html-table-header-tags +@item org-html-table-header-tags +Opening and ending tags for table's header fields. + @vindex org-html-table-row-tags -You can also modify the default tags used for each row by setting -@code{org-html-table-row-tags}. See the docstring for an example on -how to use this option. +@item org-html-table-row-tags +Opening and ending tags for table rows. -@node Images in HTML export, Math formatting in HTML export, Tables in HTML export, HTML export +@vindex org-html-table-use-header-tags-for-first-column +@item org-html-table-use-header-tags-for-first-column +Non-@code{nil} formats column one in tables with header tags. +@end table + +@node Images in HTML export @subsection Images in HTML export @cindex images, inline in HTML @cindex inlining images in HTML @vindex org-html-inline-images -HTML export can inline images given as links in the Org file, and -it can make an image the clickable part of a link. By -default@footnote{But see the variable -@code{org-html-inline-images}.}, images are inlined if a link does -not have a description. So @samp{[[file:myimg.jpg]]} will be inlined, -while @samp{[[file:myimg.jpg][the image]]} will just produce a link -@samp{the image} that points to the image. If the description part -itself is a @code{file:} link or a @code{http:} URL pointing to an -image, this image will be inlined and activated so that clicking on the -image will activate the link. For example, to include a thumbnail that -will link to a high resolution version of the image, you could use: + +The HTML export back-end has features to convert Org image links to HTML +inline images and HTML clickable image links. + +When the link in the Org file has no description, the HTML export back-end by +default in-lines that image. For example: @samp{[[file:myimg.jpg]]} is +in-lined, while @samp{[[file:myimg.jpg][the image]]} links to the text, +@samp{the image}. + +For more details, see the variable @code{org-html-inline-images}. + +On the other hand, if the description part of the Org link is itself another +link, such as @code{file:} or @code{http:} URL pointing to an image, the HTML +export back-end in-lines this image and links to the main image. This Org +syntax enables the back-end to link low-resolution thumbnail to the +high-resolution version of the image, as shown in this example: @example [[file:highres.jpg][file:thumb.jpg]] @end example -If you need to add attributes to an inlined image, use a @code{#+ATTR_HTML}. -In the example below we specify the @code{alt} and @code{title} attributes to -support text viewers and accessibility, and align it to the right. +To change attributes of in-lined images, use @code{#+ATTR_HTML} lines in the +Org file. This example shows realignment to right, and adds @code{alt} and +@code{title} attributes in support of text viewers and modern web accessibility +standards. @cindex #+CAPTION @cindex #+ATTR_HTML @@ -11284,63 +11672,72 @@ support text viewers and accessibility, and align it to the right. @end example @noindent -You could use @code{http} addresses just as well. +The HTML export back-end copies the @code{http} links from the Org file as +is. -@node Math formatting in HTML export, Text areas in HTML export, Images in HTML export, HTML export +@node Math formatting in HTML export @subsection Math formatting in HTML export @cindex MathJax @cindex dvipng +@cindex dvisvgm @cindex imagemagick @LaTeX{} math snippets (@pxref{@LaTeX{} fragments}) can be displayed in two -different ways on HTML pages. The default is to use the -@uref{http://www.mathjax.org, MathJax system} which should work out of the -box with Org mode installation because @uref{http://orgmode.org} serves -@file{MathJax} for Org mode users for small applications and for testing -purposes. @b{If you plan to use this regularly or on pages with significant -page views, you should install@footnote{Installation instructions can be -found on the MathJax website, see -@uref{http://www.mathjax.org/resources/docs/?installation.html}.} MathJax on -your own server in order to limit the load of our server.} To configure -@file{MathJax}, use the variable @code{org-html-mathjax-options} or -insert something like the following into the buffer: - -@example -#+HTML_MATHJAX: align:"left" mathml:t path:"/MathJax/MathJax.js" -@end example +different ways on HTML pages. The default is to use +@uref{http://www.mathjax.org, MathJax} which should work out of the box with +Org@footnote{By default Org loads MathJax from @uref{https://cdnjs.com, cdnjs.com} as +recommended by @uref{http://www.mathjax.org, MathJax}.}. Some MathJax display +options can be configured via @code{org-html-mathjax-options}, or in the +buffer. For example, with the following settings, +@smallexample +#+HTML_MATHJAX: align: left indent: 5em tagside: left font: Neo-Euler +@end smallexample +equation labels will be displayed on the left margin and equations will be +five ems from the left margin. -@noindent See the docstring of the variable -@code{org-html-mathjax-options} for the meaning of the parameters in -this line. +@noindent See the docstring of +@code{org-html-mathjax-options} for all supported variables. The MathJax +template can be configure via @code{org-html-mathjax-template}. If you prefer, you can also request that @LaTeX{} fragments are processed into small images that will be inserted into the browser page. Before the availability of MathJax, this was the default method for Org files. This -method requires that the @file{dvipng} program or @file{imagemagick} suite is -available on your system. You can still get this processing with +method requires that the @file{dvipng} program, @file{dvisvgm} or +@file{imagemagick} suite is available on your system. You can still get +this processing with @example #+OPTIONS: tex:dvipng @end example +@example +#+OPTIONS: tex:dvisvgm +@end example + or: @example #+OPTIONS: tex:imagemagick @end example -@node Text areas in HTML export, CSS support, Math formatting in HTML export, HTML export +@node Text areas in HTML export @subsection Text areas in HTML export @cindex text areas, in HTML -An alternative way to publish literal code examples in HTML is to use text -areas, where the example can even be edited before pasting it into an -application. It is triggered by @code{:textarea} attribute at an -@code{example} or @code{src} block. +Before Org mode's Babel, one popular approach to publishing code in HTML was +by using @code{:textarea}. The advantage of this approach was that copying +and pasting was built into browsers with simple JavaScript commands. Even +editing before pasting was made simple. -You may also use @code{:height} and @code{:width} attributes to specify the -height and width of the text area, which default to the number of lines in -the example, and 80, respectively. For example +The HTML export back-end can create such text areas. It requires an +@code{#+ATTR_HTML:} line as shown in the example below with the +@code{:textarea} option. This must be followed by either an +@code{example} or a @code{src} code block. Other Org block types will not +honor the @code{:textarea} option. + +By default, the HTML export back-end creates a text area 80 characters wide +and height just enough to fit the content. Override these defaults with +@code{:width} and @code{:height} options on the @code{#+ATTR_HTML:} line. @example #+ATTR_HTML: :textarea t :width 40 @@ -11352,7 +11749,7 @@ the example, and 80, respectively. For example @end example -@node CSS support, JavaScript support, Text areas in HTML export, HTML export +@node CSS support @subsection CSS support @cindex CSS, for HTML export @cindex HTML export, CSS @@ -11371,6 +11768,7 @@ p.author @r{author information, including email} p.date @r{publishing date} p.creator @r{creator info, about org mode version} .title @r{document title} +.subtitle @r{document subtitle} .todo @r{TODO keywords, all not-done states} .done @r{the DONE keywords, all states that count as done} .WAITING @r{each TODO keyword also uses a class named after itself} @@ -11388,7 +11786,7 @@ div.outline-text-N @r{extra div for text at outline level N} .figure-number @r{label like "Figure 1:"} .table-number @r{label like "Table 1:"} .listing-number @r{label like "Listing 1:"} -div.figure @r{how to format an inlined image} +div.figure @r{how to format an in-lined image} pre.src @r{formatted source code} pre.example @r{normal example} p.verse @r{verse paragraph} @@ -11396,6 +11794,7 @@ div.footnotes @r{footnote section headline} p.footnote @r{footnote definition paragraph, containing a footnote} .footref @r{a footnote reference number (always a <sup>)} .footnum @r{footnote number in footnote definition (always <sup>)} +.org-svg @r{default class for a linked @file{.svg} image} @end example @vindex org-html-style-default @@ -11403,15 +11802,10 @@ p.footnote @r{footnote definition paragraph, containing a footnote} @vindex org-html-head @vindex org-html-head-extra @cindex #+HTML_INCLUDE_STYLE -Each exported file contains a compact default style that defines these -classes in a basic way@footnote{This style is defined in the constant -@code{org-html-style-default}, which you should not modify. To turn -inclusion of these defaults off, customize -@code{org-html-head-include-default-style} or set @code{html-style} to -@code{nil} in an @code{OPTIONS} line.}. You may overwrite these settings, or -add to them by using the variables @code{org-html-head} and -@code{org-html-head-extra}. You can override the global values of these -variables for each file by using these keywords: +The HTML export back-end includes a compact default style in each exported +HTML file. To override the default style with another style, use these +keywords in the Org file. They will replace the global defaults the HTML +exporter uses. @cindex #+HTML_HEAD @cindex #+HTML_HEAD_EXTRA @@ -11420,38 +11814,49 @@ variables for each file by using these keywords: #+HTML_HEAD_EXTRA: <link rel="alternate stylesheet" type="text/css" href="style2.css" /> @end example +To just turn off the default style, customize +@code{org-html-head-include-default-style} variable, or use this option line in +the Org file. + +@example +#+OPTIONS: html-style:nil +@end example + @noindent -For longer style definitions, you can use several such lines. You could also -directly write a @code{<style>} @code{</style>} section in this way, without -referring to an external file. +For longer style definitions, either use several @code{#+HTML_HEAD} and +@code{#+HTML_HEAD_EXTRA} lines, or use @code{<style>} @code{</style>} blocks +around them. Both of these approaches can avoid referring to an external +file. -In order to add styles to a subtree, use the @code{:HTML_CONTAINER_CLASS:} +In order to add styles to a sub-tree, use the @code{:HTML_CONTAINER_CLASS:} property to assign a class to the tree. In order to specify CSS styles for a particular headline, you can use the id specified in a @code{:CUSTOM_ID:} property. +Never change the @code{org-html-style-default} constant. Instead use other +simpler ways of customizing as described above. + + @c FIXME: More about header and footer styles @c FIXME: Talk about links and targets. -@node JavaScript support, , CSS support, HTML export +@node JavaScript support @subsection JavaScript supported display of web pages @cindex Rose, Sebastian Sebastian Rose has written a JavaScript program especially designed to enhance the web viewing experience of HTML files created with Org. This -program allows you to view large files in two different ways. The first one -is an @emph{Info}-like mode where each section is displayed separately and +program enhances large files in two different ways of viewing. One is an +@emph{Info}-like mode where each section is displayed separately and navigation can be done with the @kbd{n} and @kbd{p} keys (and some other keys as well, press @kbd{?} for an overview of the available keys). The second -view type is a @emph{folding} view much like Org provides inside Emacs. The -script is available at @url{http://orgmode.org/org-info.js} and you can find -the documentation for it at @url{http://orgmode.org/worg/code/org-info-js/}. -We host the script at our site, but if you use it a lot, you might not want -to be dependent on @url{http://orgmode.org} and prefer to install a local -copy on your own web server. +one has a @emph{folding} view, much like Org provides inside Emacs. The +script is available at @url{http://orgmode.org/org-info.js} and the +documentation at @url{http://orgmode.org/worg/code/org-info-js/}. The script +is hosted on @url{http://orgmode.org}, but for reliability, prefer installing +it on your own web server. -All it then takes to use this program is adding a single line to the Org -file: +To use this program, just add this line to the Org file: @cindex #+INFOJS_OPT @example @@ -11459,12 +11864,12 @@ file: @end example @noindent -If this line is found, the HTML header will automatically contain the code -needed to invoke the script. Using the line above, you can set the following -viewing options: +The HTML header now has the code needed to automatically invoke the script. +For setting options, use the syntax from the above line for options described +below: @example -path: @r{The path to the script. The default is to grab the script from} +path: @r{The path to the script. The default grabs the script from} @r{@url{http://orgmode.org/org-info.js}, but you might want to have} @r{a local copy and use a path like @samp{../scripts/org-info.js}.} view: @r{Initial view when the website is first shown. Possible values are:} @@ -11494,105 +11899,204 @@ buttons: @r{Should view-toggle buttons be everywhere? When @code{nil} (the} @vindex org-html-infojs-options @vindex org-html-use-infojs You can choose default values for these options by customizing the variable -@code{org-html-infojs-options}. If you always want to apply the script to your -pages, configure the variable @code{org-html-use-infojs}. +@code{org-html-infojs-options}. If you want the script to always apply to +your pages, configure the variable @code{org-html-use-infojs}. -@node @LaTeX{} and PDF export, Markdown export, HTML export, Exporting -@section @LaTeX{} and PDF export +@node @LaTeX{} export +@section @LaTeX{} export @cindex @LaTeX{} export @cindex PDF export -@LaTeX{} export can produce an arbitrarily complex LaTeX document of any -standard or custom document class. With further processing@footnote{The -default @LaTeX{} output is designed for processing with @code{pdftex} or -@LaTeX{}. It includes packages that are not compatible with @code{xetex} and -possibly @code{luatex}. The @LaTeX{} exporter can be configured to support -alternative TeX engines, see the options -@code{org-latex-default-packages-alist} and @code{org-latex-packages-alist}.}, -which the @LaTeX{} exporter is able to control, this back-end is able to -produce PDF output. Because the @LaTeX{} exporter can be configured to use -the @code{hyperref} package, the default setup produces fully-linked PDF -output. - -As in @LaTeX{}, blank lines are meaningful for this back-end: a paragraph -will not be started if two contiguous syntactical elements are not separated -by an empty line. - -This back-end also offers enhanced support for footnotes. Thus, it handles -nested footnotes, footnotes in tables and footnotes in a list item's -description. +The @LaTeX{} export back-end can handle complex documents, incorporate +standard or custom @LaTeX{} document classes, generate documents using +alternate @LaTeX{} engines, and produce fully linked PDF files with indexes, +bibliographies, and tables of contents, destined for interactive online +viewing or high-quality print publication. + +While the details are covered in-depth in this section, here are some quick +references to variables for the impatient: for engines, see +@code{org-latex-compiler}; for build sequences, see +@code{org-latex-pdf-process}; for packages, see +@code{org-latex-default-packages-alist} and @code{org-latex-packages-alist}. + +An important note about the @LaTeX{} export back-end: it is sensitive to +blank lines in the Org document. That's because @LaTeX{} itself depends on +blank lines to tell apart syntactical elements, such as paragraphs. @menu -* @LaTeX{} export commands:: How to export to LaTeX and PDF -* Header and sectioning:: Setting up the export file structure -* Quoting @LaTeX{} code:: Incorporating literal @LaTeX{} code -* @LaTeX{} specific attributes:: Controlling @LaTeX{} output +* @LaTeX{} export commands:: For producing @LaTeX{} and PDF documents. +* @LaTeX{} specific export settings:: Unique to this @LaTeX{} back-end. +* @LaTeX{} header and sectioning:: For file structure. +* Quoting @LaTeX{} code:: Directly in the Org document. +* Tables in @LaTeX{} export:: Attributes specific to tables. +* Images in @LaTeX{} export:: Attributes specific to images. +* Plain lists in @LaTeX{} export:: Attributes specific to lists. +* Source blocks in @LaTeX{} export:: Attributes specific to source code blocks. +* Example blocks in @LaTeX{} export:: Attributes specific to example blocks. +* Special blocks in @LaTeX{} export:: Attributes specific to special blocks. +* Horizontal rules in @LaTeX{} export:: Attributes specific to horizontal rules. @end menu -@node @LaTeX{} export commands, Header and sectioning, @LaTeX{} and PDF export, @LaTeX{} and PDF export +@node @LaTeX{} export commands @subsection @LaTeX{} export commands @table @kbd @orgcmd{C-c C-e l l,org-latex-export-to-latex} -Export as a @LaTeX{} file. For an Org file @file{myfile.org}, the @LaTeX{} -file will be @file{myfile.tex}. The file will be overwritten without -warning. +Export as @LaTeX{} file with a @file{.tex} extension. For @file{myfile.org}, +Org exports to @file{myfile.tex}, overwriting without warning. @kbd{C-c C-e +l l} Exports to @LaTeX{} file. + @orgcmd{C-c C-e l L,org-latex-export-as-latex} Export to a temporary buffer. Do not create a file. @orgcmd{C-c C-e l p,org-latex-export-to-pdf} -Export as @LaTeX{} and then process to PDF. +Export as @LaTeX{} file and convert it to PDF file. @item C-c C-e l o -Export as @LaTeX{} and then process to PDF, then open the resulting PDF file. +Export as @LaTeX{} file and convert it to PDF, then open the PDF using the default viewer. +@end table + +@vindex org-latex-compiler +@vindex org-latex-bibtex-compiler +@vindex org-latex-default-packages-alist +The @LaTeX{} export back-end can use any of these @LaTeX{} engines: +@samp{pdflatex}, @samp{xelatex}, and @samp{lualatex}. These engines compile +@LaTeX{} files with different compilers, packages, and output options. The +@LaTeX{} export back-end finds the compiler version to use from +@code{org-latex-compiler} variable or the @code{#+LATEX_COMPILER} keyword in +the Org file. See the docstring for the +@code{org-latex-default-packages-alist} for loading packages with certain +compilers. Also see @code{org-latex-bibtex-compiler} to set the bibliography +compiler@footnote{This does not allow setting different bibliography +compilers for different files. However, ``smart'' @LaTeX{} compilation +systems, such as @samp{latexmk}, can select the correct bibliography +compiler.}. + +@node @LaTeX{} specific export settings +@subsection @LaTeX{} specific export settings + +The @LaTeX{} export back-end has several additional keywords for customizing +@LaTeX{} output. Setting these keywords works similar to the general options +(@pxref{Export settings}). + +@table @samp +@item DESCRIPTION +@cindex #+DESCRIPTION (@LaTeX{}) +The document's description. The description along with author name, +keywords, and related file metadata are inserted in the output file by the +@samp{hyperref} package. See @code{org-latex-hyperref-template} for +customizing metadata items. See @code{org-latex-title-command} for +typesetting description into the document's front matter. Use multiple +@code{#+DESCRIPTION} lines for long descriptions. + +@item LATEX_CLASS +@cindex #+LATEX_CLASS +@vindex org-latex-default-class +@vindex org-latex-classes +This is @LaTeX{} document class, such as @code{article}, @code{report}, +@code{book}, and so on, which contain predefined preamble and headline level +mapping that the @LaTeX{} export back-end needs. The back-end reads the +default class name from the @code{org-latex-default-class} variable. Org has +@code{article} as the default class. A valid default class must be an +element of @code{org-latex-classes}. + +@item LATEX_CLASS_OPTIONS +@cindex #+LATEX_CLASS_OPTIONS +Options the @LaTeX{} export back-end uses when calling the @LaTeX{} document +class. + +@item LATEX_COMPILER +@cindex #+LATEX_COMPILER +@vindex org-latex-compiler +The compiler, such as @samp{pdflatex}, @samp{xelatex}, @samp{lualatex}, for +producing the PDF (@code{org-latex-compiler}). + +@item LATEX_HEADER +@cindex #+LATEX_HEADER +@vindex org-latex-classes +Arbitrary lines to add to the document's preamble, before the @samp{hyperref} +settings. See @code{org-latex-classes} for adjusting the structure and order +of the @LaTeX{} headers. + +@item LATEX_HEADER_EXTRA +@cindex #+LATEX_HEADER_EXTRA +@vindex org-latex-classes +Arbitrary lines to add to the document's preamble, before the @samp{hyperref} +settings. See @code{org-latex-classes} for adjusting the structure and order +of the @LaTeX{} headers. + +@item KEYWORDS +@cindex #+KEYWORDS (@LaTeX{}) +The keywords for the document. The description along with author name, +keywords, and related file metadata are inserted in the output file by the +@samp{hyperref} package. See @code{org-latex-hyperref-template} for +customizing metadata items. See @code{org-latex-title-command} for +typesetting description into the document's front matter. Use multiple +@code{#+KEYWORDS} lines if necessary. + +@item SUBTITLE +@cindex #+SUBTITLE (@LaTeX{}) +@vindex org-latex-subtitle-separate +@vindex org-latex-subtitle-format +The document's subtitle. It is typeset as per +@code{org-latex-subtitle-format}. If @code{org-latex-subtitle-separate} is +non-@code{nil}, it is typed as part of the @samp{\title}-macro. See +@code{org-latex-hyperref-template} for customizing metadata items. See +@code{org-latex-title-command} for typesetting description into the +document's front matter. @end table -@node Header and sectioning, Quoting @LaTeX{} code, @LaTeX{} export commands, @LaTeX{} and PDF export -@subsection Header and sectioning structure +The following sections have further details. + +@node @LaTeX{} header and sectioning +@subsection @LaTeX{} header and sectioning structure @cindex @LaTeX{} class @cindex @LaTeX{} sectioning structure @cindex @LaTeX{} header @cindex header, for @LaTeX{} files @cindex sectioning structure, for @LaTeX{} export -By default, the first three outline levels become headlines, defining a -general document structure. Additional levels are exported as @code{itemize} -or @code{enumerate} lists. The transition can also occur at a different -level (@pxref{Export settings}). +The @LaTeX{} export back-end converts the first three of Org's outline levels +into @LaTeX{} headlines. The remaining Org levels are exported as +@code{itemize} or @code{enumerate} lists. To change this globally for the +cut-off point between levels and lists, (@pxref{Export settings}). -By default, the @LaTeX{} output uses the class @code{article}. +By default, the @LaTeX{} export back-end uses the @code{article} class. @vindex org-latex-default-class @vindex org-latex-classes @vindex org-latex-default-packages-alist @vindex org-latex-packages-alist -You can change this globally by setting a different value for -@code{org-latex-default-class} or locally by adding an option like -@code{#+LATEX_CLASS: myclass} in your file, or with -a @code{EXPORT_LATEX_CLASS} property that applies when exporting a region -containing only this (sub)tree. The class must be listed in -@code{org-latex-classes}. This variable defines a header template for each -class@footnote{Into which the values of -@code{org-latex-default-packages-alist} and @code{org-latex-packages-alist} -are spliced.}, and allows you to define the sectioning structure for each -class. You can also define your own classes there. +To change the default class globally, edit @code{org-latex-default-class}. +To change the default class locally in an Org file, add option lines +@code{#+LATEX_CLASS: myclass}. To change the default class for just a part +of the Org file, set a sub-tree property, @code{EXPORT_LATEX_CLASS}. The +class name entered here must be valid member of @code{org-latex-classes}. +This variable defines a header template for each class into which the +exporter splices the values of @code{org-latex-default-packages-alist} and +@code{org-latex-packages-alist}. Use the same three variables to define +custom sectioning or custom classes. @cindex #+LATEX_CLASS @cindex #+LATEX_CLASS_OPTIONS @cindex property, EXPORT_LATEX_CLASS @cindex property, EXPORT_LATEX_CLASS_OPTIONS -The @code{LATEX_CLASS_OPTIONS} keyword or @code{EXPORT_LATEX_CLASS_OPTIONS} -property can specify the options for the @code{\documentclass} macro. These -options have to be provided, as expected by @LaTeX{}, within square brackets. +The @LaTeX{} export back-end sends the @code{LATEX_CLASS_OPTIONS} keyword and +@code{EXPORT_LATEX_CLASS_OPTIONS} property as options to the @LaTeX{} +@code{\documentclass} macro. The options and the syntax for specifying them, +including enclosing them in square brackets, follow @LaTeX{} conventions. + +@example +#+LATEX_CLASS_OPTIONS: [a4paper,11pt,twoside,twocolumn] +@end example @cindex #+LATEX_HEADER @cindex #+LATEX_HEADER_EXTRA -You can also use the @code{LATEX_HEADER} and -@code{LATEX_HEADER_EXTRA}@footnote{Unlike @code{LATEX_HEADER}, contents -from @code{LATEX_HEADER_EXTRA} keywords will not be loaded when previewing -@LaTeX{} snippets (@pxref{Previewing @LaTeX{} fragments}).} keywords in order -to add lines to the header. See the docstring of @code{org-latex-classes} for -more information. +The @LaTeX{} export back-end appends values from @code{LATEX_HEADER} and +@code{LATEX_HEADER_EXTRA} keywords to the @LaTeX{} header. The docstring for +@code{org-latex-classes} explains in more detail. Also note that @LaTeX{} +export back-end does not append @code{LATEX_HEADER_EXTRA} to the header when +previewing @LaTeX{} snippets (@pxref{Previewing @LaTeX{} fragments}). -An example is shown below. +A sample Org file with the above headers: @example #+LATEX_CLASS: article @@ -11601,103 +12105,117 @@ An example is shown below. * Headline 1 some text +* Headline 2 + some more text @end example -@node Quoting @LaTeX{} code, @LaTeX{} specific attributes, Header and sectioning, @LaTeX{} and PDF export +@node Quoting @LaTeX{} code @subsection Quoting @LaTeX{} code -Embedded @LaTeX{} as described in @ref{Embedded @LaTeX{}}, will be correctly -inserted into the @LaTeX{} file. Furthermore, you can add special code that -should only be present in @LaTeX{} export with the following constructs: +The @LaTeX{} export back-end can insert any arbitrary @LaTeX{} code, +@pxref{Embedded @LaTeX{}}. There are three ways to embed such code in the +Org file and they all use different quoting syntax. -@cindex #+LATEX -@cindex #+BEGIN_LATEX +Inserting in-line quoted with @ symbols: +@cindex inline, in @LaTeX{} export @example -Code within @@@@latex:some code@@@@ a paragraph. - -#+LATEX: Literal @LaTeX{} code for export - -#+BEGIN_LATEX -All lines between these markers are exported literally -#+END_LATEX +Code embedded in-line @@@@latex:any arbitrary LaTeX code@@@@ in a paragraph. @end example -@node @LaTeX{} specific attributes, , Quoting @LaTeX{} code, @LaTeX{} and PDF export -@subsection @LaTeX{} specific attributes -@cindex #+ATTR_LATEX +Inserting as one or more keyword lines in the Org file: +@cindex #+LATEX +@example +#+LATEX: any arbitrary LaTeX code +@end example -@LaTeX{} understands attributes specified in an @code{ATTR_LATEX} line. They -affect tables, images, plain lists, special blocks and source blocks. +Inserting as an export block in the Org file, where the back-end exports any +code between begin and end markers: +@cindex #+BEGIN_EXPORT latex +@example +#+BEGIN_EXPORT latex +any arbitrary LaTeX code +#+END_EXPORT +@end example -@subsubheading Tables in @LaTeX{} export +@node Tables in @LaTeX{} export +@subsection Tables in @LaTeX{} export @cindex tables, in @LaTeX{} export +@cindex #+ATTR_LATEX, in tables -For @LaTeX{} export of a table, you can specify a label and a caption -(@pxref{Images and tables}). You can also use attributes to control table -layout and contents. Valid @LaTeX{} attributes include: +The @LaTeX{} export back-end can pass several @LaTeX{} attributes for table +contents and layout. Besides specifying label and caption (@pxref{Images and +tables}), the other valid @LaTeX{} attributes include: @table @code @item :mode @vindex org-latex-default-table-mode -Nature of table's contents. It can be set to @code{table}, @code{math}, -@code{inline-math} or @code{verbatim}. In particular, when in @code{math} or -@code{inline-math} mode, every cell is exported as-is, horizontal rules are -ignored and the table will be wrapped in a math environment. Also, -contiguous tables sharing the same math mode will be wrapped within the same -environment. Default mode is determined in -@code{org-latex-default-table-mode}. +The @LaTeX{} export back-end wraps the table differently depending on the +mode for accurate rendering of math symbols. Mode is either @code{table}, +@code{math}, @code{inline-math} or @code{verbatim}. For @code{math} or +@code{inline-math} mode, @LaTeX{} export back-end wraps the table in a math +environment, but every cell in it is exported as-is. The @LaTeX{} export +back-end determines the default mode from +@code{org-latex-default-table-mode}. For , The @LaTeX{} export back-end +merges contiguous tables in the same mode into a single environment. @item :environment @vindex org-latex-default-table-environment -Environment used for the table. It can be set to any @LaTeX{} table -environment, like @code{tabularx}@footnote{Requires adding the -@code{tabularx} package to @code{org-latex-packages-alist}.}, -@code{longtable}, @code{array}, @code{tabu}@footnote{Requires adding the -@code{tabu} package to @code{org-latex-packages-alist}.}, -@code{bmatrix}@enddots{} It defaults to -@code{org-latex-default-table-environment} value. +Set the default @LaTeX{} table environment for the @LaTeX{} export back-end +to use when exporting Org tables. Common @LaTeX{} table environments are +provided by these packages: @code{tabularx}, @code{longtable}, @code{array}, +@code{tabu}, and @code{bmatrix}. For packages, such as @code{tabularx} and +@code{tabu}, or any newer replacements, include them in the +@code{org-latex-packages-alist} variable so the @LaTeX{} export back-end can +insert the appropriate load package headers in the converted @LaTeX{} file. +Look in the docstring for the @code{org-latex-packages-alist} variable for +configuring these packages for @LaTeX{} snippet previews, if any. @item :caption -@code{#+CAPTION} keyword is the simplest way to set a caption for a table -(@pxref{Images and tables}). If you need more advanced commands for that -task, you can use @code{:caption} attribute instead. Its value should be raw -@LaTeX{} code. It has precedence over @code{#+CAPTION}. +Use @code{#+CAPTION} keyword to set a simple caption for a table +(@pxref{Images and tables}). For custom captions, use @code{:caption} +attribute, which accepts raw @LaTeX{} code. @code{:caption} value overrides +@code{#+CAPTION} value. @item :float @itemx :placement -Float environment for the table. Possible values are @code{sidewaystable}, -@code{multicolumn}, @code{t} and @code{nil}. When unspecified, a table with -a caption will have a @code{table} environment. Moreover, @code{:placement} -attribute can specify the positioning of the float. +The table environments by default are not floats in @LaTeX{}. To make them +floating objects use @code{:float} with one of the following options: +@code{sideways}, @code{multicolumn}, @code{t}, and @code{nil}. Note that +@code{sidewaystable} has been deprecated since Org 8.3. @LaTeX{} floats can +also have additional layout @code{:placement} attributes. These are the +usual @code{[h t b p ! H]} permissions specified in square brackets. Note +that for @code{:float sideways} tables, the @LaTeX{} export back-end ignores +@code{:placement} attributes. @item :align @itemx :font @itemx :width -Set, respectively, the alignment string of the table, its font size and its -width. They only apply on regular tables. +The @LaTeX{} export back-end uses these attributes for regular tables to set +their alignments, fonts, and widths. @item :spread -Boolean specific to the @code{tabu} and @code{longtabu} environments, and -only takes effect when used in conjunction with the @code{:width} attribute. -When @code{:spread} is non-@code{nil}, the table will be spread or shrunk by the -value of @code{:width}. +When @code{:spread} is non-@code{nil}, the @LaTeX{} export back-end spreads +or shrinks the table by the @code{:width} for @code{tabu} and @code{longtabu} +environments. @code{:spread} has no effect if @code{:width} is not set. @item :booktabs @itemx :center @itemx :rmlines @vindex org-latex-tables-booktabs @vindex org-latex-tables-centered -They toggle, respectively, @code{booktabs} usage (assuming the package is -properly loaded), table centering and removal of every horizontal rule but -the first one (in a "table.el" table only). In particular, -@code{org-latex-tables-booktabs} (respectively @code{org-latex-tables-centered}) -activates the first (respectively second) attribute globally. +All three commands are toggles. @code{:booktabs} brings in modern +typesetting enhancements to regular tables. The @code{booktabs} package has +to be loaded through @code{org-latex-packages-alist}. @code{:center} is for +centering the table. @code{:rmlines} removes all but the very first +horizontal line made of ASCII characters from "table.el" tables only. @item :math-prefix @itemx :math-suffix @itemx :math-arguments -A string that will be inserted, respectively, before the table within the -math environment, after the table within the math environment, and between -the macro name and the contents of the table. The @code{:math-arguments} -attribute is used for matrix macros that require more than one argument -(e.g., @code{qbordermatrix}). +The @LaTeX{} export back-end inserts @code{:math-prefix} string value in a +math environment before the table. The @LaTeX{} export back-end inserts +@code{:math-suffix} string value in a math environment after the table. The +@LaTeX{} export back-end inserts @code{:math-arguments} string value between +the macro name and the table's contents. @code{:math-arguments} comes in use +for matrix macros that require more than one argument, such as +@code{qbordermatrix}. @end table -Thus, attributes can be used in a wide array of situations, like writing -a table that will span over multiple pages, or a matrix product: +@LaTeX{} table attributes help formatting tables for a wide range of +situations, such as matrix product or spanning multiple pages: @example #+ATTR_LATEX: :environment longtable :align l|lp@{3cm@}r|l @@ -11712,8 +12230,8 @@ a table that will span over multiple pages, or a matrix product: | 3 | 4 | @end example -In the example below, @LaTeX{} command -@code{\bicaption@{HeadingA@}@{HeadingB@}} will set the caption. +Set the caption with the @LaTeX{} command +@code{\bicaption@{HeadingA@}@{HeadingB@}}: @example #+ATTR_LATEX: :caption \bicaption@{HeadingA@}@{HeadingB@} @@ -11722,128 +12240,203 @@ In the example below, @LaTeX{} command @end example -@subsubheading Images in @LaTeX{} export +@node Images in @LaTeX{} export +@subsection Images in @LaTeX{} export @cindex images, inline in @LaTeX{} @cindex inlining images in @LaTeX{} +@cindex #+ATTR_LATEX, in images -Images that are linked to without a description part in the link, like -@samp{[[file:img.jpg]]} or @samp{[[./img.jpg]]} will be inserted into the PDF -output file resulting from @LaTeX{} processing. Org will use an -@code{\includegraphics} macro to insert the image@footnote{In the case of -TikZ (@url{http://sourceforge.net/projects/pgf/}) images, it will become an -@code{\input} macro wrapped within a @code{tikzpicture} environment.}. +The @LaTeX{} export back-end processes image links in Org files that do not +have descriptions, such as these links @samp{[[file:img.jpg]]} or +@samp{[[./img.jpg]]}, as direct image insertions in the final PDF output. In +the PDF, they are no longer links but actual images embedded on the page. +The @LaTeX{} export back-end uses @code{\includegraphics} macro to insert the +image. But for TikZ@footnote{@url{http://sourceforge.net/projects/pgf/}} +images, the back-end uses an @code{\input} macro wrapped within +a @code{tikzpicture} environment. -You can specify specify image width or height with, respectively, -@code{:width} and @code{:height} attributes. It is also possible to add any -other option with the @code{:options} attribute, as shown in the following -example: +For specifying image @code{:width}, @code{:height}, and other +@code{:options}, use this syntax: @example #+ATTR_LATEX: :width 5cm :options angle=90 [[./img/sed-hr4049.pdf]] @end example -If you need a specific command for the caption, use @code{:caption} -attribute. It will override standard @code{#+CAPTION} value, if any. +For custom commands for captions, use the @code{:caption} attribute. It will +override the default @code{#+CAPTION} value: @example #+ATTR_LATEX: :caption \bicaption@{HeadingA@}@{HeadingB@} [[./img/sed-hr4049.pdf]] @end example -If you have specified a caption as described in @ref{Images and tables}, the -picture will be wrapped into a @code{figure} environment and thus become -a floating element. You can also ask Org to export an image as a float -without specifying caption by setting the @code{:float} attribute. You may -also set it to: +When captions follow the method as described in @ref{Images and tables}, the +@LaTeX{} export back-end wraps the picture in a floating @code{figure} +environment. To float an image without specifying a caption, set the +@code{:float} attribute to one of the following: @itemize @minus @item -@code{t}: if you want to use the standard @samp{figure} environment. It is -used by default if you provide a caption to the image. +@code{t}: for a standard @samp{figure} environment; used by default whenever +an image has a caption. @item -@code{multicolumn}: if you wish to include an image which spans multiple -columns in a page. This will export the image wrapped in a @code{figure*} -environment. +@code{multicolumn}: to span the image across multiple columns of a page; the +back-end wraps the image in a @code{figure*} environment. @item -@code{wrap}: if you would like to let text flow around the image. It will -make the figure occupy the left half of the page. +@code{wrap}: for text to flow around the image on the right; the figure +occupies the left half of the page. @item -@code{nil}: if you need to avoid any floating environment, even when -a caption is provided. +@code{sideways}: for a new page with the image sideways, rotated ninety +degrees, in a @code{sidewaysfigure} environment; overrides @code{:placement} +setting. +@item +@code{nil}: to avoid a @code{:float} even if using a caption. @end itemize @noindent -To modify the placement option of any floating environment, set the -@code{placement} attribute. +Use the @code{placement} attribute to modify a floating environment's placement. @example -#+ATTR_LATEX: :float wrap :width 0.38\textwidth :placement @{r@}@{0.4\textwidth@} -[[./img/hst.png]] +#+ATTR_LATEX: :float wrap :width 0.38\textwidth :placement +@{r@}@{0.4\textwidth@} [[./img/hst.png]] @end example -If the @code{:comment-include} attribute is set to a non-@code{nil} value, -the @LaTeX{} @code{\includegraphics} macro will be commented out. +@vindex org-latex-images-centered +@cindex center image (@LaTeX{} export) +@cindex image, centering (@LaTeX{} export) + +The @LaTeX{} export back-end centers all images by default. Setting +@code{:center} attribute to @code{nil} disables centering. To disable +centering globally, set @code{org-latex-images-centered} to @code{t}. -@subsubheading Plain lists in @LaTeX{} export +Set the @code{:comment-include} attribute to non-@code{nil} value for the +@LaTeX{} export back-end to comment out the @code{\includegraphics} macro. + +@node Plain lists in @LaTeX{} export +@subsection Plain lists in @LaTeX{} export @cindex plain lists, in @LaTeX{} export +@cindex #+ATTR_LATEX, in plain lists + +The @LaTeX{} export back-end accepts the @code{:environment} and +@code{:options} attributes for plain lists. Both attributes work together +for customizing lists, as shown in the examples: + +@example +#+LATEX_HEADER: \usepackage[inline]@{enumitem@} +Some ways to say "Hello": +#+ATTR_LATEX: :environment itemize* +#+ATTR_LATEX: :options [label=@{@}, itemjoin=@{,@}, itemjoin*=@{, and@}] +- Hola +- Bonjour +- Guten Tag. +@end example -Plain lists accept two optional attributes: @code{:environment} and -@code{:options}. The first one allows the use of a non-standard environment -(e.g., @samp{inparaenum}). The second one specifies additional arguments for -that environment. +Since @LaTeX{} supports only four levels of nesting for lists, use an +external package, such as @samp{enumitem} in @LaTeX{}, for levels deeper than +four: @example -#+ATTR_LATEX: :environment compactitem :options [$\circ$] -- you need ``paralist'' package to reproduce this example. +#+LATEX_HEADER: \usepackage@{enumitem@} +#+LATEX_HEADER: \renewlist@{itemize@}@{itemize@}@{9@} +#+LATEX_HEADER: \setlist[itemize]@{label=$\circ$@} +- One + - Two + - Three + - Four + - Five @end example -@subsubheading Source blocks in @LaTeX{} export +@node Source blocks in @LaTeX{} export +@subsection Source blocks in @LaTeX{} export @cindex source blocks, in @LaTeX{} export +@cindex #+ATTR_LATEX, in source blocks + +The @LaTeX{} export back-end can make source code blocks into floating +objects through the attributes @code{:float} and @code{:options}. For +@code{:float}: -In addition to syntax defined in @ref{Literal examples}, names and captions -(@pxref{Images and tables}), source blocks also accept a @code{:float} -attribute. You may set it to: @itemize @minus @item -@code{t}: if you want to make the source block a float. It is the default -value when a caption is provided. +@code{t}: makes a source block float; by default floats any source block with +a caption. @item -@code{multicolumn}: if you wish to include a source block which spans multiple -columns in a page. +@code{multicolumn}: spans the source block across multiple columns of a page. @item -@code{nil}: if you need to avoid any floating environment, even when a caption -is provided. It is useful for source code that may not fit in a single page. +@code{nil}: avoids a @code{:float} even if using a caption; useful for +source code blocks that may not fit on a page. @end itemize @example #+ATTR_LATEX: :float nil #+BEGIN_SRC emacs-lisp -Code that may not fit in a single page. +Lisp code that may not fit in a single page. +#+END_SRC +@end example + +@vindex org-latex-listings-options +@vindex org-latex-minted-options +The @LaTeX{} export back-end passes string values in @code{:options} to +@LaTeX{} packages for customization of that specific source block. In the +example below, the @code{:options} are set for Minted. Minted is a source +code highlighting @LaTeX{}package with many configurable options. + +@example +#+ATTR_LATEX: :options commentstyle=\bfseries +#+BEGIN_SRC emacs-lisp + (defun Fib (n) + (if (< n 2) n (+ (Fib (- n 1)) (Fib (- n 2))))) #+END_SRC @end example -@subsubheading Special blocks in @LaTeX{} export +To apply similar configuration options for all source blocks in a file, use +the @code{org-latex-listings-options} and @code{org-latex-minted-options} +variables. + +@node Example blocks in @LaTeX{} export +@subsection Example blocks in @LaTeX{} export +@cindex example blocks, in @LaTeX{} export +@cindex verbatim blocks, in @LaTeX{} export +@cindex #+ATTR_LATEX, in example blocks + +The @LaTeX{} export back-end wraps the contents of example blocks in a +@samp{verbatim} environment. To change this behavior to use another +environment globally, specify an appropriate export filter (@pxref{Advanced +configuration}). To change this behavior to use another environment for each +block, use the @code{:environment} parameter to specify a custom environment. + +@example +#+ATTR_LATEX: :environment myverbatim +#+BEGIN_EXAMPLE +This sentence is false. +#+END_EXAMPLE +@end example + +@node Special blocks in @LaTeX{} export +@subsection Special blocks in @LaTeX{} export @cindex special blocks, in @LaTeX{} export @cindex abstract, in @LaTeX{} export @cindex proof, in @LaTeX{} export +@cindex #+ATTR_LATEX, in special blocks -In @LaTeX{} back-end, special blocks become environments of the same name. -Value of @code{:options} attribute will be appended as-is to that -environment's opening string. For example: + +For other special blocks in the Org file, the @LaTeX{} export back-end makes +a special environment of the same name. The back-end also takes +@code{:options}, if any, and appends as-is to that environment's opening +string. For example: @example -#+BEGIN_ABSTRACT +#+BEGIN_abstract We demonstrate how to solve the Syracuse problem. -#+END_ABSTRACT +#+END_abstract #+ATTR_LATEX: :options [Proof of important theorem] -#+BEGIN_PROOF +#+BEGIN_proof ... Therefore, any even number greater than 2 is the sum of two primes. -#+END_PROOF +#+END_proof @end example @noindent -becomes +exports to @example \begin@{abstract@} @@ -11862,43 +12455,43 @@ example: @example #+ATTR_LATEX: :caption \MyCaption@{HeadingA@} -#+BEGIN_PROOF +#+BEGIN_proof ... -#+END_PROOF +#+END_proof @end example -@subsubheading Horizontal rules +@node Horizontal rules in @LaTeX{} export +@subsection Horizontal rules in @LaTeX{} export @cindex horizontal rules, in @LaTeX{} export +@cindex #+ATTR_LATEX, in horizontal rules -Width and thickness of a given horizontal rule can be controlled with, -respectively, @code{:width} and @code{:thickness} attributes: +The @LaTeX{} export back-end converts horizontal rules by the specified +@code{:width} and @code{:thickness} attributes. For example: @example #+ATTR_LATEX: :width .6\textwidth :thickness 0.8pt ----- @end example -@node Markdown export, OpenDocument Text export, @LaTeX{} and PDF export, Exporting +@node Markdown export @section Markdown export @cindex Markdown export -@code{md} export back-end generates Markdown syntax@footnote{Vanilla flavor, -as defined at @url{http://daringfireball.net/projects/markdown/}.} for an Org -mode buffer. +The Markdown export back-end, @code{md}, converts an Org file to a Markdown +format, as defined at @url{http://daringfireball.net/projects/markdown/}. -It is built over HTML back-end: any construct not supported by Markdown -syntax (e.g., tables) will be controlled and translated by @code{html} -back-end (@pxref{HTML export}). +Since @code{md} is built on top of the HTML back-end, any Org constructs not +supported by Markdown, such as tables, the underlying @code{html} back-end +(@pxref{HTML export}) converts them. @subheading Markdown export commands @table @kbd @orgcmd{C-c C-e m m,org-md-export-to-markdown} -Export as a text file written in Markdown syntax. For an Org file, -@file{myfile.org}, the resulting file will be @file{myfile.md}. The file -will be overwritten without warning. +Export to a text file with Markdown syntax. For @file{myfile.org}, Org +exports to @file{myfile.md}, overwritten without warning. @orgcmd{C-c C-e m M,org-md-export-as-markdown} -Export to a temporary buffer. Do not create a file. +Export to a temporary buffer. Does not create a file. @item C-c C-e m o Export as a text file with Markdown syntax, then open it. @end table @@ -11906,54 +12499,52 @@ Export as a text file with Markdown syntax, then open it. @subheading Header and sectioning structure @vindex org-md-headline-style -Markdown export can generate both @code{atx} and @code{setext} types for -headlines, according to @code{org-md-headline-style}. The former introduces -a hard limit of two levels, whereas the latter pushes it to six. Headlines -below that limit are exported as lists. You can also set a soft limit before -that one (@pxref{Export settings}). +Based on @code{org-md-headline-style}, markdown export can generate headlines +of both @code{atx} and @code{setext} types. @code{atx} limits headline +levels to two. @code{setext} limits headline levels to six. Beyond these +limits, the export back-end converts headlines to lists. To set a limit to a +level before the absolute limit (@pxref{Export settings}). @c begin opendocument -@node OpenDocument Text export, Org export, Markdown export, Exporting +@node OpenDocument Text export @section OpenDocument Text export @cindex ODT @cindex OpenDocument @cindex export, OpenDocument @cindex LibreOffice -Org mode@footnote{Versions 7.8 or later} supports export to OpenDocument Text -(ODT) format. Documents created by this exporter use the -@cite{OpenDocument-v1.2 +The ODT export back-end handles creating of OpenDocument Text (ODT) format +files. The format complies with @cite{OpenDocument-v1.2 specification}@footnote{@url{http://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2.html, Open Document Format for Office Applications (OpenDocument) Version 1.2}} and -are compatible with LibreOffice 3.4. +is compatible with LibreOffice 3.4. @menu -* Pre-requisites for ODT export:: What packages ODT exporter relies on -* ODT export commands:: How to invoke ODT export -* Extending ODT export:: How to produce @samp{doc}, @samp{pdf} files -* Applying custom styles:: How to apply custom styles to the output -* Links in ODT export:: How links will be interpreted and formatted -* Tables in ODT export:: How Tables are exported -* Images in ODT export:: How to insert images -* Math formatting in ODT export:: How @LaTeX{} fragments are formatted -* Labels and captions in ODT export:: How captions are rendered -* Literal examples in ODT export:: How source and example blocks are formatted -* Advanced topics in ODT export:: Read this if you are a power user +* Pre-requisites for ODT export:: Required packages. +* ODT export commands:: Invoking export. +* ODT specific export settings:: Configuration options. +* Extending ODT export:: Producing @file{.doc}, @file{.pdf} files. +* Applying custom styles:: Styling the output. +* Links in ODT export:: Handling and formatting links. +* Tables in ODT export:: Org table conversions. +* Images in ODT export:: Inserting images. +* Math formatting in ODT export:: Formatting @LaTeX{} fragments. +* Labels and captions in ODT export:: Rendering objects. +* Literal examples in ODT export:: For source code and example blocks. +* Advanced topics in ODT export:: For power users. @end menu -@node Pre-requisites for ODT export, ODT export commands, OpenDocument Text export, OpenDocument Text export +@node Pre-requisites for ODT export @subsection Pre-requisites for ODT export @cindex zip -The ODT exporter relies on the @file{zip} program to create the final -output. Check the availability of this program before proceeding further. +The ODT export back-end relies on the @file{zip} program to create the final +compressed ODT output. Check if @file{zip} is locally available and +executable. Without @file{zip}, export cannot finish. -@node ODT export commands, Extending ODT export, Pre-requisites for ODT export, OpenDocument Text export +@node ODT export commands @subsection ODT export commands - -@subsubheading Exporting to ODT @anchor{x-export-to-odt} - @cindex region, active @cindex active region @cindex transient-mark-mode @@ -11964,94 +12555,121 @@ output. Check the availability of this program before proceeding further. Export as OpenDocument Text file. @vindex org-odt-preferred-output-format -If @code{org-odt-preferred-output-format} is specified, automatically convert -the exported file to that format. @xref{x-export-to-other-formats, , -Automatically exporting to other formats}. - -For an Org file @file{myfile.org}, the ODT file will be -@file{myfile.odt}. The file will be overwritten without warning. If there -is an active region,@footnote{This requires @code{transient-mark-mode} to be -turned on} only the region will be exported. If the selected region is a -single tree,@footnote{To select the current subtree, use @kbd{C-c @@}} the -tree head will become the document title. If the tree head entry has, or -inherits, an @code{EXPORT_FILE_NAME} property, that name will be used for the -export. +If @code{org-odt-preferred-output-format} is specified, the ODT export +back-end automatically converts the exported file to that format. +@xref{x-export-to-other-formats, , Automatically exporting to other formats}. + +For @file{myfile.org}, Org exports to @file{myfile.odt}, overwriting without +warning. The ODT export back-end exports a region only if a region was +active. Note for exporting active regions, the @code{transient-mark-mode} +has to be turned on. + +If the selected region is a single tree, the ODT export back-end makes the +tree head the document title. Incidentally, @kbd{C-c @@} selects the current +sub-tree. If the tree head entry has, or inherits, an +@code{EXPORT_FILE_NAME} property, the ODT export back-end uses that for file +name. @kbd{C-c C-e o O} -Export as an OpenDocument Text file and open the resulting file. +Export to an OpenDocument Text file format and open it. @vindex org-odt-preferred-output-format -If @code{org-odt-preferred-output-format} is specified, open the converted +When @code{org-odt-preferred-output-format} is specified, open the converted file instead. @xref{x-export-to-other-formats, , Automatically exporting to other formats}. @end table -@node Extending ODT export, Applying custom styles, ODT export commands, OpenDocument Text export +@node ODT specific export settings +@subsection ODT specific export settings +The ODT export back-end has several additional keywords for customizing ODT +output. Setting these keywords works similar to the general options +(@pxref{Export settings}). + +@table @samp +@item DESCRIPTION +@cindex #+DESCRIPTION (ODT) +This is the document's description, which the ODT export back-end inserts as +document metadata. For long descriptions, use multiple @code{#+DESCRIPTION} +lines. + +@item KEYWORDS +@cindex #+KEYWORDS (ODT) +The keywords for the document. The ODT export back-end inserts the +description along with author name, keywords, and related file metadata as +metadata in the output file. Use multiple @code{#+KEYWORDS} lines if +necessary. + +@item ODT_STYLES_FILE +@cindex ODT_STYLES_FILE +@vindex org-odt-styles-file +The ODT export back-end uses the @code{org-odt-styles-file} by default. See +@ref{Applying custom styles} for details. + +@item SUBTITLE +@cindex SUBTITLE (ODT) +The document subtitle. +@end table + +@node Extending ODT export @subsection Extending ODT export -The ODT exporter can interface with a variety of document -converters and supports popular converters out of the box. As a result, you -can use it to export to formats like @samp{doc} or convert a document from -one format (say @samp{csv}) to another format (say @samp{ods} or @samp{xls}). +The ODT export back-end can produce documents in other formats besides ODT +using a specialized ODT converter process. Its common interface works with +popular converters to produce formats such as @samp{doc}, or convert a +document from one format, say @samp{csv}, to another format, say @samp{xls}. @cindex @file{unoconv} @cindex LibreOffice -If you have a working installation of LibreOffice, a document converter is -pre-configured for you and you can use it right away. If you would like to -use @file{unoconv} as your preferred converter, customize the variable -@code{org-odt-convert-process} to point to @code{unoconv}. You can -also use your own favorite converter or tweak the default settings of the -@file{LibreOffice} and @samp{unoconv} converters. @xref{Configuring a -document converter}. - -@subsubsection Automatically exporting to other formats + +Customize @code{org-odt-convert-process} variable to point to @code{unoconv}, +which is the ODT's preferred converter. Working installations of LibreOffice +would already have @code{unoconv} installed. Alternatively, other converters +may be substituted here. @xref{Configuring a document converter}. + +@subsubheading Automatically exporting to other formats @anchor{x-export-to-other-formats} @vindex org-odt-preferred-output-format -Very often, you will find yourself exporting to ODT format, only to -immediately save the exported document to other formats like @samp{doc}, -@samp{docx}, @samp{rtf}, @samp{pdf} etc. In such cases, you can specify your -preferred output format by customizing the variable -@code{org-odt-preferred-output-format}. This way, the export commands -(@pxref{x-export-to-odt,,Exporting to ODT}) can be extended to export to a -format that is of immediate interest to you. - -@subsubsection Converting between document formats +If ODT format is just an intermediate step to get to other formats, such as +@samp{doc}, @samp{docx}, @samp{rtf}, or @samp{pdf}, etc., then extend the ODT +export back-end to directly produce that format. Specify the final format in +the @code{org-odt-preferred-output-format} variable. This is one way to +extend (@pxref{x-export-to-odt,,Exporting to ODT}). + +@subsubheading Converting between document formats @anchor{x-convert-to-other-formats} -There are many document converters in the wild which support conversion to -and from various file formats, including, but not limited to the -ODT format. LibreOffice converter, mentioned above, is one such -converter. Once a converter is configured, you can interact with it using -the following command. +The Org export back-end is made to be inter-operable with a wide range of text +document format converters. Newer generation converters, such as LibreOffice +and Pandoc, can handle hundreds of formats at once. Org provides a +consistent interaction with whatever converter is installed. Here are some +generic commands: @vindex org-odt-convert @table @kbd @item M-x org-odt-convert RET Convert an existing document from one format to another. With a prefix -argument, also open the newly produced file. +argument, opens the newly produced file. @end table -@node Applying custom styles, Links in ODT export, Extending ODT export, OpenDocument Text export +@node Applying custom styles @subsection Applying custom styles @cindex styles, custom @cindex template, custom -The ODT exporter ships with a set of OpenDocument styles -(@pxref{Working with OpenDocument style files}) that ensure a well-formatted -output. These factory styles, however, may not cater to your specific -tastes. To customize the output, you can either modify the above styles -files directly, or generate the required styles using an application like -LibreOffice. The latter method is suitable for expert and non-expert -users alike, and is described here. +The ODT export back-end comes with many OpenDocument styles (@pxref{Working +with OpenDocument style files}). To expand or further customize these +built-in style sheets, either edit the style sheets directly or generate them +using an application such as LibreOffice. The example here shows creating a +style using LibreOffice. -@subsubsection Applying custom styles: the easy way +@subsubheading Applying custom styles: the easy way @enumerate @item -Create a sample @file{example.org} file with the below settings and export it -to ODT format. +Create a sample @file{example.org} file with settings as shown below, and +export it to ODT format. @example #+OPTIONS: H:10 num:t @@ -12059,9 +12677,9 @@ to ODT format. @item Open the above @file{example.odt} using LibreOffice. Use the @file{Stylist} -to locate the target styles---these typically have the @samp{Org} prefix---and -modify those to your taste. Save the modified file either as an -OpenDocument Text (@file{.odt}) or OpenDocument Template (@file{.ott}) file. +to locate the target styles, which typically have the @samp{Org} prefix. +Open one, modify, and save as either OpenDocument Text (@file{.odt}) or +OpenDocument Template (@file{.ott}) file. @item @cindex #+ODT_STYLES_FILE @@ -12070,8 +12688,8 @@ Customize the variable @code{org-odt-styles-file} and point it to the newly created file. For additional configuration options @pxref{x-overriding-factory-styles,,Overriding factory styles}. -If you would like to choose a style on a per-file basis, you can use the -@code{#+ODT_STYLES_FILE} option. A typical setting will look like +To apply and ODT style to a particular file, use the @code{#+ODT_STYLES_FILE} +option as shown in the example below: @example #+ODT_STYLES_FILE: "/path/to/example.ott" @@ -12085,51 +12703,48 @@ or @end enumerate -@subsubsection Using third-party styles and templates +@subsubheading Using third-party styles and templates -You can use third-party styles and templates for customizing your output. -This will produce the desired output only if the template provides all -style names that the @samp{ODT} exporter relies on. Unless this condition is -met, the output is going to be less than satisfactory. So it is highly -recommended that you only work with templates that are directly derived from -the factory settings. +The ODT export back-end relies on many templates and style names. Using +third-party styles and templates can lead to mismatches. Templates derived +from built in ODT templates and styles seem to have fewer problems. -@node Links in ODT export, Tables in ODT export, Applying custom styles, OpenDocument Text export +@node Links in ODT export @subsection Links in ODT export @cindex links, in ODT export -ODT exporter creates native cross-references for internal links. It creates -Internet-style links for all other links. +ODT export back-end creates native cross-references for internal links and +Internet-style links for all other link types. -A link with no description and destined to a regular (un-itemized) outline +A link with no description and pointing to a regular---un-itemized---outline heading is replaced with a cross-reference and section number of the heading. A @samp{\ref@{label@}}-style reference to an image, table etc.@: is replaced with a cross-reference and sequence number of the labeled entity. @xref{Labels and captions in ODT export}. -@node Tables in ODT export, Images in ODT export, Links in ODT export, OpenDocument Text export +@node Tables in ODT export @subsection Tables in ODT export @cindex tables, in ODT export -Export of native Org mode tables (@pxref{Tables}) and simple @file{table.el} -tables is supported. However, export of complex @file{table.el} tables---tables -that have column or row spans---is not supported. Such tables are -stripped from the exported document. +The ODT export back-end handles native Org mode tables (@pxref{Tables}) and +simple @file{table.el} tables. Complex @file{table.el} tables having column +or row spans are not supported. Such tables are stripped from the exported +document. + +By default, the ODT export back-end exports a table with top and bottom +frames and with ruled lines separating row and column groups (@pxref{Column +groups}). All tables are typeset to occupy the same width. The ODT export +back-end honors any table alignments and relative widths for columns +(@pxref{Column width and alignment}). -By default, a table is exported with top and bottom frames and with rules -separating row and column groups (@pxref{Column groups}). Furthermore, all -tables are typeset to occupy the same width. If the table specifies -alignment and relative width for its columns (@pxref{Column width and -alignment}) then these are honored on export.@footnote{The column widths are -interpreted as weighted ratios with the default weight being 1} +Note that the ODT export back-end interprets column widths as weighted +ratios, the default weight being 1. @cindex #+ATTR_ODT -You can control the width of the table by specifying @code{:rel-width} -property using an @code{#+ATTR_ODT} line. -For example, consider the following table which makes use of all the rules -mentioned above. +Specifying @code{:rel-width} property on an @code{#+ATTR_ODT} line controls +the width of the table. For example: @example #+ATTR_ODT: :rel-width 50 @@ -12144,25 +12759,25 @@ mentioned above. | Sum | 16 | 123 | 2560 | 2699 | @end example -On export, the table will occupy 50% of text area. The columns will be sized -(roughly) in the ratio of 13:5:5:5:6. The first column will be left-aligned -and rest of the columns will be right-aligned. There will be vertical rules -after separating the header and last columns from other columns. There will -be horizontal rules separating the header and last rows from other rows. +On export, the above table takes 50% of text width area. The exporter sizes +the columns in the ratio: 13:5:5:5:6. The first column is left-aligned and +rest of the columns, right-aligned. Vertical rules separate the header and +the last column. Horizontal rules separate the header and the last row. -If you are not satisfied with the above formatting options, you can create -custom table styles and associate them with a table using the -@code{#+ATTR_ODT} line. @xref{Customizing tables in ODT export}. +For even more customization, create custom table styles and associate them +with a table using the @code{#+ATTR_ODT} line. @xref{Customizing tables in +ODT export}. -@node Images in ODT export, Math formatting in ODT export, Tables in ODT export, OpenDocument Text export +@node Images in ODT export @subsection Images in ODT export @cindex images, embedding in ODT @cindex embedding images in ODT @subsubheading Embedding images -You can embed images within the exported document by providing a link to the -desired image file with no link description. For example, to embed -@samp{img.png} do either of the following: +The ODT export back-end processes image links in Org files that do not have +descriptions, such as these links @samp{[[file:img.jpg]]} or +@samp{[[./img.jpg]]}, as direct image insertions in the final output. Either +of these examples works: @example [[file:img.png]] @@ -12173,10 +12788,9 @@ desired image file with no link description. For example, to embed @end example @subsubheading Embedding clickable images -You can create clickable images by providing a link whose description is a -link to an image file. For example, to embed a image -@file{org-mode-unicorn.png} which when clicked jumps to -@uref{http://Orgmode.org} website, do the following +For clickable images, provide a link whose description is another link to an +image file. For example, to embed a image @file{org-mode-unicorn.png} which +when clicked jumps to @uref{http://Orgmode.org} website, do the following @example [[http://orgmode.org][./org-mode-unicorn.png]] @@ -12185,25 +12799,22 @@ link to an image file. For example, to embed a image @subsubheading Sizing and scaling of embedded images @cindex #+ATTR_ODT -You can control the size and scale of the embedded images using the -@code{#+ATTR_ODT} attribute. +Control the size and scale of the embedded images with the @code{#+ATTR_ODT} +attribute. @cindex identify, ImageMagick @vindex org-odt-pixels-per-inch -The exporter specifies the desired size of the image in the final document in -units of centimeters. In order to scale the embedded images, the exporter -queries for pixel dimensions of the images using one of a) ImageMagick's -@file{identify} program or b) Emacs @code{create-image} and @code{image-size} -APIs@footnote{Use of @file{ImageMagick} is only desirable. However, if you -routinely produce documents that have large images or you export your Org -files that has images using a Emacs batch script, then the use of -@file{ImageMagick} is mandatory.}. The pixel dimensions are subsequently -converted in to units of centimeters using -@code{org-odt-pixels-per-inch}. The default value of this variable is -set to @code{display-pixels-per-inch}. You can tweak this variable to -achieve the best results. - -The examples below illustrate the various possibilities. +The ODT export back-end starts with establishing the size of the image in the +final document. The dimensions of this size is measured in centimeters. The +back-end then queries the image file for its dimensions measured in pixels. +For this measurement, the back-end relies on ImageMagick's @file{identify} +program or Emacs @code{create-image} and @code{image-size} API. ImageMagick +is the preferred choice for large file sizes or frequent batch operations. +The back-end then converts the pixel dimensions using +@code{org-odt-pixels-per-inch} into the familiar 72 dpi or 96 dpi. The +default value for this is in @code{display-pixels-per-inch}, which can be +tweaked for better results based on the capabilities of the output device. +Here are some common image scaling operations: @table @asis @item Explicitly size the image @@ -12244,38 +12855,37 @@ height:width ratio, do the following @subsubheading Anchoring of images @cindex #+ATTR_ODT -You can control the manner in which an image is anchored by setting the -@code{:anchor} property of it's @code{#+ATTR_ODT} line. You can specify one -of the following three values for the @code{:anchor} property: -@samp{"as-char"}, @samp{"paragraph"} and @samp{"page"}. +The ODT export back-end can anchor images to @samp{"as-char"}, +@samp{"paragraph"}, or @samp{"page"}. Set the preferred anchor using the +@code{:anchor} property of the @code{#+ATTR_ODT} line. -To create an image that is anchored to a page, do the following: +To create an image that is anchored to a page: @example #+ATTR_ODT: :anchor "page" [[./img.png]] @end example -@node Math formatting in ODT export, Labels and captions in ODT export, Images in ODT export, OpenDocument Text export +@node Math formatting in ODT export @subsection Math formatting in ODT export -The ODT exporter has special support for handling math. +The ODT export back-end has special support built-in for handling math. @menu -* Working with @LaTeX{} math snippets:: How to embed @LaTeX{} math fragments -* Working with MathML or OpenDocument formula files:: How to embed equations in native format +* Working with @LaTeX{} math snippets:: Embedding in @LaTeX{} format. +* Working with MathML or OpenDocument formula files:: Embedding in native format. @end menu -@node Working with @LaTeX{} math snippets, Working with MathML or OpenDocument formula files, Math formatting in ODT export, Math formatting in ODT export -@subsubsection Working with @LaTeX{} math snippets +@node Working with @LaTeX{} math snippets +@subsubheading Working with @LaTeX{} math snippets -@LaTeX{} math snippets (@pxref{@LaTeX{} fragments}) can be embedded in the ODT +@LaTeX{} math snippets (@pxref{@LaTeX{} fragments}) can be embedded in an ODT document in one of the following ways: @cindex MathML @enumerate @item MathML -This option is activated on a per-file basis with +Add this line to the Org file. This option is activated on a per-file basis. @example #+OPTIONS: LaTeX:t @@ -12289,13 +12899,13 @@ the exported document. @vindex org-latex-to-mathml-convert-command @vindex org-latex-to-mathml-jar-file -You can specify the @LaTeX{}-to-MathML converter by customizing the variables +To specify the @LaTeX{}-to-MathML converter, customize the variables @code{org-latex-to-mathml-convert-command} and @code{org-latex-to-mathml-jar-file}. -If you prefer to use @file{MathToWeb}@footnote{See -@uref{http://www.mathtoweb.com/cgi-bin/mathtoweb_home.pl, MathToWeb}} as your -converter, you can configure the above variables as shown below. +To use MathToWeb@footnote{See +@uref{http://www.mathtoweb.com/cgi-bin/mathtoweb_home.pl, MathToWeb}.} as the +preferred converter, configure the above variables as @lisp (setq org-latex-to-mathml-convert-command @@ -12303,9 +12913,14 @@ converter, you can configure the above variables as shown below. org-latex-to-mathml-jar-file "/path/to/mathtoweb.jar") @end lisp +To use @LaTeX{}ML@footnote{See @uref{http://dlmf.nist.gov/LaTeXML/}.} use +@lisp +(setq org-latex-to-mathml-convert-command + "latexmlmath \"%i\" --presentationmathml=%o") +@end lisp -You can use the following commands to quickly verify the reliability of -the @LaTeX{}-to-MathML converter. +To quickly verify the reliability of the @LaTeX{}-to-MathML converter, use +the following commands: @table @kbd @item M-x org-odt-export-as-odf RET @@ -12317,34 +12932,39 @@ and open the formula file with the system-registered application. @end table @cindex dvipng +@cindex dvisvgm @cindex imagemagick @item PNG images -This option is activated on a per-file basis with +Add this line to the Org file. This option is activated on a per-file basis. @example #+OPTIONS: tex:dvipng @end example +@example +#+OPTIONS: tex:dvisvgm +@end example + or: @example #+OPTIONS: tex:imagemagick @end example -With this option, @LaTeX{} fragments are processed into PNG images and the -resulting images are embedded in the exported document. This method requires -that the @file{dvipng} program or @file{imagemagick} suite be available on -your system. +Under this option, @LaTeX{} fragments are processed into PNG or SVG images +and the resulting images are embedded in the exported document. This method +requires @file{dvipng} program, @file{dvisvgm} or @file{imagemagick} +programs. @end enumerate -@node Working with MathML or OpenDocument formula files, , Working with @LaTeX{} math snippets, Math formatting in ODT export -@subsubsection Working with MathML or OpenDocument formula files +@node Working with MathML or OpenDocument formula files +@subsubheading Working with MathML or OpenDocument formula files -For various reasons, you may find embedding @LaTeX{} math snippets in an -ODT document less than reliable. In that case, you can embed a -math equation by linking to its MathML (@file{.mml}) source or its -OpenDocument formula (@file{.odf}) file as shown below: +When embedding @LaTeX{} math snippets in ODT documents is not reliable, there +is one more option to try. Embed an equation by linking to its MathML +(@file{.mml}) source or its OpenDocument formula (@file{.odf}) file as shown +below: @example [[./equation.mml]] @@ -12356,19 +12976,14 @@ or [[./equation.odf]] @end example -@node Labels and captions in ODT export, Literal examples in ODT export, Math formatting in ODT export, OpenDocument Text export +@node Labels and captions in ODT export @subsection Labels and captions in ODT export -You can label and caption various category of objects---an inline image, a -table, a @LaTeX{} fragment or a Math formula---using @code{#+LABEL} and -@code{#+CAPTION} lines. @xref{Images and tables}. ODT exporter enumerates -each labeled or captioned object of a given category separately. As a -result, each such object is assigned a sequence number based on order of it's -appearance in the Org file. - -In the exported document, a user-provided caption is augmented with the -category and sequence number. Consider the following inline image in an Org -file. +ODT format handles labeling and captioning of objects based on their +types. Inline images, tables, @LaTeX{} fragments, and Math formulas are +numbered and captioned separately. Each object also gets a unique sequence +number based on its order of first appearance in the Org file. Each category +has its own sequence. A caption is just a label applied to these objects. @example #+CAPTION: Bell curve @@ -12376,94 +12991,86 @@ file. [[./img/a.png]] @end example -It could be rendered as shown below in the exported document. +When rendered, it may show as follows in the exported document: @example Figure 2: Bell curve @end example @vindex org-odt-category-map-alist -You can modify the category component of the caption by customizing the -option @code{org-odt-category-map-alist}. For example, to tag all embedded -images with the string @samp{Illustration} (instead of the default -@samp{Figure}) use the following setting: +To modify the category component of the caption, customize the option +@code{org-odt-category-map-alist}. For example, to tag embedded images with +the string @samp{Illustration} instead of the default string @samp{Figure}, +use the following setting: @lisp (setq org-odt-category-map-alist - (("__Figure__" "Illustration" "value" "Figure" org-odt--enumerable-image-p))) + '(("__Figure__" "Illustration" "value" "Figure" org-odt--enumerable-image-p))) @end lisp -With this, previous image will be captioned as below in the exported -document. +With the above modification, the previous example changes to: @example Illustration 2: Bell curve @end example -@node Literal examples in ODT export, Advanced topics in ODT export, Labels and captions in ODT export, OpenDocument Text export +@node Literal examples in ODT export @subsection Literal examples in ODT export -Export of literal examples (@pxref{Literal examples}) with full fontification -is supported. Internally, the exporter relies on @file{htmlfontify.el} to -generate all style definitions needed for a fancy listing.@footnote{Your -@file{htmlfontify.el} library must at least be at Emacs 24.1 levels for -fontification to be turned on.} The auto-generated styles have @samp{OrgSrc} -as prefix and inherit their color from the faces used by Emacs -@code{font-lock} library for the source language. +The ODT export back-end supports literal examples (@pxref{Literal examples}) +with full fontification. Internally, the ODT export back-end relies on +@file{htmlfontify.el} to generate the style definitions needed for fancy +listings. The auto-generated styles get @samp{OrgSrc} prefix and inherit +colors from the faces used by Emacs @code{font-lock} library for that source +language. @vindex org-odt-fontify-srcblocks -If you prefer to use your own custom styles for fontification, you can do -so by customizing the option -@code{org-odt-create-custom-styles-for-srcblocks}. +For custom fontification styles, customize the +@code{org-odt-create-custom-styles-for-srcblocks} option. @vindex org-odt-create-custom-styles-for-srcblocks -You can turn off fontification of literal examples by customizing the -option @code{org-odt-fontify-srcblocks}. +To turn off fontification of literal examples, customize the +@code{org-odt-fontify-srcblocks} option. -@node Advanced topics in ODT export, , Literal examples in ODT export, OpenDocument Text export +@node Advanced topics in ODT export @subsection Advanced topics in ODT export -If you rely heavily on ODT export, you may want to exploit the full -set of features that the exporter offers. This section describes features -that would be of interest to power users. +The ODT export back-end has extensive features useful for power users and +frequent uses of ODT formats. @menu -* Configuring a document converter:: How to register a document converter -* Working with OpenDocument style files:: Explore the internals -* Creating one-off styles:: How to produce custom highlighting etc -* Customizing tables in ODT export:: How to define and use Table templates -* Validating OpenDocument XML:: How to debug corrupt OpenDocument files +* Configuring a document converter:: Registering a document converter. +* Working with OpenDocument style files:: Exploring internals. +* Creating one-off styles:: Customizing styles, highlighting. +* Customizing tables in ODT export:: Defining table templates. +* Validating OpenDocument XML:: Debugging corrupted OpenDocument files. @end menu -@node Configuring a document converter, Working with OpenDocument style files, Advanced topics in ODT export, Advanced topics in ODT export -@subsubsection Configuring a document converter +@node Configuring a document converter +@subsubheading Configuring a document converter @cindex convert @cindex doc, docx, rtf @cindex converter -The ODT exporter can work with popular converters with little or no -extra configuration from your side. @xref{Extending ODT export}. -If you are using a converter that is not supported by default or if you would -like to tweak the default converter settings, proceed as below. +The ODT export back-end works with popular converters with little or no extra +configuration. @xref{Extending ODT export}. The following is for unsupported +converters or tweaking existing defaults. @enumerate @item Register the converter @vindex org-odt-convert-processes -Name your converter and add it to the list of known converters by -customizing the option @code{org-odt-convert-processes}. Also specify how -the converter can be invoked via command-line to effect the conversion. +Add the name of the converter to the @code{org-odt-convert-processes} +variable. Note that it also requires how the converter is invoked on the +command line. See the variable's docstring for details. @item Configure its capabilities @vindex org-odt-convert-capabilities -@anchor{x-odt-converter-capabilities} Specify the set of formats the -converter can handle by customizing the variable -@code{org-odt-convert-capabilities}. Use the default value for this -variable as a guide for configuring your converter. As suggested by the -default setting, you can specify the full set of formats supported by the -converter and not limit yourself to specifying formats that are related to -just the OpenDocument Text format. +@anchor{x-odt-converter-capabilities} Specify which formats the converter can +handle by customizing the variable @code{org-odt-convert-capabilities}. Use +the entry for the default values in this variable for configuring the new +converter. Also see its docstring for details. @item Choose the converter @@ -12472,18 +13079,17 @@ Select the newly added converter as the preferred one by customizing the option @code{org-odt-convert-process}. @end enumerate -@node Working with OpenDocument style files, Creating one-off styles, Configuring a document converter, Advanced topics in ODT export -@subsubsection Working with OpenDocument style files +@node Working with OpenDocument style files +@subsubheading Working with OpenDocument style files @cindex styles, custom @cindex template, custom -This section explores the internals of the ODT exporter and the -means by which it produces styled documents. Read this section if you are -interested in exploring the automatic and custom OpenDocument styles used by -the exporter. +This section explores the internals of the ODT exporter; the means by which +it produces styled documents; the use of automatic and custom OpenDocument +styles. @anchor{x-factory-styles} -@subsubheading Factory styles +@subsubheading a) Factory styles The ODT exporter relies on two files for generating its output. These files are bundled with the distribution under the directory pointed to @@ -12524,25 +13130,25 @@ the exporter. @item It contains @samp{<text:sequence-decl>}@dots{}@samp{</text:sequence-decl>} -elements that control how various entities---tables, images, equations, -etc.---are numbered. +elements that control numbering of tables, images, equations, and similar +entities. @end enumerate @end itemize @anchor{x-overriding-factory-styles} -@subsubheading Overriding factory styles -The following two variables control the location from which the ODT -exporter picks up the custom styles and content template files. You can -customize these variables to override the factory styles used by the -exporter. +@subsubheading b) Overriding factory styles +The following two variables control the location from where the ODT exporter +picks up the custom styles and content template files. Customize these +variables to override the factory styles used by the exporter. @itemize @anchor{x-org-odt-styles-file} @item @code{org-odt-styles-file} -Use this variable to specify the @file{styles.xml} that will be used in the -final output. You can specify one of the following values: +The ODT export back-end uses the file pointed to by this variable, such as +@file{styles.xml}, for the final output. It can take one of the following +values: @enumerate @item A @file{styles.xml} file @@ -12576,28 +13182,26 @@ Use this variable to specify the blank @file{content.xml} that will be used in the final output. @end itemize -@node Creating one-off styles, Customizing tables in ODT export, Working with OpenDocument style files, Advanced topics in ODT export -@subsubsection Creating one-off styles +@node Creating one-off styles +@subsubheading Creating one-off styles -There are times when you would want one-off formatting in the exported -document. You can achieve this by embedding raw OpenDocument XML in the Org -file. The use of this feature is better illustrated with couple of examples. +The ODT export back-end can read embedded raw OpenDocument XML from the Org +file. Such direct formatting are useful for one-off instances. @enumerate @item Embedding ODT tags as part of regular text -You can inline OpenDocument syntax by enclosing it within -@samp{@@@@odt:...@@@@} markup. For example, to highlight a region of text do -the following: +Enclose OpenDocument syntax in @samp{@@@@odt:...@@@@} for inline markup. For +example, to highlight a region of text do the following: @example -@@@@odt:<text:span text:style-name="Highlight">This is a highlighted -text</text:span>@@@@. But this is a regular text. +@@@@odt:<text:span text:style-name="Highlight">This is highlighted +text</text:span>@@@@. But this is regular text. @end example -@strong{Hint:} To see the above example in action, edit your -@file{styles.xml} (@pxref{x-orgodtstyles-xml,,Factory styles}) and add a -custom @samp{Highlight} style as shown below. +@strong{Hint:} To see the above example in action, edit the @file{styles.xml} +(@pxref{x-orgodtstyles-xml,,Factory styles}) and add a custom +@samp{Highlight} style as shown below: @example <style:style style:name="Highlight" style:family="text"> @@ -12607,8 +13211,8 @@ custom @samp{Highlight} style as shown below. @item Embedding a one-line OpenDocument XML -You can add a simple OpenDocument one-liner using the @code{#+ODT:} -directive. For example, to force a page break do the following: +The ODT export back-end can read one-liner options with @code{#+ODT:} +in the Org file. For example, to force a page break: @example #+ODT: <text:p text:style-name="PageBreak"/> @@ -12627,41 +13231,40 @@ custom @samp{PageBreak} style as shown below. @item Embedding a block of OpenDocument XML -You can add a large block of OpenDocument XML using the -@code{#+BEGIN_ODT}@dots{}@code{#+END_ODT} construct. +The ODT export back-end can also read ODT export blocks for OpenDocument XML. +Such blocks use the @code{#+BEGIN_EXPORT odt}@dots{}@code{#+END_EXPORT} +constructs. For example, to create a one-off paragraph that uses bold text, do the following: @example -#+BEGIN_ODT +#+BEGIN_EXPORT odt <text:p text:style-name="Text_20_body_20_bold"> This paragraph is specially formatted and uses bold text. </text:p> -#+END_ODT +#+END_EXPORT @end example @end enumerate -@node Customizing tables in ODT export, Validating OpenDocument XML, Creating one-off styles, Advanced topics in ODT export -@subsubsection Customizing tables in ODT export +@node Customizing tables in ODT export +@subsubheading Customizing tables in ODT export @cindex tables, in ODT export @cindex #+ATTR_ODT -You can override the default formatting of the table by specifying a custom -table style with the @code{#+ATTR_ODT} line. For a discussion on default -formatting of tables @pxref{Tables in ODT export}. +Override the default table format by specifying a custom table style with the +@code{#+ATTR_ODT} line. For a discussion on default formatting of tables +@pxref{Tables in ODT export}. This feature closely mimics the way table templates are defined in the OpenDocument-v1.2 specification.@footnote{@url{http://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2.html, OpenDocument-v1.2 Specification}} -@subsubheading Custom table styles: an illustration - @vindex org-odt-table-styles -To have a quick preview of this feature, install the below setting and -export the table that follows: +For quick preview of this feature, install the settings below and export the +table that follows: @lisp (setq org-odt-table-styles @@ -12675,22 +13278,20 @@ export the table that follows: @end lisp @example -#+ATTR_ODT: :style "TableWithHeaderRowAndColumn" +#+ATTR_ODT: :style TableWithHeaderRowAndColumn | Name | Phone | Age | | Peter | 1234 | 17 | | Anna | 4321 | 25 | @end example -In the above example, you used a template named @samp{Custom} and installed -two table styles with the names @samp{TableWithHeaderRowAndColumn} and -@samp{TableWithFirstRowandLastRow}. (@strong{Important:} The OpenDocument -styles needed for producing the above template have been pre-defined for -you. These styles are available under the section marked @samp{Custom -Table Template} in @file{OrgOdtContentTemplate.xml} -(@pxref{x-orgodtcontenttemplate-xml,,Factory styles}). If you need -additional templates you have to define these styles yourselves. +The example above used @samp{Custom} template and installed two table styles +@samp{TableWithHeaderRowAndColumn} and @samp{TableWithFirstRowandLastRow}. +@strong{Important:} The OpenDocument styles needed for producing the above +template were pre-defined. They are available in the section marked +@samp{Custom Table Template} in @file{OrgOdtContentTemplate.xml} +(@pxref{x-orgodtcontenttemplate-xml,,Factory styles}. For adding new +templates, define new styles here. -@subsubheading Custom table styles: the nitty-gritty To use this feature proceed as follows: @enumerate @@ -12698,8 +13299,8 @@ To use this feature proceed as follows: Create a table template@footnote{See the @code{<table:table-template>} element of the OpenDocument-v1.2 specification} -A table template is nothing but a set of @samp{table-cell} and -@samp{paragraph} styles for each of the following table cell categories: +A table template is set of @samp{table-cell} and @samp{paragraph} styles for +each of the following table cell categories: @itemize @minus @item Body @@ -12809,25 +13410,22 @@ the @code{ATTR_ODT} line as shown below. @end example @end enumerate -@node Validating OpenDocument XML, , Customizing tables in ODT export, Advanced topics in ODT export -@subsubsection Validating OpenDocument XML +@node Validating OpenDocument XML +@subsubheading Validating OpenDocument XML -Occasionally, you will discover that the document created by the -ODT exporter cannot be opened by your favorite application. One of -the common reasons for this is that the @file{.odt} file is corrupt. In such -cases, you may want to validate the document against the OpenDocument RELAX -NG Compact Syntax (RNC) schema. - -For de-compressing the @file{.odt} file@footnote{@file{.odt} files are -nothing but @samp{zip} archives}: @inforef{File Archives,,emacs}. For -general help with validation (and schema-sensitive editing) of XML files: +Sometimes ODT format files may not open due to @file{.odt} file corruption. +To verify if the @file{.odt} file is corrupt, validate it against the +OpenDocument RELAX NG Compact Syntax---RNC---schema. But first the +@file{.odt} files have to be decompressed using @samp{zip}. Note that +@file{.odt} files are @samp{zip} archives: @inforef{File Archives,,emacs}. +The contents of @file{.odt} files are in @file{.xml}. For general help with +validation---and schema-sensitive editing---of XML files: @inforef{Introduction,,nxml-mode}. @vindex org-odt-schema-dir -If you have ready access to OpenDocument @file{.rnc} files and the needed -schema-locating rules in a single folder, you can customize the variable -@code{org-odt-schema-dir} to point to that directory. The ODT exporter -will take care of updating the @code{rng-schema-locating-files} for you. +Customize @code{org-odt-schema-dir} to point to a directory with OpenDocument +@file{.rnc} files and the needed schema-locating rules. The ODT export +back-end takes care of updating the @code{rng-schema-locating-files}. @c end opendocument @@ -12836,102 +13434,146 @@ will take care of updating the @code{rng-schema-locating-files} for you. @cindex Org export @code{org} export back-end creates a normalized version of the Org document -in current buffer. In particular, it evaluates Babel code (@pxref{Evaluating -code blocks}) and removes other back-ends specific contents. +in current buffer. The exporter evaluates Babel code (@pxref{Evaluating code +blocks}) and removes content specific to other back-ends. @subheading Org export commands @table @kbd @orgcmd{C-c C-e O o,org-org-export-to-org} -Export as an Org document. For an Org file, @file{myfile.org}, the resulting -file will be @file{myfile.org.org}. The file will be overwritten without -warning. +Export as an Org file with a @file{.org} extension. For @file{myfile.org}, +Org exports to @file{myfile.org.org}, overwriting without warning. + @orgcmd{C-c C-e O O,org-org-export-as-org} -Export to a temporary buffer. Do not create a file. +Export to a temporary buffer. Does not create a file. @item C-c C-e O v Export to an Org file, then open it. @end table -@node Texinfo export, iCalendar export, Org export, Exporting +@node Texinfo export @section Texinfo export @cindex Texinfo export -@samp{texinfo} export back-end generates Texinfo code and can compile it into -an Info file. +The @samp{texinfo} export back-end generates documents with Texinfo code that +can compile to Info format. @menu -* Texinfo export commands:: How to invoke Texinfo export -* Document preamble:: File header, title and copyright page -* Headings and sectioning structure:: Building document structure -* Indices:: Creating indices -* Quoting Texinfo code:: Incorporating literal Texinfo code -* Texinfo specific attributes:: Controlling Texinfo output -* An example:: +* Texinfo export commands:: Invoking commands. +* Texinfo specific export settings:: Setting the environment. +* Texinfo file header:: Generating the header. +* Texinfo title and copyright page:: Creating preamble pages. +* Info directory file:: Installing a manual in Info file hierarchy. +* Headings and sectioning structure:: Building document structure. +* Indices:: Creating indices. +* Quoting Texinfo code:: Incorporating literal Texinfo code. +* Plain lists in Texinfo export:: List attributes. +* Tables in Texinfo export:: Table attributes. +* Images in Texinfo export:: Image attributes. +* Special blocks in Texinfo export:: Special block attributes. +* A Texinfo example:: Processing Org to Texinfo. @end menu -@node Texinfo export commands, Document preamble, Texinfo export, Texinfo export +@node Texinfo export commands @subsection Texinfo export commands @vindex org-texinfo-info-process @table @kbd @orgcmd{C-c C-e i t,org-texinfo-export-to-texinfo} -Export as a Texinfo file. For an Org file, @file{myfile.org}, the resulting -file will be @file{myfile.texi}. The file will be overwritten without -warning. +Export as a Texinfo file with @file{.texi} extension. For @file{myfile.org}, +Org exports to @file{myfile.texi}, overwriting without warning. @orgcmd{C-c C-e i i,org-texinfo-export-to-info} -Export to Texinfo and then process to an Info file@footnote{By setting -@code{org-texinfo-info-process}, it is possible to generate other formats, -including DocBook.}. +Export to Texinfo format first and then process it to make an Info file. To +generate other formats, such as DocBook, customize the +@code{org-texinfo-info-process} variable. @end table -@node Document preamble, Headings and sectioning structure, Texinfo export commands, Texinfo export -@subsection Document preamble +@node Texinfo specific export settings +@subsection Texinfo specific export settings +The Texinfo export back-end has several additional keywords for customizing +Texinfo output. Setting these keywords works similar to the general options +(@pxref{Export settings}). + +@table @samp + +@item SUBTITLE +@cindex #+SUBTITLE (Texinfo) +The document subtitle. + +@item SUBAUTHOR +@cindex #+SUBAUTHOR +The document subauthor. + +@item TEXINFO_FILENAME +@cindex #+TEXINFO_FILENAME +The Texinfo filename. + +@item TEXINFO_CLASS +@cindex #+TEXINFO_CLASS +@vindex org-texinfo-default-class +The default document class (@code{org-texinfo-default-class}), which must be +a member of @code{org-texinfo-classes}. + +@item TEXINFO_HEADER +@cindex #+TEXINFO_HEADER +Arbitrary lines inserted at the end of the header. + +@item TEXINFO_POST_HEADER +@cindex #+TEXINFO_POST_HEADER +Arbitrary lines inserted after the end of the header. + +@item TEXINFO_DIR_CATEGORY +@cindex #+TEXINFO_DIR_CATEGORY +The directory category of the document. + +@item TEXINFO_DIR_TITLE +@cindex #+TEXINFO_DIR_TITLE +The directory title of the document. + +@item TEXINFO_DIR_DESC +@cindex #+TEXINFO_DIR_DESC +The directory description of the document. -When processing a document, @samp{texinfo} back-end generates a minimal file -header along with a title page, a copyright page, and a menu. You control -the latter through the structure of the document (@pxref{Headings and -sectioning structure}). Various keywords allow you to tweak the other parts. -It is also possible to give directions to install the document in the -@samp{Top} node. +@item TEXINFO_PRINTED_TITLE +@cindex #+TEXINFO_PRINTED_TITLE +The printed title of the document. +@end table -@subsubheading File header +@node Texinfo file header +@subsection Texinfo file header @cindex #+TEXINFO_FILENAME -Upon creating the header of a Texinfo file, the back-end guesses a name for -the Info file to be compiled. This may not be a sensible choice, e.g., if -you want to produce the final document in a different directory. Specify an -alternate path with @code{#+TEXINFO_FILENAME} keyword to override the default -destination. +After creating the header for a Texinfo file, the Texinfo back-end +automatically generates a name and destination path for the Info file. To +override this default with a more sensible path and name, specify the +@code{#+TEXINFO_FILENAME} keyword. @vindex org-texinfo-coding-system @vindex org-texinfo-classes @cindex #+TEXINFO_HEADER @cindex #+TEXINFO_CLASS -Along with the output file name, the header contains information about the -language (@pxref{Export settings}) and current encoding used@footnote{See -@code{org-texinfo-coding-system} for more information.}. Insert -a @code{#+TEXINFO_HEADER} keyword for each additional command needed, e.g., +Along with the output's file name, the Texinfo header also contains language +details (@pxref{Export settings}) and encoding system as set in the +@code{org-texinfo-coding-system} variable. Insert @code{#+TEXINFO_HEADER} +keywords for each additional command in the header, for example: @@code@{@@synindex@}. -If you happen to regularly install the same set of commands, it may be easier -to define your own class in @code{org-texinfo-classes}, which see. Set -@code{#+TEXINFO_CLASS} keyword accordingly in your document to activate it. +Instead of repeatedly installing the same set of commands, define a class in +@code{org-texinfo-classes} once, and then activate it in the document by +setting the @code{#+TEXINFO_CLASS} keyword to that class. -@subsubheading Title and copyright page +@node Texinfo title and copyright page +@subsection Texinfo title and copyright page @cindex #+TEXINFO_PRINTED_TITLE -@cindex #+SUBTITLE -The default template includes a title page for hard copy output. The title -and author displayed on this page are extracted from, respectively, -@code{#+TITLE} and @code{#+AUTHOR} keywords (@pxref{Export settings}). It is -also possible to print a different, more specific, title with -@code{#+TEXINFO_PRINTED_TITLE} keyword, and add subtitles with -@code{#+SUBTITLE} keyword. Both expect raw Texinfo code in their value. +The default template for hard copy output has a title page with +@code{#+TITLE} and @code{#+AUTHOR} (@pxref{Export settings}). To replace the +regular @code{#+TITLE} with something different for the printed version, use +the @code{#+TEXINFO_PRINTED_TITLE} and @code{#+SUBTITLE} keywords. Both +expect raw Texinfo code for setting their values. @cindex #+SUBAUTHOR -Likewise, information brought by @code{#+AUTHOR} may not be enough. You can -include other authors with several @code{#+SUBAUTHOR} keywords. Values are -also expected to be written in Texinfo code. +If one @code{#+AUTHOR} is not sufficient, add multiple @code{#+SUBAUTHOR} +keywords. They have to be set in raw Texinfo code. @example #+AUTHOR: Jane Smith @@ -12940,10 +13582,10 @@ also expected to be written in Texinfo code. @end example @cindex property, COPYING -Copying material is defined in a dedicated headline with a non-nil -@code{:COPYING:} property. The contents are inserted within -a @code{@@copying} command at the beginning of the document whereas the -heading itself does not appear in the structure of the document. +Copying material is defined in a dedicated headline with a non-@code{nil} +@code{:COPYING:} property. The back-end inserts the contents within a +@code{@@copying} command at the beginning of the document. The heading +itself does not appear in the structure of the document. Copyright information is printed on the back of the title page. @@ -12955,20 +13597,28 @@ Copyright information is printed on the back of the title page. This is a short example of a complete Texinfo file, version 1.0. - Copyright \copy 2017 Free Software Foundation, Inc. + Copyright \copy 2016 Free Software Foundation, Inc. @end example -@subsubheading The Top node +@node Info directory file +@subsection Info directory file +@cindex @samp{dir} file, in Texinfo export +@cindex Texinfo export, @samp{dir} file +@cindex Info directory file, in Texinfo export +@cindex Texinfo export, Info directory file +@cindex @code{install-info} parameters, in Texinfo export +@cindex Texinfo export, @code{install-info} parameters @cindex #+TEXINFO_DIR_CATEGORY @cindex #+TEXINFO_DIR_TITLE @cindex #+TEXINFO_DIR_DESC -You may ultimately want to install your new Info file to your system. You -can write an appropriate entry in the top level directory specifying its -category and title with, respectively, @code{#+TEXINFO_DIR_CATEGORY} and -@code{#+TEXINFO_DIR_TITLE}. Optionally, you can add a short description -using @code{#+TEXINFO_DIR_DESC}. The following example would write an entry -similar to Org's in the @samp{Top} node. +The end result of the Texinfo export process is the creation of an Info file. +This Info file's metadata has variables for category, title, and description: +@code{#+TEXINFO_DIR_CATEGORY}, @code{#+TEXINFO_DIR_TITLE}, and +@code{#+TEXINFO_DIR_DESC} that establish where in the Info hierarchy the file +fits. + +Here is an example that writes to the Info directory file: @example #+TEXINFO_DIR_CATEGORY: Emacs @@ -12976,34 +13626,38 @@ similar to Org's in the @samp{Top} node. #+TEXINFO_DIR_DESC: Outline-based notes management and organizer @end example -@node Headings and sectioning structure, Indices, Document preamble, Texinfo export +@node Headings and sectioning structure @subsection Headings and sectioning structure @vindex org-texinfo-classes @vindex org-texinfo-default-class @cindex #+TEXINFO_CLASS -@samp{texinfo} uses a pre-defined scheme, or class, to convert headlines into -Texinfo structuring commands. For example, a top level headline appears as -@code{@@chapter} if it should be numbered or as @code{@@unnumbered} -otherwise. If you need to use a different set of commands, e.g., to start -with @code{@@part} instead of @code{@@chapter}, install a new class in -@code{org-texinfo-classes}, then activate it with @code{#+TEXINFO_CLASS} -keyword. Export process defaults to @code{org-texinfo-default-class} when -there is no such keyword in the document. - -If a headline's level has no associated structuring command, or is below -a certain threshold @pxref{Export settings}, that headline becomes a list in -Texinfo output. +The Texinfo export back-end uses a pre-defined scheme to convert Org +headlines to an equivalent Texinfo structuring commands. A scheme like this +maps top-level headlines to numbered chapters tagged as @code{@@chapter} and +lower-level headlines to unnumbered chapters tagged as @code{@@unnumbered}. +To override such mappings to introduce @code{@@part} or other Texinfo +structuring commands, define a new class in @code{org-texinfo-classes}. +Activate the new class with the @code{#+TEXINFO_CLASS} keyword. When no new +class is defined and activated, the Texinfo export back-end defaults to the +@code{org-texinfo-default-class}. + +If an Org headline's level has no associated Texinfo structuring command, or +is below a certain threshold (@pxref{Export settings}), then the Texinfo +export back-end makes it into a list item. @cindex property, APPENDIX -As an exception, a headline with a non-nil @code{:APPENDIX:} property becomes -an appendix, independently on its level and the class used. +The Texinfo export back-end makes any headline with a non-@code{nil} +@code{:APPENDIX:} property into an appendix. This happens independent of the +Org headline level or the @code{#+TEXINFO_CLASS}. @cindex property, DESCRIPTION -Each regular sectioning structure creates a menu entry, named after the -heading. You can provide a different, e.g., shorter, title in -@code{:ALT_TITLE:} property (@pxref{Table of contents}). Optionally, you can -specify a description for the item in @code{:DESCRIPTION:} property. E.g., +The Texinfo export back-end creates a menu entry after the Org headline for +each regular sectioning structure. To override this with a shorter menu +entry, use the @code{:ALT_TITLE:} property (@pxref{Table of contents}). +Texinfo menu entries also have an option for a longer @code{:DESCRIPTION:} +property. Here's an example that uses both to override the default menu +entry: @example * Controlling Screen Display @@ -13013,30 +13667,51 @@ specify a description for the item in @code{:DESCRIPTION:} property. E.g., :END: @end example -@node Indices, Quoting Texinfo code, Headings and sectioning structure, Texinfo export +@cindex The Top node, in Texinfo export +@cindex Texinfo export, Top node +The text before the first headline belongs to the @samp{Top} node, i.e., the +node in which a reader enters an Info manual. As such, it is expected not to +appear in printed output generated from the @file{.texi} file. @inforef{The +Top Node,,texinfo}, for more information. + +@node Indices @subsection Indices @cindex #+CINDEX +@cindex concept index, in Texinfo export +@cindex Texinfo export, index, concept @cindex #+FINDEX +@cindex function index, in Texinfo export +@cindex Texinfo export, index, function @cindex #+KINDEX +@cindex keystroke index, in Texinfo export +@cindex Texinfo export, keystroke index @cindex #+PINDEX +@cindex program index, in Texinfo export +@cindex Texinfo export, program index @cindex #+TINDEX +@cindex data type index, in Texinfo export +@cindex Texinfo export, data type index @cindex #+VINDEX -Index entries are created using dedicated keywords. @samp{texinfo} back-end -provides one for each predefined type: @code{#+CINDEX}, @code{#+FINDEX}, -@code{#+KINDEX}, @code{#+PINDEX}, @code{#+TINDEX} and @code{#+VINDEX}. For -custom indices, you can write raw Texinfo code (@pxref{Quoting Texinfo -code}). +@cindex variable index, in Texinfo export +@cindex Texinfo export, variable index +The Texinfo export back-end recognizes these indexing keywords if used in the +Org file: @code{#+CINDEX}, @code{#+FINDEX}, @code{#+KINDEX}, @code{#+PINDEX}, +@code{#+TINDEX}, and @code{#+VINDEX}. Write their value as verbatim Texinfo +code; in particular, @samp{@{}, @samp{@}} and @samp{@@} characters need to be +escaped with @samp{@@} if they not belong to a Texinfo command. @example #+CINDEX: Defining indexing entries @end example @cindex property, INDEX -To generate an index, you need to set the @code{:INDEX:} property of -a headline to an appropriate abbreviation (e.g., @samp{cp} or @samp{vr}). -The headline is then exported as an unnumbered chapter or section command and -the index is inserted after its contents. +For the back-end to generate an index entry for a headline, set the +@code{:INDEX:} property to @samp{cp} or @samp{vr}. These abbreviations come +from Texinfo that stand for concept index and variable index. The Texinfo +manual has abbreviations for all other kinds of indexes. The back-end +exports the headline as an unnumbered chapter or section command, and then +inserts the index after its contents. @example * Concept Index @@ -13045,78 +13720,115 @@ the index is inserted after its contents. :END: @end example -@node Quoting Texinfo code, Texinfo specific attributes, Indices, Texinfo export +@node Quoting Texinfo code @subsection Quoting Texinfo code -It is possible to insert raw Texinfo code using any of the following -constructs +Use any of the following three methods to insert or escape raw Texinfo code: @cindex #+TEXINFO -@cindex #+BEGIN_TEXINFO +@cindex #+BEGIN_EXPORT texinfo @example Richard @@@@texinfo:@@sc@{@@@@Stallman@@@@texinfo:@}@@@@ commence' GNU. #+TEXINFO: @@need800 This paragraph is preceded by... -#+BEGIN_TEXINFO +#+BEGIN_EXPORT texinfo @@auindex Johnson, Mark @@auindex Lakoff, George -#+END_TEXINFO +#+END_EXPORT @end example -@node Texinfo specific attributes, An example, Quoting Texinfo code, Texinfo export -@subsection Texinfo specific attributes - -@cindex #+ATTR_TEXINFO -@samp{texinfo} back-end understands several attributes in plain lists and -tables. They must be specified using an @code{#+ATTR_TEXINFO} keyword, -written just above the list or table. - -@subsubheading Plain lists - -In Texinfo output, description lists appear as two-column tables, using the -default command @code{@@table}. You can use @code{@@ftable} or -@code{@@vtable}@footnote{For more information, @inforef{Two-column -Tables,,texinfo}.} instead with @code{:table-type} attribute. +@node Plain lists in Texinfo export +@subsection Plain lists in Texinfo export +@cindex #+ATTR_TEXINFO, in plain lists +The Texinfo export back-end by default converts description lists in the Org +file using the default command @code{@@table}, which results in a table with +two columns. To change this behavior, specify @code{:table-type} with +@code{@@ftable} or @code{@@vtable} attributes. For more information, +@inforef{Two-column Tables,,texinfo}. @vindex org-texinfo-def-table-markup -In any case, these constructs require a highlighting command for entries in -the list. You can provide one with @code{:indic} attribute. If you do not, -it defaults to the value stored in @code{org-texinfo-def-table-markup}, which -see. +The Texinfo export back-end by default also applies a text highlight based on +the defaults stored in @code{org-texinfo-def-table-markup}. To override the +default highlight command, specify another one with the @code{:indic} +attribute as shown in this example: @example #+ATTR_TEXINFO: :indic @@asis - foo :: This is the text for /foo/, with no highlighting. @end example -@subsubheading Tables +@node Tables in Texinfo export +@subsection Tables in Texinfo export +@cindex #+ATTR_TEXINFO, in tables -When exporting a table, column widths are deduced from the longest cell in -each column. You can also define them explicitly as fractions of the line -length, using @code{:columns} attribute. +When exporting tables, the Texinfo export back-end uses the widest cell width +in each column. To override this and instead specify as fractions of line +length, use the @code{:columns} attribute. See example below. @example #+ATTR_TEXINFO: :columns .5 .5 | a cell | another cell | @end example -@node An example, , Texinfo specific attributes, Texinfo export -@subsection An example +@node Images in Texinfo export +@subsection Images in Texinfo export +@cindex #+ATTR_TEXINFO, in images -Here is a thorough example, taken from @inforef{GNU Sample Texts,,texinfo}. +Insert a file link to the image in the Org file, and the Texinfo export +back-end inserts the image. These links must have the usual supported image +extensions and no descriptions. To scale the image, use @code{:width} and +@code{:height} attributes. For alternate text, use @code{:alt} and specify +the text using Texinfo code, as shown in the example: -@smallexample -#+MACRO: version 2.0 -#+MACRO: updated last updated 4 March 2014 +@example +#+ATTR_TEXINFO: :width 1in :alt Alternate @@i@{text@} +[[ridt.pdf]] +@end example -#+OPTIONS: ':t toc:t author:t email:t +@node Special blocks in Texinfo export +@subsection Special blocks +@cindex #+ATTR_TEXINFO, in special blocks + +The Texinfo export back-end converts special blocks to commands with the same +name. It also adds any @code{:options} attributes to the end of the command, +as shown in this example: + +@example +#+ATTR_TEXINFO: :options org-org-export-to-org ... +#+begin_defun +A somewhat obsessive function. +#+end_defun +@end example + +@noindent +becomes + +@example +@@defun org-org-export-to-org ... +A somewhat obsessive function. +@@end defun +@end example + +@node A Texinfo example +@subsection A Texinfo example + +Here is a more detailed example Org file. @inforef{GNU Sample +Texts,,texinfo} for an equivalent example using Texinfo code. + +@example #+TITLE: GNU Sample @{@{@{version@}@}@} +#+SUBTITLE: for version @{@{@{version@}@}@}, @{@{@{updated@}@}@} #+AUTHOR: A.U. Thor #+EMAIL: bug-sample@@gnu.org + +#+OPTIONS: ':t toc:t author:t email:t #+LANGUAGE: en +#+MACRO: version 2.0 +#+MACRO: updated last updated 4 March 2014 + #+TEXINFO_FILENAME: sample.info #+TEXINFO_HEADER: @@syncodeindex pg cp @@ -13125,7 +13837,9 @@ Here is a thorough example, taken from @inforef{GNU Sample Texts,,texinfo}. #+TEXINFO_DIR_DESC: Invoking sample #+TEXINFO_PRINTED_TITLE: GNU Sample -#+SUBTITLE: for version 2.0, last updated 4 March 2014 + +This manual is for GNU Sample (version @{@{@{version@}@}@}, +@{@{@{updated@}@}@}). * Copying :PROPERTIES: @@ -13135,8 +13849,7 @@ Here is a thorough example, taken from @inforef{GNU Sample Texts,,texinfo}. This manual is for GNU Sample (version @{@{@{version@}@}@}, @{@{@{updated@}@}@}), which is an example in the Texinfo documentation. - Copyright @@@@texinfo:@@copyright@{@}@@@@ 2013 Free Software Foundation, - Inc. + Copyright \copy 2016 Free Software Foundation, Inc. #+BEGIN_QUOTE Permission is granted to copy, distribute and/or modify this @@ -13167,9 +13880,9 @@ Here is a thorough example, taken from @inforef{GNU Sample Texts,,texinfo}. :PROPERTIES: :INDEX: cp :END: -@end smallexample +@end example -@node iCalendar export, Other built-in back-ends, Texinfo export, Exporting +@node iCalendar export @section iCalendar export @cindex iCalendar export @@ -13178,49 +13891,51 @@ Here is a thorough example, taken from @inforef{GNU Sample Texts,,texinfo}. @vindex org-icalendar-use-scheduled @vindex org-icalendar-categories @vindex org-icalendar-alarm-time -Some people use Org mode for keeping track of projects, but still prefer a -standard calendar application for anniversaries and appointments. In this -case it can be useful to show deadlines and other time-stamped items in Org -files in the calendar application. Org mode can export calendar information -in the standard iCalendar format. If you also want to have TODO entries -included in the export, configure the variable -@code{org-icalendar-include-todo}. Plain timestamps are exported as VEVENT, -and TODO items as VTODO@. It will also create events from deadlines that are -in non-TODO items. Deadlines and scheduling dates in TODO items will be used -to set the start and due dates for the TODO entry@footnote{See the variables -@code{org-icalendar-use-deadline} and @code{org-icalendar-use-scheduled}.}. -As categories, it will use the tags locally defined in the heading, and the -file/tree category@footnote{To add inherited tags or the TODO state, -configure the variable @code{org-icalendar-categories}.}. See the variable -@code{org-icalendar-alarm-time} for a way to assign alarms to entries with a -time. +A large part of Org mode's inter-operability success is its ability to easily +export to or import from external applications. The iCalendar export +back-end takes calendar data from Org files and exports to the standard +iCalendar format. + +The iCalendar export back-end can also incorporate TODO entries based on the +configuration of the @code{org-icalendar-include-todo} variable. The +back-end exports plain timestamps as VEVENT, TODO items as VTODO, and also +create events from deadlines that are in non-TODO items. The back-end uses +the deadlines and scheduling dates in Org TODO items for setting the start +and due dates for the iCalendar TODO entry. Consult the +@code{org-icalendar-use-deadline} and @code{org-icalendar-use-scheduled} +variables for more details. + +For tags on the headline, the iCalendar export back-end makes them into +iCalendar categories. To tweak the inheritance of tags and TODO states, +configure the variable @code{org-icalendar-categories}. To assign clock +alarms based on time, configure the @code{org-icalendar-alarm-time} variable. @vindex org-icalendar-store-UID @cindex property, ID -The iCalendar standard requires each entry to have a globally unique -identifier (UID). Org creates these identifiers during export. If you set -the variable @code{org-icalendar-store-UID}, the UID will be stored in the -@code{:ID:} property of the entry and re-used next time you report this -entry. Since a single entry can give rise to multiple iCalendar entries (as -a timestamp, a deadline, a scheduled item, and as a TODO item), Org adds -prefixes to the UID, depending on what triggered the inclusion of the entry. -In this way the UID remains unique, but a synchronization program can still -figure out from which entry all the different instances originate. +The iCalendar format standard requires globally unique identifier---UID---for +each entry. The iCalendar export back-end creates UIDs during export. To +save a copy of the UID in the Org file set the variable +@code{org-icalendar-store-UID}. The back-end looks for the @code{:ID:} +property of the entry for re-using the same UID for subsequent exports. + +Since a single Org entry can result in multiple iCalendar entries---as +timestamp, deadline, scheduled item, or TODO item---Org adds prefixes to the +UID, depending on which part of the Org entry triggered the creation of the +iCalendar entry. Prefixing ensures UIDs remains unique, yet enable +synchronization programs trace the connections. @table @kbd @orgcmd{C-c C-e c f,org-icalendar-export-to-ics} -Create iCalendar entries for the current buffer and store them in the same -directory, using a file extension @file{.ics}. +Create iCalendar entries from the current Org buffer and store them in the +same directory, using a file extension @file{.ics}. @orgcmd{C-c C-e c a, org-icalendar-export-agenda-files} @vindex org-agenda-files -Like @kbd{C-c C-e c f}, but do this for all files in -@code{org-agenda-files}. For each of these files, a separate iCalendar -file will be written. +Create iCalendar entries from Org files in @code{org-agenda-files} and store +in a separate iCalendar file for each Org file. @orgcmd{C-c C-e c c,org-icalendar-combine-agenda-files} @vindex org-icalendar-combined-agenda-file -Create a single large iCalendar file from all files in -@code{org-agenda-files} and write it to the file given by -@code{org-icalendar-combined-agenda-file}. +Create a combined iCalendar file from Org files in @code{org-agenda-files} +and write it to @code{org-icalendar-combined-agenda-file} file name. @end table @vindex org-use-property-inheritance @@ -13228,72 +13943,54 @@ Create a single large iCalendar file from all files in @cindex property, SUMMARY @cindex property, DESCRIPTION @cindex property, LOCATION -The export will honor SUMMARY, DESCRIPTION and LOCATION@footnote{The LOCATION -property can be inherited from higher in the hierarchy if you configure -@code{org-use-property-inheritance} accordingly.} properties if the selected -entries have them. If not, the summary will be derived from the headline, -and the description from the body (limited to -@code{org-icalendar-include-body} characters). - -How this calendar is best read and updated, depends on the application -you are using. The FAQ covers this issue. - -@node Other built-in back-ends, Export in foreign buffers, iCalendar export, Exporting +The iCalendar export back-end includes SUMMARY, DESCRIPTION and LOCATION +properties from the Org entries when exporting. To force the back-end to +inherit the LOCATION property, configure the +@code{org-use-property-inheritance} variable. + +When Org entries do not have SUMMARY, DESCRIPTION and LOCATION properties, +the iCalendar export back-end derives the summary from the headline, and +derives the description from the body of the Org item. The +@code{org-icalendar-include-body} variable limits the maximum number of +characters of the content are turned into its description. + +Exporting to iCalendar format depends in large part on the capabilities of +the destination application. Some are more lenient than others. Consult the +Org mode FAQ for advice on specific applications. + +@node Other built-in back-ends @section Other built-in back-ends @cindex export back-ends, built-in @vindex org-export-backends -On top of the aforementioned back-ends, Org comes with other built-in ones: +Other export back-ends included with Org are: @itemize @item @file{ox-man.el}: export to a man page. @end itemize -To activate these export back-end, customize @code{org-export-backends} or -load them directly with e.g., @code{(require 'ox-man)}. This will add new -keys in the export dispatcher (@pxref{The Export Dispatcher}). - -See the comment section of these files for more information on how to use -them. - -@node Export in foreign buffers, Advanced configuration, Other built-in back-ends, Exporting -@section Export in foreign buffers - -Most built-in back-ends come with a command to convert the selected region -into a selected format and replace this region by the exported output. Here -is a list of such conversion commands: - -@table @code -@item org-html-convert-region-to-html -Convert the selected region into HTML. -@item org-latex-convert-region-to-latex -Convert the selected region into @LaTeX{}. -@item org-texinfo-convert-region-to-texinfo -Convert the selected region into @code{Texinfo}. -@item org-md-convert-region-to-md -Convert the selected region into @code{MarkDown}. -@end table +To activate such back-ends, either customize @code{org-export-backends} or +load directly with @code{(require 'ox-man)}. On successful load, the +back-end adds new keys in the export dispatcher (@pxref{The export +dispatcher}). -This is particularly useful for converting tables and lists in foreign -buffers. E.g., in an HTML buffer, you can turn on @code{orgstruct-mode}, then -use Org commands for editing a list, and finally select and convert the list -with @code{M-x org-html-convert-region-to-html RET}. +Follow the comment section of such files, for example, @file{ox-man.el}, for +usage and configuration details. -@node Advanced configuration, , Export in foreign buffers, Exporting +@node Advanced configuration @section Advanced configuration @subheading Hooks @vindex org-export-before-processing-hook @vindex org-export-before-parsing-hook -Two hooks are run during the first steps of the export process. The first -one, @code{org-export-before-processing-hook} is called before expanding -macros, Babel code and include keywords in the buffer. The second one, -@code{org-export-before-parsing-hook}, as its name suggests, happens just -before parsing the buffer. Their main use is for heavy duties, that is -duties involving structural modifications of the document. For example, one -may want to remove every headline in the buffer during export. The following -code can achieve this: +The export process executes two hooks before the actual exporting begins. +The first hook, @code{org-export-before-processing-hook}, runs before any +expansions of macros, Babel code, and include keywords in the buffer. The +second hook, @code{org-export-before-parsing-hook}, runs before the buffer is +parsed. Both hooks are specified as functions, see example below. Their main +use is for heavy duty structural modifications of the Org content. For +example, removing every headline in the buffer during export: @lisp @group @@ -13307,86 +14004,83 @@ BACKEND is the export back-end being used, as a symbol." @end group @end lisp -Note that functions used in these hooks require a mandatory argument, -a symbol representing the back-end used. +Note that the hook function must have a mandatory argument that is a symbol +for the back-end. @subheading Filters @cindex Filters, exporting -Filters are lists of functions applied on a specific part of the output from -a given back-end. More explicitly, each time a back-end transforms an Org -object or element into another language, all functions within a given filter -type are called in turn on the string produced. The string returned by the -last function will be the one used in the final output. - -There are filters sets for each type of element or object, for plain text, -for the parse tree, for the export options and for the final output. They -are all named after the same scheme: @code{org-export-filter-TYPE-functions}, -where @code{TYPE} is the type targeted by the filter. Valid types are: +The Org export process relies on filters to process specific parts of +conversion process. Filters are just lists of functions to be applied to +certain parts for a given back-end. The output from the first function in +the filter is passed on to the next function in the filter. The final output +is the output from the final function in the filter. + +The Org export process has many filter sets applicable to different types of +objects, plain text, parse trees, export options, and final output formats. +The filters are named after the element type or object type: +@code{org-export-filter-TYPE-functions}, where @code{TYPE} is the type +targeted by the filter. Valid types are: @multitable @columnfractions .33 .33 .33 -@item bold +@item body +@tab bold @tab babel-call -@tab center-block -@item clock +@item center-block +@tab clock @tab code -@tab comment -@item comment-block -@tab diary-sexp +@item diary-sexp @tab drawer -@item dynamic-block -@tab entity +@tab dynamic-block +@item entity @tab example-block -@item export-block -@tab export-snippet +@tab export-block +@item export-snippet @tab final-output -@item fixed-width -@tab footnote-definition +@tab fixed-width +@item footnote-definition @tab footnote-reference -@item headline -@tab horizontal-rule +@tab headline +@item horizontal-rule @tab inline-babel-call -@item inline-src-block -@tab inlinetask +@tab inline-src-block +@item inlinetask @tab italic -@item item -@tab keyword +@tab item +@item keyword @tab latex-environment -@item latex-fragment -@tab line-break +@tab latex-fragment +@item line-break @tab link -@item node-property -@tab options +@tab node-property +@item options @tab paragraph -@item parse-tree -@tab plain-list +@tab parse-tree +@item plain-list @tab plain-text -@item planning -@tab property-drawer +@tab planning +@item property-drawer @tab quote-block -@item quote-section @tab radio-target -@tab section -@item special-block +@item section +@tab special-block @tab src-block -@tab statistics-cookie -@item strike-through +@item statistics-cookie +@tab strike-through @tab subscript -@tab superscript -@item table +@item superscript +@tab table @tab table-cell -@tab table-row -@item target +@item table-row +@tab target @tab timestamp -@tab underline -@item verbatim +@item underline +@tab verbatim @tab verse-block -@tab @end multitable -For example, the following snippet allows me to use non-breaking spaces in -the Org buffer and get them translated into @LaTeX{} without using the -@code{\nbsp} macro (where @code{_} stands for the non-breaking space): +Here is an example filter that replaces non-breaking spaces @code{~} in the +Org buffer with @code{_} for the @LaTeX{} back-end. @lisp @group @@ -13400,33 +14094,49 @@ the Org buffer and get them translated into @LaTeX{} without using the @end group @end lisp -Three arguments must be provided to a filter: the code being changed, the -back-end used, and some information about the export process. You can safely -ignore the third argument for most purposes. Note the use of -@code{org-export-derived-backend-p}, which ensures that the filter will only -be applied when using @code{latex} back-end or any other back-end derived -from it (e.g., @code{beamer}). +A filter requires three arguments: the code to be transformed, the name of +the back-end, and some optional information about the export process. The +third argument can be safely ignored. Note the use of +@code{org-export-derived-backend-p} predicate that tests for @code{latex} +back-end or any other back-end, such as @code{beamer}, derived from +@code{latex}. + +@subheading Defining filters for individual files + +The Org export can filter not just for back-ends, but also for specific files +through the @code{#+BIND} keyword. Here is an example with two filters; one +removes brackets from time stamps, and the other removes strike-through text. +The filter functions are defined in a @samp{src} code block in the same Org +file, which is a handy location for debugging. + +@example +#+BIND: org-export-filter-timestamp-functions (tmp-f-timestamp) +#+BIND: org-export-filter-strike-through-functions (tmp-f-strike-through) +#+begin_src emacs-lisp :exports results :results none + (defun tmp-f-timestamp (s backend info) + (replace-regexp-in-string "&[lg]t;\\|[][]" "" s)) + (defun tmp-f-strike-through (s backend info) "") +#+end_src +@end example @subheading Extending an existing back-end -This is obviously the most powerful customization, since the changes happen -at the parser level. Indeed, some export back-ends are built as extensions -of other ones (e.g., Markdown back-end an extension of HTML back-end). - -Extending a back-end means that if an element type is not transcoded by the -new back-end, it will be handled by the original one. Hence you can extend -specific parts of a back-end without too much work. +Some parts of the conversion process can be extended for certain elements so +as to introduce a new or revised translation. That is how the HTML export +back-end was extended to handle Markdown format. The extensions work +seamlessly so any aspect of filtering not done by the extended back-end is +handled by the original back-end. Of all the export customization in Org, +extending is very powerful as it operates at the parser level. -As an example, imagine we want the @code{ascii} back-end to display the -language used in a source block, when it is available, but only when some -attribute is non-@code{nil}, like the following: +For this example, make the @code{ascii} back-end display the language used in +a source code block. Also make it display only when some attribute is +non-@code{nil}, like the following: @example #+ATTR_ASCII: :language t @end example -Because that back-end is lacking in that area, we are going to create a new -back-end, @code{my-ascii} that will do the job. +Then extend @code{ascii} back-end with a custom @code{my-ascii} back-end. @lisp @group @@ -13450,20 +14160,47 @@ channel." @end lisp The @code{my-ascii-src-block} function looks at the attribute above the -element. If it isn't true, it gives hand to the @code{ascii} back-end. -Otherwise, it creates a box around the code, leaving room for the language. -A new back-end is then created. It only changes its behavior when -translating @code{src-block} type element. Now, all it takes to use the new -back-end is calling the following from an Org buffer: +current element. If not true, hands over to @code{ascii} back-end. If true, +which it is in this example, it creates a box around the code and leaves room +for the inserting a string for language. The last form creates the new +back-end that springs to action only when translating @code{src-block} type +elements. + +To use the newly defined back-end, call the following from an Org buffer: @smalllisp (org-export-to-buffer 'my-ascii "*Org MY-ASCII Export*") @end smalllisp -It is obviously possible to write an interactive function for this, install -it in the export dispatcher menu, and so on. +Further steps to consider would be an interactive function, self-installing +an item in the export dispatcher menu, and other user-friendly improvements. + +@node Export in foreign buffers +@section Export in foreign buffers + +The export back-ends in Org often include commands to convert selected +regions. A convenient feature of this in-place conversion is that the +exported output replaces the original source. Here are such functions: + +@table @code +@item org-html-convert-region-to-html +Convert the selected region into HTML. +@item org-latex-convert-region-to-latex +Convert the selected region into @LaTeX{}. +@item org-texinfo-convert-region-to-texinfo +Convert the selected region into @code{Texinfo}. +@item org-md-convert-region-to-md +Convert the selected region into @code{MarkDown}. +@end table + +In-place conversions are particularly handy for quick conversion of tables +and lists in foreign buffers. For example, turn on the minor mode @code{M-x +orgstruct-mode} in an HTML buffer, then use the convenient Org keyboard +commands to create a list, select it, and covert it to HTML with @code{M-x +org-html-convert-region-to-html RET}. -@node Publishing, Working With Source Code, Exporting, Top + +@node Publishing @chapter Publishing @cindex publishing @@ -13485,7 +14222,7 @@ Publishing has been contributed to Org by David O'Toole. * Triggering publication:: Publication commands @end menu -@node Configuration, Uploading files, Publishing, Publishing +@node Configuration @section Configuration Publishing needs significant configuration to specify files, destination @@ -13502,7 +14239,7 @@ and many other properties of a project. * Generating an index:: An index that reaches across pages @end menu -@node Project alist, Sources and destinations, Configuration, Configuration +@node Project alist @subsection The variable @code{org-publish-project-alist} @cindex org-publish-project-alist @cindex projects, for publishing @@ -13529,7 +14266,7 @@ together files requiring different publishing options. When you publish such a ``meta-project'', all the components will also be published, in the sequence given. -@node Sources and destinations, Selecting files, Project alist, Configuration +@node Sources and destinations @subsection Sources and destinations for files @cindex directories, for publishing @@ -13548,17 +14285,17 @@ use external tools to upload your website (@pxref{Uploading files}). @item @code{:preparation-function} @tab Function or list of functions to be called before starting the publishing process, for example, to run @code{make} for updating files to be -published. The project property list is scoped into this call as the -variable @code{project-plist}. +published. Each preparation function is called with a single argument, the +project property list. @item @code{:completion-function} @tab Function or list of functions called after finishing the publishing -process, for example, to change permissions of the resulting files. The -project property list is scoped into this call as the variable -@code{project-plist}. +process, for example, to change permissions of the resulting files. Each +completion function is called with a single argument, the project property +list. @end multitable @noindent -@node Selecting files, Publishing action, Sources and destinations, Configuration +@node Selecting files @subsection Selecting files @cindex files, selecting for publishing @@ -13584,7 +14321,7 @@ and @code{:exclude}. @tab non-@code{nil} means, check base-directory recursively for files to publish. @end multitable -@node Publishing action, Publishing options, Selecting files, Configuration +@node Publishing action @subsection Publishing action @cindex action, for publishing @@ -13623,46 +14360,26 @@ and the path to the publishing directory of the output file. It should take the specified file, make the necessary transformation (if any) and place the result into the destination folder. -@node Publishing options, Publishing links, Publishing action, Configuration +@node Publishing options @subsection Options for the exporters @cindex options, for publishing -The property list can be used to set many export options for the exporters. -In most cases, these properties correspond to user variables in Org. The -first table below lists these properties along with the variable they belong -to. The second table list HTML specific properties. See the documentation -string of these options for details. +The property list can be used to set export options during the publishing +process. In most cases, these properties correspond to user variables in +Org. While some properties are available for all export back-ends, most of +them are back-end specific. The following sections list properties along +with the variable they belong to. See the documentation string of these +options for details. -@vindex org-display-custom-times -@vindex org-export-default-language -@vindex org-export-exclude-tags -@vindex org-export-headline-levels -@vindex org-export-preserve-breaks -@vindex org-export-publishing-directory -@vindex org-export-select-tags -@vindex org-export-with-archived-trees -@vindex org-export-with-author -@vindex org-export-with-creator -@vindex org-export-with-drawers -@vindex org-export-with-email -@vindex org-export-with-emphasize -@vindex org-export-with-fixed-width -@vindex org-export-with-footnotes -@vindex org-export-with-latex -@vindex org-export-with-planning -@vindex org-export-with-priority -@vindex org-export-with-section-numbers -@vindex org-export-with-special-strings -@vindex org-export-with-sub-superscripts -@vindex org-export-with-tables -@vindex org-export-with-tags -@vindex org-export-with-tasks -@vindex org-export-with-timestamps -@vindex org-export-with-toc -@vindex org-export-with-todo-keywords -@vindex user-mail-address +@vindex org-publish-project-alist +When a property is given a value in @code{org-publish-project-alist}, its +setting overrides the value of the corresponding user variable (if any) +during publishing. Options set within a file (@pxref{Export settings}), +however, override everything. -@multitable @columnfractions 0.32 0.68 +@subsubheading Generic properties + +@multitable {@code{:with-sub-superscript}} {@code{org-export-with-sub-superscripts}} @item @code{:archived-trees} @tab @code{org-export-with-archived-trees} @item @code{:exclude-tags} @tab @code{org-export-exclude-tags} @item @code{:headline-levels} @tab @code{org-export-headline-levels} @@ -13671,7 +14388,10 @@ string of these options for details. @item @code{:section-numbers} @tab @code{org-export-with-section-numbers} @item @code{:select-tags} @tab @code{org-export-select-tags} @item @code{:with-author} @tab @code{org-export-with-author} +@item @code{:with-broken-links} @tab @code{org-export-with-broken-links} +@item @code{:with-clocks} @tab @code{org-export-with-clocks} @item @code{:with-creator} @tab @code{org-export-with-creator} +@item @code{:with-date} @tab @code{org-export-with-date} @item @code{:with-drawers} @tab @code{org-export-with-drawers} @item @code{:with-email} @tab @code{org-export-with-email} @item @code{:with-emphasize} @tab @code{org-export-with-emphasize} @@ -13680,83 +14400,225 @@ string of these options for details. @item @code{:with-latex} @tab @code{org-export-with-latex} @item @code{:with-planning} @tab @code{org-export-with-planning} @item @code{:with-priority} @tab @code{org-export-with-priority} +@item @code{:with-properties} @tab @code{org-export-with-properties} @item @code{:with-special-strings} @tab @code{org-export-with-special-strings} @item @code{:with-sub-superscript} @tab @code{org-export-with-sub-superscripts} @item @code{:with-tables} @tab @code{org-export-with-tables} @item @code{:with-tags} @tab @code{org-export-with-tags} @item @code{:with-tasks} @tab @code{org-export-with-tasks} @item @code{:with-timestamps} @tab @code{org-export-with-timestamps} +@item @code{:with-title} @tab @code{org-export-with-title} @item @code{:with-toc} @tab @code{org-export-with-toc} @item @code{:with-todo-keywords} @tab @code{org-export-with-todo-keywords} @end multitable -@vindex org-html-doctype -@vindex org-html-container-element -@vindex org-html-html5-fancy -@vindex org-html-xml-declaration -@vindex org-html-link-up -@vindex org-html-link-home -@vindex org-html-link-org-files-as-html -@vindex org-html-link-use-abs-url -@vindex org-html-head -@vindex org-html-head-extra -@vindex org-html-inline-images -@vindex org-html-extension -@vindex org-html-preamble -@vindex org-html-postamble -@vindex org-html-table-default-attributes -@vindex org-html-table-row-tags -@vindex org-html-head-include-default-style -@vindex org-html-head-include-scripts -@multitable @columnfractions 0.32 0.68 -@item @code{:html-doctype} @tab @code{org-html-doctype} -@item @code{:html-container} @tab @code{org-html-container-element} -@item @code{:html-html5-fancy} @tab @code{org-html-html5-fancy} -@item @code{:html-xml-declaration} @tab @code{org-html-xml-declaration} -@item @code{:html-link-up} @tab @code{org-html-link-up} -@item @code{:html-link-home} @tab @code{org-html-link-home} -@item @code{:html-link-org-as-html} @tab @code{org-html-link-org-files-as-html} -@item @code{:html-link-use-abs-url} @tab @code{org-html-link-use-abs-url} -@item @code{:html-head} @tab @code{org-html-head} -@item @code{:html-head-extra} @tab @code{org-html-head-extra} -@item @code{:html-inline-images} @tab @code{org-html-inline-images} -@item @code{:html-extension} @tab @code{org-html-extension} -@item @code{:html-preamble} @tab @code{org-html-preamble} -@item @code{:html-postamble} @tab @code{org-html-postamble} -@item @code{:html-table-attributes} @tab @code{org-html-table-default-attributes} -@item @code{:html-table-row-tags} @tab @code{org-html-table-row-tags} +@subsubheading ASCII specific properties + +@multitable {@code{:ascii-table-keep-all-vertical-lines}} {@code{org-ascii-table-keep-all-vertical-lines}} +@item @code{:ascii-bullets} @tab @code{org-ascii-bullets} +@item @code{:ascii-caption-above} @tab @code{org-ascii-caption-above} +@item @code{:ascii-charset} @tab @code{org-ascii-charset} +@item @code{:ascii-global-margin} @tab @code{org-ascii-global-margin} +@item @code{:ascii-format-drawer-function} @tab @code{org-ascii-format-drawer-function} +@item @code{:ascii-format-inlinetask-function} @tab @code{org-ascii-format-inlinetask-function} +@item @code{:ascii-headline-spacing} @tab @code{org-ascii-headline-spacing} +@item @code{:ascii-indented-line-width} @tab @code{org-ascii-indented-line-width} +@item @code{:ascii-inlinetask-width} @tab @code{org-ascii-inlinetask-width} +@item @code{:ascii-inner-margin} @tab @code{org-ascii-inner-margin} +@item @code{:ascii-links-to-notes} @tab @code{org-ascii-links-to-notes} +@item @code{:ascii-list-margin} @tab @code{org-ascii-list-margin} +@item @code{:ascii-paragraph-spacing} @tab @code{org-ascii-paragraph-spacing} +@item @code{:ascii-quote-margin} @tab @code{org-ascii-quote-margin} +@item @code{:ascii-table-keep-all-vertical-lines} @tab @code{org-ascii-table-keep-all-vertical-lines} +@item @code{:ascii-table-use-ascii-art} @tab @code{org-ascii-table-use-ascii-art} +@item @code{:ascii-table-widen-columns} @tab @code{org-ascii-table-widen-columns} +@item @code{:ascii-text-width} @tab @code{org-ascii-text-width} +@item @code{:ascii-underline} @tab @code{org-ascii-underline} +@item @code{:ascii-verbatim-format} @tab @code{org-ascii-verbatim-format} +@end multitable + +@subsubheading Beamer specific properties + +@multitable {@code{:beamer-frame-default-options}} {@code{org-beamer-frame-default-options}} +@item @code{:beamer-theme} @tab @code{org-beamer-theme} +@item @code{:beamer-column-view-format} @tab @code{org-beamer-column-view-format} +@item @code{:beamer-environments-extra} @tab @code{org-beamer-environments-extra} +@item @code{:beamer-frame-default-options} @tab @code{org-beamer-frame-default-options} +@item @code{:beamer-outline-frame-options} @tab @code{org-beamer-outline-frame-options} +@item @code{:beamer-outline-frame-title} @tab @code{org-beamer-outline-frame-title} +@item @code{:beamer-subtitle-format} @tab @code{org-beamer-subtitle-format} +@end multitable + +@subsubheading HTML specific properties + +@multitable {@code{:html-table-use-header-tags-for-first-column}} {@code{org-html-table-use-header-tags-for-first-column}} +@item @code{:html-allow-name-attribute-in-anchors} @tab @code{org-html-allow-name-attribute-in-anchors} +@item @code{:html-checkbox-type} @tab @code{org-html-checkbox-type} +@item @code{:html-container} @tab @code{org-html-container-element} +@item @code{:html-divs} @tab @code{org-html-divs} +@item @code{:html-doctype} @tab @code{org-html-doctype} +@item @code{:html-extension} @tab @code{org-html-extension} +@item @code{:html-footnote-format} @tab @code{org-html-footnote-format} +@item @code{:html-footnote-separator} @tab @code{org-html-footnote-separator} +@item @code{:html-footnotes-section} @tab @code{org-html-footnotes-section} +@item @code{:html-format-drawer-function} @tab @code{org-html-format-drawer-function} +@item @code{:html-format-headline-function} @tab @code{org-html-format-headline-function} +@item @code{:html-format-inlinetask-function} @tab @code{org-html-format-inlinetask-function} +@item @code{:html-head-extra} @tab @code{org-html-head-extra} @item @code{:html-head-include-default-style} @tab @code{org-html-head-include-default-style} -@item @code{:html-head-include-scripts} @tab @code{org-html-head-include-scripts} +@item @code{:html-head-include-scripts} @tab @code{org-html-head-include-scripts} +@item @code{:html-head} @tab @code{org-html-head} +@item @code{:html-home/up-format} @tab @code{org-html-home/up-format} +@item @code{:html-html5-fancy} @tab @code{org-html-html5-fancy} +@item @code{:html-indent} @tab @code{org-html-indent} +@item @code{:html-infojs-options} @tab @code{org-html-infojs-options} +@item @code{:html-infojs-template} @tab @code{org-html-infojs-template} +@item @code{:html-inline-image-rules} @tab @code{org-html-inline-image-rules} +@item @code{:html-inline-images} @tab @code{org-html-inline-images} +@item @code{:html-link-home} @tab @code{org-html-link-home} +@item @code{:html-link-org-files-as-html} @tab @code{org-html-link-org-files-as-html} +@item @code{:html-link-up} @tab @code{org-html-link-up} +@item @code{:html-link-use-abs-url} @tab @code{org-html-link-use-abs-url} +@item @code{:html-mathjax-options} @tab @code{org-html-mathjax-options} +@item @code{:html-mathjax-template} @tab @code{org-html-mathjax-template} +@item @code{:html-metadata-timestamp-format} @tab @code{org-html-metadata-timestamp-format} +@item @code{:html-postamble-format} @tab @code{org-html-postamble-format} +@item @code{:html-postamble} @tab @code{org-html-postamble} +@item @code{:html-preamble-format} @tab @code{org-html-preamble-format} +@item @code{:html-preamble} @tab @code{org-html-preamble} +@item @code{:html-table-align-individual-fields} @tab @code{org-html-table-align-individual-fields} +@item @code{:html-table-attributes} @tab @code{org-html-table-default-attributes} +@item @code{:html-table-caption-above} @tab @code{org-html-table-caption-above} +@item @code{:html-table-data-tags} @tab @code{org-html-table-data-tags} +@item @code{:html-table-header-tags} @tab @code{org-html-table-header-tags} +@item @code{:html-table-row-tags} @tab @code{org-html-table-row-tags} +@item @code{:html-table-use-header-tags-for-first-column} @tab @code{org-html-table-use-header-tags-for-first-column} +@item @code{:html-tag-class-prefix} @tab @code{org-html-tag-class-prefix} +@item @code{:html-text-markup-alist} @tab @code{org-html-text-markup-alist} +@item @code{:html-todo-kwd-class-prefix} @tab @code{org-html-todo-kwd-class-prefix} +@item @code{:html-toplevel-hlevel} @tab @code{org-html-toplevel-hlevel} +@item @code{:html-use-infojs} @tab @code{org-html-use-infojs} +@item @code{:html-validation-link} @tab @code{org-html-validation-link} +@item @code{:html-viewport} @tab @code{org-html-viewport} +@item @code{:html-xml-declaration} @tab @code{org-html-xml-declaration} @end multitable -Most of the @code{org-export-with-*} variables have the same effect in each -exporter. +@subsubheading @LaTeX{} specific properties + +@multitable {@code{:latex-link-with-unknown-path-format}} {@code{org-latex-link-with-unknown-path-format}} +@item @code{:latex-active-timestamp-format} @tab @code{org-latex-active-timestamp-format} +@item @code{:latex-caption-above} @tab @code{org-latex-caption-above} +@item @code{:latex-classes} @tab @code{org-latex-classes} +@item @code{:latex-class} @tab @code{org-latex-default-class} +@item @code{:latex-compiler} @tab @code{org-latex-compiler} +@item @code{:latex-default-figure-position} @tab @code{org-latex-default-figure-position} +@item @code{:latex-default-table-environment} @tab @code{org-latex-default-table-environment} +@item @code{:latex-default-table-mode} @tab @code{org-latex-default-table-mode} +@item @code{:latex-diary-timestamp-format} @tab @code{org-latex-diary-timestamp-format} +@item @code{:latex-footnote-defined-format} @tab @code{org-latex-footnote-defined-format} +@item @code{:latex-footnote-separator} @tab @code{org-latex-footnote-separator} +@item @code{:latex-format-drawer-function} @tab @code{org-latex-format-drawer-function} +@item @code{:latex-format-headline-function} @tab @code{org-latex-format-headline-function} +@item @code{:latex-format-inlinetask-function} @tab @code{org-latex-format-inlinetask-function} +@item @code{:latex-hyperref-template} @tab @code{org-latex-hyperref-template} +@item @code{:latex-image-default-height} @tab @code{org-latex-image-default-height} +@item @code{:latex-image-default-option} @tab @code{org-latex-image-default-option} +@item @code{:latex-image-default-width} @tab @code{org-latex-image-default-width} +@item @code{:latex-images-centered} @tab @code{org-latex-images-centered} +@item @code{:latex-inactive-timestamp-format} @tab @code{org-latex-inactive-timestamp-format} +@item @code{:latex-inline-image-rules} @tab @code{org-latex-inline-image-rules} +@item @code{:latex-link-with-unknown-path-format} @tab @code{org-latex-link-with-unknown-path-format} +@item @code{:latex-listings-langs} @tab @code{org-latex-listings-langs} +@item @code{:latex-listings-options} @tab @code{org-latex-listings-options} +@item @code{:latex-listings} @tab @code{org-latex-listings} +@item @code{:latex-minted-langs} @tab @code{org-latex-minted-langs} +@item @code{:latex-minted-options} @tab @code{org-latex-minted-options} +@item @code{:latex-prefer-user-labels} @tab @code{org-latex-prefer-user-labels} +@item @code{:latex-subtitle-format} @tab @code{org-latex-subtitle-format} +@item @code{:latex-subtitle-separate} @tab @code{org-latex-subtitle-separate} +@item @code{:latex-table-scientific-notation} @tab @code{org-latex-table-scientific-notation} +@item @code{:latex-tables-booktabs} @tab @code{org-latex-tables-booktabs} +@item @code{:latex-tables-centered} @tab @code{org-latex-tables-centered} +@item @code{:latex-text-markup-alist} @tab @code{org-latex-text-markup-alist} +@item @code{:latex-title-command} @tab @code{org-latex-title-command} +@item @code{:latex-toc-command} @tab @code{org-latex-toc-command} +@end multitable -@vindex org-publish-project-alist -When a property is given a value in @code{org-publish-project-alist}, its -setting overrides the value of the corresponding user variable (if any) -during publishing. Options set within a file (@pxref{Export settings}), -however, override everything. +@subsubheading Markdown specific properties + +@multitable {@code{:md-footnotes-section}} {@code{org-md-footnotes-section}} +@item @code{:md-footnote-format} @tab @code{org-md-footnote-format} +@item @code{:md-footnotes-section} @tab @code{org-md-footnotes-section} +@item @code{:md-headline-style} @tab @code{org-md-headline-style} +@end multitable -@node Publishing links, Sitemap, Publishing options, Configuration +@subsubheading ODT specific properties + +@multitable {@code{:odt-format-inlinetask-function}} {@code{org-odt-format-inlinetask-function}} +@item @code{:odt-content-template-file} @tab @code{org-odt-content-template-file} +@item @code{:odt-display-outline-level} @tab @code{org-odt-display-outline-level} +@item @code{:odt-fontify-srcblocks} @tab @code{org-odt-fontify-srcblocks} +@item @code{:odt-format-drawer-function} @tab @code{org-odt-format-drawer-function} +@item @code{:odt-format-headline-function} @tab @code{org-odt-format-headline-function} +@item @code{:odt-format-inlinetask-function} @tab @code{org-odt-format-inlinetask-function} +@item @code{:odt-inline-formula-rules} @tab @code{org-odt-inline-formula-rules} +@item @code{:odt-inline-image-rules} @tab @code{org-odt-inline-image-rules} +@item @code{:odt-pixels-per-inch} @tab @code{org-odt-pixels-per-inch} +@item @code{:odt-styles-file} @tab @code{org-odt-styles-file} +@item @code{:odt-table-styles} @tab @code{org-odt-table-styles} +@item @code{:odt-use-date-fields} @tab @code{org-odt-use-date-fields} +@end multitable + +@subsubheading Texinfo specific properties + +@multitable {@code{:texinfo-link-with-unknown-path-format}} {@code{org-texinfo-link-with-unknown-path-format}} +@item @code{:texinfo-active-timestamp-format} @tab @code{org-texinfo-active-timestamp-format} +@item @code{:texinfo-classes} @tab @code{org-texinfo-classes} +@item @code{:texinfo-class} @tab @code{org-texinfo-default-class} +@item @code{:texinfo-def-table-markup} @tab @code{org-texinfo-def-table-markup} +@item @code{:texinfo-diary-timestamp-format} @tab @code{org-texinfo-diary-timestamp-format} +@item @code{:texinfo-filename} @tab @code{org-texinfo-filename} +@item @code{:texinfo-format-drawer-function} @tab @code{org-texinfo-format-drawer-function} +@item @code{:texinfo-format-headline-function} @tab @code{org-texinfo-format-headline-function} +@item @code{:texinfo-format-inlinetask-function} @tab @code{org-texinfo-format-inlinetask-function} +@item @code{:texinfo-inactive-timestamp-format} @tab @code{org-texinfo-inactive-timestamp-format} +@item @code{:texinfo-link-with-unknown-path-format} @tab @code{org-texinfo-link-with-unknown-path-format} +@item @code{:texinfo-node-description-column} @tab @code{org-texinfo-node-description-column} +@item @code{:texinfo-table-scientific-notation} @tab @code{org-texinfo-table-scientific-notation} +@item @code{:texinfo-tables-verbatim} @tab @code{org-texinfo-tables-verbatim} +@item @code{:texinfo-text-markup-alist} @tab @code{org-texinfo-text-markup-alist} +@end multitable + +@node Publishing links @subsection Links between published files @cindex links, publishing To create a link from one Org file to another, you would use something like -@samp{[[file:foo.org][The foo]]} or simply @samp{file:foo.org.} -(@pxref{Hyperlinks}). When published, this link becomes a link to -@file{foo.html}. You can thus interlink the pages of your "org web" project -and the links will work as expected when you publish them to HTML@. If you -also publish the Org source file and want to link to it, use an @code{http:} -link instead of a @code{file:} link, because @code{file:} links are converted -to link to the corresponding @file{html} file. +@samp{[[file:foo.org][The foo]]} or simply @samp{file:foo.org} +(@pxref{External links}). When published, this link becomes a link to +@file{foo.html}. You can thus interlink the pages of your ``org web'' +project and the links will work as expected when you publish them to HTML. +If you also publish the Org source file and want to link to it, use an +@code{http:} link instead of a @code{file:} link, because @code{file:} links +are converted to link to the corresponding @file{html} file. You may also link to related files, such as images. Provided you are careful with relative file names, and provided you have also configured Org to upload the related files, these links will work too. See @ref{Complex example}, for an example of this usage. -@node Sitemap, Generating an index, Publishing links, Configuration +Eventually, links between published documents can contain some search options +(@pxref{Search options}), which will be resolved to the appropriate location +in the linked file. For example, once published to HTML, the following links +all point to a dedicated anchor in @file{foo.html}. + +@example +[[file:foo.org::*heading]] +[[file:foo.org::#custom-id]] +[[file:foo.org::target]] +@end example + +@node Sitemap @subsection Generating a sitemap @cindex sitemap, of published pages @@ -13816,7 +14678,7 @@ Defaults to @code{nil}. @end multitable -@node Generating an index, , Sitemap, Configuration +@node Generating an index @subsection Generating an index @cindex index, in a publishing project @@ -13833,7 +14695,17 @@ The file will be created when first publishing a project with the "theindex.inc"}. You can then build around this include statement by adding a title, style information, etc. -@node Uploading files, Sample configuration, Configuration, Publishing +@cindex #+INDEX +Index entries are specified with @code{#+INDEX} keyword. An entry that +contains an exclamation mark will create a sub item. + +@example +* Curriculum Vitae +#+INDEX: CV +#+INDEX: Application!CV +@end example + +@node Uploading files @section Uploading files @cindex rsync @cindex unison @@ -13866,7 +14738,7 @@ benefit of re-including any changed external files such as source example files you might include with @code{#+INCLUDE:}. The timestamp mechanism in Org is not smart enough to detect if included files have been modified. -@node Sample configuration, Triggering publication, Uploading files, Publishing +@node Sample configuration @section Sample configuration Below we provide two example configurations. The first one is a simple @@ -13878,7 +14750,7 @@ more complex, with a multi-component project. * Complex example:: A multi-component publishing example @end menu -@node Simple example, Complex example, Sample configuration, Sample configuration +@node Simple example @subsection Example: simple publishing configuration This example publishes a set of Org files to the @file{public_html} @@ -13896,7 +14768,7 @@ directory on the local machine. type=\"text/css\"/>"))) @end lisp -@node Complex example, , Simple example, Sample configuration +@node Complex example @subsection Example: complex publishing configuration This more complicated example publishes an entire website, including @@ -13946,7 +14818,7 @@ right place on the web server, and publishing images to it. ("website" :components ("orgfiles" "images" "other")))) @end lisp -@node Triggering publication, , Sample configuration, Publishing +@node Triggering publication @section Triggering publication Once properly configured, Org can publish with the following commands: @@ -13970,17 +14842,20 @@ above, or by customizing the variable @code{org-publish-use-timestamps-flag}. This may be necessary in particular if files include other files via @code{#+SETUPFILE:} or @code{#+INCLUDE:}. -@comment node-name, next, previous, up -@comment Working With Source Code, Miscellaneous, Publishing, Top -@node Working With Source Code, Miscellaneous, Publishing, Top +@node Working with source code @chapter Working with source code @cindex Schulte, Eric @cindex Davison, Dan @cindex source code, working with -Source code can be included in Org mode documents using a @samp{src} block, -e.g.: +Source code here refers to any code typed in Org mode documents. Org can +manage source code in any Org file once such code is tagged with begin and +end markers. Working with source code begins with tagging source code +blocks. Tagged @samp{src} code blocks are not restricted to the preamble or +the end of an Org document; they can go anywhere---with a few exceptions, +such as not inside comments and fixed width areas. Here's a sample +@samp{src} code block in emacs-lisp: @example #+BEGIN_SRC emacs-lisp @@ -13990,14 +14865,57 @@ e.g.: #+END_SRC @end example -Org mode provides a number of features for working with live source code, -including editing of code blocks in their native major-mode, evaluation of -code blocks, converting code blocks into source files (known as @dfn{tangling} -in literate programming), and exporting code blocks and their -results in several formats. This functionality was contributed by Eric -Schulte and Dan Davison, and was originally named Org-babel. - -The following sections describe Org mode's code block handling facilities. +Org can take the code in the block between the @samp{#+BEGIN_SRC} and +@samp{#+END_SRC} tags, and format, compile, execute, and show the results. +Org can simplify many housekeeping tasks essential to modern code +maintenance. That's why these blocks in Org mode literature are sometimes +referred to as @samp{live code} blocks (as compared to the static text and +documentation around it). Users can control how @samp{live} they want each +block by tweaking the headers for compiling, execution, extraction. + +Org's @samp{src} code block type is one of many block types, such as quote, +export, verse, latex, example, and verbatim. This section pertains to +@samp{src} code blocks between @samp{#+BEGIN_SRC} and @samp{#+END_SRC} + +For editing @samp{src} code blocks, Org provides native Emacs major-modes. +That leverages the latest Emacs features for that source code language mode. + +For exporting, Org can then extract @samp{src} code blocks into compilable +source files (in a conversion process known as @dfn{tangling} in literate +programming terminology). + +For publishing, Org's back-ends can handle the @samp{src} code blocks and the +text for output to a variety of formats with native syntax highlighting. + +For executing the source code in the @samp{src} code blocks, Org provides +facilities that glue the tasks of compiling, collecting the results of the +execution, and inserting them back to the Org file. Besides text output, +results may include links to other data types that Emacs can handle: audio, +video, and graphics. + +An important feature of Org's execution of the @samp{src} code blocks is +passing variables, functions, and results between @samp{src} blocks. Such +interoperability uses a common syntax even if these @samp{src} blocks are in +different source code languages. The integration extends to linking the +debugger's error messages to the line in the @samp{src} code block in the Org +file. That should partly explain why this functionality by the original +contributors, Eric Schulte and Dan Davison, was called @samp{Org Babel}. + +In literate programming, the main appeal is code and documentation +co-existing in one file. Org mode takes this several steps further. First +by enabling execution, and then by inserting results of that execution back +into the Org file. Along the way, Org provides extensive formatting +features, including handling tables. Org handles multiple source code +languages in one file, and provides a common syntax for passing variables, +functions, and results between @samp{src} code blocks. + +Org mode fulfills the promise of easy verification and maintenance of +publishing reproducible research by keeping all these in the same file: text, +data, code, configuration settings of the execution environment, the results +of the execution, and associated narratives, claims, references, and internal +and external links. + +Details of Org's facilities for working with source code are shown next. @menu * Structure of code blocks:: Code block syntax described @@ -14014,19 +14932,18 @@ The following sections describe Org mode's code block handling facilities. * Batch execution:: Call functions from the command line @end menu -@comment node-name, next, previous, up -@comment Structure of code blocks, Editing source code, Working With Source Code, Working With Source Code -@node Structure of code blocks, Editing source code, Working With Source Code, Working With Source Code +@node Structure of code blocks @section Structure of code blocks @cindex code block, structure @cindex source code, block structure @cindex #+NAME @cindex #+BEGIN_SRC -Live code blocks can be specified with a @samp{src} block or -inline.@footnote{Note that @samp{src} blocks may be inserted using Org mode's -@ref{Easy Templates} system} The structure of a @samp{src} block is +Org offers two ways to structure source code in Org documents: in a +@samp{src} block, and directly inline. Both specifications are shown below. + +A @samp{src} block conforms to this structure: @example #+NAME: <name> @@ -14035,12 +14952,15 @@ inline.@footnote{Note that @samp{src} blocks may be inserted using Org mode's #+END_SRC @end example -The @code{#+NAME:} line is optional, and can be used to name the code -block. Live code blocks require that a language be specified on the -@code{#+BEGIN_SRC} line. Switches and header arguments are optional. -@cindex source code, inline +Org mode's templates system (@pxref{Easy templates}) speeds up creating +@samp{src} code blocks with just three keystrokes. Do not be put-off by +having to remember the source block syntax. Org also works with other +completion systems in Emacs, some of which predate Org and have custom +domain-specific languages for defining templates. Regular use of templates +reduces errors, increases accuracy, and maintains consistency. -Live code blocks can also be specified inline using +@cindex source code, inline +An inline code block conforms to this structure: @example src_<language>@{<body>@} @@ -14053,36 +14973,39 @@ src_<language>[<header arguments>]@{<body>@} @end example @table @code -@item <#+NAME: name> -This line associates a name with the code block. This is similar to the -@code{#+NAME: Name} lines that can be used to name tables in Org mode -files. Referencing the name of a code block makes it possible to evaluate -the block from other places in the file, from other files, or from Org mode -table formulas (see @ref{The spreadsheet}). Names are assumed to be unique -and the behavior of Org mode when two or more blocks share the same name is -undefined. +@item #+NAME: <name> +Optional. Names the @samp{src} block so it can be called, like a function, +from other @samp{src} blocks or inline blocks to evaluate or to capture the +results. Code from other blocks, other files, and from table formulas +(@pxref{The spreadsheet}) can use the name to reference a @samp{src} block. +This naming serves the same purpose as naming Org tables. Org mode requires +unique names. For duplicate names, Org mode's behavior is undefined. @cindex #+NAME +@item #+BEGIN_SRC +@item #+END_SRC +Mandatory. They mark the start and end of a block that Org requires. The +@code{#+BEGIN_SRC} line takes additional arguments, as described next. +@cindex begin block, end block @item <language> -The language of the code in the block (see @ref{Languages}). +Mandatory for live code blocks. It is the identifier of the source code +language in the block. @xref{Languages}, for identifiers of supported +languages. @cindex source code, language @item <switches> -Optional switches control code block export (see the discussion of switches in -@ref{Literal examples}) +Optional. Switches provide finer control of the code execution, export, and +format (see the discussion of switches in @ref{Literal examples}) @cindex source code, switches @item <header arguments> -Optional header arguments control many aspects of evaluation, export and -tangling of code blocks (see @ref{Header arguments}). -Header arguments can also be set on a per-buffer or per-subtree -basis using properties. +Optional. Heading arguments control many aspects of evaluation, export and +tangling of code blocks (@pxref{Header arguments}). Using Org's properties +feature, header arguments can be selectively applied to the entire buffer or +specific sub-trees of the Org document. @item source code, header arguments @item <body> -Source code in the specified language. +Source code in the dialect of the specified language identifier. @end table -@comment node-name, next, previous, up -@comment Editing source code, Exporting code blocks, Structure of code blocks, Working With Source Code - -@node Editing source code, Exporting code blocks, Structure of code blocks, Working With Source Code +@node Editing source code @section Editing source code @cindex code block, editing @cindex source code, editing @@ -14090,116 +15013,150 @@ Source code in the specified language. @vindex org-edit-src-auto-save-idle-delay @vindex org-edit-src-turn-on-auto-save @kindex C-c ' -Use @kbd{C-c '} to edit the current code block. This brings up a language -major-mode edit buffer containing the body of the code block. Manually -saving this buffer with @key{C-x C-s} will write the contents back to the Org -buffer. You can also set @code{org-edit-src-auto-save-idle-delay} to save the -base buffer after some idle delay, or @code{org-edit-src-turn-on-auto-save} -to auto-save this buffer into a separate file using @code{auto-save-mode}. -Use @kbd{C-c '} again to exit. - -The @code{org-src-mode} minor mode will be active in the edit buffer. The -following variables can be used to configure the behavior of the edit -buffer. See also the customization group @code{org-edit-structure} for -further configuration options. +@kbd{C-c '} for editing the current code block. It opens a new major-mode +edit buffer containing the body of the @samp{src} code block, ready for any +edits. @kbd{C-c '} again to close the buffer and return to the Org buffer. + +@key{C-x C-s} saves the buffer and updates the contents of the Org buffer. + +Set @code{org-edit-src-auto-save-idle-delay} to save the base buffer after +a certain idle delay time. + +Set @code{org-edit-src-turn-on-auto-save} to auto-save this buffer into a +separate file using @code{auto-save-mode}. + +@kbd{C-c '} to close the major-mode buffer and return back to the Org buffer. + +While editing the source code in the major-mode, the @code{org-src-mode} +minor mode remains active. It provides these customization variables as +described below. For even more variables, look in the customization +group @code{org-edit-structure}. @table @code @item org-src-lang-modes -If an Emacs major-mode named @code{<lang>-mode} exists, where -@code{<lang>} is the language named in the header line of the code block, -then the edit buffer will be placed in that major-mode. This variable -can be used to map arbitrary language names to existing major modes. +If an Emacs major-mode named @code{<lang>-mode} exists, where @code{<lang>} +is the language identifier from code block's header line, then the edit +buffer uses that major-mode. Use this variable to arbitrarily map language +identifiers to major modes. @item org-src-window-setup -Controls the way Emacs windows are rearranged when the edit buffer is created. +For specifying Emacs window arrangement when the new edit buffer is created. @item org-src-preserve-indentation -By default, the value is @code{nil}, which means that when code blocks are -evaluated during export or tangled, they are re-inserted into the code block, -which may replace sequences of spaces with tab characters. When non-nil, -whitespace in code blocks will be preserved during export or tangling, -exactly as it appears. This variable is especially useful for tangling -languages such as Python, in which whitespace indentation in the output is -critical. +@cindex indentation, in source blocks +Default is @code{nil}. Source code is indented. This indentation applies +during export or tangling, and depending on the context, may alter leading +spaces and tabs. When non-@code{nil}, source code is aligned with the +leftmost column. No lines are modified during export or tangling, which is +very useful for white-space sensitive languages, such as Python. @item org-src-ask-before-returning-to-edit-buffer -By default, Org will ask before returning to an open edit buffer. Set this -variable to @code{nil} to switch without asking. +When @code{nil}, Org returns to the edit buffer without further prompts. The +default prompts for a confirmation. @end table -To turn on native code fontification in the @emph{Org} buffer, configure the -variable @code{org-src-fontify-natively}. +Set @code{org-src-fontify-natively} to non-@code{nil} to turn on native code +fontification in the @emph{Org} buffer. Fontification of @samp{src} code +blocks can give visual separation of text and code on the display page. To +further customize the appearance of @code{org-block} for specific languages, +customize @code{org-src-block-faces}. The following example shades the +background of regular blocks, and colors source blocks only for Python and +Emacs-Lisp languages. +@lisp +(require 'color) +(set-face-attribute 'org-block nil :background + (color-darken-name + (face-attribute 'default :background) 3)) -@comment node-name, next, previous, up -@comment Exporting code blocks, Extracting source code, Editing source code, Working With Source Code +(setq org-src-block-faces '(("emacs-lisp" (:background "#EEE2FF")) + ("python" (:background "#E5FFB8")))) +@end lisp -@node Exporting code blocks, Extracting source code, Editing source code, Working With Source Code +@node Exporting code blocks @section Exporting code blocks @cindex code block, exporting @cindex source code, exporting -It is possible to export the @emph{code} of code blocks, the @emph{results} -of code block evaluation, @emph{both} the code and the results of code block -evaluation, or @emph{none}. For most languages, the default exports code. -However, for some languages (e.g., @code{ditaa}) the default exports the -results of code block evaluation. For information on exporting code block -bodies, see @ref{Literal examples}. +Org can flexibly export just the @emph{code} from the code blocks, just the +@emph{results} of evaluation of the code block, @emph{both} the code and the +results of the code block evaluation, or @emph{none}. Org defaults to +exporting @emph{code} for most languages. For some languages, such as +@code{ditaa}, Org defaults to @emph{results}. To export just the body of +code blocks, @pxref{Literal examples}. To selectively export sub-trees of +an Org document, @pxref{Exporting}. -The @code{:exports} header argument can be used to specify export -behavior: +The @code{:exports} header arguments control exporting code blocks only and +not inline code: @subsubheading Header arguments: @table @code +@cindex @code{:exports}, src header argument @item :exports code -The default in most languages. The body of the code block is exported, as -described in @ref{Literal examples}. +This is the default for most languages where the body of the code block is +exported. See @ref{Literal examples} for more. @item :exports results -The code block will be evaluated and the results will be placed in the -Org mode buffer for export, either updating previous results of the code -block located anywhere in the buffer or, if no previous results exist, -placing the results immediately after the code block. The body of the code -block will not be exported. +On export, Org includes only the results and not the code block. After each +evaluation, Org inserts the results after the end of code block in the Org +buffer. By default, Org replaces any previous results. Org can also append +results. @item :exports both -Both the code block and its results will be exported. +Org exports both the code block and the results. @item :exports none -Neither the code block nor its results will be exported. +Org does not export the code block nor the results. @end table -It is possible to inhibit the evaluation of code blocks during export. -Setting the @code{org-export-babel-evaluate} variable to @code{nil} will -ensure that no code blocks are evaluated as part of the export process. This -can be useful in situations where potentially untrusted Org mode files are -exported in an automated fashion, for example when Org mode is used as the -markup language for a wiki. It is also possible to set this variable to -@code{'inline-only}. In that case, only inline code blocks will be -evaluated, in order to insert their results. Non-inline code blocks are -assumed to have their results already inserted in the buffer by manual -evaluation. This setting is useful to avoid expensive recalculations during -export, not to provide security. - -@comment node-name, next, previous, up -@comment Extracting source code, Evaluating code blocks, Exporting code blocks, Working With Source Code -@node Extracting source code, Evaluating code blocks, Exporting code blocks, Working With Source Code +@vindex org-export-babel-evaluate +To stop Org from evaluating code blocks during export, set +@code{org-export-babel-evaluate} variable to @code{nil}. + +Turning off evaluation comes in handy when batch processing. For example, +markup languages for wikis, which have a high risk of untrusted code. +Stopping code block evaluation also stops evaluation of all header arguments +of the code block. This may not be desirable in some circumstances. So +during export, to allow evaluation of just the header arguments but not any +code evaluation in the source block, set @code{:eval never-export} +(@pxref{eval}). + +To evaluate just the inline code blocks, set @code{org-export-babel-evaluate} +to @code{inline-only}. Isolating the option to allow inline evaluations +separate from @samp{src} code block evaluations during exports is not for +security but for avoiding any delays due to recalculations, such as calls to +a remote database. + +Org never evaluates code blocks in commented sub-trees when exporting +(@pxref{Comment lines}). On the other hand, Org does evaluate code blocks in +sub-trees excluded from export (@pxref{Export settings}). + +@node Extracting source code @section Extracting source code @cindex tangling @cindex source code, extracting @cindex code block, extracting source code -Creating pure source code files by extracting code from source blocks is -referred to as ``tangling''---a term adopted from the literate programming -community. During ``tangling'' of code blocks their bodies are expanded -using @code{org-babel-expand-src-block} which can expand both variable and -``noweb'' style references (see @ref{Noweb reference syntax}). +Extracting source code from code blocks is a basic task in literate +programming. Org has features to make this easy. In literate programming +parlance, documents on creation are @emph{woven} with code and documentation, +and on export, the code is @emph{tangled} for execution by a computer. Org +facilitates weaving and tangling for producing, maintaining, sharing, and +exporting literate programming documents. Org provides extensive +customization options for extracting source code. + +When Org tangles @samp{src} code blocks, it expands, merges, and transforms +them. Then Org recomposes them into one or more separate files, as +configured through the options. During this @emph{tangling} process, Org +expands variables in the source code, and resolves any ``noweb'' style +references (@pxref{Noweb reference syntax}). @subsubheading Header arguments @table @code +@cindex @code{:tangle}, src header argument @item :tangle no -The default. The code block is not included in the tangled output. +By default, Org does not tangle the @samp{src} code block on export. @item :tangle yes -Include the code block in the tangled output. The output file name is the -name of the org file with the extension @samp{.org} replaced by the extension -for the block language. +Org extracts the contents of the code block for the tangled output. By +default, the output file name is the same as the Org file but with a file +extension derived from the language identifier of the @samp{src} code block. @item :tangle filename -Include the code block in the tangled output to file @samp{filename}. +Override the default file name with this one for the tangled output. @end table @kindex C-c C-v t @@ -14209,7 +15166,7 @@ Include the code block in the tangled output to file @samp{filename}. @item org-babel-tangle Tangle the current file. Bound to @kbd{C-c C-v t}. -With prefix argument only tangle the current code block. +With prefix argument only tangle the current @samp{src} code block. @item org-babel-tangle-file Choose a file to tangle. Bound to @kbd{C-c C-v f}. @end table @@ -14218,72 +15175,67 @@ Choose a file to tangle. Bound to @kbd{C-c C-v f}. @table @code @item org-babel-post-tangle-hook -This hook is run from within code files tangled by @code{org-babel-tangle}. -Example applications could include post-processing, compilation or evaluation -of tangled code files. +This hook runs from within code tangled by @code{org-babel-tangle}, making it +suitable for post-processing, compilation, and evaluation of code in the +tangled files. @end table @subsubheading Jumping between code and Org -When tangling code from an Org-mode buffer to a source code file, you'll -frequently find yourself viewing the file of tangled source code (e.g., many -debuggers point to lines of the source code file). It is useful to be able -to navigate from the tangled source to the Org-mode buffer from which the -code originated. - -The @code{org-babel-tangle-jump-to-org} function provides this jumping from -code to Org-mode functionality. Two header arguments are required for -jumping to work, first the @code{padline} (@ref{padline}) option must be set -to true (the default setting), second the @code{comments} (@ref{comments}) -header argument must be set to @code{links}, which will insert comments into -the source code buffer which point back to the original Org-mode file. +Debuggers normally link errors and messages back to the source code. But for +tangled files, we want to link back to the Org file, not to the tangled +source file. To make this extra jump, Org uses +@code{org-babel-tangle-jump-to-org} function with two additional source code +block header arguments: One, set @code{padline} (@pxref{padline}) to true +(the default setting). Two, set @code{comments} (@pxref{comments}) to +@code{link}, which makes Org insert links to the Org file. -@node Evaluating code blocks, Library of Babel, Extracting source code, Working With Source Code +@node Evaluating code blocks @section Evaluating code blocks @cindex code block, evaluating @cindex source code, evaluating @cindex #+RESULTS -Code blocks can be evaluated@footnote{Whenever code is evaluated there is a -potential for that code to do harm. Org mode provides safeguards to ensure -that code is only evaluated after explicit confirmation from the user. For -information on these safeguards (and on how to disable them) see @ref{Code -evaluation security}.} and the results of evaluation optionally placed in the -Org mode buffer. The results of evaluation are placed following a line that -begins by default with @code{#+RESULTS} and optionally a cache identifier -and/or the name of the evaluated code block. The default value of -@code{#+RESULTS} can be changed with the customizable variable -@code{org-babel-results-keyword}. - -By default, the evaluation facility is only enabled for Lisp code blocks -specified as @code{emacs-lisp}. However, source code blocks in many languages -can be evaluated within Org mode (see @ref{Languages} for a list of supported -languages and @ref{Structure of code blocks} for information on the syntax -used to define a code block). +A note about security: With code evaluation comes the risk of harm. Org +safeguards by prompting for user's permission before executing any code in +the source block. To customize this safeguard (or disable it) see @ref{Code +evaluation security}. + +Org captures the results of the @samp{src} code block evaluation and inserts +them in the Org file, right after the @samp{src} code block. The insertion +point is after a newline and the @code{#+RESULTS} label. Org creates the +@code{#+RESULTS} label if one is not already there. + +By default, Org enables only @code{emacs-lisp} @samp{src} code blocks for +execution. See @ref{Languages} for identifiers to enable other languages. @kindex C-c C-c -There are a number of ways to evaluate code blocks. The simplest is to press -@kbd{C-c C-c} or @kbd{C-c C-v e} with the point on a code block@footnote{The -option @code{org-babel-no-eval-on-ctrl-c-ctrl-c} can be used to remove code -evaluation from the @kbd{C-c C-c} key binding.}. This will call the -@code{org-babel-execute-src-block} function to evaluate the block and insert -its results into the Org mode buffer. -@cindex #+CALL +Org provides many ways to execute @samp{src} code blocks. @kbd{C-c C-c} or +@kbd{C-c C-v e} with the point on a @samp{src} code block@footnote{The option +@code{org-babel-no-eval-on-ctrl-c-ctrl-c} can be used to remove code +evaluation from the @kbd{C-c C-c} key binding.} calls the +@code{org-babel-execute-src-block} function, which executes the code in the +block, collects the results, and inserts them in the buffer. -It is also possible to evaluate named code blocks from anywhere in an Org -mode buffer or an Org mode table. Live code blocks located in the current -Org mode buffer or in the ``Library of Babel'' (see @ref{Library of Babel}) -can be executed. Named code blocks can be executed with a separate -@code{#+CALL:} line or inline within a block of text. +@cindex #+CALL +By calling a named code block@footnote{Actually, the constructs call_<name>() +and src_<lang>@{@} are not evaluated when they appear in a keyword line +(i.e. lines starting with @code{#+KEYWORD:}, @pxref{In-buffer settings}).} +from an Org mode buffer or a table. Org can call the named @samp{src} code +blocks from the current Org mode buffer or from the ``Library of Babel'' +(@pxref{Library of Babel}). Whether inline syntax or the @code{#+CALL:} +syntax is used, the result is wrapped based on the variable +@code{org-babel-inline-result-wrap}, which by default is set to @code{"=%s="} +to produce verbatim text suitable for markup. -The syntax of the @code{#+CALL:} line is +The syntax for @code{#+CALL:} is @example #+CALL: <name>(<arguments>) #+CALL: <name>[<inside header arguments>](<arguments>) <end header arguments> @end example -The syntax for inline evaluation of named code blocks is +The syntax for inline named code block is @example ... call_<name>(<arguments>) ... @@ -14292,98 +15244,88 @@ The syntax for inline evaluation of named code blocks is @table @code @item <name> -The name of the code block to be evaluated (see @ref{Structure of code blocks}). +This is the name of the code block to be evaluated (@pxref{Structure of +code blocks}). @item <arguments> -Arguments specified in this section will be passed to the code block. These -arguments use standard function call syntax, rather than -header argument syntax. For example, a @code{#+CALL:} line that passes the -number four to a code block named @code{double}, which declares the header -argument @code{:var n=2}, would be written as @code{#+CALL: double(n=4)}. +Org passes arguments to the code block using standard function call syntax. +For example, a @code{#+CALL:} line that passes @samp{4} to a code block named +@code{double}, which declares the header argument @code{:var n=2}, would be +written as @code{#+CALL: double(n=4)}. Note how this function call syntax is +different from the header argument syntax. @item <inside header arguments> -Inside header arguments are passed through and applied to the named code -block. These arguments use header argument syntax rather than standard -function call syntax. Inside header arguments affect how the code block is -evaluated. For example, @code{[:results output]} will collect the results of -everything printed to @code{STDOUT} during execution of the code block. +Org passes inside header arguments to the named @samp{src} code block using +the header argument syntax. Inside header arguments apply to code block +evaluation. For example, @code{[:results output]} collects results printed +to @code{STDOUT} during code execution of that block. Note how this header +argument syntax is different from the function call syntax. @item <end header arguments> -End header arguments are applied to the calling instance and do not affect -evaluation of the named code block. They affect how the results are -incorporated into the Org mode buffer and how the call line is exported. For -example, @code{:results html} will insert the results of the call line -evaluation in the Org buffer, wrapped in a @code{BEGIN_HTML:} block. - -For more examples of passing header arguments to @code{#+CALL:} lines see -@ref{Header arguments in function calls}. +End header arguments affect the results returned by the code block. For +example, @code{:results html} wraps the results in a @code{BEGIN_EXPORT html} +block before inserting the results in the Org buffer. + +For more examples of header arguments for @code{#+CALL:} lines, +@pxref{Arguments in function calls}. @end table -@node Library of Babel, Languages, Evaluating code blocks, Working With Source Code +@node Library of Babel @section Library of Babel @cindex babel, library of @cindex source code, library @cindex code block, library -The ``Library of Babel'' consists of code blocks that can be called from any -Org mode file. Code blocks defined in the ``Library of Babel'' can be called -remotely as if they were in the current Org mode buffer (see @ref{Evaluating -code blocks} for information on the syntax of remote code block evaluation). - - -The central repository of code blocks in the ``Library of Babel'' is housed -in an Org mode file located in the @samp{contrib} directory of Org mode. - -Users can add code blocks they believe to be generally useful to their -``Library of Babel.'' The code blocks can be stored in any Org mode file and -then loaded into the library with @code{org-babel-lob-ingest}. - +The ``Library of Babel'' is a collection of code blocks. Like a function +library, these code blocks can be called from other Org files. This +collection is in a repository file in Org mode format in the @samp{doc} +directory of Org mode installation. For remote code block evaluation syntax, +@pxref{Evaluating code blocks}. @kindex C-c C-v i -Code blocks located in any Org mode file can be loaded into the ``Library of -Babel'' with the @code{org-babel-lob-ingest} function, bound to @kbd{C-c C-v -i}. +For any user to add code to the library, first save the code in regular +@samp{src} code blocks of an Org file, and then load the Org file with +@code{org-babel-lob-ingest}, which is bound to @kbd{C-c C-v i}. -@node Languages, Header arguments, Library of Babel, Working With Source Code +@node Languages @section Languages @cindex babel, languages @cindex source code, languages @cindex code block, languages -Code blocks in the following languages are supported. +Org supports the following languages for the @samp{src} code blocks: -@multitable @columnfractions 0.28 0.3 0.22 0.2 -@item @b{Language} @tab @b{Identifier} @tab @b{Language} @tab @b{Identifier} +@multitable @columnfractions 0.25 0.25 0.25 0.25 +@headitem @b{Language} @tab @b{Identifier} @tab @b{Language} @tab @b{Identifier} @item Asymptote @tab asymptote @tab Awk @tab awk -@item Emacs Calc @tab calc @tab C @tab C -@item C++ @tab C++ @tab Clojure @tab clojure -@item CSS @tab css @tab ditaa @tab ditaa -@item Graphviz @tab dot @tab Emacs Lisp @tab emacs-lisp +@item C @tab C @tab C++ @tab C++ +@item Clojure @tab clojure @tab CSS @tab css +@item D @tab d @tab ditaa @tab ditaa +@item Graphviz @tab dot @tab Emacs Calc @tab calc +@item Emacs Lisp @tab emacs-lisp @tab Fortran @tab fortran @item gnuplot @tab gnuplot @tab Haskell @tab haskell -@item Java @tab java @tab @tab -@item Javascript @tab js @tab LaTeX @tab latex -@item Ledger @tab ledger @tab Lisp @tab lisp -@item Lilypond @tab lilypond @tab MATLAB @tab matlab +@item Java @tab java @tab Javascript @tab js +@item LaTeX @tab latex @tab Ledger @tab ledger +@item Lisp @tab lisp @tab Lilypond @tab lilypond +@item Lua @tab lua @tab MATLAB @tab matlab @item Mscgen @tab mscgen @tab Objective Caml @tab ocaml @item Octave @tab octave @tab Org mode @tab org @item Oz @tab oz @tab Perl @tab perl -@item Plantuml @tab plantuml @tab Python @tab python -@item R @tab R @tab Ruby @tab ruby -@item Sass @tab sass @tab Scheme @tab scheme -@item GNU Screen @tab screen @tab shell @tab sh +@item Plantuml @tab plantuml @tab Processing.js @tab processing +@item Python @tab python @tab R @tab R +@item Ruby @tab ruby @tab Sass @tab sass +@item Scheme @tab scheme @tab GNU Screen @tab screen +@item Sed @tab sed @tab shell @tab sh @item SQL @tab sql @tab SQLite @tab sqlite @end multitable -Language-specific documentation is available for some languages. If -available, it can be found at +Additional documentation for some languages are at @uref{http://orgmode.org/worg/org-contrib/babel/languages.html}. -The option @code{org-babel-load-languages} controls which languages are -enabled for evaluation (by default only @code{emacs-lisp} is enabled). This -variable can be set using the customization interface or by adding code like -the following to your emacs configuration. +By default, only @code{emacs-lisp} is enabled for evaluation. To enable or +disable other languages, customize the @code{org-babel-load-languages} +variable either through the Emacs customization interface, or by adding code +to the init file as shown next: -@quotation -The following disables @code{emacs-lisp} evaluation and enables evaluation of -@code{R} code blocks. -@end quotation +In this example, evaluation is disabled for @code{emacs-lisp}, and enabled +for @code{R}. @lisp (org-babel-do-load-languages @@ -14392,55 +15334,54 @@ The following disables @code{emacs-lisp} evaluation and enables evaluation of (R . t))) @end lisp -It is also possible to enable support for a language by loading the related -elisp file with @code{require}. - -@quotation -The following adds support for evaluating @code{clojure} code blocks. -@end quotation +Note that this is not the only way to enable a language. Org also enables +languages when loaded with @code{require} statement. For example, the +following enables execution of @code{clojure} code blocks: @lisp (require 'ob-clojure) @end lisp -@node Header arguments, Results of evaluation, Languages, Working With Source Code +@node Header arguments @section Header arguments @cindex code block, header arguments @cindex source code, block header arguments -Code block functionality can be configured with header arguments. This -section provides an overview of the use of header arguments, and then -describes each header argument in detail. +Details of configuring header arguments are shown here. @menu * Using header arguments:: Different ways to set header arguments * Specific header arguments:: List of header arguments @end menu -@node Using header arguments, Specific header arguments, Header arguments, Header arguments +@node Using header arguments @subsection Using header arguments -The values of header arguments can be set in several way. When the header -arguments in each layer have been determined, they are combined in order from -the first, least specific (having the lowest priority) up to the last, most -specific (having the highest priority). A header argument with a higher -priority replaces the same header argument specified at lower priority. +Since header arguments can be set in several ways, Org prioritizes them in +case of overlaps or conflicts by giving local settings a higher priority. +Header values in function calls, for example, override header values from +global defaults. @menu -* System-wide header arguments:: Set global default values -* Language-specific header arguments:: Set default values by language -* Header arguments in Org mode properties:: Set default values for a buffer or heading -* Language-specific header arguments in Org mode properties:: Set language-specific default values for a buffer or heading -* Code block specific header arguments:: The most common way to set values -* Header arguments in function calls:: The most specific level +* System-wide header arguments:: Set globally, language-specific +* Language-specific header arguments:: Set in the Org file's headers +* Header arguments in Org mode properties:: Set in the Org file +* Language-specific mode properties:: +* Code block specific header arguments:: The most commonly used method +* Arguments in function calls:: The most specific level, takes highest priority @end menu -@node System-wide header arguments, Language-specific header arguments, Using header arguments, Using header arguments +@node System-wide header arguments @subsubheading System-wide header arguments @vindex org-babel-default-header-args System-wide values of header arguments can be specified by adapting the @code{org-babel-default-header-args} variable: +@cindex @code{:session}, src header argument +@cindex @code{:results}, src header argument +@cindex @code{:exports}, src header argument +@cindex @code{:cache}, src header argument +@cindex @code{:noweb}, src header argument @example :session => "none" :results => "replace" @@ -14449,10 +15390,8 @@ System-wide values of header arguments can be specified by adapting the :noweb => "no" @end example -For example, the following example could be used to set the default value of -@code{:noweb} header arguments to @code{yes}. This would have the effect of -expanding @code{:noweb} references by default when evaluating source code -blocks. +This example sets @code{:noweb} header arguments to @code{yes}, which makes +Org expand @code{:noweb} references by default. @lisp (setq org-babel-default-header-args @@ -14460,48 +15399,40 @@ blocks. (assq-delete-all :noweb org-babel-default-header-args))) @end lisp -@node Language-specific header arguments, Header arguments in Org mode properties, System-wide header arguments, Using header arguments +@node Language-specific header arguments @subsubheading Language-specific header arguments -Each language can define its own set of default header arguments in variable -@code{org-babel-default-header-args:<lang>}, where @code{<lang>} is the name -of the language. See the language-specific documentation available online at -@uref{http://orgmode.org/worg/org-contrib/babel}. +Each language can have separate default header arguments by customizing the +variable @code{org-babel-default-header-args:<lang>}, where @code{<lang>} is +the name of the language. For details, see the language-specific online +documentation at @uref{http://orgmode.org/worg/org-contrib/babel}. -@node Header arguments in Org mode properties, Language-specific header arguments in Org mode properties, Language-specific header arguments, Using header arguments +@node Header arguments in Org mode properties @subsubheading Header arguments in Org mode properties -Buffer-wide header arguments may be specified as properties through the use -of @code{#+PROPERTY:} lines placed anywhere in an Org mode file (see -@ref{Property syntax}). +For header arguments applicable to the buffer, use @code{#+PROPERTY:} lines +anywhere in the Org mode file (@pxref{Property syntax}). -For example the following would set @code{session} to @code{*R*} (only for R -code blocks), and @code{results} to @code{silent} for every code block in the -buffer, ensuring that all execution took place in the same session, and no -results would be inserted into the buffer. +The following example sets only for @samp{R} code blocks to @code{session}, +making all the @samp{R} code blocks execute in the same session. Setting +@code{results} to @code{silent} ignores the results of executions for all +blocks, not just @samp{R} code blocks; no results inserted for any block. @example #+PROPERTY: header-args:R :session *R* #+PROPERTY: header-args :results silent @end example -Header arguments read from Org mode properties can also be set on a -per-subtree basis using property drawers (see @ref{Property syntax}). @vindex org-use-property-inheritance -When properties are used to set default header arguments, they are always -looked up with inheritance, regardless of the value of -@code{org-use-property-inheritance}. Properties are evaluated as seen by the -outermost call or source block.@footnote{The deprecated syntax for default -header argument properties, using the name of the header argument as a -property name directly, evaluates the property as seen by the corresponding -source block definition. This behavior has been kept for backwards -compatibility.} +Header arguments set through Org's property drawers (@pxref{Property syntax}) +apply at the sub-tree level on down. Since these property drawers can appear +anywhere in the file hierarchy, Org uses outermost call or source block to +resolve the values. Org ignores @code{org-use-property-inheritance} setting. -In the following example the value of -the @code{:cache} header argument will default to @code{yes} in all code -blocks in the subtree rooted at the following heading: +In this example, @code{:cache} defaults to @code{yes} for all code blocks in +the sub-tree starting with @samp{sample header}. @example -* outline header +* sample header :PROPERTIES: :header-args: :cache yes :END: @@ -14509,17 +15440,16 @@ blocks in the subtree rooted at the following heading: @kindex C-c C-x p @vindex org-babel-default-header-args -Properties defined in this way override the properties set in -@code{org-babel-default-header-args} and are applied for all activated -languages. It is convenient to use the @code{org-set-property} function -bound to @kbd{C-c C-x p} to set properties in Org mode documents. +Properties defined through @code{org-set-property} function, bound to +@kbd{C-c C-x p}, apply to all active languages. They override properties set +in @code{org-babel-default-header-args}. -@node Language-specific header arguments in Org mode properties, Code block specific header arguments, Header arguments in Org mode properties, Using header arguments -@subsubheading Language-specific header arguments in Org mode properties +@node Language-specific mode properties +@subsubheading Language-specific mode properties Language-specific header arguments are also read from properties -@code{header-args:<lang>} where @code{<lang>} is the name of the language -targeted. As an example +@code{header-args:<lang>} where @code{<lang>} is the language identifier. +For example, @example * Heading @@ -14533,24 +15463,21 @@ targeted. As an example :END: @end example -would independently set a default session header argument for R and clojure -for calls and source blocks under subtree ``Heading'' and change to a -different clojure setting for evaluations under subtree ``Subheading'', while -the R session is inherited from ``Heading'' and therefore unchanged. +would force separate sessions for clojure blocks in Heading and Subheading, +but use the same session for all @samp{R} blocks. Blocks in Subheading +inherit settings from Heading. -@node Code block specific header arguments, Header arguments in function calls, Language-specific header arguments in Org mode properties, Using header arguments +@node Code block specific header arguments @subsubheading Code block specific header arguments -The most common way to assign values to header arguments is at the -code block level. This can be done by listing a sequence of header -arguments and their values as part of the @code{#+BEGIN_SRC} line. -Properties set in this way override both the values of -@code{org-babel-default-header-args} and header arguments specified as -properties. In the following example, the @code{:results} header argument -is set to @code{silent}, meaning the results of execution will not be -inserted in the buffer, and the @code{:exports} header argument is set to -@code{code}, meaning only the body of the code block will be -preserved on export to HTML or @LaTeX{}. +Header arguments are most commonly set at the @samp{src} code block level, on +the @code{#+BEGIN_SRC} line. Arguments set at this level take precedence +over those set in the @code{org-babel-default-header-args} variable, and also +those set as header properties. + +In the following example, setting @code{results} to @code{silent} makes it +ignore results of the code execution. Setting @code{:exports} to @code{code} +exports only the body of the @samp{src} code block to HTML or @LaTeX{}.: @example #+NAME: factorial @@ -14559,93 +15486,93 @@ fac 0 = 1 fac n = n * fac (n-1) #+END_SRC @end example -Similarly, it is possible to set header arguments for inline code blocks + +The same header arguments in an inline @samp{src} code block: @example src_haskell[:exports both]@{fac 5@} @end example -Code block header arguments can span multiple lines using @code{#+HEADER:} or -@code{#+HEADERS:} lines preceding a code block or nested between the -@code{#+NAME:} line and the @code{#+BEGIN_SRC} line of a named code block. +Code block header arguments can span multiple lines using @code{#+HEADER:} on +each line. Note that Org currently accepts the plural spelling of +@code{#+HEADER:} only as a convenience for backward-compatibility. It may be +removed at some point. + @cindex #+HEADER: -@cindex #+HEADERS: -Multi-line header arguments on an un-named code block: +Multi-line header arguments on an unnamed @samp{src} code block: @example - #+HEADERS: :var data1=1 - #+BEGIN_SRC emacs-lisp :var data2=2 +#+HEADER: :var data1=1 +#+BEGIN_SRC emacs-lisp :var data2=2 (message "data1:%S, data2:%S" data1 data2) - #+END_SRC +#+END_SRC - #+RESULTS: - : data1:1, data2:2 +#+RESULTS: +: data1:1, data2:2 @end example -Multi-line header arguments on a named code block: +Multi-line header arguments on a named @samp{src} code block: @example - #+NAME: named-block - #+HEADER: :var data=2 - #+BEGIN_SRC emacs-lisp - (message "data:%S" data) - #+END_SRC +#+NAME: named-block +#+HEADER: :var data=2 +#+BEGIN_SRC emacs-lisp + (message "data:%S" data) +#+END_SRC - #+RESULTS: named-block - : data:2 +#+RESULTS: named-block + : data:2 @end example -@node Header arguments in function calls, , Code block specific header arguments, Using header arguments -@comment node-name, next, previous, up -@subsubheading Header arguments in function calls +@node Arguments in function calls +@subsubheading Arguments in function calls -At the most specific level, header arguments for ``Library of Babel'' or -@code{#+CALL:} lines can be set as shown in the two examples below. For more -information on the structure of @code{#+CALL:} lines see @ref{Evaluating code -blocks}. +Header arguments in function calls are the most specific and override all +other settings in case of an overlap. They get the highest priority. Two +@code{#+CALL:} examples are shown below. For the complete syntax of +@code{#+CALL:} lines, see @ref{Evaluating code blocks}. -The following will apply the @code{:exports results} header argument to the +In this example, @code{:exports results} header argument is applied to the evaluation of the @code{#+CALL:} line. @example #+CALL: factorial(n=5) :exports results @end example -The following will apply the @code{:session special} header argument to the -evaluation of the @code{factorial} code block. +In this example, @code{:session special} header argument is applied to the +evaluation of @code{factorial} code block. @example #+CALL: factorial[:session special](n=5) @end example -@node Specific header arguments, , Using header arguments, Header arguments +@node Specific header arguments @subsection Specific header arguments -Header arguments consist of an initial colon followed by the name of the -argument in lowercase letters. The following header arguments are defined: +Org comes with many header arguments common to all languages. New header +arguments are added for specific languages as they become available for use +in @samp{src} code blocks. A header argument is specified with an initial +colon followed by the argument's name in lowercase. Common header arguments +are: @menu -* var:: Pass arguments to code blocks -* results:: Specify the type of results and how they will - be collected and handled -* file:: Specify a path for file output +* var:: Pass arguments to @samp{src} code blocks +* results:: Specify results type; how to collect +* file:: Specify a path for output file * file-desc:: Specify a description for file results -* dir:: Specify the default (possibly remote) - directory for code block execution -* exports:: Export code and/or results -* tangle:: Toggle tangling and specify file name -* mkdirp:: Toggle creation of parent directories of target - files during tangling -* comments:: Toggle insertion of comments in tangled - code files -* padline:: Control insertion of padding lines in tangled - code files -* no-expand:: Turn off variable assignment and noweb - expansion during tangling +* file-ext:: Specify an extension for file output +* output-dir:: Specify a directory for output file +* dir:: Specify the default directory for code block execution +* exports:: Specify exporting code, results, both, none +* tangle:: Toggle tangling; or specify file name +* mkdirp:: Toggle for parent directory creation for target files during tangling +* comments:: Toggle insertion of comments in tangled code files +* padline:: Control insertion of padding lines in tangled code files +* no-expand:: Turn off variable assignment and noweb expansion during tangling * session:: Preserve the state of code evaluation * noweb:: Toggle expansion of noweb references * noweb-ref:: Specify block's noweb reference resolution target -* noweb-sep:: String used to separate noweb references +* noweb-sep:: String to separate noweb references * cache:: Avoid re-evaluating unchanged code blocks * sep:: Delimiter for writing tabular results outside Org * hlines:: Handle horizontal lines in tables @@ -14655,45 +15582,46 @@ argument in lowercase letters. The following header arguments are defined: * tangle-mode:: Set permission of tangled files * eval:: Limit evaluation of specific code blocks * wrap:: Mark source block evaluation results -* post:: Post processing of code block results -* prologue:: Text to prepend to code block body -* epilogue:: Text to append to code block body +* post:: Post processing of results of code block evaluation +* prologue:: Text to prepend to body of code block +* epilogue:: Text to append to body of code block @end menu -Additional header arguments are defined on a language-specific basis, see -@ref{Languages}. +For language-specific header arguments, see @ref{Languages}. -@node var, results, Specific header arguments, Specific header arguments +@node var @subsubsection @code{:var} -The @code{:var} header argument is used to pass arguments to code blocks. -The specifics of how arguments are included in a code block vary by language; -these are addressed in the language-specific documentation. However, the -syntax used to specify arguments is the same across all languages. In every -case, variables require a default value when they are declared. +@cindex @code{:var}, src header argument +Use @code{:var} for passing arguments to @samp{src} code blocks. The +specifics of variables in @samp{src} code blocks vary by the source language +and are covered in the language-specific documentation. The syntax for +@code{:var}, however, is the same for all languages. This includes declaring +a variable, and assigning a default value. -The values passed to arguments can either be literal values, references, or -Emacs Lisp code (see @ref{var, Emacs Lisp evaluation of variables}). -References include anything in the Org mode file that takes a @code{#+NAME:} -or @code{#+RESULTS:} line: tables, lists, @code{#+BEGIN_EXAMPLE} blocks, -other code blocks and the results of other code blocks. +Arguments can take values as literals, or as references, or even as Emacs +Lisp code (@pxref{var, Emacs Lisp evaluation of variables}). References are +names from the Org file from the lines @code{#+NAME:} or @code{#+RESULTS:}. +References can also refer to tables, lists, @code{#+BEGIN_EXAMPLE} blocks, +other types of @samp{src} code blocks, or the results of execution of +@samp{src} code blocks. -Note: When a reference is made to another code block, the referenced block -will be evaluated unless it has current cached results (see @ref{cache}). +For better performance, Org can cache results of evaluations. But caching +comes with severe limitations (@pxref{cache}). -Argument values can be indexed in a manner similar to arrays (see @ref{var, -Indexable variable values}). +Argument values are indexed like arrays (@pxref{var, Indexable variable +values}). -The following syntax is used to pass arguments to code blocks using the -@code{:var} header argument. +The following syntax is used to pass arguments to @samp{src} code blocks +using the @code{:var} header argument. @example :var name=assign @end example -The argument, @code{assign}, can either be a literal value, such as a string -@samp{"string"} or a number @samp{9}, or a reference to a table, a list, a -literal example, another code block (with or without arguments), or the -results of evaluating another code block. +The @code{assign} is a literal value, such as a string @samp{"string"}, a +number @samp{9}, a reference to a table, a list, a literal example, another +code block (with or without arguments), or the results from evaluating a code +block. Here are examples of passing values by reference: @@ -14719,8 +15647,8 @@ an Org mode table named with either a @code{#+NAME:} line @end example @item list -a simple list named with a @code{#+NAME:} line (note that nesting is not -carried through to the source code block) +a simple list named with a @code{#+NAME:} line. Note that only the top level +list items are passed along. Nested list items are ignored. @example #+NAME: example-list @@ -14751,9 +15679,9 @@ optionally followed by parentheses @end example @item code block with arguments -a code block name, as assigned by @code{#+NAME:}, followed by parentheses and -optional arguments passed within the parentheses following the -code block name using standard function call syntax +a @samp{src} code block name, as assigned by @code{#+NAME:}, followed by +parentheses and optional arguments passed within the parentheses following +the @samp{src} code block name using standard function call syntax @example #+NAME: double @@ -14765,7 +15693,7 @@ code block name using standard function call syntax : 16 #+NAME: squared -#+BEGIN_SRC emacs-lisp :var input=double(input=1) +#+BEGIN_SRC emacs-lisp :var input=double(input=2) (* input input) #+END_SRC @@ -14797,14 +15725,14 @@ on two lines @end table @subsubheading Indexable variable values -It is possible to reference portions of variable values by ``indexing'' into -the variables. Indexes are 0 based with negative values counting back from -the end. If an index is separated by @code{,}s then each subsequent section -will index into the next deepest nesting or dimension of the value. Note -that this indexing occurs @emph{before} other table related header arguments -like @code{:hlines}, @code{:colnames} and @code{:rownames} are applied. The -following example assigns the last cell of the first row the table -@code{example-table} to the variable @code{data}: +Indexing variable values enables referencing portions of a variable. Indexes +are 0 based with negative values counting backwards from the end. If an +index is separated by @code{,}s then each subsequent section will index as +the next dimension. Note that this indexing occurs @emph{before} other +table-related header arguments are applied, such as @code{:hlines}, +@code{:colnames} and @code{:rownames}. The following example assigns the +last cell of the first row the table @code{example-table} to the variable +@code{data}: @example #+NAME: example-table @@ -14844,10 +15772,9 @@ to @code{data}. | 4 | d | @end example -Additionally, an empty index, or the single character @code{*}, are both -interpreted to mean the entire range and as such are equivalent to -@code{0:-1}, as shown in the following example in which the entire first -column is referenced. +To pick the entire range, use an empty index, or the single character +@code{*}. @code{0:-1} does the same thing. Example below shows how to +reference the first column only. @example #+NAME: example-table @@ -14864,9 +15791,9 @@ column is referenced. | 1 | 2 | 3 | 4 | @end example -It is possible to index into the results of code blocks as well as tables. -Any number of dimensions can be indexed. Dimensions are separated from one -another by commas, as shown in the following example. +Index referencing can be used for tables and code blocks. Index referencing +can handle any number of dimensions. Commas delimit multiple dimensions, as +shown below. @example #+NAME: 3D @@ -14886,14 +15813,13 @@ another by commas, as shown in the following example. @subsubheading Emacs Lisp evaluation of variables -Emacs lisp code can be used to initialize variable values. When a variable -value starts with @code{(}, @code{[}, @code{'} or @code{`} it will be -evaluated as Emacs Lisp and the result of the evaluation will be assigned as -the variable value. The following example demonstrates use of this -evaluation to reliably pass the file-name of the Org mode buffer to a code -block---note that evaluation of header arguments is guaranteed to take place -in the original Org mode file, while there is no such guarantee for -evaluation of the code block body. +Emacs lisp code can set the values for variables. To differentiate a value +from lisp code, Org interprets any value starting with @code{(}, @code{[}, +@code{'} or @code{`} as Emacs Lisp code. The result of evaluating that code +is then assigned to the value of that variable. The following example shows +how to reliably query and pass file name of the Org mode buffer to a code +block using headers. We need reliability here because the file's name could +change once the code in the block starts executing. @example #+BEGIN_SRC sh :var filename=(buffer-file-name) :exports both @@ -14901,14 +15827,14 @@ evaluation of the code block body. #+END_SRC @end example -Note that values read from tables and lists will not be evaluated as -Emacs Lisp, as shown in the following example. +Note that values read from tables and lists will not be mistakenly evaluated +as Emacs Lisp code, as illustrated in the following example. @example #+NAME: table | (a b c) | -#+HEADERS: :var data=table[0,0] +#+HEADER: :var data=table[0,0] #+BEGIN_SRC perl $data #+END_SRC @@ -14917,167 +15843,171 @@ Emacs Lisp, as shown in the following example. : (a b c) @end example -@node results, file, var, Specific header arguments +@node results @subsubsection @code{:results} +@cindex @code{:results}, src header argument -There are four classes of @code{:results} header argument. Only one option -per class may be supplied per code block. +There are four classes of @code{:results} header arguments. Each @samp{src} +code block can take only one option per class. @itemize @bullet @item -@b{collection} header arguments specify how the results should be collected -from the code block +@b{collection} for how the results should be collected from the @samp{src} +code block @item -@b{type} header arguments specify what type of result the code block will -return---which has implications for how they will be processed before -insertion into the Org mode buffer +@b{type} for which type of result the code block will return; affects how Org +processes and inserts results in the Org buffer @item -@b{format} header arguments specify what type of result the code block will -return---which has implications for how they will be inserted into the -Org mode buffer +@b{format} for the result; affects how Org processes and inserts results in +the Org buffer @item -@b{handling} header arguments specify how the results of evaluating the code -block should be handled. +@b{handling} for processing results after evaluation of the @samp{src} code +block @end itemize @subsubheading Collection -The following options are mutually exclusive, and specify how the results -should be collected from the code block. +Collection options specify the results. Choose one of the options; they are +mutually exclusive. @itemize @bullet @item @code{value} -This is the default. The result is the value of the last statement in the -code block. This header argument places the evaluation in functional -mode. Note that in some languages, e.g., Python, use of this result type -requires that a @code{return} statement be included in the body of the source -code block. E.g., @code{:results value}. +Default. Functional mode. Result is the value returned by the last +statement in the @samp{src} code block. Languages like Python may require an +explicit @code{return} statement in the @samp{src} code block. Usage +example: @code{:results value}. @item @code{output} -The result is the collection of everything printed to STDOUT during the -execution of the code block. This header argument places the -evaluation in scripting mode. E.g., @code{:results output}. +Scripting mode. Result is collected from STDOUT during execution of the code +in the @samp{src} code block. Usage example: @code{:results output}. @end itemize @subsubheading Type - -The following options are mutually exclusive and specify what type of results -the code block will return. By default, results are inserted as either a -table or scalar depending on their value. +Type tells what result types to expect from the execution of the code +block. Choose one of the options; they are mutually exclusive. The default +behavior is to automatically determine the result type. @itemize @bullet @item @code{table}, @code{vector} -The results should be interpreted as an Org mode table. If a single value is -returned, it will be converted into a table with one row and one column. -E.g., @code{:results value table}. +Interpret the results as an Org table. If the result is a single value, +create a table with one row and one column. Usage example: @code{:results +value table}. @item @code{list} -The results should be interpreted as an Org mode list. If a single scalar -value is returned it will be converted into a list with only one element. +Interpret the results as an Org list. If the result is a single value, +create a list of one element. @item @code{scalar}, @code{verbatim} -The results should be interpreted literally---they will not be -converted into a table. The results will be inserted into the Org mode -buffer as quoted text. E.g., @code{:results value verbatim}. +Interpret literally and insert as quoted text. Do not create a table. Usage +example: @code{:results value verbatim}. @item @code{file} -The results will be interpreted as the path to a file, and will be inserted -into the Org mode buffer as a file link. E.g., @code{:results value file}. +Interpret as path to a file. Inserts a link to the file. Usage example: +@code{:results value file}. @end itemize @subsubheading Format - -The following options are mutually exclusive and specify what type of results -the code block will return. By default, results are inserted according to the -type as specified above. +Format pertains to the type of the result returned by the @samp{src} code +block. Choose one of the options; they are mutually exclusive. The default +follows from the type specified above. @itemize @bullet @item @code{raw} -The results are interpreted as raw Org mode code and are inserted directly -into the buffer. If the results look like a table they will be aligned as -such by Org mode. E.g., @code{:results value raw}. +Interpreted as raw Org mode. Inserted directly into the buffer. Aligned if +it is a table. Usage example: @code{:results value raw}. @item @code{org} -The results are will be enclosed in a @code{BEGIN_SRC org} block. -They are not comma-escaped by default but they will be if you hit @kbd{TAB} -in the block and/or if you export the file. E.g., @code{:results value org}. +Results enclosed in a @code{BEGIN_SRC org} block. For comma-escape, either +@kbd{TAB} in the block, or export the file. Usage example: @code{:results +value org}. @item @code{html} -Results are assumed to be HTML and will be enclosed in a @code{BEGIN_HTML} -block. E.g., @code{:results value html}. +Results enclosed in a @code{BEGIN_EXPORT html} block. Usage example: +@code{:results value html}. @item @code{latex} -Results assumed to be @LaTeX{} and are enclosed in a @code{BEGIN_LaTeX} block. -E.g., @code{:results value latex}. +Results enclosed in a @code{BEGIN_EXPORT latex} block. Usage example: +@code{:results value latex}. @item @code{code} -Result are assumed to be parsable code and are enclosed in a code block. -E.g., @code{:results value code}. +Result enclosed in a @samp{src} code block. Useful for parsing. Usage +example: @code{:results value code}. @item @code{pp} -The result is converted to pretty-printed code and is enclosed in a code -block. This option currently supports Emacs Lisp, Python, and Ruby. E.g., +Result converted to pretty-print source code. Enclosed in a @samp{src} code +block. Languages supported: Emacs Lisp, Python, and Ruby. Usage example: @code{:results value pp}. @item @code{drawer} -The result is wrapped in a RESULTS drawer. This can be useful for -inserting @code{raw} or @code{org} syntax results in such a way that their -extent is known and they can be automatically removed or replaced. +Result wrapped in a RESULTS drawer. Useful for containing @code{raw} or +@code{org} results for later scripting and automated processing. Usage +example: @code{:results value drawer}. @end itemize @subsubheading Handling -The following results options indicate what happens with the -results once they are collected. +Handling options after collecting the results. @itemize @bullet @item @code{silent} -The results will be echoed in the minibuffer but will not be inserted into -the Org mode buffer. E.g., @code{:results output silent}. +Do not insert results in the Org mode buffer, but echo them in the +minibuffer. Usage example: @code{:results output silent}. @item @code{replace} -The default value. Any existing results will be removed, and the new results -will be inserted into the Org mode buffer in their place. E.g., -@code{:results output replace}. +Default. Insert results in the Org buffer. Remove previous results. Usage +example: @code{:results output replace}. @item @code{append} -If there are pre-existing results of the code block then the new results will -be appended to the existing results. Otherwise the new results will be -inserted as with @code{replace}. +Append results to the Org buffer. Latest results are at the bottom. Does +not remove previous results. Usage example: @code{:results output append}. @item @code{prepend} -If there are pre-existing results of the code block then the new results will -be prepended to the existing results. Otherwise the new results will be -inserted as with @code{replace}. +Prepend results to the Org buffer. Latest results are at the top. Does not +remove previous results. Usage example: @code{:results output prepend}. @end itemize -@node file, file-desc, results, Specific header arguments +@node file @subsubsection @code{:file} +@cindex @code{:file}, src header argument + +An external @code{:file} that saves the results of execution of the code +block. The @code{:file} is either a file name or two strings, where the +first is the file name and the second is the description. A link to the file +is inserted. It uses an Org mode style @code{[[file:]]} link (@pxref{Link +format}). Some languages, such as @samp{R}, @samp{dot}, @samp{ditaa}, and +@samp{gnuplot}, automatically wrap the source code in additional boilerplate +code. Such code wrapping helps recreate the output, especially graphics +output, by executing just the @code{:file} contents. + +@node file-desc +@subsubsection @code{:file-desc} -The header argument @code{:file} is used to specify an external file in which -to save code block results. After code block evaluation an Org mode style -@code{[[file:]]} link (see @ref{Link format}) to the file will be inserted -into the Org mode buffer. Some languages including R, gnuplot, dot, and -ditaa provide special handling of the @code{:file} header argument -automatically wrapping the code block body in the boilerplate code required -to save output to the specified file. This is often useful for saving -graphical output of a code block to the specified file. +A description of the results file. Org uses this description for the link +(see @ref{Link format}) it inserts in the Org file. If the @code{:file-desc} +has no value, Org will use file name for both the ``link'' and the +``description'' portion of the Org mode link. -The argument to @code{:file} should be either a string specifying the path to -a file, or a list of two strings in which case the first element of the list -should be the path to a file and the second a description for the link. +@node file-ext +@subsubsection @code{:file-ext} +@cindex @code{:file-ext}, src header argument -@node file-desc, dir, file, Specific header arguments -@subsubsection @code{:file-desc} +File name extension for the output file. Org generates the file's complete +name, and extension by combining @code{:file-ext}, @code{#+NAME:} of the +source block, and the @ref{output-dir} header argument. To override this +auto generated file name, use the @code{:file} header argument. -The value of the @code{:file-desc} header argument is used to provide a -description for file code block results which are inserted as Org mode links -(see @ref{Link format}). If the @code{:file-desc} header argument is given -with no value the link path will be placed in both the ``link'' and the -``description'' portion of the Org mode link. +@node output-dir +@subsubsection @code{:output-dir} +@cindex @code{:output-dir}, src header argument + +Specifies the @code{:output-dir} for the results file. Org accepts an +absolute path (beginning with @code{/}) or a relative directory (without +@code{/}). The value can be combined with @code{#+NAME:} of the source block +and @ref{file} or @ref{file-ext} header arguments. -@node dir, exports, file-desc, Specific header arguments +@node dir @subsubsection @code{:dir} and remote execution +@cindex @code{:dir}, src header argument While the @code{:file} header argument can be used to specify the path to the -output file, @code{:dir} specifies the default directory during code block -execution. If it is absent, then the directory associated with the current -buffer is used. In other words, supplying @code{:dir path} temporarily has -the same effect as changing the current directory with @kbd{M-x cd path RET}, and -then not supplying @code{:dir}. Under the surface, @code{:dir} simply sets -the value of the Emacs variable @code{default-directory}. +output file, @code{:dir} specifies the default directory during @samp{src} +code block execution. If it is absent, then the directory associated with +the current buffer is used. In other words, supplying @code{:dir path} +temporarily has the same effect as changing the current directory with +@kbd{M-x cd path RET}, and then not supplying @code{:dir}. Under the +surface, @code{:dir} simply sets the value of the Emacs variable +@code{default-directory}. -When using @code{:dir}, you should supply a relative path for file output -(e.g., @code{:file myfile.jpg} or @code{:file results/myfile.jpg}) in which -case that path will be interpreted relative to the default directory. +When using @code{:dir}, relative paths (for example, @code{:file myfile.jpg} +or @code{:file results/myfile.jpg}) become relative to the default directory. -In other words, if you want your plot to go into a folder called @file{Work} -in your home directory, you could use +For example, to save the plot file in the @samp{Work} folder of the home +directory (notice tilde is expanded): @example #+BEGIN_SRC R :file myplot.png :dir ~/Work @@ -15086,198 +16016,205 @@ matplot(matrix(rnorm(100), 10), type="l") @end example @subsubheading Remote execution -A directory on a remote machine can be specified using tramp file syntax, in -which case the code will be evaluated on the remote machine. An example is +To evaluate the @samp{src} code block on a remote machine, supply a remote s +directory name using @samp{Tramp} syntax. For example: @example -#+BEGIN_SRC R :file plot.png :dir /dand@@yakuba.princeton.edu: +#+BEGIN_SRC R :file plot.png :dir /scp:dand@@yakuba.princeton.edu: plot(1:10, main=system("hostname", intern=TRUE)) #+END_SRC @end example -Text results will be returned to the local Org mode buffer as usual, and file -output will be created on the remote machine with relative paths interpreted -relative to the remote directory. An Org mode link to the remote file will be -created. - -So, in the above example a plot will be created on the remote machine, -and a link of the following form will be inserted in the org buffer: +Org first captures the text results as usual for insertion in the Org file. +Then Org also inserts a link to the remote file, thanks to Emacs +@samp{Tramp}. Org constructs the remote path to the file name from +@code{:dir} and @code{default-directory}, as illustrated here: @example [[file:/scp:dand@@yakuba.princeton.edu:/home/dand/plot.png][plot.png]] @end example -Most of this functionality follows immediately from the fact that @code{:dir} -sets the value of the Emacs variable @code{default-directory}, thanks to -tramp. Those using XEmacs, or GNU Emacs prior to version 23 may need to -install tramp separately in order for these features to work correctly. -@subsubheading Further points +@subsubheading Some more warnings @itemize @bullet @item -If @code{:dir} is used in conjunction with @code{:session}, although it will -determine the starting directory for a new session as expected, no attempt is -currently made to alter the directory associated with an existing session. +When @code{:dir} is used with @code{:session}, Org sets the starting +directory for a new session. But Org will not alter the directory of an +already existing session. @item -@code{:dir} should typically not be used to create files during export with -@code{:exports results} or @code{:exports both}. The reason is that, in order -to retain portability of exported material between machines, during export -links inserted into the buffer will @emph{not} be expanded against @code{default -directory}. Therefore, if @code{default-directory} is altered using -@code{:dir}, it is probable that the file will be created in a location to -which the link does not point. +Do not use @code{:dir} with @code{:exports results} or with @code{:exports +both} to avoid Org inserting incorrect links to remote files. That is because +Org does not expand @code{default directory} to avoid some underlying +portability issues. @end itemize -@node exports, tangle, dir, Specific header arguments +@node exports @subsubsection @code{:exports} +@cindex @code{:exports}, src header argument -The @code{:exports} header argument specifies what should be included in HTML -or @LaTeX{} exports of the Org mode file. +The @code{:exports} header argument is to specify if that part of the Org +file is exported to, say, HTML or @LaTeX{} formats. Note that +@code{:exports} affects only @samp{src} code blocks and not inline code. @itemize @bullet @item @code{code} -The default. The body of code is included into the exported file. E.g., +The default. The body of code is included into the exported file. Example: @code{:exports code}. @item @code{results} -The result of evaluating the code is included in the exported file. E.g., -@code{:exports results}. +The results of evaluation of the code is included in the exported file. +Example: @code{:exports results}. @item @code{both} -Both the code and results are included in the exported file. E.g., -@code{:exports both}. +Both the code and results of evaluation are included in the exported file. +Example: @code{:exports both}. @item @code{none} -Nothing is included in the exported file. E.g., @code{:exports none}. +Neither the code nor the results of evaluation is included in the exported +file. Whether the code is evaluated at all depends on other +options. Example: @code{:exports none}. @end itemize -@node tangle, mkdirp, exports, Specific header arguments +@node tangle @subsubsection @code{:tangle} +@cindex @code{:tangle}, src header argument -The @code{:tangle} header argument specifies whether or not the code -block should be included in tangled extraction of source code files. +The @code{:tangle} header argument specifies if the @samp{src} code block is +exported to source file(s). @itemize @bullet @item @code{tangle} -The code block is exported to a source code file named after the full path -(including the directory) and file name (w/o extension) of the Org mode file. -E.g., @code{:tangle yes}. +Export the @samp{src} code block to source file. The file name for the +source file is derived from the name of the Org file, and the file extension +is derived from the source code language identifier. Example: @code{:tangle +yes}. @item @code{no} -The default. The code block is not exported to a source code file. -E.g., @code{:tangle no}. +The default. Do not extract the code a source code file. Example: +@code{:tangle no}. @item other -Any other string passed to the @code{:tangle} header argument is interpreted -as a path (directory and file name relative to the directory of the Org mode -file) to which the block will be exported. E.g., @code{:tangle path}. +Export the @samp{src} code block to source file whose file name is derived +from any string passed to the @code{:tangle} header argument. Org derives +the file name as being relative to the directory of the Org file's location. +Example: @code{:tangle path}. @end itemize -@node mkdirp, comments, tangle, Specific header arguments +@node mkdirp @subsubsection @code{:mkdirp} +@cindex @code{:mkdirp}, src header argument -The @code{:mkdirp} header argument can be used to create parent directories -of tangled files when missing. This can be set to @code{yes} to enable -directory creation or to @code{no} to inhibit directory creation. +The @code{:mkdirp} header argument creates parent directories for tangled +files if the directory does not exist. @code{yes} enables directory creation +and @code{no} inhibits directory creation. -@node comments, padline, mkdirp, Specific header arguments +@node comments @subsubsection @code{:comments} -By default code blocks are tangled to source-code files without any insertion -of comments beyond those which may already exist in the body of the code -block. The @code{:comments} header argument can be set as follows to control -the insertion of extra comments into the tangled code file. +@cindex @code{:comments}, src header argument +Controls inserting comments into tangled files. These are above and beyond +whatever comments may already exist in the @samp{src} code block. @itemize @bullet @item @code{no} -The default. No extra comments are inserted during tangling. +The default. Do not insert any extra comments during tangling. @item @code{link} -The code block is wrapped in comments which contain pointers back to the -original Org file from which the code was tangled. +Wrap the @samp{src} code block in comments. Include links pointing back to +the place in the Org file from where the code was tangled. @item @code{yes} -A synonym for ``link'' to maintain backwards compatibility. +Kept for backward compatibility; same as ``link''. @item @code{org} -Include text from the Org mode file as a comment. -The text is picked from the leading context of the tangled code and is -limited by the nearest headline or source block as the case may be. +Nearest headline text from Org file is inserted as comment. The exact text +that is inserted is picked from the leading context of the source block. @item @code{both} -Turns on both the ``link'' and ``org'' comment options. +Includes both ``link'' and ``org'' comment options. @item @code{noweb} -Turns on the ``link'' comment option, and additionally wraps expanded noweb -references in the code block body in link comments. +Includes ``link'' comment option, expands noweb references, and wraps them in +link comments inside the body of the @samp{src} code block. @end itemize -@node padline, no-expand, comments, Specific header arguments +@node padline @subsubsection @code{:padline} -Control in insertion of padding lines around code block bodies in tangled -code files. The default value is @code{yes} which results in insertion of -newlines before and after each tangled code block. The following arguments -are accepted. - +@cindex @code{:padline}, src header argument +Control insertion of newlines to pad @samp{src} code blocks in the tangled +file. @itemize @bullet @item @code{yes} -Insert newlines before and after each code block body in tangled code files. +Default. Insert a newline before and after each @samp{src} code block in the +tangled file. @item @code{no} -Do not insert any newline padding in tangled output. +Do not insert newlines to pad the tangled @samp{src} code blocks. @end itemize -@node no-expand, session, padline, Specific header arguments +@node no-expand @subsubsection @code{:no-expand} - -By default, code blocks are expanded with @code{org-babel-expand-src-block} -during tangling. This has the effect of assigning values to variables -specified with @code{:var} (see @ref{var}), and of replacing ``noweb'' -references (see @ref{Noweb reference syntax}) with their targets. The -@code{:no-expand} header argument can be used to turn off this behavior. - -@node session, noweb, no-expand, Specific header arguments +@cindex @code{:no-expand}, src header argument + +By default Org expands @samp{src} code blocks during tangling. The +@code{:no-expand} header argument turns off such expansions. Note that one +side-effect of expansion by @code{org-babel-expand-src-block} also assigns +values to @code{:var} (@pxref{var}) variables. Expansions also replace +``noweb'' references with their targets (@pxref{Noweb reference syntax}). +Some of these expansions may cause premature assignment, hence this option. +This option makes a difference only for tangling. It has no effect when +exporting since @samp{src} code blocks for execution have to be expanded +anyway. + +@node session @subsubsection @code{:session} +@cindex @code{:session}, src header argument -The @code{:session} header argument starts a session for an interpreted -language where state is preserved. - -By default, a session is not started. +The @code{:session} header argument is for running multiple source code +blocks under one session. Org runs @samp{src} code blocks with the same +session name in the same interpreter process. -A string passed to the @code{:session} header argument will give the session -a name. This makes it possible to run concurrent sessions for each -interpreted language. +@itemize @bullet +@item @code{none} +Default. Each @samp{src} code block gets a new interpreter process to +execute. The process terminates once the block is evaluated. +@item @code{other} +Any string besides @code{none} turns that string into the name of that +session. For example, @code{:session mysession} names it @samp{mysession}. +If @code{:session} has no argument, then the session name is derived from the +source language identifier. Subsequent blocks with the same source code +language use the same session. Depending on the language, state variables, +code from other blocks, and the overall interpreted environment may be +shared. Some interpreted languages support concurrent sessions when +subsequent source code language blocks change session names. +@end itemize -@node noweb, noweb-ref, session, Specific header arguments +@node noweb @subsubsection @code{:noweb} +@cindex @code{:noweb}, src header argument The @code{:noweb} header argument controls expansion of ``noweb'' syntax -references (see @ref{Noweb reference syntax}) when the code block is -evaluated, tangled, or exported. The @code{:noweb} header argument can have -one of the five values: @code{no}, @code{yes}, @code{tangle}, or -@code{no-export} @code{strip-export}. +references (@pxref{Noweb reference syntax}). Expansions occur when source +code blocks are evaluated, tangled, or exported. @itemize @bullet @item @code{no} -The default. ``Noweb'' syntax references in the body of the code block will -not be expanded before the code block is evaluated, tangled or exported. +Default. No expansion of ``Noweb'' syntax references in the body of the code +when evaluating, tangling, or exporting. @item @code{yes} -``Noweb'' syntax references in the body of the code block will be -expanded before the code block is evaluated, tangled or exported. +Expansion of ``Noweb'' syntax references in the body of the @samp{src} code +block when evaluating, tangling, or exporting. @item @code{tangle} -``Noweb'' syntax references in the body of the code block will be expanded -before the code block is tangled. However, ``noweb'' syntax references will -not be expanded when the code block is evaluated or exported. +Expansion of ``Noweb'' syntax references in the body of the @samp{src} code +block when tangling. No expansion when evaluating or exporting. @item @code{no-export} -``Noweb'' syntax references in the body of the code block will be expanded -before the block is evaluated or tangled. However, ``noweb'' syntax -references will not be expanded when the code block is exported. +Expansion of ``Noweb'' syntax references in the body of the @samp{src} code +block when evaluating or tangling. No expansion when exporting. @item @code{strip-export} -``Noweb'' syntax references in the body of the code block will be expanded -before the block is evaluated or tangled. However, ``noweb'' syntax -references will be removed when the code block is exported. +Expansion of ``Noweb'' syntax references in the body of the @samp{src} code +block when expanding prior to evaluating or tangling. Removes ``noweb'' +syntax references when exporting. @item @code{eval} -``Noweb'' syntax references in the body of the code block will only be -expanded before the block is evaluated. +Expansion of ``Noweb'' syntax references in the body of the @samp{src} code +block only before evaluating. @end itemize @subsubheading Noweb prefix lines -Noweb insertions are now placed behind the line prefix of the -@code{<<reference>>}. -This behavior is illustrated in the following example. Because the -@code{<<example>>} noweb reference appears behind the SQL comment syntax, -each line of the expanded noweb reference will be commented. +Noweb insertions now honor prefix characters that appear before +@code{<<reference>>}. This behavior is illustrated in the following example. +Because the @code{<<example>>} noweb reference appears behind the SQL comment +syntax, each line of the expanded noweb reference will be commented. -This code block: +This @samp{src} code block: @example -- <<example>> @@ -15290,23 +16227,20 @@ expands to: -- multi-line body of example @end example -Note that noweb replacement text that does not contain any newlines will not -be affected by this change, so it is still possible to use inline noweb -references. +Since this change will not affect noweb replacement text without newlines in +them, inline noweb references are acceptable. -@node noweb-ref, noweb-sep, noweb, Specific header arguments +@node noweb-ref @subsubsection @code{:noweb-ref} -When expanding ``noweb'' style references the bodies of all code block with -@emph{either} a block name matching the reference name @emph{or} a -@code{:noweb-ref} header argument matching the reference name will be -concatenated together to form the replacement text. +@cindex @code{:noweb-ref}, src header argument + +When expanding ``noweb'' style references, Org concatenates @samp{src} code +blocks by matching the reference name to either the block name or the +@code{:noweb-ref} header argument. -By setting this header argument at the sub-tree or file level, simple code -block concatenation may be achieved. For example, when tangling the -following Org mode file, the bodies of code blocks will be concatenated into -the resulting pure code file@footnote{(The example needs property inheritance -to be turned on for the @code{noweb-ref} property, see @ref{Property -inheritance}).}. +For simple concatenation, set this @code{:noweb-ref} header argument at the +sub-tree or file level. In the example Org file shown next, the body of the +source code in each block is extracted for concatenation to a pure code file. @example #+BEGIN_SRC sh :tangle yes :noweb yes :shebang #!/bin/sh @@ -15314,7 +16248,7 @@ inheritance}).}. #+END_SRC * the mount point of the fullest disk :PROPERTIES: - :noweb-ref: fullest-disk + :header-args: :noweb-ref fullest-disk :END: ** query all mounted disks @@ -15327,56 +16261,66 @@ inheritance}).}. |sed '1d' \ #+END_SRC - ** sort by the percent full + ** output mount point of fullest disk #+BEGIN_SRC sh - |awk '@{print $5 " " $6@}'|sort -n |tail -1 \ - #+END_SRC - - ** extract the mount point - #+BEGIN_SRC sh - |awk '@{print $2@}' + |awk '@{if (u < +$5) @{u = +$5; m = $6@}@} END @{print m@}' #+END_SRC @end example -The @code{:noweb-sep} (see @ref{noweb-sep}) header argument holds the string -used to separate accumulate noweb references like those above. By default a -newline is used. - -@node noweb-sep, cache, noweb-ref, Specific header arguments +@node noweb-sep @subsubsection @code{:noweb-sep} +@cindex @code{:noweb-sep}, src header argument -The @code{:noweb-sep} header argument holds the string used to separate -accumulate noweb references (see @ref{noweb-ref}). By default a newline is -used. +By default a newline separates each noweb reference concatenation. To change +this newline separator, edit the @code{:noweb-sep} (@pxref{noweb-sep}) header +argument. -@node cache, sep, noweb-sep, Specific header arguments +@node cache @subsubsection @code{:cache} - -The @code{:cache} header argument controls the use of in-buffer caching of -the results of evaluating code blocks. It can be used to avoid re-evaluating -unchanged code blocks. Note that the @code{:cache} header argument will not -attempt to cache results when the @code{:session} header argument is used, -because the results of the code block execution may be stored in the session -outside of the Org mode buffer. The @code{:cache} header argument can have -one of two values: @code{yes} or @code{no}. +@cindex @code{:cache}, src header argument + +The @code{:cache} header argument is for caching results of evaluating code +blocks. Caching results can avoid re-evaluating @samp{src} code blocks that +have not changed since the previous run. To benefit from the cache and avoid +redundant evaluations, the source block must have a result already present in +the buffer, and neither the header arguments (including the value of +@code{:var} references) nor the text of the block itself has changed since +the result was last computed. This feature greatly helps avoid long-running +calculations. For some edge cases, however, the cached results may not be +reliable. + +The caching feature is best for when @samp{src} blocks are pure functions, +that is functions that return the same value for the same input arguments +(@pxref{var}), and that do not have side effects, and do not rely on external +variables other than the input arguments. Functions that depend on a timer, +file system objects, and random number generators are clearly unsuitable for +caching. + +A note of warning: when @code{:cache} is used for a @code{:session}, caching +may cause unexpected results. + +When the caching mechanism tests for any source code changes, it will not +expand ``noweb'' style references (@pxref{Noweb reference syntax}). For +reasons why, see @uref{http://thread.gmane.org/gmane.emacs.orgmode/79046}. + +The @code{:cache} header argument can have one of two values: @code{yes} or +@code{no}. @itemize @bullet @item @code{no} -The default. No caching takes place, and the code block will be evaluated -every time it is called. +Default. No caching of results; @samp{src} code block evaluated every time. @item @code{yes} -Every time the code block is run a SHA1 hash of the code and arguments -passed to the block will be generated. This hash is packed into the -@code{#+RESULTS:} line and will be checked on subsequent -executions of the code block. If the code block has not -changed since the last time it was evaluated, it will not be re-evaluated. +Whether to run the code or return the cached results is determined by +comparing the SHA1 hash value of the combined @samp{src} code block and +arguments passed to it. This hash value is packed on the @code{#+RESULTS:} +line from previous evaluation. When hash values match, Org does not evaluate +the @samp{src} code block. When hash values mismatch, Org evaluates the +@samp{src} code block, inserts the results, recalculates the hash value, and +updates @code{#+RESULTS:} line. @end itemize -Code block caches notice if the value of a variable argument -to the code block has changed. If this is the case, the cache is -invalidated and the code block is re-run. In the following example, -@code{caller} will not be re-run unless the results of @code{random} have -changed since it was last run. +In this example, both functions are cached. But @code{caller} runs only if +the result from @code{random} has changed since the last run. @example #+NAME: random @@ -15396,32 +16340,31 @@ changed since it was last run. 0.254227238707244 @end example -@node sep, hlines, cache, Specific header arguments +@node sep @subsubsection @code{:sep} +@cindex @code{:sep}, src header argument -The @code{:sep} header argument can be used to control the delimiter used -when writing tabular results out to files external to Org mode. This is used -either when opening tabular results of a code block by calling the -@code{org-open-at-point} function bound to @kbd{C-c C-o} on the code block, -or when writing code block results to an external file (see @ref{file}) -header argument. +The @code{:sep} header argument is the delimiter for saving results as tables +to files (@pxref{file}) external to Org mode. Org defaults to tab delimited +output. The function, @code{org-open-at-point}, which is bound to @kbd{C-c +C-o}, also uses @code{:sep} for opening tabular results. -By default, when @code{:sep} is not specified output tables are tab -delimited. - -@node hlines, colnames, sep, Specific header arguments +@node hlines @subsubsection @code{:hlines} +@cindex @code{:hlines}, src header argument -Tables are frequently represented with one or more horizontal lines, or -hlines. The @code{:hlines} argument to a code block accepts the -values @code{yes} or @code{no}, with a default value of @code{no}. +In-between each table row or below the table headings, sometimes results have +horizontal lines, which are also known as hlines. The @code{:hlines} +argument with the value @code{yes} accepts such lines. The default is +@code{no}. @itemize @bullet @item @code{no} -Strips horizontal lines from the input table. In most languages this is the -desired effect because an @code{hline} symbol is interpreted as an unbound -variable and raises an error. Setting @code{:hlines no} or relying on the -default value yields the following results. +Strips horizontal lines from the input table. For most code, this is +desirable, or else those @code{hline} symbols raise unbound variable errors. + +The default is @code{:hlines no}. The example shows hlines removed from the +input table. @example #+NAME: many-cols @@ -15443,7 +16386,7 @@ default value yields the following results. @end example @item @code{yes} -Leaves hlines in the table. Setting @code{:hlines yes} has this effect. +For @code{:hlines yes}, the example shows hlines unchanged. @example #+NAME: many-cols @@ -15467,20 +16410,20 @@ Leaves hlines in the table. Setting @code{:hlines yes} has this effect. @end example @end itemize -@node colnames, rownames, hlines, Specific header arguments +@node colnames @subsubsection @code{:colnames} +@cindex @code{:colnames}, src header argument -The @code{:colnames} header argument accepts the values @code{yes}, -@code{no}, or @code{nil} for unassigned. The default value is @code{nil}. -Note that the behavior of the @code{:colnames} header argument may differ -across languages. +The @code{:colnames} header argument accepts @code{yes}, @code{no}, or +@code{nil} values. The default value is @code{nil}, which is unassigned. +But this header argument behaves differently depending on the source code +language. @itemize @bullet @item @code{nil} -If an input table looks like it has column names -(because its second row is an hline), then the column -names will be removed from the table before -processing, then reapplied to the results. +If an input table has column names (because the second row is an hline), then +Org removes the column names, processes the table, puts back the column +names, and then writes the table to the results block. @example #+NAME: less-cols @@ -15501,33 +16444,36 @@ processing, then reapplied to the results. | c* | @end example -Please note that column names are not removed before the table is indexed -using variable indexing @xref{var, Indexable variable values}. +Note that column names have to accounted for when using variable indexing +(@pxref{var, Indexable variable values}) because column names are not removed +for indexing. @item @code{no} -No column name pre-processing takes place +Do not pre-process column names. @item @code{yes} -Column names are removed and reapplied as with @code{nil} even if the table -does not ``look like'' it has column names (i.e., the second row is not an -hline) +For an input table that has no hlines, process it like the @code{nil} +value. That is, Org removes the column names, processes the table, puts back +the column names, and then writes the table to the results block. @end itemize -@node rownames, shebang, colnames, Specific header arguments +@node rownames @subsubsection @code{:rownames} +@cindex @code{:rownames}, src header argument -The @code{:rownames} header argument can take on the values @code{yes} or -@code{no}, with a default value of @code{no}. Note that Emacs Lisp code -blocks ignore the @code{:rownames} header argument entirely given the ease -with which tables with row names may be handled directly in Emacs Lisp. +The @code{:rownames} header argument can take on values @code{yes} or +@code{no} values. The default is @code{no}. Note that @code{emacs-lisp} +code blocks ignore @code{:rownames} header argument because of the ease of +table-handling in Emacs. @itemize @bullet @item @code{no} -No row name pre-processing will take place. +Org will not pre-process row names. @item @code{yes} -The first column of the table is removed from the table before processing, -and is then reapplied to the results. +If an input table has row names, then Org removes the row names, processes +the table, puts back the row names, and then writes the table to the results +block. @example #+NAME: with-rownames @@ -15544,82 +16490,88 @@ and is then reapplied to the results. | two | 16 | 17 | 18 | 19 | 20 | @end example -Please note that row names are not removed before the table is indexed using -variable indexing @xref{var, Indexable variable values}. +Note that row names have to accounted for when using variable indexing +(@pxref{var, Indexable variable values}) because row names are not removed +for indexing. @end itemize -@node shebang, tangle-mode, rownames, Specific header arguments +@node shebang @subsubsection @code{:shebang} +@cindex @code{:shebang}, src header argument -Setting the @code{:shebang} header argument to a string value -(e.g., @code{:shebang "#!/bin/bash"}) causes the string to be inserted as the -first line of any tangled file holding the code block, and the file -permissions of the tangled file are set to make it executable. +This header argument can turn results into executable script files. By +setting the @code{:shebang} header argument to a string value (for example, +@code{:shebang "#!/bin/bash"}), Org inserts that string as the first line of +the tangled file that the @samp{src} code block is extracted to. Org then +turns on the tangled file's executable permission. - -@node tangle-mode, eval, shebang, Specific header arguments +@node tangle-mode @subsubsection @code{:tangle-mode} +@cindex @code{:tangle-mode}, src header argument + +The @code{tangle-mode} header argument specifies what permissions to set for +tangled files by @code{set-file-modes}. For example, to make read-only +tangled file, use @code{:tangle-mode (identity #o444)}. To make it +executable, use @code{:tangle-mode (identity #o755)}. + +On @samp{src} code blocks with @code{shebang} (@pxref{shebang}) header +argument, Org will automatically set the tangled file to executable +permissions. But this can be overridden with custom permissions using +@code{tangle-mode} header argument. + +When multiple @samp{src} code blocks tangle to a single file with different +and conflicting @code{tangle-mode} header arguments, Org's behavior is +undefined. -The @code{tangle-mode} header argument controls the permission set on tangled -files. The value of this header argument will be passed to -@code{set-file-modes}. For example, to set a tangled file as read only use -@code{:tangle-mode (identity #o444)}, or to set a tangled file as executable -use @code{:tangle-mode (identity #o755)}. Blocks with @code{shebang} -(@ref{shebang}) header arguments will automatically be made executable unless -the @code{tangle-mode} header argument is also used. The behavior is -undefined if multiple code blocks with different values for the -@code{tangle-mode} header argument are tangled to the same file. - -@node eval, wrap, tangle-mode, Specific header arguments +@node eval @subsubsection @code{:eval} -The @code{:eval} header argument can be used to limit the evaluation of -specific code blocks. The @code{:eval} header argument can be useful for -protecting against the evaluation of dangerous code blocks or to ensure that -evaluation will require a query regardless of the value of the -@code{org-confirm-babel-evaluate} variable. The possible values of -@code{:eval} and their effects are shown below. +@cindex @code{:eval}, src header argument +The @code{:eval} header argument can limit evaluation of specific code +blocks. It is useful for protection against evaluating untrusted @samp{src} +code blocks by prompting for a confirmation. This protection is independent +of the @code{org-confirm-babel-evaluate} setting. @table @code @item never or no -The code block will not be evaluated under any circumstances. +Org will never evaluate this @samp{src} code block. @item query -Evaluation of the code block will require a query. +Org prompts the user for permission to evaluate this @samp{src} code block. @item never-export or no-export -The code block will not be evaluated during export but may still be called -interactively. +Org will not evaluate this @samp{src} code block when exporting, yet the user +can evaluate this source block interactively. @item query-export -Evaluation of the code block during export will require a query. +Org prompts the user for permission to export this @samp{src} code block. @end table -If this header argument is not set then evaluation is determined by the value -of the @code{org-confirm-babel-evaluate} variable see @ref{Code evaluation -security}. +If @code{:eval} header argument is not set for a source block, then Org +determines whether to evaluate from the @code{org-confirm-babel-evaluate} +variable (@pxref{Code evaluation security}). -@node wrap, post, eval, Specific header arguments +@node wrap @subsubsection @code{:wrap} -The @code{:wrap} header argument is used to mark the results of source block -evaluation. The header argument can be passed a string that will be appended -to @code{#+BEGIN_} and @code{#+END_}, which will then be used to wrap the -results. If not string is specified then the results will be wrapped in a -@code{#+BEGIN/END_RESULTS} block. +@cindex @code{:wrap}, src header argument +The @code{:wrap} header argument marks the results block by appending strings +to @code{#+BEGIN_} and @code{#+END_}. If no string is specified, Org wraps +the results in a @code{#+BEGIN/END_RESULTS} block. -@node post, prologue, wrap, Specific header arguments +@node post @subsubsection @code{:post} -The @code{:post} header argument is used to post-process the results of a -code block execution. When a post argument is given, the results of the code -block will temporarily be bound to the @code{*this*} variable. This variable -may then be included in header argument forms such as those used in @ref{var} -header argument specifications allowing passing of results to other code -blocks, or direct execution via Emacs Lisp. - -The following example illustrates the usage of the @code{:post} header -argument. +@cindex @code{:post}, src header argument +The @code{:post} header argument is for post-processing results from +@samp{src} block evaluation. When @code{:post} has any value, Org binds the +results to @code{*this*} variable for easy passing to @ref{var} header +argument specifications. That makes results available to other @samp{src} +code blocks, or for even direct Emacs Lisp code execution. + +The following two examples illustrate @code{:post} header argument in action. +The first one shows how to attach @code{#+ATTR_LATEX:} line using +@code{:post}. @example #+name: attr_wrap #+begin_src sh :var data="" :var width="\\textwidth" :results output - echo "#+ATTR_LATEX :width $width" + echo "#+ATTR_LATEX: :width $width" echo "$data" #+end_src @@ -15639,33 +16591,65 @@ argument. :END: @end example -@node prologue, epilogue, post, Specific header arguments +The second example shows use of @code{:colnames} in @code{:post} to pass +data between @samp{src} code blocks. + +@example +#+name: round-tbl +#+begin_src emacs-lisp :var tbl="" fmt="%.3f" + (mapcar (lambda (row) + (mapcar (lambda (cell) + (if (numberp cell) + (format fmt cell) + cell)) + row)) + tbl) +#+end_src + +#+begin_src R :colnames yes :post round-tbl[:colnames yes](*this*) +set.seed(42) +data.frame(foo=rnorm(1)) +#+end_src + +#+RESULTS: +| foo | +|-------| +| 1.371 | +@end example + +@node prologue @subsubsection @code{:prologue} -The value of the @code{prologue} header argument will be prepended to the -code block body before execution. For example, @code{:prologue "reset"} may -be used to reset a gnuplot session before execution of a particular code -block, or the following configuration may be used to do this for all gnuplot -code blocks. Also see @ref{epilogue}. +@cindex @code{:prologue}, src header argument +The @code{prologue} header argument is for appending to the top of the code +block for execution. For example, a clear or reset code at the start of new +execution of a @samp{src} code block. A @code{reset} for @samp{gnuplot}: +@code{:prologue "reset"}. See also @ref{epilogue}. @lisp (add-to-list 'org-babel-default-header-args:gnuplot '((:prologue . "reset"))) @end lisp -@node epilogue, , prologue, Specific header arguments +@node epilogue @subsubsection @code{:epilogue} -The value of the @code{epilogue} header argument will be appended to the code -block body before execution. Also see @ref{prologue}. +@cindex @code{:epilogue}, src header argument +The value of the @code{epilogue} header argument is for appending to the end +of the code block for execution. See also @ref{prologue}. -@node Results of evaluation, Noweb reference syntax, Header arguments, Working With Source Code +@node Results of evaluation @section Results of evaluation @cindex code block, results of evaluation @cindex source code, results of evaluation -The way in which results are handled depends on whether a session is invoked, -as well as on whether @code{:results value} or @code{:results output} is -used. The following table shows the table possibilities. For a full listing -of the possible results header arguments see @ref{results}. +How Org handles results of a code block execution depends on many header +arguments working together. Here is only a summary of these. For an +enumeration of all the header arguments that affect results, see +@ref{results}. + +The primary determinant is the execution context. Is it in a @code{:session} +or not? Orthogonal to that is if the expected result is a @code{:results +value} or @code{:results output}, which is a concatenation of output from +start to finish of the @samp{src} code block's evaluation. @multitable @columnfractions 0.26 0.33 0.41 @item @tab @b{Non-session} @tab @b{Session} @@ -15673,51 +16657,54 @@ of the possible results header arguments see @ref{results}. @item @code{:results output} @tab contents of STDOUT @tab concatenation of interpreter output @end multitable -Note: With @code{:results value}, the result in both @code{:session} and -non-session is returned to Org mode as a table (a one- or two-dimensional -vector of strings or numbers) when appropriate. +For @code{:session} and non-session, the @code{:results value} turns the +results into an Org mode table format. Single values are wrapped in a one +dimensional vector. Rows and columns of a table are wrapped in a +two-dimensional vector. @subsection Non-session @subsubsection @code{:results value} -This is the default. Internally, the value is obtained by wrapping the code -in a function definition in the external language, and evaluating that -function. Therefore, code should be written as if it were the body of such a -function. In particular, note that Python does not automatically return a -value from a function unless a @code{return} statement is present, and so a -@samp{return} statement will usually be required in Python. +@cindex @code{:results}, src header argument +Default. Org gets the value by wrapping the code in a function definition in +the language of the @samp{src} block. That is why when using @code{:results +value}, code should execute like a function and return a value. For +languages like Python, an explicit @code{return} statement is mandatory when +using @code{:results value}. -This is the only one of the four evaluation contexts in which the code is -automatically wrapped in a function definition. +This is one of four evaluation contexts where Org automatically wraps the +code in a function definition. @subsubsection @code{:results output} -The code is passed to the interpreter as an external process, and the -contents of the standard output stream are returned as text. (In certain -languages this also contains the error output stream; this is an area for -future work.) +@cindex @code{:results}, src header argument +For @code{:results output}, the code is passed to an external process running +the interpreter. Org returns the contents of the standard output stream as +as text results. @subsection Session @subsubsection @code{:results value} -The code is passed to an interpreter running as an interactive Emacs inferior -process. Only languages which provide tools for interactive evaluation of -code have session support, so some language (e.g., C and ditaa) do not -support the @code{:session} header argument, and in other languages (e.g., -Python and Haskell) which have limitations on the code which may be entered -into interactive sessions, those limitations apply to the code in code blocks -using the @code{:session} header argument as well. - -Unless the @code{:results output} option is supplied (see below) the result -returned is the result of the last evaluation performed by the -interpreter. (This is obtained in a language-specific manner: the value of -the variable @code{_} in Python and Ruby, and the value of @code{.Last.value} -in R). +@cindex @code{:results}, src header argument +For @code{:results value} from a @code{:session}, Org passes the code to an +interpreter running as an interactive Emacs inferior process. So only +languages that provide interactive evaluation can have session support. Not +all languages provide this support, such as @samp{C} and @samp{ditaa}. Even +those that do support, such as @samp{Python} and @samp{Haskell}, they impose +limitations on allowable language constructs that can run interactively. Org +inherits those limitations for those @samp{src} code blocks running in a +@code{:session}. + +Org gets the value from the source code interpreter's last statement +output. Org has to use language-specific methods to obtain the value. For +example, from the variable @code{_} in @samp{Python} and @samp{Ruby}, and the +value of @code{.Last.value} in @samp{R}). @subsubsection @code{:results output} -The code is passed to the interpreter running as an interactive Emacs -inferior process. The result returned is the concatenation of the sequence of -(text) output from the interactive interpreter. Notice that this is not -necessarily the same as what would be sent to @code{STDOUT} if the same code -were passed to a non-interactive interpreter running as an external -process. For example, compare the following two blocks: +@cindex @code{:results}, src header argument +For @code{:results output}, Org passes the code to the interpreter running as +an interactive Emacs inferior process. Org concatenates whatever text output +emitted by the interpreter to return the collection as a result. Note that +this collection is not the same as collected from @code{STDOUT} of a +non-interactive interpreter running as an external process. Compare for +example these two blocks: @example #+BEGIN_SRC python :results output @@ -15731,7 +16718,8 @@ process. For example, compare the following two blocks: : bye @end example -In non-session mode, the ``2'' is not printed and does not appear. +In the above non-session mode, the ``2'' is not printed; so does not appear +in results. @example #+BEGIN_SRC python :results output :session @@ -15746,60 +16734,61 @@ In non-session mode, the ``2'' is not printed and does not appear. : bye @end example -But in @code{:session} mode, the interactive interpreter receives input ``2'' -and prints out its value, ``2''. (Indeed, the other print statements are -unnecessary here). +In the above @code{:session} mode, the interactive interpreter receives and +prints ``2''. Results show that. -@node Noweb reference syntax, Key bindings and useful functions, Results of evaluation, Working With Source Code +@node Noweb reference syntax @section Noweb reference syntax @cindex code block, noweb reference @cindex syntax, noweb @cindex source code, noweb reference -The ``noweb'' (see @uref{http://www.cs.tufts.edu/~nr/noweb/}) Literate -Programming system allows named blocks of code to be referenced by using the -familiar Noweb syntax: +Org supports named blocks in ``noweb'' style syntax. For ``noweb'' literate +programming details, see @uref{http://www.cs.tufts.edu/~nr/noweb/}). @example <<code-block-name>> @end example -When a code block is tangled or evaluated, whether or not ``noweb'' -references are expanded depends upon the value of the @code{:noweb} header -argument. If @code{:noweb yes}, then a Noweb reference is expanded before -evaluation. If @code{:noweb no}, the default, then the reference is not -expanded before evaluation. See the @ref{noweb-ref} header argument for -a more flexible way to resolve noweb references. +For the header argument @code{:noweb yes}, Org expands ``noweb'' style +references in the @samp{src} code block before evaluation. + +For the header argument @code{:noweb no}, Org does not expand ``noweb'' style +references in the @samp{src} code block before evaluation. + +The default is @code{:noweb no}. + +Org offers a more flexible way to resolve ``noweb'' style references +(@pxref{noweb-ref}). -It is possible to include the @emph{results} of a code block rather than the -body. This is done by appending parenthesis to the code block name which may -optionally contain arguments to the code block as shown below. +Org can handle naming of @emph{results} block, rather than the body of the +@samp{src} code block, using ``noweb'' style references. + +For ``noweb'' style reference, append parenthesis to the code block name for +arguments, as shown in this example: @example <<code-block-name(optional arguments)>> @end example -Note: the default value, @code{:noweb no}, was chosen to ensure that -correct code is not broken in a language, such as Ruby, where -@code{<<arg>>} is a syntactically valid construct. If @code{<<arg>>} is not -syntactically valid in languages that you use, then please consider setting -the default value. +Note: Org defaults to @code{:noweb no} so as not to cause errors in languages +such as @samp{Ruby} where ``noweb'' syntax is equally valid characters. For +example, @code{<<arg>>}. Change Org's default to @code{:noweb yes} for +languages where there is no risk of confusion. -Note: if noweb tangling is slow in large Org mode files consider setting the +For faster tangling of large Org mode files, set @code{org-babel-use-quick-and-dirty-noweb-expansion} variable to @code{t}. -This will result in faster noweb reference resolution at the expense of not -correctly resolving inherited values of the @code{:noweb-ref} header -argument. +The speedup comes at the expense of not correctly resolving inherited values +of the @code{:noweb-ref} header argument. -@node Key bindings and useful functions, Batch execution, Noweb reference syntax, Working With Source Code + +@node Key bindings and useful functions @section Key bindings and useful functions @cindex code block, key bindings -Many common Org mode key sequences are re-bound depending on -the context. +Many common Org mode key sequences are re-bound depending on the context. -Within a code block, the following key bindings -are active: +Active key bindings in code blocks: @multitable @columnfractions 0.25 0.75 @kindex C-c C-c @@ -15812,9 +16801,9 @@ are active: @item @kbd{M-@key{down}} @tab @code{org-babel-switch-to-session} @end multitable -In an Org mode buffer, the following key bindings are active: +Active key bindings in Org mode buffer: -@multitable @columnfractions 0.45 0.55 +@multitable @columnfractions 0.5 0.5 @kindex C-c C-v p @kindex C-c C-v C-p @item @kbd{C-c C-v p} @ @ @r{or} @ @ @kbd{C-c C-v C-p} @tab @code{org-babel-previous-src-block} @@ -15883,8 +16872,7 @@ In an Org mode buffer, the following key bindings are active: @item @kbd{C-c C-v x} @ @ @r{or} @ @ @kbd{C-c C-v C-x} @tab @code{org-babel-do-key-sequence-in-edit-buffer} @end multitable -@c When possible these keybindings were extended to work when the control key is -@c kept pressed, resulting in the following additional keybindings. +@c Extended key bindings when control key is kept pressed: @c @multitable @columnfractions 0.25 0.75 @c @item @kbd{C-c C-v C-a} @tab @code{org-babel-sha1-hash} @@ -15897,15 +16885,18 @@ In an Org mode buffer, the following key bindings are active: @c @item @kbd{C-c C-v C-z} @tab @code{org-babel-switch-to-session} @c @end multitable -@node Batch execution, , Key bindings and useful functions, Working With Source Code +@node Batch execution @section Batch execution @cindex code block, batch execution @cindex source code, batch execution -It is possible to call functions from the command line. This shell -script calls @code{org-babel-tangle} on every one of its arguments. +Org mode features, including working with source code facilities can be +invoked from the command line. This enables building shell scripts for batch +processing, running automated system tasks, and expanding Org mode's +usefulness. -Be sure to adjust the paths to fit your system. +The sample script shows batch processing of multiple files using +@code{org-babel-tangle}. @example #!/bin/sh @@ -15922,35 +16913,33 @@ for i in $@@; do done emacs -Q --batch \ ---eval "(progn -(add-to-list 'load-path (expand-file-name \"~/src/org/lisp/\")) -(add-to-list 'load-path (expand-file-name \"~/src/org/contrib/lisp/\" t)) -(require 'org)(require 'org-exp)(require 'ob)(require 'ob-tangle) -(mapc (lambda (file) - (find-file (expand-file-name file \"$DIR\")) - (org-babel-tangle) - (kill-buffer)) '($FILES)))" 2>&1 |grep tangled + --eval "(progn + (require 'org)(require 'ob)(require 'ob-tangle) + (mapc (lambda (file) + (find-file (expand-file-name file \"$DIR\")) + (org-babel-tangle) + (kill-buffer)) '($FILES)))" 2>&1 |grep -i tangled @end example -@node Miscellaneous, Hacking, Working With Source Code, Top +@node Miscellaneous @chapter Miscellaneous @menu -* Completion:: M-TAB knows what you need -* Easy Templates:: Quick insertion of structural elements +* Completion:: M-TAB guesses completions +* Easy templates:: Quick insertion of structural elements * Speed keys:: Electric commands at the beginning of a headline * Code evaluation security:: Org mode files evaluate inline code -* Customization:: Adapting Org to your taste +* Customization:: Adapting Org to changing tastes * In-buffer settings:: Overview of the #+KEYWORDS * The very busy C-c C-c key:: When in doubt, press C-c C-c * Clean view:: Getting rid of leading stars in the outline * TTY keys:: Using Org on a tty -* Interaction:: Other Emacs packages +* Interaction:: With other Emacs packages * org-crypt:: Encrypting Org files @end menu -@node Completion, Easy Templates, Miscellaneous, Miscellaneous +@node Completion @section Completion @cindex completion, of @TeX{} symbols @cindex completion, of TODO keywords @@ -15966,15 +16955,13 @@ emacs -Q --batch \ @cindex tag completion @cindex link abbreviations, completion of -Emacs would not be Emacs without completion, and Org mode uses it whenever it -makes sense. If you prefer an @i{iswitchb}- or @i{ido}-like interface for -some of the completion prompts, you can specify your preference by setting at -most one of the variables @code{org-completion-use-iswitchb} -@code{org-completion-use-ido}. - -Org supports in-buffer completion. This type of completion does -not make use of the minibuffer. You simply type a few letters into -the buffer and use the key to complete text right there. +Org has in-buffer completions. Unlike minibuffer completions, which are +useful for quick command interactions, Org's in-buffer completions are more +suitable for content creation in Org documents. Type one or more letters and +invoke the hot key to complete the text in-place. Depending on the context +and the keys, Org will offer different types of completions. No minibuffer +is involved. Such mode-specific hot keys have become an integral part of +Emacs and Org provides several shortcuts. @table @kbd @kindex M-@key{TAB} @@ -16001,112 +16988,123 @@ buffer. After @samp{[}, complete link abbreviations (@pxref{Link abbreviations}). @item After @samp{#+}, complete the special keywords like @samp{TYP_TODO} or -@samp{OPTIONS} which set file-specific options for Org mode. When the -option keyword is already complete, pressing @kbd{M-@key{TAB}} again -will insert example settings for this keyword. +file-specific @samp{OPTIONS}. After option keyword is complete, pressing +@kbd{M-@key{TAB}} again will insert example settings for that option. @item -In the line after @samp{#+STARTUP: }, complete startup keywords, -i.e., valid keys for this line. +After @samp{#+STARTUP: }, complete startup keywords. @item -Elsewhere, complete dictionary words using Ispell. +When the point is anywhere else, complete dictionary words using Ispell. @end itemize +@kindex C-M-i +If your desktop intercepts the combo @kbd{M-@key{TAB}} to switch windows, use +@kbd{C-M-i} or @kbd{@key{ESC} @key{TAB}} as an alternative or customize your +environment. @end table -@node Easy Templates, Speed keys, Completion, Miscellaneous -@section Easy Templates +@node Easy templates +@section Easy templates @cindex template insertion @cindex insertion, of templates -Org mode supports insertion of empty structural elements (like -@code{#+BEGIN_SRC} and @code{#+END_SRC} pairs) with just a few key -strokes. This is achieved through a native template expansion mechanism. -Note that Emacs has several other template mechanisms which could be used in -a similar way, for example @file{yasnippet}. +With just a few keystrokes, Org's easy templates inserts empty pairs of +structural elements, such as @code{#+BEGIN_SRC} and @code{#+END_SRC}. Easy +templates use an expansion mechanism, which is native to Org, in a process +similar to @file{yasnippet} and other Emacs template expansion packages. + +@kbd{@key{<}} @kbd{@key{s}} @kbd{@key{TAB}} completes the @samp{src} code +block. + +@kbd{<} @kbd{l} @kbd{@key{TAB}} + +expands to: + +#+BEGIN_EXPORT latex -To insert a structural element, type a @samp{<}, followed by a template -selector and @kbd{@key{TAB}}. Completion takes effect only when the above -keystrokes are typed on a line by itself. +#+END_EXPORT -The following template selectors are currently supported. +Org comes with these pre-defined easy templates: @multitable @columnfractions 0.1 0.9 -@item @kbd{s} @tab @code{#+BEGIN_SRC ... #+END_SRC} +@item @kbd{s} @tab @code{#+BEGIN_SRC ... #+END_SRC} @item @kbd{e} @tab @code{#+BEGIN_EXAMPLE ... #+END_EXAMPLE} -@item @kbd{q} @tab @code{#+BEGIN_QUOTE ... #+END_QUOTE} -@item @kbd{v} @tab @code{#+BEGIN_VERSE ... #+END_VERSE} -@item @kbd{c} @tab @code{#+BEGIN_CENTER ... #+END_CENTER} -@item @kbd{l} @tab @code{#+BEGIN_LaTeX ... #+END_LaTeX} -@item @kbd{L} @tab @code{#+LaTeX:} -@item @kbd{h} @tab @code{#+BEGIN_HTML ... #+END_HTML} +@item @kbd{q} @tab @code{#+BEGIN_QUOTE ... #+END_QUOTE} +@item @kbd{v} @tab @code{#+BEGIN_VERSE ... #+END_VERSE} +@item @kbd{c} @tab @code{#+BEGIN_CENTER ... #+END_CENTER} +@item @kbd{l} @tab @code{#+BEGIN_EXPORT latex ... #+END_EXPORT} +@item @kbd{L} @tab @code{#+LATEX:} +@item @kbd{h} @tab @code{#+BEGIN_EXPORT html ... #+END_EXPORT} @item @kbd{H} @tab @code{#+HTML:} -@item @kbd{a} @tab @code{#+BEGIN_ASCII ... #+END_ASCII} +@item @kbd{a} @tab @code{#+BEGIN_EXPORT ascii ... #+END_EXPORT} @item @kbd{A} @tab @code{#+ASCII:} @item @kbd{i} @tab @code{#+INDEX:} line @item @kbd{I} @tab @code{#+INCLUDE:} line @end multitable -For example, on an empty line, typing "<e" and then pressing TAB, will expand -into a complete EXAMPLE template. +More templates can added by customizing the variable +@code{org-structure-template-alist}, whose docstring has additional details. -You can install additional templates by customizing the variable -@code{org-structure-template-alist}. See the docstring of the variable for -additional details. - -@node Speed keys, Code evaluation security, Easy Templates, Miscellaneous +@node Speed keys @section Speed keys @cindex speed keys + +Single keystrokes can execute custom commands in an Org file when the cursor +is on a headline. Without the extra burden of a meta or modifier key, Speed +Keys can speed navigation or execute custom commands. Besides faster +navigation, Speed Keys may come in handy on small mobile devices that do not +have full keyboards. Speed Keys may also work on TTY devices known for their +problems when entering Emacs keychords. + @vindex org-use-speed-commands -@vindex org-speed-commands-user +By default, Org has Speed Keys disabled. To activate Speed Keys, set the +variable @code{org-use-speed-commands} to a non-@code{nil} value. To trigger +a Speed Key, the cursor must be at the beginning of an Org headline, before +any of the stars. -Single keys can be made to execute commands when the cursor is at the -beginning of a headline, i.e., before the first star. Configure the variable -@code{org-use-speed-commands} to activate this feature. There is a -pre-defined list of commands, and you can add more such commands using the -variable @code{org-speed-commands-user}. Speed keys do not only speed up -navigation and other commands, but they also provide an alternative way to -execute commands bound to keys that are not or not easily available on a TTY, -or on a small mobile device with a limited keyboard. +@vindex org-speed-commands-user +@findex org-speed-command-help +Org comes with a pre-defined list of Speed Keys. To add or modify Speed +Keys, customize the variable, @code{org-speed-commands-user}. For more +details, see the variable's docstring. With Speed Keys activated, @kbd{M-x +org-speed-command-help}, or @kbd{?} when cursor is at the beginning of an Org +headline, shows currently active Speed Keys, including the user-defined ones. -To see which commands are available, activate the feature and press @kbd{?} -with the cursor at the beginning of a headline. -@node Code evaluation security, Customization, Speed keys, Miscellaneous +@node Code evaluation security @section Code evaluation and security issues -Org provides tools to work with the code snippets, including evaluating them. - -Running code on your machine always comes with a security risk. Badly -written or malicious code can be executed on purpose or by accident. Org has -default settings which will only evaluate such code if you give explicit -permission to do so, and as a casual user of these features you should leave -these precautions intact. +Unlike plain text, running code comes with risk. Each @samp{src} code block, +in terms of risk, is equivalent to an executable file. Org therefore puts a +few confirmation prompts by default. This is to alert the casual user from +accidentally running untrusted code. -For people who regularly work with such code, the confirmation prompts can -become annoying, and you might want to turn them off. This can be done, but -you must be aware of the risks that are involved. +For users who do not run code blocks or write code regularly, Org's default +settings should suffice. However, some users may want to tweak the prompts +for fewer interruptions. To weigh the risks of automatic execution of code +blocks, here are some details about code evaluation. -Code evaluation can happen under the following circumstances: +Org evaluates code in the following circumstances: @table @i @item Source code blocks -Source code blocks can be evaluated during export, or when pressing @kbd{C-c -C-c} in the block. The most important thing to realize here is that Org mode -files which contain code snippets are, in a certain sense, like executable -files. So you should accept them and load them into Emacs only from trusted -sources---just like you would do with a program you install on your computer. - -Make sure you know what you are doing before customizing the variables -which take off the default security brakes. +Org evaluates @samp{src} code blocks in an Org file during export. Org also +evaluates a @samp{src} code block with the @kbd{C-c C-c} key chord. Users +exporting or running code blocks must load files only from trusted sources. +Be weary of customizing variables that remove or alter default security +measures. @defopt org-confirm-babel-evaluate -When t (the default), the user is asked before every code block evaluation. -When @code{nil}, the user is not asked. When set to a function, it is called with -two arguments (language and body of the code block) and should return t to -ask and @code{nil} not to ask. +When @code{t}, Org prompts the user for confirmation before executing each +code block. When @code{nil}, Org executes code blocks without prompting the +user for confirmation. When this option is set to a custom function, Org +invokes the function with these two arguments: the source code language and +the body of the code block. The custom function must return either a +@code{t} or @code{nil}, which determines if the user is prompted. Each +source code language can be handled separately through this function +argument. @end defopt -For example, here is how to execute "ditaa" code (which is considered safe) -without asking: +For example, this function enables execution of @samp{ditaa} code +blocks +without prompting: @lisp (defun my-org-confirm-babel-evaluate (lang body) @@ -16115,86 +17113,73 @@ without asking: @end lisp @item Following @code{shell} and @code{elisp} links -Org has two link types that can directly evaluate code (@pxref{External -links}). These links can be problematic because the code to be evaluated is -not visible. +Org has two link types that can also directly evaluate code (@pxref{External +links}). Because such code is not visible, these links have a potential +risk. Org therefore prompts the user when it encounters such links. The +customization variables are: @defopt org-confirm-shell-link-function -Function to queries user about shell link execution. +Function that prompts the user before executing a shell link. @end defopt @defopt org-confirm-elisp-link-function -Functions to query user for Emacs Lisp link execution. +Function that prompts the user before executing an Emacs Lisp link. @end defopt @item Formulas in tables -Formulas in tables (@pxref{The spreadsheet}) are code that is evaluated -either by the @i{calc} interpreter, or by the @i{Emacs Lisp} interpreter. +Org executes formulas in tables (@pxref{The spreadsheet}) either through the +@emph{calc} or the @emph{Emacs Lisp} interpreters. @end table -@node Customization, In-buffer settings, Code evaluation security, Miscellaneous +@node Customization @section Customization @cindex customization @cindex options, for customization @cindex variables, for customization -There are more than 500 variables that can be used to customize -Org. For the sake of compactness of the manual, I am not -describing the variables here. A structured overview of customization -variables is available with @kbd{M-x org-customize RET}. Or select -@code{Browse Org Group} from the @code{Org->Customization} menu. Many -settings can also be activated on a per-file basis, by putting special -lines into the buffer (@pxref{In-buffer settings}). +Org has more than 500 variables for customization. They can be accessed +through the usual @kbd{M-x org-customize RET} command. Or through the Org +menu, @code{Org->Customization->Browse Org Group}. Org also has per-file +settings for some variables (@pxref{In-buffer settings}). -@node In-buffer settings, The very busy C-c C-c key, Customization, Miscellaneous +@node In-buffer settings @section Summary of in-buffer settings @cindex in-buffer settings @cindex special keywords +In-buffer settings start with @samp{#+}, followed by a keyword, a colon, and +then a word for each setting. Org accepts multiple settings on the same +line. Org also accepts multiple lines for a keyword. This manual describes +these settings throughout. A summary follows here. -Org mode uses special lines in the buffer to define settings on a -per-file basis. These lines start with a @samp{#+} followed by a -keyword, a colon, and then individual words defining a setting. Several -setting words can be in the same line, but you can also have multiple -lines for the keyword. While these settings are described throughout -the manual, here is a summary. After changing any of those lines in the -buffer, press @kbd{C-c C-c} with the cursor still in the line to -activate the changes immediately. Otherwise they become effective only -when the file is visited again in a new Emacs session. +@kbd{C-c C-c} activates any changes to the in-buffer settings. Closing and +reopening the Org file in Emacs also activates the changes. @vindex org-archive-location @table @kbd @item #+ARCHIVE: %s_done:: -This line sets the archive location for the agenda file. It applies for -all subsequent lines until the next @samp{#+ARCHIVE} line, or the end -of the file. The first such line also applies to any entries before it. +Sets the archive location of the agenda file. This location applies to the +lines until the next @samp{#+ARCHIVE} line, if any, in the Org file. The +first archive location in the Org file also applies to any entries before it. The corresponding variable is @code{org-archive-location}. @item #+CATEGORY: -This line sets the category for the agenda file. The category applies -for all subsequent lines until the next @samp{#+CATEGORY} line, or the -end of the file. The first such line also applies to any entries before it. +Sets the category of the agenda file, which applies to the entire document. @item #+COLUMNS: %25ITEM ... @cindex property, COLUMNS -Set the default format for columns view. This format applies when -columns view is invoked in locations where no @code{COLUMNS} property -applies. +Sets the default format for columns view. Org uses this format for column +views where there is no @code{COLUMNS} property. @item #+CONSTANTS: name1=value1 ... @vindex org-table-formula-constants @vindex org-table-formula -Set file-local values for constants to be used in table formulas. This -line sets the local variable @code{org-table-formula-constants-local}. -The global version of this variable is -@code{org-table-formula-constants}. +Set file-local values for constants that table formulas can use. This line +sets the local variable @code{org-table-formula-constants-local}. The global +version of this variable is @code{org-table-formula-constants}. @item #+FILETAGS: :tag1:tag2:tag3: -Set tags that can be inherited by any entry in the file, including the +Set tags that all entries in the file will inherit from here, including the top-level entries. -@item #+DRAWERS: NAME1 ... -@vindex org-drawers -Set the file-local set of additional drawers. The corresponding global -variable is @code{org-drawers}. @item #+LINK: linkword replace @vindex org-link-abbrev-alist -These lines (several are allowed) specify link abbreviations. -@xref{Link abbreviations}. The corresponding variable is -@code{org-link-abbrev-alist}. +Each line specifies one abbreviation for one link. Use multiple +@code{#+LINK:} lines for more, @pxref{Link abbreviations}. The corresponding +variable is @code{org-link-abbrev-alist}. @item #+PRIORITIES: highest lowest default @vindex org-highest-priority @vindex org-lowest-priority @@ -16207,22 +17192,22 @@ This line sets a default inheritance value for entries in the current buffer, most useful for specifying the allowed values of a property. @cindex #+SETUPFILE @item #+SETUPFILE: file -This line defines a file that holds more in-buffer setup. Normally this is -entirely ignored. Only when the buffer is parsed for option-setting lines -(i.e., when starting Org mode for a file, when pressing @kbd{C-c C-c} in a -settings line, or when exporting), then the contents of this file are parsed -as if they had been included in the buffer. In particular, the file can be -any other Org mode file with internal setup. You can visit the file the -cursor is in the line with @kbd{C-c '}. +The setup file is for additional in-buffer settings. Org loads this file and +parses it for any settings in it only when Org opens the main file. @kbd{C-c +C-c} on the settings line will also parse and load. Org also parses and +loads the file during normal exporting process. Org parses the contents of +this file as if it was included in the buffer. It can be another Org file. +To visit the file, @kbd{C-c '} while the cursor is on the line with the file +name. @item #+STARTUP: @cindex #+STARTUP -This line sets options to be used at startup of Org mode, when an -Org file is being visited. +Startup options Org uses when first visiting a file. The first set of options deals with the initial visibility of the outline tree. The corresponding variable for global default settings is -@code{org-startup-folded}, with a default value @code{t}, which means -@code{overview}. +@code{org-startup-folded} with a default value of @code{t}, which is the same +as @code{overview}. + @vindex org-startup-folded @cindex @code{overview}, STARTUP keyword @cindex @code{content}, STARTUP keyword @@ -16239,17 +17224,17 @@ showeverything @r{show even drawer contents} @cindex @code{indent}, STARTUP keyword @cindex @code{noindent}, STARTUP keyword Dynamic virtual indentation is controlled by the variable -@code{org-startup-indented}@footnote{Emacs 23 and Org mode 6.29 are required} +@code{org-startup-indented} @example indent @r{start with @code{org-indent-mode} turned on} noindent @r{start with @code{org-indent-mode} turned off} @end example @vindex org-startup-align-all-tables -Then there are options for aligning tables upon visiting a file. This -is useful in files containing narrowed table columns. The corresponding -variable is @code{org-startup-align-all-tables}, with a default value -@code{nil}. +Aligns tables consistently upon visiting a file; useful for restoring +narrowed table columns. The corresponding variable is +@code{org-startup-align-all-tables} with @code{nil} as default value. + @cindex @code{align}, STARTUP keyword @cindex @code{noalign}, STARTUP keyword @example @@ -16258,9 +17243,9 @@ noalign @r{don't align tables on startup} @end example @vindex org-startup-with-inline-images -When visiting a file, inline images can be automatically displayed. The -corresponding variable is @code{org-startup-with-inline-images}, with a -default value @code{nil} to avoid delays when visiting a file. +Whether Org should automatically display inline images. The corresponding +variable is @code{org-startup-with-inline-images}, with a default value +@code{nil} to avoid delays when visiting a file. @cindex @code{inlineimages}, STARTUP keyword @cindex @code{noinlineimages}, STARTUP keyword @example @@ -16269,10 +17254,9 @@ noinlineimages @r{don't show inline images on startup} @end example @vindex org-startup-with-latex-preview -When visiting a file, @LaTeX{} fragments can be converted to images -automatically. The variable @code{org-startup-with-latex-preview} which -controls this behavior, is set to @code{nil} by default to avoid delays on -startup. +Whether Org should automatically convert @LaTeX{} fragments to images. The +variable @code{org-startup-with-latex-preview}, which controls this setting, +is set to @code{nil} by default to avoid startup delays. @cindex @code{latexpreview}, STARTUP keyword @cindex @code{nolatexpreview}, STARTUP keyword @example @@ -16333,21 +17317,21 @@ nologstatesreversed @r{do not reverse the order of states notes} @vindex org-hide-leading-stars @vindex org-odd-levels-only -Here are the options for hiding leading stars in outline headings, and for -indenting outlines. The corresponding variables are -@code{org-hide-leading-stars} and @code{org-odd-levels-only}, both with a -default setting @code{nil} (meaning @code{showstars} and @code{oddeven}). +These options hide leading stars in outline headings, and indent outlines. +The corresponding variables are @code{org-hide-leading-stars} and +@code{org-odd-levels-only}, both with a default setting of @code{nil} +(meaning @code{showstars} and @code{oddeven}). @cindex @code{hidestars}, STARTUP keyword @cindex @code{showstars}, STARTUP keyword @cindex @code{odd}, STARTUP keyword @cindex @code{even}, STARTUP keyword @example -hidestars @r{make all but one of the stars starting a headline invisible.} -showstars @r{show all stars starting a headline} -indent @r{virtual indentation according to outline level} -noindent @r{no virtual indentation according to outline level} -odd @r{allow only odd outline levels (1,3,...)} -oddeven @r{allow all outline levels} +hidestars @r{hide all stars on the headline except one.} +showstars @r{show all stars on the headline} +indent @r{virtual indents according to the outline level} +noindent @r{no virtual indents} +odd @r{show odd outline levels only (1,3,...)} +oddeven @r{show all outline levels} @end example @vindex org-put-time-stamp-overlays @@ -16373,8 +17357,8 @@ constSI @r{@file{constants.el} should use the SI unit system} @vindex org-footnote-define-inline @vindex org-footnote-auto-label @vindex org-footnote-auto-adjust -To influence footnote settings, use the following keywords. The -corresponding variables are @code{org-footnote-define-inline}, +For footnote settings, use the following keywords. The corresponding +variables are @code{org-footnote-define-inline}, @code{org-footnote-auto-label}, and @code{org-footnote-auto-adjust}. @cindex @code{fninline}, STARTUP keyword @cindex @code{nofninline}, STARTUP keyword @@ -16419,67 +17403,57 @@ entitiesplain @r{Leave entities plain} @item #+TAGS: TAG1(c1) TAG2(c2) @vindex org-tag-alist -These lines (several such lines are allowed) specify the valid tags in -this file, and (potentially) the corresponding @emph{fast tag selection} -keys. The corresponding variable is @code{org-tag-alist}. +These lines specify valid tags for this file. Org accepts multiple tags +lines. Tags could correspond to the @emph{fast tag selection} keys. The +corresponding variable is @code{org-tag-alist}. @cindex #+TBLFM @item #+TBLFM: -This line contains the formulas for the table directly above the line. - -Table can have multiple lines containing @samp{#+TBLFM:}. Note -that only the first line of @samp{#+TBLFM:} will be applied when -you recalculate the table. For more details see @ref{Using -multiple #+TBLFM lines} in @ref{Editing and debugging formulas}. - +This line is for formulas for the table directly above. A table can have +multiple @samp{#+TBLFM:} lines. On table recalculation, Org applies only the +first @samp{#+TBLFM:} line. For details see @ref{Using multiple #+TBLFM +lines} in @ref{Editing and debugging formulas}. @item #+TITLE:, #+AUTHOR:, #+EMAIL:, #+LANGUAGE:, #+DATE:, @itemx #+OPTIONS:, #+BIND:, -@itemx #+DESCRIPTION:, #+KEYWORDS:, -@itemx #+LaTeX_HEADER:, #+LaTeX_HEADER_EXTRA:, -@itemx #+HTML_HEAD:, #+HTML_HEAD_EXTRA:, #+HTML_LINK_UP:, #+HTML_LINK_HOME:, @itemx #+SELECT_TAGS:, #+EXCLUDE_TAGS: These lines provide settings for exporting files. For more details see @ref{Export settings}. @item #+TODO: #+SEQ_TODO: #+TYP_TODO: @vindex org-todo-keywords -These lines set the TODO keywords and their interpretation in the -current file. The corresponding variable is @code{org-todo-keywords}. +These lines set the TODO keywords and their significance to the current file. +The corresponding variable is @code{org-todo-keywords}. @end table -@node The very busy C-c C-c key, Clean view, In-buffer settings, Miscellaneous +@node The very busy C-c C-c key @section The very busy C-c C-c key @kindex C-c C-c @cindex C-c C-c, overview -The key @kbd{C-c C-c} has many purposes in Org, which are all -mentioned scattered throughout this manual. One specific function of -this key is to add @emph{tags} to a headline (@pxref{Tags}). In many -other circumstances it means something like @emph{``Hey Org, look -here and update according to what you see here''}. Here is a summary of -what this means in different contexts. +The @kbd{C-c C-c} key in Org serves many purposes depending on the context. +It is probably the most over-worked, multi-purpose key combination in Org. +Its uses are well-documented through out this manual, but here is a +consolidated list for easy reference. @itemize @minus @item -If there are highlights in the buffer from the creation of a sparse -tree, or from clock display, remove these highlights. +If any highlights shown in the buffer from the creation of a sparse tree, or +from clock display, remove such highlights. @item -If the cursor is in one of the special @code{#+KEYWORD} lines, this -triggers scanning the buffer for these lines and updating the -information. +If the cursor is in one of the special @code{#+KEYWORD} lines, scan the +buffer for these lines and update the information. @item -If the cursor is inside a table, realign the table. This command -works even if the automatic table editor has been turned off. +If the cursor is inside a table, realign the table. The table realigns even +if automatic table editor is turned off. @item If the cursor is on a @code{#+TBLFM} line, re-apply the formulas to the entire table. @item -If the current buffer is a capture buffer, close the note and file it. -With a prefix argument, file it, without further interaction, to the -default location. +If the current buffer is a capture buffer, close the note and file it. With +a prefix argument, also jump to the target location after saving the note. @item If the cursor is on a @code{<<<target>>>}, update radio targets and corresponding links in this buffer. @item -If the cursor is in a property line or at the start or end of a property +If the cursor is on a property line or at the start or end of a property drawer, offer property commands. @item If the cursor is at a footnote reference, go to the corresponding @@ -16499,18 +17473,18 @@ block is updated. If the cursor is at a timestamp, fix the day name in the timestamp. @end itemize -@node Clean view, TTY keys, The very busy C-c C-c key, Miscellaneous +@node Clean view @section A cleaner outline view @cindex hiding leading stars @cindex dynamic indentation @cindex odd-levels-only outlines @cindex clean outline view -Some people find it noisy and distracting that the Org headlines start with a -potentially large number of stars, and that text below the headlines is not -indented. While this is no problem when writing a @emph{book-like} document -where the outline headings are really section headings, in a more -@emph{list-oriented} outline, indented structure is a lot cleaner: +Org's default outline with stars and no indents can become too cluttered for +short documents. For @emph{book-like} long documents, the effect is not as +noticeable. Org provides an alternate stars and indentation scheme, as shown +on the right in the following table. It uses only one star and indents text +to line with the heading: @example @group @@ -16526,38 +17500,40 @@ more text | more text @noindent -If you are using at least Emacs 23.2@footnote{Emacs 23.1 can actually crash -with @code{org-indent-mode}} and version 6.29 of Org, this kind of view can -be achieved dynamically at display time using @code{org-indent-mode}. In -this minor mode, all lines are prefixed for display with the necessary amount -of space@footnote{@code{org-indent-mode} also sets the @code{wrap-prefix} -property, such that @code{visual-line-mode} (or purely setting -@code{word-wrap}) wraps long lines (including headlines) correctly indented. -}. Also headlines are prefixed with additional stars, so that the amount of -indentation shifts by two@footnote{See the variable -@code{org-indent-indentation-per-level}.} spaces per level. All headline -stars but the last one are made invisible using the @code{org-hide} -face@footnote{Turning on @code{org-indent-mode} sets +To turn this mode on, use the minor mode, @code{org-indent-mode}. Text lines +that are not headlines are prefixed with spaces to vertically align with the +headline text@footnote{The @code{org-indent-mode} also sets the +@code{wrap-prefix} correctly for indenting and wrapping long lines of +headlines or text. This minor mode handles @code{visual-line-mode} and +directly applied settings through @code{word-wrap}.}. + +To make more horizontal space, the headlines are shifted by two stars. This +can be configured by the @code{org-indent-indentation-per-level} variable. +Only one star on each headline is visible, the rest are masked with the same +font color as the background. This font face can be configured with the +@code{org-hide} variable. + +Note that turning on @code{org-indent-mode} sets @code{org-hide-leading-stars} to @code{t} and @code{org-adapt-indentation} to -@code{nil}.}; see below under @samp{2.} for more information on how this -works. You can turn on @code{org-indent-mode} for all files by customizing -the variable @code{org-startup-indented}, or you can turn it on for -individual files using +@code{nil}; @samp{2.} below shows how this works. + +To globally turn on @code{org-indent-mode} for all files, customize the +variable @code{org-startup-indented}. + +To turn on indenting for individual files, use @code{#+STARTUP} option as +follows: @example #+STARTUP: indent @end example -If you want a similar effect in an earlier version of Emacs and/or Org, or if -you want the indentation to be hard space characters so that the plain text -file looks as similar as possible to the Emacs display, Org supports you in -the following way: +Indent on startup makes Org use hard spaces to align text with headings as +shown in examples below. @enumerate @item @emph{Indentation of text below headlines}@* -You may indent text below each headline to make the left boundary line up -with the headline, like +Indent text to align with the headline. @example *** 3rd level @@ -16565,23 +17541,21 @@ with the headline, like @end example @vindex org-adapt-indentation -Org supports this with paragraph filling, line wrapping, and structure -editing@footnote{See also the variable @code{org-adapt-indentation}.}, -preserving or adapting the indentation as appropriate. +Org adapts indentations with paragraph filling, line wrapping, and structure +editing@footnote{Also see the variable @code{org-adapt-indentation}.}. @item @vindex org-hide-leading-stars -@emph{Hiding leading stars}@* You can modify the display in such a way that -all leading stars become invisible. To do this in a global way, configure -the variable @code{org-hide-leading-stars} or change this on a per-file basis -with +@emph{Hiding leading stars}@* Org can make leading stars invisible. For +global preference, configure the variable @code{org-hide-leading-stars}. For +per-file preference, use these file @code{#+STARTUP} options: @example #+STARTUP: hidestars #+STARTUP: showstars @end example -With hidden stars, the tree becomes: +With stars hidden, the tree is shown as: @example @group @@ -16594,50 +17568,39 @@ With hidden stars, the tree becomes: @noindent @vindex org-hide @r{(face)} -The leading stars are not truly replaced by whitespace, they are only -fontified with the face @code{org-hide} that uses the background color as -font color. If you are not using either white or black background, you may -have to customize this face to get the wanted effect. Another possibility is -to set this font such that the extra stars are @i{almost} invisible, for -example using the color @code{grey90} on a white background. +Because Org makes the font color same as the background color to hide to +stars, sometimes @code{org-hide} face may need tweaking to get the effect +right. For some black and white combinations, @code{grey90} on a white +background might mask the stars better. @item @vindex org-odd-levels-only -Things become cleaner still if you skip all the even levels and use only odd -levels 1, 3, 5..., effectively adding two stars to go from one outline level -to the next@footnote{When you need to specify a level for a property search -or refile targets, @samp{LEVEL=2} will correspond to 3 stars, etc.}. In this -way we get the outline view shown at the beginning of this section. In order -to make the structure editing and export commands handle this convention -correctly, configure the variable @code{org-odd-levels-only}, or set this on -a per-file basis with one of the following lines: +Using stars for only odd levels, 1, 3, 5, @dots{}, can also clean up the +clutter. This removes two stars from each level@footnote{Because +@samp{LEVEL=2} has 3 stars, @samp{LEVEL=3} has 4 stars, and so on}. For Org +to properly handle this cleaner structure during edits and exports, configure +the variable @code{org-odd-levels-only}. To set this per-file, use either +one of the following lines: @example #+STARTUP: odd #+STARTUP: oddeven @end example -You can convert an Org file from single-star-per-level to the -double-star-per-level convention with @kbd{M-x org-convert-to-odd-levels -RET} in that file. The reverse operation is @kbd{M-x -org-convert-to-oddeven-levels}. +To switch between single and double stars layouts, use @kbd{M-x +org-convert-to-odd-levels RET} and @kbd{M-x org-convert-to-oddeven-levels}. @end enumerate -@node TTY keys, Interaction, Clean view, Miscellaneous +@node TTY keys @section Using Org on a tty @cindex tty key bindings -Because Org contains a large number of commands, by default many of -Org's core commands are bound to keys that are generally not -accessible on a tty, such as the cursor keys (@key{left}, @key{right}, -@key{up}, @key{down}), @key{TAB} and @key{RET}, in particular when used -together with modifiers like @key{Meta} and/or @key{Shift}. To access -these commands on a tty when special keys are unavailable, the following -alternative bindings can be used. The tty bindings below will likely be -more cumbersome; you may find for some of the bindings below that a -customized workaround suits you better. For example, changing a timestamp -is really only fun with @kbd{S-@key{cursor}} keys, whereas on a -tty you would rather use @kbd{C-c .} to re-insert the timestamp. +Org provides alternative key bindings for TTY and modern mobile devices that +cannot handle cursor keys and complex modifier key chords. Some of these +workarounds may be more cumbersome than necessary. Users should look into +customizing these further based on their usage needs. For example, the +normal @kbd{S-@key{cursor}} for editing timestamp might be better with +@kbd{C-c .} chord. @multitable @columnfractions 0.15 0.2 0.1 0.2 @item @b{Default} @tab @b{Alternative 1} @tab @b{Speed key} @tab @b{Alternative 2} @@ -16662,74 +17625,62 @@ tty you would rather use @kbd{C-c .} to re-insert the timestamp. @end multitable -@node Interaction, org-crypt, TTY keys, Miscellaneous +@node Interaction @section Interaction with other packages @cindex packages, interaction with other -Org lives in the world of GNU Emacs and interacts in various ways -with other code out there. +Org's compatibility and the level of interaction with other Emacs packages +are documented here. + @menu * Cooperation:: Packages Org cooperates with * Conflicts:: Packages that lead to conflicts @end menu -@node Cooperation, Conflicts, Interaction, Interaction +@node Cooperation @subsection Packages that Org cooperates with @table @asis @cindex @file{calc.el} @cindex Gillespie, Dave @item @file{calc.el} by Dave Gillespie -Org uses the Calc package for implementing spreadsheet -functionality in its tables (@pxref{The spreadsheet}). Org -checks for the availability of Calc by looking for the function -@code{calc-eval} which will have been autoloaded during setup if Calc has -been installed properly. As of Emacs 22, Calc is part of the Emacs -distribution. Another possibility for interaction between the two -packages is using Calc for embedded calculations. @xref{Embedded Mode, -, Embedded Mode, calc, GNU Emacs Calc Manual}. +Org uses the Calc package for tables to implement spreadsheet functionality +(@pxref{The spreadsheet}). Org also uses Calc for embedded calculations. +@xref{Embedded Mode, , Embedded Mode, calc, GNU Emacs Calc Manual}. @item @file{constants.el} by Carsten Dominik @cindex @file{constants.el} @cindex Dominik, Carsten @vindex org-table-formula-constants -In a table formula (@pxref{The spreadsheet}), it is possible to use -names for natural constants or units. Instead of defining your own -constants in the variable @code{org-table-formula-constants}, install -the @file{constants} package which defines a large number of constants -and units, and lets you use unit prefixes like @samp{M} for -@samp{Mega}, etc. You will need version 2.0 of this package, available -at @url{http://www.astro.uva.nl/~dominik/Tools}. Org checks for -the function @code{constants-get}, which has to be autoloaded in your -setup. See the installation instructions in the file -@file{constants.el}. +Org can use names for constants in formulas in tables. Org can also use +calculation suffixes for units, such as @samp{M} for @samp{Mega}. For a +standard collection of such constants, install the @file{constants} package. +Install version 2.0 of this package, available at +@url{http://www.astro.uva.nl/~dominik/Tools}. Org checks if the function +@code{constants-get} has been autoloaded. Installation instructions are in +the file, @file{constants.el}. @item @file{cdlatex.el} by Carsten Dominik @cindex @file{cdlatex.el} @cindex Dominik, Carsten -Org mode can make use of the CD@LaTeX{} package to efficiently enter -@LaTeX{} fragments into Org files. See @ref{CDLaTeX mode}. +Org mode can use CD@LaTeX{} package to efficiently enter @LaTeX{} fragments +into Org files (@pxref{CDLaTeX mode}). @item @file{imenu.el} by Ake Stenhoff and Lars Lindberg @cindex @file{imenu.el} -Imenu allows menu access to an index of items in a file. Org mode -supports Imenu---all you need to do to get the index is the following: +Imenu creates dynamic menus based on an index of items in a file. Org mode +supports Imenu menus. Enable it with a mode hook as follows: @lisp (add-hook 'org-mode-hook (lambda () (imenu-add-to-menubar "Imenu"))) @end lisp @vindex org-imenu-depth -By default the index is two levels deep---you can modify the depth using -the option @code{org-imenu-depth}. -@item @file{remember.el} by John Wiegley -@cindex @file{remember.el} -@cindex Wiegley, John -Org used to use this package for capture, but no longer does. +By default the Imenu index is two levels deep. Change the index depth using +thes variable, @code{org-imenu-depth}. @item @file{speedbar.el} by Eric M. Ludlam @cindex @file{speedbar.el} @cindex Ludlam, Eric M. -Speedbar is a package that creates a special frame displaying files and -index items in files. Org mode supports Speedbar and allows you to -drill into Org files directly from the Speedbar. It also allows you to -restrict the scope of agenda commands to a file or a subtree by using -the command @kbd{<} in the Speedbar frame. +Speedbar package creates a special Emacs frame for displaying files and index +items in files. Org mode supports Speedbar; users can drill into Org files +directly from the Speedbar. The @kbd{<} in the Speedbar frame tweaks the +agenda commands to that file or to a subtree. @cindex @file{table.el} @item @file{table.el} by Takaaki Ota @kindex C-c C-c @@ -16738,13 +17689,11 @@ the command @kbd{<} in the Speedbar frame. @cindex Ota, Takaaki Complex ASCII tables with automatic line wrapping, column- and row-spanning, -and alignment can be created using the Emacs table package by Takaaki Ota -(@uref{http://sourceforge.net/projects/table}, and also part of Emacs 22). -Org mode will recognize these tables and export them properly. Because of -interference with other Org mode functionality, you unfortunately cannot edit -these tables directly in the buffer. Instead, you need to use the command -@kbd{C-c '} to edit them, similar to source code snippets. - +and alignment can be created using the Emacs table package by Takaaki Ota. +Org mode recognizes such tables and export them properly. @kbd{C-c '} to +edit these tables in a special buffer, much like Org's @samp{src} code +blocks. Because of interference with other Org mode functionality, Takaaki +Ota tables cannot be edited directly in the Org buffer. @table @kbd @orgcmd{C-c ',org-edit-special} Edit a @file{table.el} table. Works when the cursor is in a table.el table. @@ -16752,50 +17701,37 @@ Edit a @file{table.el} table. Works when the cursor is in a table.el table. @orgcmd{C-c ~,org-table-create-with-table.el} Insert a @file{table.el} table. If there is already a table at point, this command converts it between the @file{table.el} format and the Org mode -format. See the documentation string of the command -@code{org-convert-table} for the restrictions under which this is -possible. +format. See the documentation string of the command @code{org-convert-table} +for details. @end table -@file{table.el} is part of Emacs since Emacs 22. -@item @file{footnote.el} by Steven L. Baur -@cindex @file{footnote.el} -@cindex Baur, Steven L. -Org mode recognizes numerical footnotes as provided by this package. -However, Org mode also has its own footnote support (@pxref{Footnotes}), -which makes using @file{footnote.el} unnecessary. @end table -@node Conflicts, , Cooperation, Interaction -@subsection Packages that lead to conflicts with Org mode +@node Conflicts +@subsection Packages that conflict with Org mode @table @asis @cindex @code{shift-selection-mode} @vindex org-support-shift-select -In Emacs 23, @code{shift-selection-mode} is on by default, meaning that -cursor motions combined with the shift key should start or enlarge regions. -This conflicts with the use of @kbd{S-@key{cursor}} commands in Org to change -timestamps, TODO keywords, priorities, and item bullet types if the cursor is -at such a location. By default, @kbd{S-@key{cursor}} commands outside -special contexts don't do anything, but you can customize the variable -@code{org-support-shift-select}. Org mode then tries to accommodate shift -selection by (i) using it outside of the special contexts where special -commands apply, and by (ii) extending an existing active region even if the -cursor moves across a special context. +In Emacs, @code{shift-selection-mode} combines cursor motions with shift key +to enlarge regions. Emacs sets this mode by default. This conflicts with +Org's use of @kbd{S-@key{cursor}} commands to change timestamps, TODO +keywords, priorities, and item bullet types, etc. Since @kbd{S-@key{cursor}} +commands outside of specific contexts don't do anything, Org offers the +variable @code{org-support-shift-select} for customization. Org mode +accommodates shift selection by (i) making it available outside of the +special contexts where special commands apply, and (ii) extending an +existing active region even if the cursor moves across a special context. @item @file{CUA.el} by Kim. F. Storm @cindex @file{CUA.el} @cindex Storm, Kim. F. @vindex org-replace-disputed-keys -Key bindings in Org conflict with the @kbd{S-<cursor>} keys used by CUA mode -(as well as @code{pc-select-mode} and @code{s-region-mode}) to select and extend the -region. In fact, Emacs 23 has this built-in in the form of -@code{shift-selection-mode}, see previous paragraph. If you are using Emacs -23, you probably don't want to use another package for this purpose. However, -if you prefer to leave these keys to a different package while working in -Org mode, configure the variable @code{org-replace-disputed-keys}. When set, -Org will move the following key bindings in Org files, and in the agenda -buffer (but not during date selection). +Org key bindings conflict with @kbd{S-<cursor>} keys used by CUA mode. For +Org to relinquish these bindings to CUA mode, configure the variable +@code{org-replace-disputed-keys}. When set, Org moves the following key +bindings in Org files, and in the agenda buffer (but not during date +selection). @example S-UP @result{} M-p S-DOWN @result{} M-n @@ -16804,9 +17740,8 @@ C-S-LEFT @result{} M-S-- C-S-RIGHT @result{} M-S-+ @end example @vindex org-disputed-keys -Yes, these are unfortunately more difficult to remember. If you want -to have other replacement keys, look at the variable -@code{org-disputed-keys}. +Yes, these are unfortunately more difficult to remember. To define a +different replacement keys, look at the variable @code{org-disputed-keys}. @item @file{ecomplete.el} by Lars Magne Ingebrigtsen @email{larsi@@gnus.org} @cindex @file{ecomplete.el} @@ -16824,9 +17759,8 @@ manually when needed in the messages body. @cindex @file{filladapt.el} Org mode tries to do the right thing when filling paragraphs, list items and -other elements. Many users reported they had problems using both -@file{filladapt.el} and Org mode, so a safe thing to do is to disable it like -this: +other elements. Many users reported problems using both @file{filladapt.el} +and Org mode, so a safe thing to do is to disable filladapt like this: @lisp (add-hook 'org-mode-hook 'turn-off-filladapt-mode) @@ -16841,20 +17775,19 @@ fixed this problem: @lisp (add-hook 'org-mode-hook (lambda () - (org-set-local 'yas/trigger-key [tab]) + (setq-local yas/trigger-key [tab]) (define-key yas/keymap [tab] 'yas/next-field-or-maybe-expand))) @end lisp The latest version of yasnippet doesn't play well with Org mode. If the -above code does not fix the conflict, start by defining the following -function: +above code does not fix the conflict, first define the following function: @lisp (defun yas/org-very-safe-expand () (let ((yas/fallback-behavior 'return-nil)) (yas/expand))) @end lisp -Then, tell Org mode what to do with the new function: +Then tell Org mode to use that function: @lisp (add-hook 'org-mode-hook @@ -16897,21 +17830,19 @@ another key for this command, or override the key in @end table -@node org-crypt, , Interaction, Miscellaneous +@node org-crypt @section org-crypt.el @cindex @file{org-crypt.el} @cindex @code{org-decrypt-entry} -Org-crypt will encrypt the text of an entry, but not the headline, or -properties. Org-crypt uses the Emacs EasyPG library to encrypt and decrypt -files. +Org crypt encrypts the text of an Org entry, but not the headline, or +properties. Org crypt uses the Emacs EasyPG library to encrypt and decrypt. Any text below a headline that has a @samp{:crypt:} tag will be automatically -be encrypted when the file is saved. If you want to use a different tag just -customize the @code{org-crypt-tag-matcher} setting. +be encrypted when the file is saved. To use a different tag, customize the +@code{org-crypt-tag-matcher} variable. -To use org-crypt it is suggested that you have the following in your -@file{.emacs}: +Suggested Org crypt settings in Emacs init file: @lisp (require 'org-crypt) @@ -16933,14 +17864,14 @@ To use org-crypt it is suggested that you have the following in your ;; # -*- buffer-auto-save-file-name: nil; -*- @end lisp -Excluding the crypt tag from inheritance prevents already encrypted text -being encrypted again. +Excluding the crypt tag from inheritance prevents encrypting previously +encrypted text. -@node Hacking, MobileOrg, Miscellaneous, Top +@node Hacking @appendix Hacking @cindex hacking -This appendix covers some aspects where users can extend the functionality of +This appendix covers some areas where users can extend the functionality of Org. @menu @@ -16958,38 +17889,35 @@ Org. * Using the mapping API:: Mapping over all or selected entries @end menu -@node Hooks, Add-on packages, Hacking, Hacking +@node Hooks @section Hooks @cindex hooks -Org has a large number of hook variables that can be used to add -functionality. This appendix about hacking is going to illustrate the -use of some of them. A complete list of all hooks with documentation is -maintained by the Worg project and can be found at -@uref{http://orgmode.org/worg/org-configs/org-hooks.php}. +Org has a large number of hook variables for adding functionality. This +appendix illustrates using a few. A complete list of hooks with +documentation is maintained by the Worg project at +@uref{http://orgmode.org/worg/doc.html#hooks}. -@node Add-on packages, Adding hyperlink types, Hooks, Hacking +@node Add-on packages @section Add-on packages @cindex add-on packages -A large number of add-on packages have been written by various authors. +Various authors wrote a large number of add-on packages for Org. These packages are not part of Emacs, but they are distributed as contributed packages with the separate release available at @uref{http://orgmode.org}. See the @file{contrib/README} file in the source code directory for a list of -contributed files. You may also find some more information on the Worg page: +contributed files. Worg page with more information is at: @uref{http://orgmode.org/worg/org-contrib/}. -@node Adding hyperlink types, Adding export back-ends, Add-on packages, Hacking +@node Adding hyperlink types @section Adding hyperlink types @cindex hyperlinks, adding new types -Org has a large number of hyperlink types built-in -(@pxref{Hyperlinks}). If you would like to add new link types, Org -provides an interface for doing so. Let's look at an example file, -@file{org-man.el}, that will add support for creating links like -@samp{[[man:printf][The printf manpage]]} to show Unix manual pages inside -Emacs: +Org has many built-in hyperlink types (@pxref{Hyperlinks}), and an interface +for adding new link types. The example file, @file{org-man.el}, shows the +process of adding Org links to Unix man pages, which look like this: +@samp{[[man:printf][The printf manpage]]}: @lisp ;;; org-man.el - Support for links to manpages in Org @@ -17034,149 +17962,118 @@ PATH should be a topic that can be thrown at the man command." @end lisp @noindent -You would activate this new link type in @file{.emacs} with +To activate links to man pages in Org, enter this in the init file: @lisp (require 'org-man) @end lisp @noindent -Let's go through the file and see what it does. +A review of @file{org-man.el}: @enumerate @item -It does @code{(require 'org)} to make sure that @file{org.el} has been -loaded. +First, @code{(require 'org)} ensures @file{org.el} is loaded. @item -The next line calls @code{org-add-link-type} to define a new link type -with prefix @samp{man}. The call also contains the name of a function -that will be called to follow such a link. +The @code{org-add-link-type} defines a new link type with @samp{man} prefix. +The call contains the function to call that follows the link type. @item @vindex org-store-link-functions -The next line adds a function to @code{org-store-link-functions}, in -order to allow the command @kbd{C-c l} to record a useful link in a -buffer displaying a man page. +The next line adds a function to @code{org-store-link-functions} that records +a useful link with the command @kbd{C-c l} in a buffer displaying a man page. @end enumerate -The rest of the file defines the necessary variables and functions. -First there is a customization variable that determines which Emacs -command should be used to display man pages. There are two options, -@code{man} and @code{woman}. Then the function to follow a link is -defined. It gets the link path as an argument---in this case the link -path is just a topic for the manual command. The function calls the -value of @code{org-man-command} to display the man page. - -Finally the function @code{org-man-store-link} is defined. When you try -to store a link with @kbd{C-c l}, this function will be called to -try to make a link. The function must first decide if it is supposed to -create the link for this buffer type; we do this by checking the value -of the variable @code{major-mode}. If not, the function must exit and -return the value @code{nil}. If yes, the link is created by getting the -manual topic from the buffer name and prefixing it with the string -@samp{man:}. Then it must call the command @code{org-store-link-props} -and set the @code{:type} and @code{:link} properties. Optionally you -can also set the @code{:description} property to provide a default for -the link description when the link is later inserted into an Org -buffer with @kbd{C-c C-l}. - -When it makes sense for your new link type, you may also define a function -@code{org-PREFIX-complete-link} that implements special (e.g., completion) -support for inserting such a link with @kbd{C-c C-l}. Such a function should -not accept any arguments, and return the full link with prefix. - -@node Adding export back-ends, Context-sensitive commands, Adding hyperlink types, Hacking +The rest of the file defines necessary variables and functions. First is the +customization variable @code{org-man-command}. It has two options, +@code{man} and @code{woman}. Next is a function whose argument is the link +path, which for man pages is the topic of the man command. To follow the +link, the function calls the @code{org-man-command} to display the man page. + + +@kbd{C-c l} constructs and stores the link. + +@kbd{C-c l} calls the function @code{org-man-store-link}, which first checks +if the @code{major-mode} is appropriate. If check fails, the function +returns @code{nil}. Otherwise the function makes a link string by combining +the @samp{man:} prefix with the man topic. The function then calls +@code{org-store-link-props} with @code{:type} and @code{:link} properties. A +@code{:description} property is an optional string that is displayed when the +function inserts the link in the Org buffer. + +@kbd{C-c C-l} inserts the stored link. + +To define new link types, define a function that implements completion +support with @kbd{C-c C-l}. This function should not accept any arguments +but return the appropriate prefix and complete link string. + +@node Adding export back-ends @section Adding export back-ends @cindex Export, writing back-ends -Org 8.0 comes with a completely rewritten export engine which makes it easy -to write new export back-ends, either from scratch, or from deriving them -from existing ones. - -Your two entry points are respectively @code{org-export-define-backend} and -@code{org-export-define-derived-backend}. To grok these functions, you -should first have a look at @file{ox-latex.el} (for how to define a new -back-end from scratch) and @file{ox-beamer.el} (for how to derive a new -back-end from an existing one. - -When creating a new back-end from scratch, the basic idea is to set the name -of the back-end (as a symbol) and an an alist of elements and export -functions. On top of this, you will need to set additional keywords like -@code{:menu-entry} (to display the back-end in the export dispatcher), -@code{:export-block} (to specify what blocks should not be exported by this -back-end), and @code{:options-alist} (to let the user set export options that -are specific to this back-end.) - -Deriving a new back-end is similar, except that you need to set -@code{:translate-alist} to an alist of export functions that should be used -instead of the parent back-end functions. - -For a complete reference documentation, see +Org's export engine makes it easy for writing new back-ends. The framework +on which the engine was built makes it easy to derive new back-ends from +existing ones. + +The two main entry points to the export engine are: +@code{org-export-define-backend} and +@code{org-export-define-derived-backend}. To grok these functions, see +@file{ox-latex.el} for an example of defining a new back-end from scratch, +and @file{ox-beamer.el} for an example of deriving from an existing engine. + +For creating a new back-end from scratch, first set its name as a symbol in +an alist consisting of elements and export functions. To make the back-end +visible to the export dispatcher, set @code{:menu-entry} keyword. For export +options specific to this back-end, set the @code{:options-alist}. + +For creating a new back-end from an existing one, set @code{:translate-alist} +to an alist of export functions. This alist replaces the parent back-end +functions. + +For complete documentation, see @url{http://orgmode.org/worg/dev/org-export-reference.html, the Org Export Reference on Worg}. -@node Context-sensitive commands, Tables in arbitrary syntax, Adding export back-ends, Hacking +@node Context-sensitive commands @section Context-sensitive commands @cindex context-sensitive commands, hooks @cindex add-ons, context-sensitive commands @vindex org-ctrl-c-ctrl-c-hook -Org has several commands that act differently depending on context. The most -important example is the @kbd{C-c C-c} (@pxref{The very busy C-c C-c key}). -Also the @kbd{M-cursor} and @kbd{M-S-cursor} keys have this property. - -Add-ons can tap into this functionality by providing a function that detects -special context for that add-on and executes functionality appropriate for -the context. Here is an example from Dan Davison's @file{org-R.el} which -allows you to evaluate commands based on the @file{R} programming language -@footnote{@file{org-R.el} has been replaced by the Org mode functionality -described in @ref{Working With Source Code} and is now obsolete.}. For this -package, special contexts are lines that start with @code{#+R:} or -@code{#+RR:}. - -@lisp -(defun org-R-apply-maybe () - "Detect if this is context for org-R and execute R commands." - (if (save-excursion - (beginning-of-line 1) - (looking-at "#\\+RR?:")) - (progn (call-interactively 'org-R-apply) - t) ;; to signal that we took action - nil)) ;; to signal that we did not - -(add-hook 'org-ctrl-c-ctrl-c-hook 'org-R-apply-maybe) -@end lisp +Org has facilities for building context sensitive commands. Authors of Org +add-ons can tap into this functionality. -The function first checks if the cursor is in such a line. If that is the -case, @code{org-R-apply} is called and the function returns @code{t} to -signal that action was taken, and @kbd{C-c C-c} will stop looking for other -contexts. If the function finds it should do nothing locally, it returns -@code{nil} so that other, similar functions can have a try. +Some Org commands change depending on the context. The most important +example of this behavior is the @kbd{C-c C-c} (@pxref{The very busy C-c C-c +key}). Other examples are @kbd{M-cursor} and @kbd{M-S-cursor}. +These context sensitive commands work by providing a function that detects +special context for that add-on and executes functionality appropriate for +that context. -@node Tables in arbitrary syntax, Dynamic blocks, Context-sensitive commands, Hacking +@node Tables in arbitrary syntax @section Tables and lists in arbitrary syntax @cindex tables, in other modes @cindex lists, in other modes @cindex Orgtbl mode -Since Orgtbl mode can be used as a minor mode in arbitrary buffers, a -frequent feature request has been to make it work with native tables in -specific languages, for example @LaTeX{}. However, this is extremely -hard to do in a general way, would lead to a customization nightmare, -and would take away much of the simplicity of the Orgtbl mode table -editor. - -This appendix describes a different approach. We keep the Orgtbl mode -table in its native format (the @i{source table}), and use a custom -function to @i{translate} the table to the correct syntax, and to -@i{install} it in the right location (the @i{target table}). This puts -the burden of writing conversion functions on the user, but it allows -for a very flexible system. - -Bastien added the ability to do the same with lists, in Orgstruct mode. You -can use Org's facilities to edit and structure lists by turning -@code{orgstruct-mode} on, then locally exporting such lists in another format -(HTML, @LaTeX{} or Texinfo.) - +Because of Org's success in handling tables with Orgtbl, a frequently asked +feature is to Org's usability functions to other table formats native to +other modem's, such as @LaTeX{}. This would be hard to do in a general way +without complicated customization nightmares. Moreover, that would take Org +away from its simplicity roots that Orgtbl has proven. There is, however, an +alternate approach to accomplishing the same. + +This approach involves implementing a custom @emph{translate} function that +operates on a native Org @emph{source table} to produce a table in another +format. This strategy would keep the excellently working Orgtbl simple and +isolate complications, if any, confined to the translate function. To add +more alien table formats, we just add more translate functions. Also the +burden of developing custom translate functions for new table formats will be +in the hands of those who know those formats best. + +For an example of how this strategy works, see Orgstruct mode. In that mode, +Bastien added the ability to use Org's facilities to edit and re-structure +lists. He did by turning @code{orgstruct-mode} on, and then exporting the +list locally to another format, such as HTML, @LaTeX{} or Texinfo. @menu * Radio tables:: Sending and receiving radio tables @@ -17185,15 +18082,17 @@ can use Org's facilities to edit and structure lists by turning * Radio lists:: Sending and receiving lists @end menu -@node Radio tables, A @LaTeX{} example, Tables in arbitrary syntax, Tables in arbitrary syntax +@node Radio tables @subsection Radio tables @cindex radio tables -To define the location of the target table, you first need to create two -lines that are comments in the current mode, but contain magic words -@code{BEGIN/END RECEIVE ORGTBL} for Orgtbl mode to find. Orgtbl mode will -insert the translated table between these lines, replacing whatever was there -before. For example in C mode where comments are between @code{/* ... */}: +Radio tables are target locations for translated tables that are not near +their source. Org finds the target location and inserts the translated +table. + +The key to finding the target location are the magic words @code{BEGIN/END +RECEIVE ORGTBL}. They have to appear as comments in the current mode. If +the mode is C, then: @example /* BEGIN RECEIVE ORGTBL table_name */ @@ -17201,8 +18100,8 @@ before. For example in C mode where comments are between @code{/* ... */}: @end example @noindent -Just above the source table, we put a special line that tells -Orgtbl mode how to translate this table and where to install it. For +At the location of source, Org needs a special line to direct Orgtbl to +translate and to find the target for inserting the translated table. For example: @cindex #+ORGTBL @example @@ -17210,67 +18109,53 @@ example: @end example @noindent -@code{table_name} is the reference name for the table that is also used -in the receiver lines. @code{translation_function} is the Lisp function -that does the translation. Furthermore, the line can contain a list of -arguments (alternating key and value) at the end. The arguments will be -passed as a property list to the translation function for -interpretation. A few standard parameters are already recognized and -acted upon before the translation function is called: +@code{table_name} is the table's reference name, which is also used in the +receiver lines, and the @code{translation_function} is the Lisp function that +translates. This line, in addition, may also contain alternating key and +value arguments at the end. The translation function gets these values as a +property list. A few standard parameters are already recognized and acted +upon before the translation function is called: @table @code @item :skip N -Skip the first N lines of the table. Hlines do count as separate lines for -this parameter! +Skip the first N lines of the table. Hlines do count; include them if they +are to be skipped. @item :skipcols (n1 n2 ...) -List of columns that should be skipped. If the table has a column with -calculation marks, that column is automatically discarded as well. -Please note that the translator function sees the table @emph{after} the -removal of these columns, the function never knows that there have been -additional columns. - -@item :no-escape t -When non-@code{nil}, do not escape special characters @code{&%#_^} when exporting -the table. The default value is @code{nil}. +List of columns to be skipped. First Org automatically discards columns with +calculation marks and then sends the table to the translator function, which +then skips columns as specified in @samp{skipcols}. @end table @noindent -The one problem remaining is how to keep the source table in the buffer -without disturbing the normal workings of the file, for example during -compilation of a C file or processing of a @LaTeX{} file. There are a -number of different solutions: +To keep the source table intact in the buffer without being disturbed when +the source file is compiled or otherwise being worked on, use one of these +strategies: @itemize @bullet @item -The table could be placed in a block comment if that is supported by the -language. For example, in C mode you could wrap the table between -@samp{/*} and @samp{*/} lines. +Place the table in a block comment. For example, in C mode you could wrap +the table between @samp{/*} and @samp{*/} lines. @item -Sometimes it is possible to put the table after some kind of @i{END} -statement, for example @samp{\bye} in @TeX{} and @samp{\end@{document@}} -in @LaTeX{}. +Put the table after an @samp{END} statement. For example @samp{\bye} in +@TeX{} and @samp{\end@{document@}} in @LaTeX{}. @item -You can just comment the table line-by-line whenever you want to process -the file, and uncomment it whenever you need to edit the table. This -only sounds tedious---the command @kbd{M-x orgtbl-toggle-comment RET} -makes this comment-toggling very easy, in particular if you bind it to a -key. +Comment and uncomment each line of the table during edits. The @kbd{M-x +orgtbl-toggle-comment RET} command makes toggling easy. @end itemize -@node A @LaTeX{} example, Translator functions, Radio tables, Tables in arbitrary syntax +@node A @LaTeX{} example @subsection A @LaTeX{} example of radio tables @cindex @LaTeX{}, and Orgtbl mode -The best way to wrap the source table in @LaTeX{} is to use the -@code{comment} environment provided by @file{comment.sty}. It has to be -activated by placing @code{\usepackage@{comment@}} into the document -header. Orgtbl mode can insert a radio table skeleton@footnote{By -default this works only for @LaTeX{}, HTML, and Texinfo. Configure the -variable @code{orgtbl-radio-table-templates} to install templates for other -modes.} with the command @kbd{M-x orgtbl-insert-radio-table RET}. You will -be prompted for a table name, let's say we use @samp{salesfigures}. You -will then get the following template: +To wrap a source table in @LaTeX{}, use the @code{comment} environment +provided by @file{comment.sty}. To activate it, put +@code{\usepackage@{comment@}} in the document header. Orgtbl mode inserts a +radio table skeleton@footnote{By default this works only for @LaTeX{}, HTML, +and Texinfo. Configure the variable @code{orgtbl-radio-table-templates} to +install templates for other export formats.} with the command @kbd{M-x +orgtbl-insert-radio-table RET}, which prompts for a table name. For example, +if @samp{salesfigures} is the name, the template inserts: @cindex #+ORGTBL, SEND @example @@ -17284,17 +18169,17 @@ will then get the following template: @noindent @vindex @LaTeX{}-verbatim-environments -The @code{#+ORGTBL: SEND} line tells Orgtbl mode to use the function -@code{orgtbl-to-latex} to convert the table into @LaTeX{} and to put it -into the receiver location with name @code{salesfigures}. You may now -fill in the table---feel free to use the spreadsheet features@footnote{If -the @samp{#+TBLFM} line contains an odd number of dollar characters, -this may cause problems with font-lock in @LaTeX{} mode. As shown in the -example you can fix this by adding an extra line inside the -@code{comment} environment that is used to balance the dollar -expressions. If you are using AUC@TeX{} with the font-latex library, a -much better solution is to add the @code{comment} environment to the -variable @code{LaTeX-verbatim-environments}.}: +The line @code{#+ORGTBL: SEND} tells Orgtbl mode to use the function +@code{orgtbl-to-latex} to convert the table to @LaTeX{} format, then insert +the table at the target (receive) location named @code{salesfigures}. Now +the table is ready for data entry. It can even use spreadsheet +features@footnote{If the @samp{#+TBLFM} line contains an odd number of dollar +characters, this may cause problems with font-lock in @LaTeX{} mode. As +shown in the example you can fix this by adding an extra line inside the +@code{comment} environment that is used to balance the dollar expressions. +If you are using AUC@TeX{} with the font-latex library, a much better +solution is to add the @code{comment} environment to the variable +@code{LaTeX-verbatim-environments}.}: @example % BEGIN RECEIVE ORGTBL salesfigures @@ -17312,14 +18197,12 @@ variable @code{LaTeX-verbatim-environments}.}: @end example @noindent -When you are done, press @kbd{C-c C-c} in the table to get the converted -table inserted between the two marker lines. +After editing, @kbd{C-c C-c} inserts translated table at the target location, +between the two marker lines. -Now let's assume you want to make the table header by hand, because you -want to control how columns are aligned, etc. In this case we make sure -that the table translator skips the first 2 lines of the source -table, and tell the command to work as a @i{splice}, i.e., to not produce -header and footer commands of the target table: +For hand-made custom tables, note that the translator needs to skip the first +two lines of the source table. Also the command has to @emph{splice} out the +target table without the header and footer. @example \begin@{tabular@}@{lrrr@} @@ -17340,135 +18223,109 @@ Month & \multicolumn@{1@}@{c@}@{Days@} & Nr.\ sold & per day\\ @end example The @LaTeX{} translator function @code{orgtbl-to-latex} is already part of -Orgtbl mode. It uses a @code{tabular} environment to typeset the table -and marks horizontal lines with @code{\hline}. Furthermore, it -interprets the following parameters (see also @pxref{Translator functions}): +Orgtbl mode and uses @code{tabular} environment by default to typeset the +table and mark the horizontal lines with @code{\hline}. For additional +parameters to control output, @pxref{Translator functions}: @table @code @item :splice nil/t -When set to t, return only table body lines, don't wrap them into a -tabular environment. Default is @code{nil}. +When non-@code{nil}, returns only table body lines; not wrapped in tabular +environment. Default is @code{nil}. @item :fmt fmt -A format to be used to wrap each field, it should contain @code{%s} for the -original field value. For example, to wrap each field value in dollars, -you could use @code{:fmt "$%s$"}. This may also be a property list with +Format to warp each field. It should contain @code{%s} for the original +field value. For example, to wrap each field value in dollar symbol, you +could use @code{:fmt "$%s$"}. Format can also wrap a property list with column numbers and formats, for example @code{:fmt (2 "$%s$" 4 "%s\\%%")}. -A function of one argument can be used in place of the strings; the -function must return a formatted string. +In place of a string, a function of one argument can be used; the function +must return a formatted string. @item :efmt efmt -Use this format to print numbers with exponentials. The format should -have @code{%s} twice for inserting mantissa and exponent, for example -@code{"%s\\times10^@{%s@}"}. The default is @code{"%s\\,(%s)"}. This -may also be a property list with column numbers and formats, for example +Format numbers as exponentials. The spec should have @code{%s} twice for +inserting mantissa and exponent, for example @code{"%s\\times10^@{%s@}"}. +This may also be a property list with column numbers and formats, for example @code{:efmt (2 "$%s\\times10^@{%s@}$" 4 "$%s\\cdot10^@{%s@}$")}. After -@code{efmt} has been applied to a value, @code{fmt} will also be -applied. Similar to @code{fmt}, functions of two arguments can be -supplied instead of strings. +@code{efmt} has been applied to a value, @code{fmt} will also be applied. +Functions with two arguments can be supplied instead of strings. By default, +no special formatting is applied. @end table -@node Translator functions, Radio lists, A @LaTeX{} example, Tables in arbitrary syntax +@node Translator functions @subsection Translator functions @cindex HTML, and Orgtbl mode @cindex translator function -Orgtbl mode has several translator functions built-in: @code{orgtbl-to-csv} -(comma-separated values), @code{orgtbl-to-tsv} (TAB-separated values) -@code{orgtbl-to-latex}, @code{orgtbl-to-html}, and @code{orgtbl-to-texinfo}. -Except for @code{orgtbl-to-html}@footnote{The HTML translator uses the same -code that produces tables during HTML export.}, these all use a generic -translator, @code{orgtbl-to-generic}. For example, @code{orgtbl-to-latex} -itself is a very short function that computes the column definitions for the -@code{tabular} environment, defines a few field and line separators and then -hands processing over to the generic translator. Here is the entire code: - -@lisp -@group -(defun orgtbl-to-latex (table params) - "Convert the Orgtbl mode TABLE to LaTeX." - (let* ((alignment (mapconcat (lambda (x) (if x "r" "l")) - org-table-last-alignment "")) - (params2 - (list - :tstart (concat "\\begin@{tabular@}@{" alignment "@}") - :tend "\\end@{tabular@}" - :lstart "" :lend " \\\\" :sep " & " - :efmt "%s\\,(%s)" :hline "\\hline"))) - (orgtbl-to-generic table (org-combine-plists params2 params)))) -@end group -@end lisp +Orgtbl mode has built-in translator functions: @code{orgtbl-to-csv} +(comma-separated values), @code{orgtbl-to-tsv} (TAB-separated values), +@code{orgtbl-to-latex}, @code{orgtbl-to-html}, @code{orgtbl-to-texinfo}, +@code{orgtbl-to-unicode} and @code{orgtbl-to-orgtbl}. They use the generic +translator, @code{orgtbl-to-generic}, which delegates translations to various +export back-ends. -As you can see, the properties passed into the function (variable -@var{PARAMS}) are combined with the ones newly defined in the function -(variable @var{PARAMS2}). The ones passed into the function (i.e., the -ones set by the @samp{ORGTBL SEND} line) take precedence. So if you -would like to use the @LaTeX{} translator, but wanted the line endings to -be @samp{\\[2mm]} instead of the default @samp{\\}, you could just -overrule the default with +Properties passed to the function through the @samp{ORGTBL SEND} line take +precedence over properties defined inside the function. For example, this +overrides the default @LaTeX{} line endings, @samp{\\}, with @samp{\\[2mm]}: @example #+ORGTBL: SEND test orgtbl-to-latex :lend " \\\\[2mm]" @end example -For a new language, you can either write your own converter function in -analogy with the @LaTeX{} translator, or you can use the generic function -directly. For example, if you have a language where a table is started -with @samp{!BTBL!}, ended with @samp{!ETBL!}, and where table lines are -started with @samp{!BL!}, ended with @samp{!EL!}, and where the field -separator is a TAB, you could call the generic translator like this (on -a single line!): +For a new language translator, define a converter function. It can be a +generic function, such as shown in this example. It marks a beginning and +ending of a table with @samp{!BTBL!} and @samp{!ETBL!}; a beginning and +ending of lines with @samp{!BL!} and @samp{!EL!}; and uses a TAB for a field +separator: -@example -#+ORGTBL: SEND test orgtbl-to-generic :tstart "!BTBL!" :tend "!ETBL!" - :lstart "!BL! " :lend " !EL!" :sep "\t" -@end example +@lisp +(defun orgtbl-to-language (table params) + "Convert the orgtbl-mode TABLE to language." + (orgtbl-to-generic + table + (org-combine-plists + '(:tstart "!BTBL!" :tend "!ETBL!" :lstart "!BL!" :lend "!EL!" :sep "\t") + params))) +@end lisp @noindent -Please check the documentation string of the function -@code{orgtbl-to-generic} for a full list of parameters understood by -that function, and remember that you can pass each of them into +The documentation for the @code{orgtbl-to-generic} function shows a complete +list of parameters, each of which can be passed through to @code{orgtbl-to-latex}, @code{orgtbl-to-texinfo}, and any other function -using the generic function. - -Of course you can also write a completely new function doing complicated -things the generic translator cannot do. A translator function takes -two arguments. The first argument is the table, a list of lines, each -line either the symbol @code{hline} or a list of fields. The second -argument is the property list containing all parameters specified in the -@samp{#+ORGTBL: SEND} line. The function must return a single string -containing the formatted table. If you write a generally useful -translator, please post it on @email{emacs-orgmode@@gnu.org} so that -others can benefit from your work. - -@node Radio lists, , Translator functions, Tables in arbitrary syntax +using that generic function. + +For complicated translations the generic translator function could be +replaced by a custom translator function. Such a custom function must take +two arguments and return a single string containing the formatted table. The +first argument is the table whose lines are a list of fields or the symbol +@code{hline}. The second argument is the property list consisting of +parameters specified in the @samp{#+ORGTBL: SEND} line. Please share your +translator functions by posting them to the Org users mailing list, +@email{emacs-orgmode@@gnu.org}. + +@node Radio lists @subsection Radio lists @cindex radio lists @cindex org-list-insert-radio-list -Sending and receiving radio lists works exactly the same way as sending and -receiving radio tables (@pxref{Radio tables}). As for radio tables, you can -insert radio list templates in HTML, @LaTeX{} and Texinfo modes by calling -@code{org-list-insert-radio-list}. - -Here are the differences with radio tables: +Call the @code{org-list-insert-radio-list} function to insert a radio list +template in HTML, @LaTeX{}, and Texinfo mode documents. Sending and +receiving radio lists works is the same as for radio tables (@pxref{Radio +tables}) except for these differences: +@cindex #+ORGLST @itemize @minus @item Orgstruct mode must be active. @item -Use the @code{ORGLST} keyword instead of @code{ORGTBL}. +Use @code{ORGLST} keyword instead of @code{ORGTBL}. @item -The available translation functions for radio lists don't take -parameters. -@item -@kbd{C-c C-c} will work when pressed on the first item of the list. +@kbd{C-c C-c} works only on the first list item. @end itemize -Here is a @LaTeX{} example. Let's say that you have this in your -@LaTeX{} file: +Built-in translators functions are: @code{org-list-to-latex}, +@code{org-list-to-html} and @code{org-list-to-texinfo}. They use the +@code{org-list-to-generic} translator function. See its documentation for +parameters for accurate customizations of lists. Here is a @LaTeX{} example: -@cindex #+ORGLST @example % BEGIN RECEIVE ORGLST to-buy % END RECEIVE ORGLST to-buy @@ -17482,21 +18339,21 @@ Here is a @LaTeX{} example. Let's say that you have this in your \end@{comment@} @end example -Pressing @kbd{C-c C-c} on @code{a new house} and will insert the converted -@LaTeX{} list between the two marker lines. +@kbd{C-c C-c} on @samp{a new house} inserts the translated @LaTeX{} list +in-between the BEGIN and END marker lines. -@node Dynamic blocks, Special agenda views, Tables in arbitrary syntax, Hacking +@node Dynamic blocks @section Dynamic blocks @cindex dynamic blocks -Org documents can contain @emph{dynamic blocks}. These are -specially marked regions that are updated by some user-written function. -A good example for such a block is the clock table inserted by the -command @kbd{C-c C-x C-r} (@pxref{Clocking work time}). +Org supports @emph{dynamic blocks} in Org documents. They are inserted with +begin and end markers like any other @samp{src} code block, but the contents +are updated automatically by a user function. For example, @kbd{C-c C-x C-r} +inserts a dynamic table that updates the work time (@pxref{Clocking work +time}). -Dynamic blocks are enclosed by a BEGIN-END structure that assigns a name -to the block and can also specify parameters for the function producing -the content of the block. +Dynamic blocks can have names and function parameters. The syntax is similar +to @samp{src} code block specifications: @cindex #+BEGIN:dynamic block @example @@ -17505,7 +18362,7 @@ the content of the block. #+END: @end example -Dynamic blocks are updated with the following commands +These command update dynamic blocks: @table @kbd @orgcmd{C-c C-x C-u,org-dblock-update} @@ -17514,17 +18371,16 @@ Update dynamic block at point. Update all dynamic blocks in the current file. @end table -Updating a dynamic block means to remove all the text between BEGIN and -END, parse the BEGIN line for parameters and then call the specific -writer function for this block to insert the new content. If you want -to use the original content in the writer function, you can use the -extra parameter @code{:content}. +Before updating a dynamic block, Org removes content between the BEGIN and +END markers. Org then reads the parameters on the BEGIN line for passing to +the writer function. If the function expects to access the removed content, +then Org expects an extra parameter, @code{:content}, on the BEGIN line. -For a block with name @code{myblock}, the writer function is -@code{org-dblock-write:myblock} with as only parameter a property list -with the parameters given in the begin line. Here is a trivial example -of a block that keeps track of when the block update function was last -run: +To syntax for calling a writer function with a named block, @code{myblock} +is: @code{org-dblock-write:myblock}. Parameters come from the BEGIN line. + +The following is an example of a dynamic block and a block writer function +that updates the time when the function was last run: @example #+BEGIN: block-update-time :format "on %m/%d/%Y at %H:%M" @@ -17533,7 +18389,7 @@ run: @end example @noindent -The corresponding block writer function could look like this: +The dynamic block's writer function: @lisp (defun org-dblock-write:block-update-time (params) @@ -17542,47 +18398,40 @@ The corresponding block writer function could look like this: (format-time-string fmt)))) @end lisp -If you want to make sure that all dynamic blocks are always up-to-date, -you could add the function @code{org-update-all-dblocks} to a hook, for -example @code{before-save-hook}. @code{org-update-all-dblocks} is -written in a way such that it does nothing in buffers that are not in -@code{org-mode}. +To keep dynamic blocks up-to-date in an Org file, use the function, +@code{org-update-all-dblocks} in hook, such as @code{before-save-hook}. The +@code{org-update-all-dblocks} function does not run if the file is not in +Org mode. -You can narrow the current buffer to the current dynamic block (like any -other block) with @code{org-narrow-to-block}. +Dynamic blocks, like any other block, can be narrowed with +@code{org-narrow-to-block}. -@node Special agenda views, Speeding up your agendas, Dynamic blocks, Hacking +@node Special agenda views @section Special agenda views @cindex agenda views, user-defined @vindex org-agenda-skip-function @vindex org-agenda-skip-function-global -Org provides a special hook that can be used to narrow down the selection -made by these agenda views: @code{agenda}, @code{agenda*}@footnote{The -@code{agenda*} view is the same than @code{agenda} except that it only -considers @emph{appointments}, i.e., scheduled and deadline items that have a -time specification @code{[h]h:mm} in their time-stamps.}, @code{todo}, -@code{alltodo}, @code{tags}, @code{tags-todo}, @code{tags-tree}. You may -specify a function that is used at each match to verify if the match should -indeed be part of the agenda view, and if not, how much should be skipped. -You can specify a global condition that will be applied to all agenda views, -this condition would be stored in the variable -@code{org-agenda-skip-function-global}. More commonly, such a definition is -applied only to specific custom searches, using -@code{org-agenda-skip-function}. - -Let's say you want to produce a list of projects that contain a WAITING -tag anywhere in the project tree. Let's further assume that you have -marked all tree headings that define a project with the TODO keyword -PROJECT@. In this case you would run a TODO search for the keyword -PROJECT, but skip the match unless there is a WAITING tag anywhere in -the subtree belonging to the project line. - -To achieve this, you must write a function that searches the subtree for -the tag. If the tag is found, the function must return @code{nil} to -indicate that this match should not be skipped. If there is no such -tag, return the location of the end of the subtree, to indicate that -search should continue from there. +Org provides a special hook to further limit items in agenda views: +@code{agenda}, @code{agenda*}@footnote{The @code{agenda*} view is the same as +@code{agenda} except that it only considers @emph{appointments}, i.e., +scheduled and deadline items that have a time specification @samp{[h]h:mm} in +their time-stamps.}, @code{todo}, @code{alltodo}, @code{tags}, +@code{tags-todo}, @code{tags-tree}. Specify a custom function that tests +inclusion of every matched item in the view. This function can also +skip as much as is needed. + +For a global condition applicable to agenda views, use the +@code{org-agenda-skip-function-global} variable. Org uses a global condition +with @code{org-agenda-skip-function} for custom searching. + +This example defines a function for a custom view showing TODO items with +WAITING status. Manually this is a multi step search process, but with a +custom view, this can be automated as follows: + +The custom function searches the subtree for the WAITING tag and returns +@code{nil} on match. Otherwise it gives the location from where the search +continues. @lisp (defun my-skip-unless-waiting () @@ -17593,8 +18442,7 @@ search should continue from there. subtree-end))) ; tag not found, continue after end of subtree @end lisp -Now you may use this function in an agenda custom command, for example -like this: +To use this custom function in a custom agenda command: @lisp (org-add-agenda-custom-command @@ -17604,22 +18452,20 @@ like this: @end lisp @vindex org-agenda-overriding-header -Note that this also binds @code{org-agenda-overriding-header} to get a -meaningful header in the agenda view. +Note that this also binds @code{org-agenda-overriding-header} to a more +meaningful string suitable for the agenda view. @vindex org-odd-levels-only @vindex org-agenda-skip-function -A general way to create custom searches is to base them on a search for -entries with a certain level limit. If you want to study all entries with -your custom search function, simply do a search for -@samp{LEVEL>0}@footnote{Note that, when using @code{org-odd-levels-only}, a -level number corresponds to order in the hierarchy, not to the number of -stars.}, and then use @code{org-agenda-skip-function} to select the entries -you really want to have. - -You may also put a Lisp form into @code{org-agenda-skip-function}. In -particular, you may use the functions @code{org-agenda-skip-entry-if} -and @code{org-agenda-skip-subtree-if} in this form, for example: + +Search for entries with a limit set on levels for the custom search. This is +a general approach to creating custom searches in Org. To include all +levels, use @samp{LEVEL>0}@footnote{Note that, for +@code{org-odd-levels-only}, a level number corresponds to order in the +hierarchy, not to the number of stars.}. Then to selectively pick the +matched entries, use @code{org-agenda-skip-function}, which also accepts Lisp +forms, such as @code{org-agenda-skip-entry-if} and +@code{org-agenda-skip-subtree-if}. For example: @table @code @item (org-agenda-skip-entry-if 'scheduled) @@ -17645,8 +18491,8 @@ Skip current entry unless the regular expression matches. Same as above, but check and skip the entire subtree. @end table -Therefore we could also have written the search for WAITING projects -like this, even without defining a special function: +The following is an example of a search for @samp{WAITING} without the +special function: @lisp (org-add-agenda-custom-command @@ -17656,72 +18502,71 @@ like this, even without defining a special function: (org-agenda-overriding-header "Projects waiting for something: ")))) @end lisp -@node Speeding up your agendas, Extracting agenda information, Special agenda views, Hacking +@node Speeding up your agendas @section Speeding up your agendas @cindex agenda views, optimization -When your Org files grow in both number and size, agenda commands may start -to become slow. Below are some tips on how to speed up the agenda commands. +Some agenda commands slow down when the Org files grow in size or number. +Here are tips to speed up: @enumerate @item -Reduce the number of Org agenda files: this will reduce the slowness caused -by accessing a hard drive. +Reduce the number of Org agenda files to avoid slowdowns due to hard drive +accesses. @item -Reduce the number of DONE and archived headlines: this way the agenda does -not need to skip them. +Reduce the number of @samp{DONE} and archived headlines so agenda operations +that skip over these can finish faster. @item @vindex org-agenda-dim-blocked-tasks -Inhibit the dimming of blocked tasks: +Do not dim blocked tasks: @lisp (setq org-agenda-dim-blocked-tasks nil) @end lisp @item @vindex org-startup-folded @vindex org-agenda-inhibit-startup -Inhibit agenda files startup options: +Stop preparing agenda buffers on startup: @lisp (setq org-agenda-inhibit-startup nil) @end lisp @item @vindex org-agenda-show-inherited-tags @vindex org-agenda-use-tag-inheritance -Disable tag inheritance in agenda: +Disable tag inheritance for agendas: @lisp (setq org-agenda-use-tag-inheritance nil) @end lisp @end enumerate -You can set these options for specific agenda views only. See the docstrings -of these variables for details on why they affect the agenda generation, and -this @uref{http://orgmode.org/worg/agenda-optimization.html, dedicated Worg -page} for further explanations. +These options can be applied to selected agenda views. For more details +about generation of agenda views, see the docstrings for the relevant +variables, and this @uref{http://orgmode.org/worg/agenda-optimization.html, +dedicated Worg page} for agenda optimization. -@node Extracting agenda information, Using the property API, Speeding up your agendas, Hacking +@node Extracting agenda information @section Extracting agenda information @cindex agenda, pipe @cindex Scripts, for agenda processing @vindex org-agenda-custom-commands -Org provides commands to access agenda information for the command -line in Emacs batch mode. This extracted information can be sent -directly to a printer, or it can be read by a program that does further -processing of the data. The first of these commands is the function -@code{org-batch-agenda}, that produces an agenda view and sends it as -ASCII text to STDOUT@. The command takes a single string as parameter. -If the string has length 1, it is used as a key to one of the commands -you have configured in @code{org-agenda-custom-commands}, basically any -key you can use after @kbd{C-c a}. For example, to directly print the -current TODO list, you could use +Org provides commands to access agendas through Emacs batch mode. Through +this command-line interface, agendas are automated for further processing or +printing. + +@code{org-batch-agenda} creates an agenda view in ASCII and outputs to +STDOUT. This command takes one string parameter. When string length=1, Org +uses it as a key to @code{org-agenda-custom-commands}. These are the same +ones available through @kbd{C-c a}. + +This example command line directly prints the TODO list to the printer: @example emacs -batch -l ~/.emacs -eval '(org-batch-agenda "t")' | lpr @end example -If the parameter is a string with 2 or more characters, it is used as a -tags/TODO match string. For example, to print your local shopping list -(all items with the tag @samp{shop}, but excluding the tag -@samp{NewYork}), you could use +When the string parameter length is two or more characters, Org matches it +with tags/TODO strings. For example, this example command line prints items +tagged with @samp{shop}, but excludes items tagged with @samp{NewYork}: @example emacs -batch -l ~/.emacs \ @@ -17729,7 +18574,7 @@ emacs -batch -l ~/.emacs \ @end example @noindent -You may also modify parameters on the fly like this: +An example showing on-the-fly parameter modifications: @example emacs -batch -l ~/.emacs \ @@ -17741,14 +18586,11 @@ emacs -batch -l ~/.emacs \ @end example @noindent -which will produce a 30-day agenda, fully restricted to the Org file -@file{~/org/projects.org}, not even including the diary. +which will produce an agenda for the next 30 days from just the +@file{~/org/projects.org} file. -If you want to process the agenda data in more sophisticated ways, you -can use the command @code{org-batch-agenda-csv} to get a comma-separated -list of values for each agenda item. Each line in the output will -contain a number of fields separated by commas. The fields in a line -are: +For structured processing of agenda output, use @code{org-batch-agenda-csv} +with the following fields: @example category @r{The category of the item} @@ -17774,12 +18616,15 @@ priority-n @r{The computed numerical priority} @end example @noindent -Time and date will only be given if a timestamp (or deadline/scheduled) -led to the selection of the item. +If the selection of the agenda item was based on a timestamp, including those +items with @samp{DEADLINE} and @samp{SCHEDULED} keywords, then Org includes +date and time in the output. -A CSV list like this is very easy to use in a post-processing script. -For example, here is a Perl program that gets the TODO list from -Emacs/Org and prints all the items, preceded by a checkbox: +If the selection of the agenda item was based on a timestamp (or +deadline/scheduled), then Org includes date and time in the output. + +Here is an example of a post-processing script in Perl. It takes the CSV +output from Emacs and prints with a checkbox: @example #!/usr/bin/perl @@ -17800,13 +18645,12 @@ foreach $line (split(/\n/,$agenda)) @{ @} @end example -@node Using the property API, Using the mapping API, Extracting agenda information, Hacking +@node Using the property API @section Using the property API @cindex API, for properties @cindex properties, API -Here is a description of the functions that can be used to work with -properties. +Functions for working with properties. @defun org-entry-properties &optional pom which Get all properties of the entry at point-or-marker POM.@* @@ -17818,14 +18662,15 @@ POM may also be @code{nil}, in which case the current entry is used. If WHICH is @code{nil} or @code{all}, get all properties. If WHICH is @code{special} or @code{standard}, only get that subclass. @end defun + @vindex org-use-property-inheritance @findex org-insert-property-drawer @defun org-entry-get pom property &optional inherit -Get value of @code{PROPERTY} for entry at point-or-marker @code{POM}@. By default, -this only looks at properties defined locally in the entry. If @code{INHERIT} -is non-@code{nil} and the entry does not have the property, then also check -higher levels of the hierarchy. If @code{INHERIT} is the symbol -@code{selective}, use inheritance if and only if the setting of +Get value of @code{PROPERTY} for entry at point-or-marker @code{POM}@. By +default, this only looks at properties defined locally in the entry. If +@code{INHERIT} is non-@code{nil} and the entry does not have the property, +then also check higher levels of the hierarchy. If @code{INHERIT} is the +symbol @code{selective}, use inheritance if and only if the setting of @code{org-use-property-inheritance} selects @code{PROPERTY} for inheritance. @end defun @@ -17842,7 +18687,7 @@ Get all property keys in the current buffer. @end defun @defun org-insert-property-drawer -Insert a property drawer for the current entry. Also +Insert a property drawer for the current entry. @end defun @defun org-entry-put-multivalued-property pom property &rest values @@ -17880,41 +18725,37 @@ to be entered. The functions must return @code{nil} if they are not responsible for this property. @end defopt -@node Using the mapping API, , Using the property API, Hacking +@node Using the mapping API @section Using the mapping API @cindex API, for mapping @cindex mapping entries, API -Org has sophisticated mapping capabilities to find all entries satisfying -certain criteria. Internally, this functionality is used to produce agenda -views, but there is also an API that can be used to execute arbitrary -functions for each or selected entries. The main entry point for this API -is: +Org has sophisticated mapping capabilities for finding entries. Org uses +this functionality internally for generating agenda views. Org also exposes +an API for executing arbitrary functions for each selected entry. The API's +main entry point is: @defun org-map-entries func &optional match scope &rest skip -Call @code{FUNC} at each headline selected by @code{MATCH} in @code{SCOPE}. +Call @samp{FUNC} at each headline selected by @code{MATCH} in @code{SCOPE}. -@code{FUNC} is a function or a Lisp form. The function will be called -without arguments, with the cursor positioned at the beginning of the -headline. The return values of all calls to the function will be collected -and returned as a list. +@samp{FUNC} is a function or a Lisp form. With the cursor positioned at the +beginning of the headline, call the function without arguments. Org returns +an alist of return values of calls to the function. -The call to @code{FUNC} will be wrapped into a save-excursion form, so -@code{FUNC} does not need to preserve point. After evaluation, the cursor -will be moved to the end of the line (presumably of the headline of the -processed entry) and search continues from there. Under some circumstances, -this may not produce the wanted results. For example, if you have removed -(e.g., archived) the current (sub)tree it could mean that the next entry will -be skipped entirely. In such cases, you can specify the position from where -search should continue by making @code{FUNC} set the variable -@code{org-map-continue-from} to the desired buffer position. +To avoid preserving point, Org wraps the call to @code{FUNC} in +save-excursion form. After evaluation, Org moves the cursor to the end of +the line that was just processed. Search continues from that point forward. +This may not always work as expected under some conditions, such as if the +current sub-tree was removed by a previous archiving operation. In such rare +circumstances, Org skips the next entry entirely when it should not. To stop +Org from such skips, make @samp{FUNC} set the variable +@code{org-map-continue-from} to a specific buffer position. -@code{MATCH} is a tags/property/todo match as it is used in the agenda match -view. Only headlines that are matched by this query will be considered -during the iteration. When @code{MATCH} is @code{nil} or @code{t}, all -headlines will be visited by the iteration. +@samp{MATCH} is a tags/property/TODO match. Org iterates only matched +headlines. Org iterates over all headlines when @code{MATCH} is @code{nil} +or @code{t}. -@code{SCOPE} determines the scope of this command. It can be any of: +@samp{SCOPE} determines the scope of this command. It can be any of: @example nil @r{the current buffer, respecting the restriction if any} @@ -17930,8 +18771,8 @@ agenda-with-archives @r{if this is a list, all files in the list will be scanned} @end example @noindent -The remaining args are treated as settings for the skipping facilities of -the scanner. The following items can be given here: +The remaining args are treated as settings for the scanner's skipping +facilities. Valid args are: @vindex org-agenda-skip-function @example @@ -17945,10 +18786,9 @@ function or Lisp form @end example @end defun -The function given to that mapping routine can really do anything you like. -It can use the property API (@pxref{Using the property API}) to gather more -information about the entry, or in order to change metadata in the entry. -Here are a couple of functions that might be handy: +The mapping routine can call any arbitrary function, even functions that +change meta data or query the property API (@pxref{Using the property API}). +Here are some handy functions: @defun org-todo &optional arg Change the TODO state of the entry. See the docstring of the functions for @@ -17974,9 +18814,9 @@ Promote the current entry. Demote the current entry. @end defun -Here is a simple example that will turn all entries in the current file with -a tag @code{TOMORROW} into TODO entries with the keyword @code{UPCOMING}. -Entries in comment trees and in archive trees will be ignored. +This example turns all entries tagged with @code{TOMORROW} into TODO entries +with keyword @code{UPCOMING}. Org ignores entries in comment trees and +archive trees. @lisp (org-map-entries @@ -17991,105 +18831,103 @@ The following example counts the number of entries with TODO keyword (length (org-map-entries t "/+WAITING" 'agenda)) @end lisp -@node MobileOrg, History and Acknowledgments, Hacking, Top +@node MobileOrg @appendix MobileOrg @cindex iPhone @cindex MobileOrg -@i{MobileOrg} is the name of the mobile companion app for Org mode, currently -available for iOS and for Android. @i{MobileOrg} offers offline viewing and -capture support for an Org mode system rooted on a ``real'' computer. It -does also allow you to record changes to existing entries. The -@uref{https://github.com/MobileOrg/, iOS implementation} for the -@i{iPhone/iPod Touch/iPad} series of devices, was started by Richard Moreland -and is now in the hands Sean Escriva. Android users should check out -@uref{http://wiki.github.com/matburt/mobileorg-android/, MobileOrg Android} -by Matt Jones. The two implementations are not identical but offer similar -features. - -This appendix describes the support Org has for creating agenda views in a -format that can be displayed by @i{MobileOrg}, and for integrating notes -captured and changes made by @i{MobileOrg} into the main system. - -For changing tags and TODO states in MobileOrg, you should have set up the -customization variables @code{org-todo-keywords} and @code{org-tag-alist} to -cover all important tags and TODO keywords, even if individual files use only -part of these. MobileOrg will also offer you states and tags set up with -in-buffer settings, but it will understand the logistics of TODO state -@i{sets} (@pxref{Per-file keywords}) and @i{mutually exclusive} tags +MobileOrg is a companion mobile app that runs on iOS and Android devices. +MobileOrg enables offline-views and capture support for an Org mode system +that is rooted on a ``real'' computer. MobileOrg can record changes to +existing entries. + +The @uref{https://github.com/MobileOrg/, iOS implementation} for the +@emph{iPhone/iPod Touch/iPad} series of devices, was started by Richard +Moreland and is now in the hands Sean Escriva. Android users should check +out @uref{http://wiki.github.com/matburt/mobileorg-android/, MobileOrg +Android} by Matt Jones. Though the two implementations are not identical, +they offer similar features. + +This appendix describes Org's support for agenda view formats compatible with +MobileOrg. It also describes synchronizing changes, such as to notes, +between MobileOrg and the computer. + +To change tags and TODO states in MobileOrg, first customize the variables +@code{org-todo-keywords} and @code{org-tag-alist}. These should cover all +the important tags and TODO keywords, even if Org files use only some of +them. Though MobileOrg has in-buffer settings, it understands TODO states +@emph{sets} (@pxref{Per-file keywords}) and @emph{mutually exclusive} tags (@pxref{Setting tags}) only for those set in these variables. @menu -* Setting up the staging area:: Where to interact with the mobile device +* Setting up the staging area:: For the mobile device * Pushing to MobileOrg:: Uploading Org files and agendas * Pulling from MobileOrg:: Integrating captured and flagged items @end menu -@node Setting up the staging area, Pushing to MobileOrg, MobileOrg, MobileOrg +@node Setting up the staging area @section Setting up the staging area -MobileOrg needs to interact with Emacs through a directory on a server. If you -are using a public server, you should consider to encrypt the files that are -uploaded to the server. This can be done with Org mode 7.02 and with -@i{MobileOrg 1.5} (iPhone version), and you need an @file{openssl} -installation on your system. To turn on encryption, set a password in -@i{MobileOrg} and, on the Emacs side, configure the variable -@code{org-mobile-use-encryption}@footnote{If you can safely store the -password in your Emacs setup, you might also want to configure -@code{org-mobile-encryption-password}. Please read the docstring of that -variable. Note that encryption will apply only to the contents of the -@file{.org} files. The file names themselves will remain visible.}. - -The easiest way to create that directory is to use a free -@uref{http://dropbox.com,Dropbox.com} account@footnote{If you cannot use -Dropbox, or if your version of MobileOrg does not support it, you can use a -webdav server. For more information, check out the documentation of MobileOrg and also this +MobileOrg needs access to a file directory on a server to interact with +Emacs. With a public server, consider encrypting the files. MobileOrg +version 1.5 supports encryption for the iPhone. Org also requires +@file{openssl} installed on the local computer. To turn on encryption, set +the same password in MobileOrg and in Emacs. Set the password in the +variable @code{org-mobile-use-encryption}@footnote{If Emacs is configured for +safe storing of passwords, then configure the variable, +@code{org-mobile-encryption-password}; please read the docstring of that +variable.}. Note that even after MobileOrg encrypts the file contents, the +file names will remain visible on the file systems of the local computer, the +server, and the mobile device. + +For a server to host files, consider options like +@uref{http://dropbox.com,Dropbox.com} account@footnote{An alternative is to +use webdav server. MobileOrg documentation has details of webdav server +configuration. Additional help is at @uref{http://orgmode.org/worg/org-faq.html#mobileorg_webdav, FAQ entry}.}. -When MobileOrg first connects to your Dropbox, it will create a directory -@i{MobileOrg} inside the Dropbox. After the directory has been created, tell -Emacs about it: +On first connection, MobileOrg creates a directory @file{MobileOrg/} on +Dropbox. Pass its location to Emacs through an init file variable as +follows: @lisp (setq org-mobile-directory "~/Dropbox/MobileOrg") @end lisp -Org mode has commands to put files for @i{MobileOrg} into that directory, -and to read captured notes from there. +Org copies files to the above directory for MobileOrg. Org also uses the +same directory for sharing notes between Org and MobileOrg. -@node Pushing to MobileOrg, Pulling from MobileOrg, Setting up the staging area, MobileOrg +@node Pushing to MobileOrg @section Pushing to MobileOrg -This operation copies all files currently listed in @code{org-mobile-files} -to the directory @code{org-mobile-directory}. By default this list contains -all agenda files (as listed in @code{org-agenda-files}), but additional files -can be included by customizing @code{org-mobile-files}. File names will be -staged with paths relative to @code{org-directory}, so all files should be -inside this directory@footnote{Symbolic links in @code{org-directory} need to -have the same name than their targets.}. - -The push operation also creates a special Org file @file{agendas.org} with -all custom agenda view defined by the user@footnote{While creating the -agendas, Org mode will force ID properties on all referenced entries, so that -these entries can be uniquely identified if @i{MobileOrg} flags them for -further action. If you do not want to get these properties in so many -entries, you can set the variable @code{org-mobile-force-id-on-agenda-items} -to @code{nil}. Org mode will then rely on outline paths, in the hope that -these will be unique enough.}. - -Finally, Org writes the file @file{index.org}, containing links to all other -files. @i{MobileOrg} first reads this file from the server, and then -downloads all agendas and Org files listed in it. To speed up the download, -MobileOrg will only read files whose checksums@footnote{Checksums are stored -automatically in the file @file{checksums.dat}} have changed. - -@node Pulling from MobileOrg, , Pushing to MobileOrg, MobileOrg +Org pushes files listed in @code{org-mobile-files} to +@code{org-mobile-directory}. Files include agenda files (as listed in +@code{org-agenda-files}). Customize @code{org-mobile-files} to add other +files. File names will be staged with paths relative to +@code{org-directory}, so all files should be inside this +directory@footnote{Symbolic links in @code{org-directory} should have the +same name as their targets.}. + +Push creates a special Org file @file{agendas.org} with custom agenda views +defined by the user@footnote{While creating the agendas, Org mode will force +ID properties on all referenced entries, so that these entries can be +uniquely identified if MobileOrg flags them for further action. To avoid +setting properties configure the variable +@code{org-mobile-force-id-on-agenda-items} to @code{nil}. Org mode will then +rely on outline paths, assuming they are unique.}. + +Org writes the file @file{index.org}, containing links to other files. +MobileOrg reads this file first from the server to determine what other files +to download for agendas. For faster downloads, MobileOrg will read only +those files whose checksums@footnote{Checksums are stored automatically in +the file @file{checksums.dat}.} have changed. + +@node Pulling from MobileOrg @section Pulling from MobileOrg -When @i{MobileOrg} synchronizes with the server, it not only pulls the Org -files for viewing. It also appends captured entries and pointers to flagged -and changed entries to the file @file{mobileorg.org} on the server. Org has -a @emph{pull} operation that integrates this information into an inbox file -and operates on the pointers to flagged entries. Here is how it works: +When MobileOrg synchronizes with the server, it pulls the Org files for +viewing. It then appends to the file @file{mobileorg.org} on the server the +captured entries, pointers to flagged and changed entries. Org integrates +its data in an inbox file format. @enumerate @item @@ -18097,46 +18935,37 @@ Org moves all entries found in @file{mobileorg.org}@footnote{@file{mobileorg.org} will be empty after this operation.} and appends them to the file pointed to by the variable @code{org-mobile-inbox-for-pull}. Each captured entry and each editing event -will be a top-level entry in the inbox file. +is a top-level entry in the inbox file. @item -After moving the entries, Org will attempt to implement the changes made in -@i{MobileOrg}. Some changes are applied directly and without user -interaction. Examples are all changes to tags, TODO state, headline and body -text that can be cleanly applied. Entries that have been flagged for further -action will receive a tag @code{:FLAGGED:}, so that they can be easily found -again. When there is a problem finding an entry or applying the change, the -pointer entry will remain in the inbox and will be marked with an error -message. You need to later resolve these issues by hand. +After moving the entries, Org attempts changes to MobileOrg. Some changes +are applied directly and without user interaction. Examples include changes +to tags, TODO state, headline and body text. Entries for further action are +tagged as @code{:FLAGGED:}. Org marks entries with problems with an error +message in the inbox. They have to be resolved manually. @item -Org will then generate an agenda view with all flagged entries. The user -should then go through these entries and do whatever actions are necessary. -If a note has been stored while flagging an entry in @i{MobileOrg}, that note -will be displayed in the echo area when the cursor is on the corresponding -agenda line. +Org generates an agenda view for flagged entries for user intervention to +clean up. For notes stored in flagged entries, MobileOrg displays them in +the echo area when the cursor is on the corresponding agenda item. @table @kbd @kindex ? @item ? -Pressing @kbd{?} in that special agenda will display the full flagging note in -another window and also push it onto the kill ring. So you could use @kbd{? -z C-y C-c C-c} to store that flagging note as a normal note in the entry. -Pressing @kbd{?} twice in succession will offer to remove the -@code{:FLAGGED:} tag along with the recorded flagging note (which is stored -in a property). In this way you indicate that the intended processing for -this flagged entry is finished. +Pressing @kbd{?} displays the entire flagged note in another window. Org +also pushes it to the kill ring. To store flagged note as a normal note, use +@kbd{? z C-y C-c C-c}. Pressing @kbd{?} twice does these things: first it +removes the @code{:FLAGGED:} tag; second, it removes the flagged note from +the property drawer; third, it signals that manual editing of the flagged +entry is now finished. @end table @end enumerate @kindex C-c a ? -If you are not able to process all flagged entries directly, you can always -return to this agenda view@footnote{Note, however, that there is a subtle -difference. The view created automatically by @kbd{M-x org-mobile-pull RET} -is guaranteed to search all files that have been addressed by the last pull. -This might include a file that is not currently in your list of agenda files. -If you later use @kbd{C-c a ?} to regenerate the view, only the current -agenda files will be searched.} using @kbd{C-c a ?}. - -@node History and Acknowledgments, GNU Free Documentation License, MobileOrg, Top +@kbd{C-c a ?} returns to the agenda view to finish processing flagged +entries. Note that these entries may not be the most recent since MobileOrg +searches files that were last pulled. To get an updated agenda view with +changes since the last pull, pull again. + +@node History and acknowledgments @appendix History and acknowledgments @cindex acknowledgments @cindex history @@ -18148,17 +18977,17 @@ Org was born in 2003, out of frustration over the user interface of the Emacs Outline mode. I was trying to organize my notes and projects, and using Emacs seemed to be the natural way to go. However, having to remember eleven different commands with two or three keys per command, only to hide and show -parts of the outline tree, that seemed entirely unacceptable to me. Also, -when using outlines to take notes, I constantly wanted to restructure the -tree, organizing it parallel to my thoughts and plans. @emph{Visibility -cycling} and @emph{structure editing} were originally implemented in the -package @file{outline-magic.el}, but quickly moved to the more general -@file{org.el}. As this environment became comfortable for project planning, -the next step was adding @emph{TODO entries}, basic @emph{timestamps}, and -@emph{table support}. These areas highlighted the two main goals that Org -still has today: to be a new, outline-based, plain text mode with innovative -and intuitive editing features, and to incorporate project planning -functionality directly into a notes file. +parts of the outline tree, that seemed entirely unacceptable. Also, when +using outlines to take notes, I constantly wanted to restructure the tree, +organizing it paralleling my thoughts and plans. @emph{Visibility cycling} +and @emph{structure editing} were originally implemented in the package +@file{outline-magic.el}, but quickly moved to the more general @file{org.el}. +As this environment became comfortable for project planning, the next step +was adding @emph{TODO entries}, basic @emph{timestamps}, and @emph{table +support}. These areas highlighted the two main goals that Org still has +today: to be a new, outline-based, plain text mode with innovative and +intuitive editing features, and to incorporate project planning functionality +directly into a notes file. Since the first release, literally thousands of emails to me or to @email{emacs-orgmode@@gnu.org} have provided a constant stream of bug @@ -18174,15 +19003,17 @@ Before I get to this list, a few special mentions are in order: @table @i @item Bastien Guerry Bastien has written a large number of extensions to Org (most of them -integrated into the core by now), including the @LaTeX{} exporter and the plain -list parser. His support during the early days, when he basically acted as -co-maintainer, was central to the success of this project. Bastien also -invented Worg, helped establishing the Web presence of Org, and sponsored -hosting costs for the orgmode.org website. +integrated into the core by now), including the @LaTeX{} exporter and the +plain list parser. His support during the early days was central to the +success of this project. Bastien also invented Worg, helped establishing the +Web presence of Org, and sponsored hosting costs for the orgmode.org website. +Bastien stepped in as maintainer of Org between 2011 and 2013, at a time when +I desperately needed a break. @item Eric Schulte and Dan Davison Eric and Dan are jointly responsible for the Org-babel system, which turns Org into a multi-language environment for evaluating code and doing literate -programming and reproducible research. +programming and reproducible research. This has become one of Org's killer +features that define what Org is today. @item John Wiegley John has contributed a number of great ideas and patches directly to Org, including the attachment system (@file{org-attach.el}), integration with @@ -18203,9 +19034,8 @@ let me know what I am missing here! @section From Bastien -I (Bastien) have been maintaining Org since January 2011. This appendix -would not be complete without adding a few more acknowledgements and thanks -to Carsten's ones above. +I (Bastien) have been maintaining Org between 2011 and 2013. This appendix +would not be complete without adding a few more acknowledgments and thanks. I am first grateful to Carsten for his trust while handing me over the maintainership of Org. His unremitting support is what really helped me @@ -18223,13 +19053,13 @@ Eric is maintaining the Babel parts of Org. His reactivity here kept me away from worrying about possible bugs here and let me focus on other parts. @item Nicolas Goaziou -Nicolas is maintaining the consistency of the deepest parts of Org. His -work on @file{org-element.el} and @file{ox.el} has been outstanding, and -opened the doors for many new ideas and features. He rewrote many of the -old exporters to use the new export engine, and helped with documenting -this major change. More importantly (if that's possible), he has been more -than reliable during all the work done for Org 8.0, and always very -reactive on the mailing list. +Nicolas is maintaining the consistency of the deepest parts of Org. His work +on @file{org-element.el} and @file{ox.el} has been outstanding, and it opened +the doors for many new ideas and features. He rewrote many of the old +exporters to use the new export engine, and helped with documenting this +major change. More importantly (if that's possible), he has been more than +reliable during all the work done for Org 8.0, and always very reactive on +the mailing list. @item Achim Gratz Achim rewrote the building process of Org, turning some @emph{ad hoc} tools @@ -18285,13 +19115,14 @@ specified time. calculations and improved XEmacs compatibility, in particular by porting @file{nouline.el} to XEmacs. @item -@i{Sacha Chua} suggested copying some linking code from Planner. +@i{Sacha Chua} suggested copying some linking code from Planner, and helped +make Org popular through her blog. @item @i{Toby S. Cubitt} contributed to the code for clock formats. @item -@i{Baoqiu Cui} contributed the DocBook exporter. It has been deleted from -Org 8.0: you can now export to Texinfo and export the @file{.texi} file to -DocBook using @code{makeinfo}. +@i{Baoqiu Cui} contributed the first DocBook exporter. In Org 8.0, we go a +different route: you can now export to Texinfo and export the @file{.texi} +file to DocBook using @code{makeinfo}. @item @i{Eddward DeVilla} proposed and tested checkbox statistics. He also came up with the idea of properties, and that there should be an API for @@ -18388,7 +19219,7 @@ basis. @i{Stefan Monnier} provided a patch to keep the Emacs-Lisp compiler happy. @item -@i{Richard Moreland} wrote @i{MobileOrg} for the iPhone. +@i{Richard Moreland} wrote MobileOrg for the iPhone. @item @i{Rick Moynihan} proposed allowing multiple TODO sequences in a file and being able to quickly restrict the agenda to a subtree. @@ -18506,35 +19337,37 @@ work on a tty. @item @i{Piotr Zielinski} wrote @file{org-mouse.el}, proposed agenda blocks and contributed various ideas and code snippets. +@item +@i{Marco Wahl} wrote @file{org-eww.el}. @end itemize -@node GNU Free Documentation License, Main Index, History and Acknowledgments, Top +@node GNU Free Documentation License @appendix GNU Free Documentation License @include doclicense.texi -@node Main Index, Key Index, GNU Free Documentation License, Top +@node Main Index @unnumbered Concept index @printindex cp -@node Key Index, Command and Function Index, Main Index, Top +@node Key Index @unnumbered Key index @printindex ky -@node Command and Function Index, Variable Index, Key Index, Top +@node Command and Function Index @unnumbered Command and function index @printindex fn -@node Variable Index, , Command and Function Index, Top +@node Variable Index @unnumbered Variable index This is not a complete index of variables and faces, only the ones that are -mentioned in the manual. For a more complete list, use @kbd{M-x -org-customize @key{RET}} and then click yourself through the tree. +mentioned in the manual. For a complete list, use @kbd{M-x org-customize +@key{RET}}. @printindex vr diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex index 338bcf65040..3844333faec 100644 --- a/doc/misc/texinfo.tex +++ b/doc/misc/texinfo.tex @@ -3,11 +3,11 @@ % Load plain if necessary, i.e., if running under initex. \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi % -\def\texinfoversion{2017-01-14.15} +\def\texinfoversion{2017-07-04.16} % % Copyright 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, % 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, -% 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 +% 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 % Free Software Foundation, Inc. % % This texinfo.tex file is free software: you can redistribute it and/or @@ -5493,17 +5493,15 @@ \let\indexlbrace\{ % Likewise, set these sequences for braces \let\indexrbrace\} % used in the sort key. \begindoublecolumns - \let\entrywidowpenalty=\indexwidowpenalty + \let\dotheinsertentrybox\dotheinsertentryboxwithpenalty % % Read input from the index file line by line. \loopdo - \ifeof1 - \let\firsttoken\relax - \else + \ifeof1 \else \read 1 to \nextline - \edef\act{\gdef\noexpand\firsttoken{\getfirsttoken\nextline}}% - \act \fi + % + \indexinputprocessing \thisline % \ifeof1\else @@ -5515,12 +5513,20 @@ \fi \closein 1 \endgroup} +\def\loopdo#1\repeat{\def\body{#1}\loopdoxxx} +\def\loopdoxxx{\let\next=\relax\body\let\next=\loopdoxxx\fi\next} +\def\indexinputprocessing{% + \ifeof1 + \let\firsttoken\relax + \else + \edef\act{\gdef\noexpand\firsttoken{\getfirsttoken\nextline}}% + \act + \fi +} \def\getfirsttoken#1{\expandafter\getfirsttokenx#1\endfirsttoken} \long\def\getfirsttokenx#1#2\endfirsttoken{\noexpand#1} -\def\loopdo#1\repeat{\def\body{#1}\loopdoxxx} -\def\loopdoxxx{\let\next=\relax\body\let\next=\loopdoxxx\fi\next} % These macros are used by the sorted index file itself. % Change them to control the appearance of the index. @@ -5597,7 +5603,7 @@ % For pdfTeX and XeTeX. % The redefinition of \domark stops marks being added in \pdflink to % preserve coloured links across page boundaries. Otherwise the marks - % would get in the way of \lastbox in \insertindexentrybox. + % would get in the way of \lastbox in \insertentrybox. \let\domark\relax % % Start a new paragraph if necessary, so our assignments below can't @@ -5658,9 +5664,9 @@ \fi \egroup % end \boxA \ifdim\wd\boxB = 0pt - \global\setbox\entryindexbox=\vbox{\unhbox\boxA}% + \global\setbox\entrybox=\vbox{\unhbox\boxA}% \else - \global\setbox\entryindexbox=\vbox\bgroup + \global\setbox\entrybox=\vbox\bgroup % We want the text of the entries to be aligned to the left, and the % page numbers to be aligned to the right. % @@ -5722,19 +5728,20 @@ \egroup % The \vbox \fi \endgroup - % delay text of entry until after penalty - \bgroup\aftergroup\insertindexentrybox - \entrywidowpenalty + \dotheinsertentrybox }} \newskip\thinshrinkable \skip\thinshrinkable=.15em minus .15em -\newbox\entryindexbox -\def\insertindexentrybox{% - \ourunvbox\entryindexbox +\newbox\entrybox +\def\insertentrybox{% + \ourunvbox\entrybox } +% default definition +\let\dotheinsertentrybox\insertentrybox + % Use \lastbox to take apart vbox box by box, and add each sub-box % to the current vertical list. \def\ourunvbox#1{% @@ -5757,21 +5764,18 @@ \newbox\delayedbox \newbox\interbox -% Default is no penalty -\let\entrywidowpenalty\egroup - % Used from \printindex. \firsttoken should be the first token % after the \entry. If it's not another \entry, we are at the last % line of a group of index entries, so insert a penalty to discourage % widowed index entries. -\long\def\indexwidowpenalty{% - \def\isentry{\entry}% +\def\dotheinsertentryboxwithpenalty{% \ifx\firsttoken\isentry \else \penalty 9000 \fi - \egroup % now comes the box added with \aftergroup + \insertentrybox } +\def\isentry{\entry}% % Like plain.tex's \dotfill, except uses up at least 1 em. % The filll stretch here overpowers both the fil and fill stretch to push @@ -5888,8 +5892,8 @@ \divide\doublecolumnhsize by 2 \hsize = \doublecolumnhsize % - % Double the \vsize as well. (We don't need a separate register here, - % since nobody clobbers \vsize.) + % Double the \vsize as well. + \advance\vsize by -\ht\partialpage \vsize = 2\vsize % % For the benefit of balancing columns @@ -5907,12 +5911,12 @@ % previous page. \dimen@ = \vsize \divide\dimen@ by 2 - \advance\dimen@ by -\ht\partialpage % % box0 will be the left-hand column, box2 the right. - \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ + \setbox0=\vsplit\PAGE to\dimen@ \setbox2=\vsplit\PAGE to\dimen@ + \global\advance\vsize by 2\ht\partialpage \onepageout\pagesofar - \unvbox255 + \unvbox\PAGE \penalty\outputpenalty } % @@ -5976,9 +5980,9 @@ % % \pagegoal was set to the doubled \vsize above, since we restarted % the current page. We're now back to normal single-column - % typesetting, so reset \pagegoal to the normal \vsize (after the - % \endgroup where \vsize got restored). - \pagegoal = \vsize + % typesetting, so reset \pagegoal to the normal \vsize. + \global\vsize = \txipageheight % + \pagegoal = \txipageheight % } \newbox\balancedcolumns \setbox\balancedcolumns=\vbox{shouldnt see this}% @@ -5986,7 +5990,7 @@ % Only called for the last of the double column material. \doublecolumnout % does the others. \def\balancecolumns{% - \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. + \setbox0 = \vbox{\unvbox\PAGE}% like \box255 but more efficient, see p.120. \dimen@ = \ht0 \advance\dimen@ by \topskip \advance\dimen@ by-\baselineskip @@ -9118,7 +9122,13 @@ \xdef\safexrefname{#1}% }% % - \expandafter\gdef\csname XR\safexrefname\endcsname{#2}% remember this xref + \bgroup + \expandafter\gdef\csname XR\safexrefname\endcsname{#2}% + \egroup + % We put the \gdef inside a group to avoid the definitions building up on + % TeX's save stack, which can cause it to run out of space for aux files with + % thousands of lines. \gdef doesn't use the save stack, but \csname does + % when it defines an unknown control sequence as \relax. % % Was that xref control sequence that we just defined for a float? \expandafter\iffloat\csname XR\safexrefname\endcsname @@ -10999,7 +11009,6 @@ \DeclareUnicodeCharacter{2113}{\ensuremath\ell}% \DeclareUnicodeCharacter{2118}{\ensuremath\wp}% \DeclareUnicodeCharacter{211C}{\ensuremath\Re}% - \DeclareUnicodeCharacter{2127}{\ensuremath\mho}% \DeclareUnicodeCharacter{2135}{\ensuremath\aleph}% \DeclareUnicodeCharacter{2190}{\ensuremath\leftarrow}% \DeclareUnicodeCharacter{2191}{\ensuremath\uparrow}% @@ -11015,7 +11024,6 @@ \DeclareUnicodeCharacter{21AA}{\ensuremath\hookrightarrow}% \DeclareUnicodeCharacter{21BC}{\ensuremath\leftharpoonup}% \DeclareUnicodeCharacter{21BD}{\ensuremath\leftharpoondown}% - \DeclareUnicodeCharacter{21BE}{\ensuremath\upharpoonright}% \DeclareUnicodeCharacter{21C0}{\ensuremath\rightharpoonup}% \DeclareUnicodeCharacter{21C1}{\ensuremath\rightharpoondown}% \DeclareUnicodeCharacter{21CC}{\ensuremath\rightleftharpoons}% @@ -11024,8 +11032,6 @@ \DeclareUnicodeCharacter{21D3}{\ensuremath\Downarrow}% \DeclareUnicodeCharacter{21D4}{\ensuremath\Leftrightarrow}% \DeclareUnicodeCharacter{21D5}{\ensuremath\Updownarrow}% - \DeclareUnicodeCharacter{21DD}{\ensuremath\leadsto}% - \DeclareUnicodeCharacter{2201}{\ensuremath\complement}% \DeclareUnicodeCharacter{2202}{\ensuremath\partial}% \DeclareUnicodeCharacter{2205}{\ensuremath\emptyset}% \DeclareUnicodeCharacter{2207}{\ensuremath\nabla}% @@ -11059,8 +11065,6 @@ \DeclareUnicodeCharacter{2283}{\ensuremath\supset}% \DeclareUnicodeCharacter{2286}{\ensuremath\subseteq}% \DeclareUnicodeCharacter{228E}{\ensuremath\uplus}% - \DeclareUnicodeCharacter{228F}{\ensuremath\sqsubset}% - \DeclareUnicodeCharacter{2290}{\ensuremath\sqsupset}% \DeclareUnicodeCharacter{2291}{\ensuremath\sqsubseteq}% \DeclareUnicodeCharacter{2292}{\ensuremath\sqsupseteq}% \DeclareUnicodeCharacter{2293}{\ensuremath\sqcap}% @@ -11075,8 +11079,6 @@ \DeclareUnicodeCharacter{22A4}{\ensuremath\ptextop}% \DeclareUnicodeCharacter{22A5}{\ensuremath\bot}% \DeclareUnicodeCharacter{22A8}{\ensuremath\models}% - \DeclareUnicodeCharacter{22B4}{\ensuremath\unlhd}% - \DeclareUnicodeCharacter{22B5}{\ensuremath\unrhd}% \DeclareUnicodeCharacter{22C0}{\ensuremath\bigwedge}% \DeclareUnicodeCharacter{22C1}{\ensuremath\bigvee}% \DeclareUnicodeCharacter{22C2}{\ensuremath\bigcap}% @@ -11092,12 +11094,11 @@ \DeclareUnicodeCharacter{2322}{\ensuremath\frown}% \DeclareUnicodeCharacter{2323}{\ensuremath\smile}% % - \DeclareUnicodeCharacter{25A1}{\ensuremath\Box}% \DeclareUnicodeCharacter{25B3}{\ensuremath\triangle}% \DeclareUnicodeCharacter{25B7}{\ensuremath\triangleright}% \DeclareUnicodeCharacter{25BD}{\ensuremath\bigtriangledown}% \DeclareUnicodeCharacter{25C1}{\ensuremath\triangleleft}% - \DeclareUnicodeCharacter{25C7}{\ensuremath\Diamond}% + \DeclareUnicodeCharacter{25C7}{\ensuremath\diamond}% \DeclareUnicodeCharacter{2660}{\ensuremath\spadesuit}% \DeclareUnicodeCharacter{2661}{\ensuremath\heartsuit}% \DeclareUnicodeCharacter{2662}{\ensuremath\diamondsuit}% @@ -11119,7 +11120,6 @@ \DeclareUnicodeCharacter{2A02}{\ensuremath\bigotimes}% \DeclareUnicodeCharacter{2A04}{\ensuremath\biguplus}% \DeclareUnicodeCharacter{2A06}{\ensuremath\bigsqcup}% - \DeclareUnicodeCharacter{2A1D}{\ensuremath\Join}% \DeclareUnicodeCharacter{2A3F}{\ensuremath\amalg}% \DeclareUnicodeCharacter{2AAF}{\ensuremath\preceq}% \DeclareUnicodeCharacter{2AB0}{\ensuremath\succeq}% @@ -11274,6 +11274,7 @@ \pdfvorigin = 1 true in \else \ifx\XeTeXrevision\thisisundefined + \special{papersize=#8,#7}% \else \pdfpageheight #7\relax \pdfpagewidth #8\relax @@ -11311,7 +11312,6 @@ % \lispnarrowing = 0.3in \tolerance = 700 - \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = .5cm }} @@ -11329,7 +11329,6 @@ % \lispnarrowing = 0.25in \tolerance = 700 - \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = .4cm }} @@ -11355,7 +11354,6 @@ {297mm}{210mm}% % \tolerance = 700 - \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = 5mm }} @@ -11374,7 +11372,6 @@ % \lispnarrowing = 0.2in \tolerance = 800 - \hfuzz = 1.2pt \contentsrightmargin = 0pt \defbodyindent = 2mm \tableindent = 12mm @@ -11430,6 +11427,9 @@ % \letterpaper +% Default value of \hfuzz, for suppressing warnings about overfull hboxes. +\hfuzz = 1pt + \message{and turning on texinfo input format.} @@ -11595,6 +11595,9 @@ @def ^^M{@let^^M@secondlinenl}% % Definition for a newline in the main Texinfo file. @gdef @secondlinenl{@fixbackslash}% + % In case the first line has a whole-line command on it + @let@originalparsearg@parsearg + @def@parsearg{@fixbackslash@originalparsearg} }} {@catcode`@^=7 @catcode`@^^M=13% @@ -11615,6 +11618,7 @@ @catcode13=5 % regular end of line @enableemergencynewline @let@c=@texinfoc + @let@parsearg@originalparsearg % Also turn back on active characters that might appear in the input % file name, in case not using a pre-dumped format. @catcode`+=@active diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index fab2b532d6e..1b751a01db6 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -24,13 +24,6 @@ \userhost\@value{postfix}\localname\ @end macro -@c Similar, but without a method prefix. - -@macro trampf {userhost, localname} -@value{prefix}@c -\userhost\@value{postfix}\localname\ -@end macro - @copying Copyright @copyright{} 1999--2017 Free Software Foundation, Inc. @@ -50,7 +43,7 @@ copy and modify this GNU manual.'' @c Entries for @command{install-info} to use @dircategory Emacs network features @direntry -* TRAMP: (tramp). Transparent Remote Access, Multiple Protocol +* @value{tramp}: (tramp). Transparent Remote Access, Multiple Protocol Emacs remote file access via ssh and scp. @end direntry @@ -79,21 +72,21 @@ local and the remote host, whereas @value{tramp} uses a combination of @command{ssh}/@command{scp}. You can find the latest version of this document on the web at -@uref{http://www.gnu.org/software/tramp/}. +@uref{https://www.gnu.org/software/tramp/}. @ifhtml The latest release of @value{tramp} is available for -@uref{ftp://ftp.gnu.org/gnu/tramp/, download}, or you may see -@ref{Obtaining Tramp} for more details, including the Git server -details. +@uref{https://ftp.gnu.org/gnu/tramp/, download}, or you may see +@ref{Obtaining @value{tramp}} for more details, including the Git +server details. -@value{tramp} also has a @uref{http://savannah.gnu.org/projects/tramp/, +@value{tramp} also has a @uref{https://savannah.gnu.org/projects/tramp/, Savannah Project Page}. @end ifhtml There is a mailing list for @value{tramp}, available at @email{tramp-devel@@gnu.org}, and archived at -@uref{http://lists.gnu.org/archive/html/tramp-devel/, the +@uref{https://lists.gnu.org/archive/html/tramp-devel/, the @value{tramp} Mail Archive}. @page @@ -104,11 +97,12 @@ There is a mailing list for @value{tramp}, available at For the end user: -* Obtaining Tramp:: How to obtain @value{tramp}. +* Obtaining @value{tramp}:: How to obtain @value{tramp}. * History:: History of @value{tramp}. @ifset installchapter * Installation:: Installing @value{tramp} with your Emacs. @end ifset +* Quick Start Guide:: Short introduction how to use @value{tramp}. * Configuration:: Configuring @value{tramp} for use. * Usage:: An overview of the operation of @value{tramp}. * Bug Reports:: Reporting Bugs and Problems. @@ -133,8 +127,8 @@ For the developer: Installing @value{tramp} with your Emacs * Installation parameters:: Parameters in order to control installation. +* Testing:: A test suite for @value{tramp}. * Load paths:: How to plug-in @value{tramp} into your environment. - @end ifset Configuring @value{tramp} for use @@ -162,7 +156,10 @@ Configuring @value{tramp} for use Using @value{tramp} -* File name Syntax:: @value{tramp} file name conventions. +* File name syntax:: @value{tramp} file name conventions. +@ifset unified +* Change file name syntax:: Alternative file name syntax. +@end ifset * File name completion:: File name completion. * Ad-hoc multi-hops:: Declaring multiple hops in the file name. * Remote processes:: Integration with other Emacs packages. @@ -196,7 +193,7 @@ and related programs. If these programs can successfully pass more secure alternative to @command{ftp} and other older access methods. -@value{tramp} on Windows operating systems is integrated with the +@value{tramp} on MS Windows operating systems is integrated with the PuTTY package, and uses the @command{plink} program. @value{tramp} mostly operates transparently in the background using @@ -211,7 +208,7 @@ benefit of direct integration of @value{tramp} in Emacs. @value{tramp} can transfer files using any number of available host programs for remote files, such as @command{rcp}, @command{scp}, -@command{rsync} or (under Windows) @command{pscp}. @value{tramp} +@command{rsync} or (under MS Windows) @command{pscp}. @value{tramp} provides easy ways to specify these programs and customize them to specific files, hosts, or access methods. @@ -318,14 +315,14 @@ behind the scenes when you open a file with @value{tramp}. @c For the end user -@node Obtaining Tramp +@node Obtaining @value{tramp} @chapter Obtaining @value{tramp} -@cindex obtaining Tramp +@cindex obtaining @value{tramp} @value{tramp} is included as part of Emacs (since Emacs version 22.1). @value{tramp} is also freely packaged for download on the Internet at -@uref{ftp://ftp.gnu.org/gnu/tramp/}. +@uref{https://ftp.gnu.org/gnu/tramp/}. @value{tramp} development versions are available on Git servers. Development versions contain new and incomplete features. @@ -335,7 +332,7 @@ page at the following URL and then clicking on the Git link in the navigation bar at the top. @noindent -@uref{http://savannah.gnu.org/projects/tramp/} +@uref{https://savannah.gnu.org/projects/tramp/} @noindent Another way is to follow the terminal session below: @@ -353,12 +350,12 @@ From behind a firewall: @example @group ] @strong{git config --global http.proxy http://user:pwd@@proxy.server.com:8080} -] @strong{git clone http://git.savannah.gnu.org/r/tramp.git} +] @strong{git clone https://git.savannah.gnu.org/r/tramp.git} @end group @end example @noindent -Tramp developers: +@value{tramp} developers: @example ] @strong{git clone login@@git.sv.gnu.org:/srv/git/tramp.git} @@ -398,21 +395,22 @@ Run @command{autoconf} as follows to generate an up-to-date @value{tramp} development started at the end of November 1998 as @file{rssh.el}. It provided only one method of access. It used @command{ssh} for login and @command{scp} to transfer file contents. -The name was changed to @file{rcp.el} before it got its preset name +The name was changed to @file{rcp.el} before it got its present name @value{tramp}. New methods of remote access were added, so was support for version control. April 2000 was the first time when multi-hop methods were added. In -July 2002, @value{tramp} unified file names with Ange-FTP@. In July +July 2002, @value{tramp} unified file names with Ange FTP@. In July 2004, proxy hosts replaced multi-hop methods. Running commands on remote hosts was introduced in December 2005. Support for gateways since April 2007 (and removed in December 2016). GVFS integration -started in February 2009. Remote commands on Windows hosts since +started in February 2009. Remote commands on MS Windows hosts since September 2011. Ad-hoc multi-hop methods (with a changed syntax) re-enabled in November 2011. In November 2012, added Juergen Hoetzel's @file{tramp-adb.el}. -XEmacs support has been stopped in January 2016. +XEmacs support was stopped in January 2016. Since March 2017, +@value{tramp} syntax mandates a method. @c Installation chapter is necessary only in case of standalone @c installation. Text taken from trampinst.texi. @@ -421,6 +419,147 @@ XEmacs support has been stopped in January 2016. @end ifset +@node Quick Start Guide +@chapter Short introduction how to use @value{tramp} +@cindex quick start guide + +@value{tramp} extends the Emacs file name syntax by a remote +component. A remote file name looks always like +@file{@trampfn{method,user@@host,/path/to/file}}. + +You can use remote files exactly like ordinary files, that means you +could open a file or directory by @kbd{C-x C-f +@trampfn{method,user@@host,/path/to/file} @key{RET}}, edit the file, +and save it. You can also mix local files and remote files in file +operations with two arguments, like @code{copy-file} or +@code{rename-file}. And finally, you can run even processes on a +remote host, when the buffer you call the process from has a remote +@code{default-directory}. + + +@anchor{Quick Start Guide: File name syntax} +@section File name syntax +@cindex file name syntax + +Remote file names are prepended by the @code{method}, @code{user} and +@code{host} parts. All of them, and also the local file name part, +are optional, in case of a missing part a default value is assumed. +The default value for an empty local file name part is the remote +user's home directory. The shortest remote file name is +@file{@trampfn{-,,}}, therefore. The @samp{-} notation for the +default host is used for syntactical reasons, @ref{Default Host}. + +The @code{method} part describes the connection method used to reach +the remote host, see below. + +The @code{user} part is the user name for accessing the remote host. +For the @option{smb} method, this could also require a domain name, in +this case it is written as @code{user%domain}. + +The @code{host} part must be a host name which could be resolved on +your local host. It could be a short host name, a fully qualified +domain name, an IPv4 or IPv6 address, @ref{File name syntax}. Some +connection methods support also a notation of the port to be used, in +this case it is written as @code{host#port}. + + +@anchor{Quick Start Guide: @option{ssh} and @option{plink} methods} +@section Using @option{ssh} and @option{plink} +@cindex method ssh +@cindex ssh method +@cindex method plink +@cindex plink method + +If your local host runs an SSH client, and the remote host runs an SSH +server, the most simple remote file name is +@file{@trampfn{ssh,user@@host,/path/to/file}}. The remote file name +@file{@trampfn{ssh,,}} opens a remote connection to yourself on the +local host, and is taken often for testing @value{tramp}. + +On MS Windows, PuTTY is often used as SSH client. Its @command{plink} +method can be used there to open a connection to a remote host running +an @command{ssh} server: +@file{@trampfn{plink,user@@host,/path/to/file}}. + + +@anchor{Quick Start Guide: @option{su}, @option{sudo} and @option{sg} methods} +@section Using @option{su}, @option{sudo} and @option{sg} +@cindex method su +@cindex su method +@cindex method sudo +@cindex sudo method +@cindex method sg +@cindex sg method + +Sometimes, it is necessary to work on your local host under different +permissions. For this, you could use the @option{su} or @option{sudo} +connection method. Both methods use @samp{root} as default user name +and the return value of @code{(system-name)} as default host name. +Therefore, it is convenient to open a file as +@file{@trampfn{sudo,,/path/to/file}}. + +The method @option{sg} stands for ``switch group''; the changed group +must be used here as user name. The default host name is the same. + + +@anchor{Quick Start Guide: @option{smb} method} +@section Using @command{smbclient} +@cindex method smb +@cindex smb method +@cindex ms windows (with smb method) +@cindex smbclient + +In order to access a remote MS Windows host or Samba server, the +@command{smbclient} client is used. The remote file name syntax is +@file{@trampfn{smb,user%domain@@host,/path/to/file}}. The first part +of the local file name is the share exported by the remote host, +@samp{path} in this example. + + +@anchor{Quick Start Guide: GVFS-based methods} +@section Using GVFS-based methods +@cindex methods, gvfs +@cindex gvfs based methods +@cindex method sftp +@cindex sftp method +@cindex method afp +@cindex afp method +@cindex method dav +@cindex method davs +@cindex dav method +@cindex davs method + +On systems, which have installed the virtual file system for the Gnome +Desktop (GVFS), its offered methods could be used by @value{tramp}. +Examples are @file{@trampfn{sftp,user@@host,/path/to/file}}, +@file{@trampfn{afp,user@@host,/path/to/file}} (accessing Apple's AFP +file system), @file{@trampfn{dav,user@@host,/path/to/file}} and +@file{@trampfn{davs,user@@host,/path/to/file}} (for WebDAV shares). + + +@anchor{Quick Start Guide: Google Drive} +@section Using Google Drive +@cindex method gdrive +@cindex gdrive method +@cindex google drive + +Another GVFS-based method allows to access a Google Drive file system. +The file name syntax is here always +@file{@trampfn{gdrive,john.doe@@gmail.com,/path/to/file}}. +@samp{john.doe@@gmail.com} stands here for your Google Drive account. + + +@anchor{Quick Start Guide: Android} +@section Using Android +@cindex method adb +@cindex adb method +@cindex android + +An Android device, which is connected via USB to your local host, can +be accessed via the @command{adb} command. No user or host name is +needed. The file name syntax is @file{@trampfn{adb,,/path/to/file}}. + + @node Configuration @chapter Configuring @value{tramp} @cindex configuration @@ -428,7 +567,7 @@ XEmacs support has been stopped in January 2016. @value{tramp} is initially configured to use the @command{scp} program to connect to the remote host. Just type @kbd{C-x C-f} and then enter -file name @file{@trampf{user@@host,/path/to.file}}. For details, +file name @file{@trampfn{scp,user@@host,/path/to/file}}. For details, @xref{Default Method}, @xref{Default User}, @xref{Default Host}. For problems related to the behavior of the remote shell, @xref{Remote @@ -613,16 +752,16 @@ continue connecting?''. @value{tramp} cannot handle such questions. Connections will have to be setup where logins can proceed without such questions. -@option{sshx} is useful for Windows users when @command{ssh} triggers -an error about allocating a pseudo tty. This happens due to missing -shell prompts that confuses @value{tramp}. +@option{sshx} is useful for MS Windows users when @command{ssh} +triggers an error about allocating a pseudo tty. This happens due to +missing shell prompts that confuses @value{tramp}. @option{sshx} supports the @samp{-p} argument. @item @option{krlogin} @cindex method krlogin @cindex krlogin method -@cindex Kerberos (with krlogin method) +@cindex kerberos (with krlogin method) This method is also similar to @option{ssh}. It uses the @command{krlogin -x} command only for remote host login. @@ -630,7 +769,7 @@ This method is also similar to @option{ssh}. It uses the @item @option{ksu} @cindex method ksu @cindex ksu method -@cindex Kerberos (with ksu method) +@cindex kerberos (with ksu method) This is another method from the Kerberos suite. It behaves like @option{su}. @@ -638,7 +777,7 @@ This is another method from the Kerberos suite. It behaves like @option{su}. @cindex method plink @cindex plink method -@option{plink} method is for Windows users with the PuTTY +@option{plink} method is for MS Windows users with the PuTTY implementation of SSH@. It uses @samp{plink -ssh} to log in to the remote host. @@ -651,9 +790,9 @@ session. @cindex method plinkx @cindex plinkx method -Another method using PuTTY on Windows with session names instead of -host names. @option{plinkx} calls @samp{plink -load @var{session} -t}. -User names and port numbers must be defined in the session. +Another method using PuTTY on MS Windows with session names instead of +host names. @option{plinkx} calls @samp{plink -load @var{session} +-t}. User names and port numbers must be defined in the session. Check the @samp{Share SSH connections if possible} control for that session. @@ -733,9 +872,9 @@ This method supports the @samp{-p} argument. in performance to @option{scp}. @option{scpx} uses @samp{ssh -t -t @var{host} -l @var{user} /bin/sh} to open a connection. -@option{scpx} is useful for Windows users when @command{ssh} triggers -an error about allocating a pseudo tty. This happens due to missing -shell prompts that confuses @value{tramp}. +@option{scpx} is useful for MS Windows users when @command{ssh} +triggers an error about allocating a pseudo tty. This happens due to +missing shell prompts that confuses @value{tramp}. This method supports the @samp{-p} argument. @@ -745,17 +884,17 @@ This method supports the @samp{-p} argument. @cindex pscp method @cindex pscp (with pscp method) @cindex plink (with pscp method) -@cindex PuTTY (with pscp method) +@cindex putty (with pscp method) @cindex method psftp @cindex psftp method @cindex pscp (with psftp method) @cindex plink (with psftp method) -@cindex PuTTY (with psftp method) +@cindex putty (with psftp method) These methods are similar to @option{scp} or @option{sftp}, but they use the @command{plink} command to connect to the remote host, and they use @command{pscp} or @command{psftp} for transferring the files. -These programs are part of PuTTY, an SSH implementation for Windows. +These programs are part of PuTTY, an SSH implementation for MS Windows. Check the @samp{Share SSH connections if possible} control for that session. @@ -808,6 +947,8 @@ capable of servicing requests from @value{tramp}. @item @option{smb} @cindex method smb @cindex smb method +@cindex ms windows (with smb method) +@cindex smbclient This non-native @value{tramp} method connects via the Server Message Block (SMB) networking protocol to hosts running file servers that are @@ -819,9 +960,9 @@ Using @command{smbclient} requires a few tweaks when working with The first directory in the localname must be a share name on the remote host. -Since SMB shares end in the @code{$} character, @value{tramp} must use -@code{$$} when specifying those shares to avoid environment variable -substitutions. +Since some SMB share names end in the @code{$} character, +@value{tramp} must use @code{$$} when specifying those shares to avoid +environment variable substitutions. When @value{tramp} is not specific about the share name or uses the generic remote directory @file{/}, @command{smbclient} returns all @@ -834,15 +975,16 @@ handling}. To accommodate user name/domain name syntax required by MS Windows authorization, @value{tramp} provides for an extended syntax in -@code{user%domain} format (where user is username, @code{%} is the -percent symbol, and domain is the windows domain name). An example: +@code{user%domain} format (where @code{user} is the user name, +@code{%} is the percent symbol, and @code{domain} is the MS Windows +domain name). An example: @example @trampfn{smb,daniel%BIZARRE@@melancholia,/daniel$$/.emacs} @end example where user @code{daniel} connects as a domain user to the SMB host -@code{melancholia} in the windows domain @code{BIZARRE} to edit +@code{melancholia} in the MS Windows domain @code{BIZARRE} to edit @file{.emacs} located in the home directory (share @code{daniel$}). Alternatively, for local WINS users (as opposed to domain users), @@ -879,6 +1021,7 @@ can. @item @option{adb} @cindex method adb @cindex adb method +@cindex android (with adb method) This method uses Android Debug Bridge program for accessing Android devices. The Android Debug Bridge must be installed locally for @@ -920,7 +1063,7 @@ numbers are not applicable to Android devices connected through USB@. @cindex dbus GVFS is the virtual file system for the Gnome Desktop, -@uref{http://en.wikipedia.org/wiki/GVFS}. Remote files on GVFS are +@uref{https://en.wikipedia.org/wiki/GVFS}. Remote files on GVFS are mounted locally through FUSE and @value{tramp} uses this locally mounted directory internally. @@ -952,7 +1095,7 @@ but with SSL encryption. Both methods support the port numbers. @item @option{gdrive} @cindex method gdrive @cindex gdrive method -@cindex Google Drive +@cindex google drive Via the @option{gdrive} method it is possible to access your Google Drive online storage. User and host name of the remote file name are @@ -984,8 +1127,8 @@ that for security reasons refuse @command{ssh} connections. @cindex method synce @cindex synce method -@option{synce} method allows connecting to Windows Mobile devices. It -uses GVFS for mounting remote files and directories via FUSE and +@option{synce} method allows connecting to MS Windows Mobile devices. +It uses GVFS for mounting remote files and directories via FUSE and requires the SYNCE-GVFS plugin. @end table @@ -1002,6 +1145,9 @@ Other methods to include are: @option{ftp} and @option{smb}. @section Selecting a default method @cindex default method +In a remote file name, the use of a default method is indicated by the +pseudo method @option{-}, @ref{File name syntax}. + @defopt tramp-default-method Default method is for transferring files. The user option @option{tramp-default-method} sets it. @value{tramp} uses this user @@ -1070,7 +1216,7 @@ access and it has the most reasonable security protocols, use @end example If @option{ssh} is unavailable for whatever reason, look for other -obvious options. For Windows, try the @option{plink} method. For +obvious options. For MS Windows, try the @option{plink} method. For Kerberos, try @option{krlogin}. For editing local files as @option{su} or @option{sudo} methods, try @@ -1145,25 +1291,21 @@ for catch-all or most often used login. @defopt tramp-default-host When host name is omitted, @value{tramp} substitutes the value from the @option{tramp-default-host} user option. It is initially -populated with the local hostname where Emacs is running. Both the -default user and default host can be overridden as follows: +populated with the local host name where Emacs is running. The +default method, default user and default host can be overridden as +follows: @lisp @group (custom-set-variables + '(tramp-default-method "ssh" nil (tramp)) '(tramp-default-user "john" nil (tramp)) '(tramp-default-host "target" nil (tramp))) @end group @end lisp -With both defaults set, @samp{@trampfn{ssh,,}} will connect -@value{tramp} to John's home directory on @code{target}. - -@strong{Note} @samp{/::} won't work, because @samp{/:} is the prefix -for quoted file names. -@ifinfo -@pxref{Quoted File Names, , , emacs}. -@end ifinfo +With all defaults set, @samp{@trampfn{-,,}} will connect @value{tramp} +to John's home directory on @code{target} via @code{ssh}. @end defopt @defopt tramp-default-host-alist @@ -1248,7 +1390,7 @@ access, then use this alist entry: Opening @file{@trampfn{sudo,randomhost.your.domain,}} first connects to @samp{randomhost.your.domain} via @code{ssh} under your account -name, and then perform @code{sudo -u root} on that host. +name, and then performs @code{sudo -u root} on that host. It is key for the sudo method in the above example to be applied on the host after reaching it and not on the local host. @@ -1293,8 +1435,8 @@ restricted shell: @node Firewalls @section Passing firewalls -@cindex HTTP tunnel -@cindex proxy hosts, HTTP tunnel +@cindex http tunnel +@cindex proxy hosts, http tunnel Sometimes, it is not possible to reach a remote host directly. A firewall might be in the way, which could be passed via a proxy @@ -1507,9 +1649,15 @@ machine melancholia port scp login daniel password geheim The port can take any @value{tramp} method (@pxref{Inline methods}, @pxref{External methods}). Omitting port values matches all -@value{tramp} methods. +@value{tramp} methods. Domain and ports, as used in @value{tramp} +file name syntax, must be appended to the machine and login items: -Setting @code{auth-source-debug} to @code{t} to debug messages. +@example +machine melancholia#4711 port davs login daniel%BIZARRE password geheim +@end example + +@vindex auth-source-debug +Set @code{auth-source-debug} to @code{t} to debug messages. @anchor{Caching passwords} @@ -1744,8 +1892,8 @@ Similar localization may be necessary for handling wrong password prompts, for which @value{tramp} uses @option{tramp-wrong-passwd-regexp}. @item @command{tset} and other questions -@cindex Unix command tset -@cindex tset Unix command +@cindex unix command tset +@cindex tset unix command @vindex tramp-terminal-type To suppress inappropriate prompts for terminal type, @value{tramp} @@ -1845,7 +1993,7 @@ Then re-set the prompt string in @file{~/.emacs_SHELLNAME} as follows: @example @group -# Reset the prompt for remote Tramp shells. +# Reset the prompt for remote @value{tramp} shells. if [ "$@{INSIDE_EMACS/*tramp*/tramp@}" == "tramp" ] ; then PS1="[\u@@\h \w]$ " fi @@ -1857,8 +2005,8 @@ fi @end ifinfo @item @command{busybox} / @command{nc} -@cindex Unix command nc -@cindex nc Unix command +@cindex unix command nc +@cindex nc unix command @value{tramp}'s @option{nc} method uses the @command{nc} command to install and execute a listener as follows (see @code{tramp-methods}): @@ -1889,16 +2037,21 @@ where @samp{192.168.0.1} is the remote host IP address @node Android shell setup @section Android shell setup hints -@cindex android shell setup +@cindex android shell setup for ssh -@value{tramp} uses the @option{adb} method to access Android -devices. Android devices provide a restricted shell access through an -USB connection. The local host must have the Android SDK installed. +@value{tramp} uses the @option{adb} method to access Android devices. +Android devices provide a restricted shell access through an USB +connection. The local host must have the @command{adb} program +installed. Usually, it is sufficient to open the file +@file{@trampfn{adb,,/}}. Then you can navigate in the filesystem via +@code{dired}. -Applications such as @code{SSHDroid} that run @command{sshd} process -on the Android device can accept any @option{ssh}-based methods -provided these settings are adjusted: +Alternatively, applications such as @code{SSHDroid} that run +@command{sshd} process on the Android device can accept any +@option{ssh}-based methods provided these settings are adjusted: +@itemize +@item @command{sh} must be specified for remote shell since Android devices do not provide @command{/bin/sh}. @command{sh} will then invoke whatever shell is installed on the device with this setting: @@ -1914,6 +2067,7 @@ whatever shell is installed on the device with this setting: where @samp{192.168.0.26} is the Android device's IP address. (@pxref{Predefined connection information}). +@item @value{tramp} requires preserving @env{PATH} environment variable from user settings. Android devices prefer @file{/system/xbin} path over @file{/system/bin}. Both of these are set as follows: @@ -1925,7 +2079,7 @@ user settings. Android devices prefer @file{/system/xbin} path over @end group @end lisp -@noindent +@item When the Android device is not @samp{rooted}, specify a writable directory for temporary files: @@ -1933,7 +2087,7 @@ directory for temporary files: (add-to-list 'tramp-remote-process-environment "TMPDIR=$HOME") @end lisp -@noindent +@item Open a remote connection with the command @kbd{C-x C-f @trampfn{ssh,192.168.0.26#2222,}}, where @command{sshd} is listening on port @samp{2222}. @@ -1964,6 +2118,7 @@ the previous example, fix the connection properties as follows: @noindent Open a remote connection with a more concise command @kbd{C-x C-f @trampfn{ssh,android,}}. +@end itemize @node Auto-save and Backup @@ -2063,12 +2218,12 @@ to direct all auto saves to that location. @node Windows setup hints @section Issues with Cygwin ssh -@cindex Cygwin, issues +@cindex cygwin, issues This section is incomplete. Please share your solutions. -@cindex method sshx with Cygwin -@cindex sshx method with Cygwin +@cindex method sshx with cygwin +@cindex sshx method with cygwin Cygwin's @command{ssh} works only with a Cygwin version of Emacs. To check for compatibility: type @kbd{M-x eshell}, and start @kbd{ssh @@ -2080,36 +2235,36 @@ Pseudo-terminal will not be allocated because stdin is not a terminal. Some older versions of Cygwin's @command{ssh} work with the @option{sshx} access method. Consult Cygwin's FAQ at -@uref{http://cygwin.com/faq/} for details. +@uref{https://cygwin.com/faq/} for details. -@cindex Cygwin and fakecygpty -@cindex fakecygpty and Cygwin +@cindex cygwin and fakecygpty +@cindex fakecygpty and cygwin On @uref{https://www.emacswiki.org/emacs/SshWithNTEmacs, the Emacs Wiki} it is explained how to use the helper program @code{fakecygpty} to fix this problem. -@cindex method scpx with Cygwin -@cindex scpx method with Cygwin +@cindex method scpx with cygwin +@cindex scpx method with cygwin When using the @option{scpx} access method, Emacs may call -@command{scp} with Windows file naming, such as @code{c:/foo}. But +@command{scp} with MS Windows file naming, such as @code{c:/foo}. But the version of @command{scp} that is installed with Cygwin does not -know about Windows file naming, which causes it to incorrectly look +know about MS Windows file naming, which causes it to incorrectly look for a host named @code{c}. A workaround: write a wrapper script for @option{scp} to convert Windows file names to Cygwin file names. -@cindex Cygwin and ssh-agent -@cindex SSH_AUTH_SOCK and Emacs on Windows +@cindex cygwin and ssh-agent +@cindex SSH_AUTH_SOCK and emacs on ms windows -When using the @command{ssh-agent} on Windows for password-less +When using the @command{ssh-agent} on MS Windows for password-less interaction, @option{ssh} methods depend on the environment variable @env{SSH_AUTH_SOCK}. But this variable is not set when Emacs is started from a Desktop shortcut and authentication fails. -One workaround is to use a Windows based SSH Agent, such as +One workaround is to use an MS Windows based SSH Agent, such as Pageant. It is part of the Putty Suite of tools. The fallback is to start Emacs from a shell. @@ -2137,7 +2292,10 @@ is a feature of Emacs that may cause missed prompts when using @value{tramp}. @menu -* File name Syntax:: @value{tramp} file name conventions. +* File name syntax:: @value{tramp} file name conventions. +@ifset unified +* Change file name syntax:: Alternative file name syntax. +@end ifset * File name completion:: File name completion. * Ad-hoc multi-hops:: Declaring multiple hops in the file name. * Remote processes:: Integration with other Emacs packages. @@ -2145,40 +2303,39 @@ is a feature of Emacs that may cause missed prompts when using @end menu -@node File name Syntax +@node File name syntax @section @value{tramp} file name conventions @cindex file name syntax @cindex file name examples -@file{@trampf{host,localfilename}} opens file @var{localfilename} on -the remote host @var{host}, using the default method. @xref{Default -Method}. +@file{@trampfn{method,host,/path/to/file}} opens file @var{/path/to/file} +on the remote host @var{host}, using the method @var{method}. @table @file -@item @value{prefix}melancholia@value{postfix}.emacs +@item @value{prefix}ssh@value{postfixhop}melancholia@value{postfix}.emacs For the file @file{.emacs} located in the home directory, on the host -@code{melancholia}. +@code{melancholia}, using method @code{ssh}. -@item @value{prefix}melancholia.danann.net@value{postfix}.emacs +@item @value{prefix}ssh@value{postfixhop}melancholia.danann.net@value{postfix}.emacs For the file @file{.emacs} specified using the fully qualified domain name of the host. -@item @value{prefix}melancholia@value{postfix}~/.emacs +@item @value{prefix}ssh@value{postfixhop}melancholia@value{postfix}~/.emacs For the file @file{.emacs} specified using the @file{~}, which is expanded. -@item @value{prefix}melancholia@value{postfix}~daniel/.emacs +@item @value{prefix}ssh@value{postfixhop}melancholia@value{postfix}~daniel/.emacs For the file @file{.emacs} located in @code{daniel}'s home directory on the host, @code{melancholia}. The @file{~<user>} construct is expanded to the home directory of that user on the remote host. -@item @value{prefix}melancholia@value{postfix}/etc/squid.conf +@item @value{prefix}ssh@value{postfixhop}melancholia@value{postfix}/etc/squid.conf For the file @file{/etc/squid.conf} on the host @code{melancholia}. @end table @var{host} can take IPv4 or IPv6 address, as in -@file{@trampf{127.0.0.1,.emacs}} or -@file{@trampf{@value{ipv6prefix}::1@value{ipv6postfix},.emacs}}. +@file{@trampfn{ssh,127.0.0.1,.emacs}} or +@file{@trampfn{ssh,@value{ipv6prefix}::1@value{ipv6postfix},.emacs}}. @ifset unified For syntactical reasons, IPv6 addresses must be embedded in square brackets @file{@value{ipv6prefix}} and @file{@value{ipv6postfix}}. @@ -2189,30 +2346,74 @@ remote user name for log in to the remote host. Specifying a different name using the proper syntax will override this default behavior: @example -@trampf{user@@host,path/to.file} +@trampfn{method,user@@host,path/to/file} @end example -@file{@trampf{daniel@@melancholia,.emacs}} is for file @file{.emacs} -in @code{daniel}'s home directory on the host, @code{melancholia}. +@file{@trampfn{ssh,daniel@@melancholia,.emacs}} is for file +@file{.emacs} in @code{daniel}'s home directory on the host, +@code{melancholia}, accessing via method @code{ssh}. + +For specifying port numbers, affix @file{#<port>} to the host +name. For example: @file{@trampfn{ssh,daniel@@melancholia#42,.emacs}}. + +All method, user name, host name, port number and local name parts are +optional, @xref{Default Method}, @xref{Default User}, @xref{Default Host}. +@ifset unified +For syntactical reasons, the default method must be indicated by the +pseudo method @file{-}. +@end ifset + -Specify other file access methods (@pxref{Inline methods}, -@pxref{External methods}) as part of the file name. +@ifset unified +@node Change file name syntax +@section Alternative file name syntax +@cindex change file name syntax +@cindex alternative file name syntax -Method name comes before user name, as in -@file{@value{prefix}@var{method}@value{postfixhop}} (Note the trailing -colon). The syntax specifications for user, host, and file do not -change. +The syntax described in @ref{File name syntax} is the @code{default} +syntax, which is active after Emacs startup. However, this can be +changed. -To connect to the host @code{melancholia} as @code{daniel}, using -@option{ssh} method for @file{.emacs} in @code{daniel}'s home -directory, the full specification is: -@file{@trampfn{ssh,daniel@@melancholia,.emacs}}. +@deffn Command tramp-change-syntax syntax +This command changes the syntax @value{tramp} uses for remote file +names. Beside the @code{default} value, @var{syntax} can be -A remote file name containing a host name, which is the same string as -a method name, is not allowed. +@itemize +@item @code{simplified} +@cindex simplified syntax -For specifying port numbers, affix @file{#<port>} to the host -name. For example: @file{@trampfn{ssh,daniel@@melancholia#42,.emacs}}. +The remote file name syntax is similar to the syntax used by Ange FTP. +A remote file name has the form +@code{@value{prefix}user@@host@value{postfix}path/to/file}. The +@code{user@@} part is optional, and the method is determined by +@ref{Default Method}. + +@item @code{separate} +@cindex separate syntax + +@clear unified +@set separate +@include trampver.texi +The remote file name syntax is similar to the syntax used by XEmacs. +A remote file name has the form +@code{@trampfn{method,user@@host,path/to/file}}. The @code{method} +and @code{user@@} parts are optional. +@clear separate +@set unified +@include trampver.texi +@end itemize +@end deffn + +@defvar tramp-file-name-regexp +This variable keeps a regexp which matches the selected remote file +name syntax. However, it is not recommended to use this variable in +external packages, a call of @code{file-remote-p} is much more +appropriate. +@ifinfo +@pxref{Magic File Names, , , elisp} +@end ifinfo +@end defvar +@end ifset @node File name completion @@ -2227,38 +2428,52 @@ in @file{.emacs}. @xref{Completion Options, , , emacs}. @end ifinfo -For example, type @kbd{C-x C-f @value{prefix}t @key{TAB}}, +For example, type @kbd{C-x C-f @value{prefixwithspace} s @key{TAB}}, @value{tramp} completion choices show up as @example @group -@c @multitable {@trampfn{telnet,melancholia.danann.net,}} {@trampfn{telnet,192.168.0.1,}} -@multitable @columnfractions .5 .5 -@item @value{prefixhop}telnet@value{postfixhop} @tab tmp/ -@item @value{prefixhop}toto@value{postfix} @tab +@multitable @columnfractions .2 .2 .2 .2 .2 +@item @c + sbin/ @tab @c + @value{prefixhop}scp@value{postfix} @tab @c + @value{prefixhop}scpx@value{postfix} @tab @c + @value{prefixhop}sftp@value{postfix} @tab @c + @value{prefixhop}sg@value{postfix} +@item @c + @value{prefixhop}smb@value{postfix} @tab @c + srv/ @tab @c + @value{prefixhop}ssh@value{postfix} @tab @c + @value{prefixhop}sshx@value{postfix} @tab @c + @value{prefixhop}su@value{postfix} +@item @c + @value{prefixhop}sudo@value{postfix} @tab @c + sys/ @end multitable @end group @end example -@samp{@value{prefixhop}telnet@value{postfixhop}} is a possible -completion for the respective method, @samp{tmp/} stands for the -directory @file{/tmp} on your local host, and -@samp{@value{prefixhop}toto@value{postfix}} might be a host -@value{tramp} has detected in your @file{~/.ssh/known_hosts} file -(when using @option{ssh} as default method). +@samp{@value{prefixhop}ssh@value{postfixhop}} is a possible +completion for the respective method, and @samp{sbin/} stands for the +directory @file{/sbin} on your local host. -Type @kbd{e @key{TAB}} for the minibuffer completion to -@samp{@value{prefix}telnet@value{postfixhop}}. Typing @kbd{@key{TAB}} -shows host names @value{tramp} from @file{/etc/hosts} file, for example. +Type @kbd{s h @value{postfixhop}} for the minibuffer completion to +@samp{@value{prefix}ssh@value{postfixhop}}. Typing @kbd{@key{TAB}} +shows host names @value{tramp} extracts from @file{~/.ssh/config} +file, for example. @example @group @multitable @columnfractions .5 .5 -@c @multitable {@trampfn{telnet,melancholia.danann.net,}} {@trampfn{telnet,192.168.0.1,}} -@item @trampfn{telnet,127.0.0.1,} @tab @trampfn{telnet,192.168.0.1,} -@c @item @trampfn{telnet,@value{ipv6prefix}::1@value{ipv6postfix},} @tab @trampfn{telnet,localhost,} -@item @value{prefix}telnet@value{postfixhop}@value{ipv6prefix}::1@value{ipv6postfix}@value{postfix} @tab @trampfn{telnet,localhost,} -@item @trampfn{telnet,melancholia.danann.net,} @tab @trampfn{telnet,melancholia,} +@item @c + @value{prefixhop}ssh@value{postfixhop}127.0.0.1@value{postfix} @tab @c + @value{prefixhop}ssh@value{postfixhop}192.168.0.1@value{postfix} +@item @c + @value{prefixhop}ssh@value{postfixhop}@value{ipv6prefix}::1@value{ipv6postfix}@value{postfix} @tab @c + @value{prefixhop}ssh@value{postfixhop}localhost@value{postfix} +@item @c + @value{prefixhop}ssh@value{postfixhop}melancholia.danann.net@value{postfix} @tab @c + @value{prefixhop}ssh@value{postfixhop}melancholia@value{postfix} @end multitable @end group @end example @@ -2287,13 +2502,13 @@ Example: @example @group -@kbd{C-x C-f @trampfn{telnet,melancholia,/usr/local/bin//etc} @key{TAB}} - @print{} @trampfn{telnet,melancholia,/etc} +@kbd{C-x C-f @trampfn{ssh,melancholia,/usr/local/bin//etc} @key{TAB}} + @print{} @trampfn{ssh,melancholia,/etc} -@kbd{C-x C-f @trampfn{telnet,melancholia,//etc} @key{TAB}} +@kbd{C-x C-f @trampfn{ssh,melancholia,//etc} @key{TAB}} @print{} /etc -@kbd{C-x C-f @trampfn{telnet,melancholia,/usr/local/bin///etc} @key{TAB}} +@kbd{C-x C-f @trampfn{ssh,melancholia,/usr/local/bin///etc} @key{TAB}} @print{} /etc @end group @end example @@ -2496,9 +2711,44 @@ when using @value{tramp} between two hosts with different operating systems, such as @samp{windows-nt} and @samp{gnu/linux}. This option ensures the correct name of the remote shell program. -Starting with Emacs 24, when @option{explicit-shell-file-name} is -equal to @code{nil}, calling @code{shell} interactively will prompt -for a shell name. +When @option{explicit-shell-file-name} is equal to @code{nil}, calling +@code{shell} interactively will prompt for a shell name. + +Starting with Emacs 26, you could use connection-local variables for +setting different values of @option{explicit-shell-file-name} for +different remote hosts. +@ifinfo +@pxref{Connection Local Variables, , , elisp} +@end ifinfo + +@lisp +@group +(connection-local-set-profile-variables + 'remote-bash + '((explicit-shell-file-name . "/bin/bash") + (explicit-bash-args . ("-i")))) +@end group + +@group +(connection-local-set-profile-variables + 'remote-ksh + '((explicit-shell-file-name . "/bin/ksh") + (explicit-ksh-args . ("-i")))) +@end group + +@group +(connection-local-set-profiles + '(:application tramp :protocol "ssh" :machine "localhost") + 'remote-bash) +@end group + +@group +(connection-local-set-profiles + `(:application tramp :protocol "sudo" + :user "root" :machine ,(system-name)) + 'remote-ksh) +@end group +@end lisp @subsection Running @code{shell-command} on a remote host @@ -2526,9 +2776,9 @@ host. Example: @value{tramp} is integrated into @file{eshell.el}, which enables interactive eshell sessions on remote hosts at the command prompt. -You must add the module @code{eshell-tramp} to -@code{eshell-modules-list}. Here's a sample interaction after opening -@kbd{M-x eshell} on a remote host: +You must add the module @code{em-tramp} to @code{eshell-modules-list}. +Here's a sample interaction after opening @kbd{M-x eshell} on a remote +host: @example @group @@ -2543,11 +2793,10 @@ uid=0(root) gid=0(root) groups=0(root) @end group @end example -@code{eshell} in Emacs 23.2 added custom @code{su} and @code{sudo} -commands that set the default directory correctly for the -@file{*eshell*} buffer. @value{tramp} silently updates -@option{tramp-default-proxies-alist} with an entry for this directory -(@pxref{Multi-hops}): +@code{eshell} added custom @code{su} and @code{sudo} commands that set +the default directory correctly for the @file{*eshell*} buffer. +@value{tramp} silently updates @option{tramp-default-proxies-alist} +with an entry for this directory (@pxref{Multi-hops}): @example @group @@ -2613,11 +2862,11 @@ Arguments of the program to be debugged must be literal, can take relative or absolute paths, but not remote paths. -@subsection Running remote processes on Windows hosts +@subsection Running remote processes on MS Windows hosts @cindex winexe @cindex powershell -@command{winexe} runs processes on a remote Windows host, and +@command{winexe} runs processes on a remote MS Windows host, and @value{tramp} can use it for @code{process-file} and @code{start-file-process}. @@ -2627,7 +2876,7 @@ processes triggered from @value{tramp}. @option{explicit-shell-file-name} and @option{explicit-*-args} have to be set properly so @kbd{M-x shell} can open a proper remote shell on a -Windows host. To open @command{cmd}, set it as follows: +MS Windows host. To open @command{cmd}, set it as follows: @lisp @group @@ -2700,7 +2949,7 @@ this address go to all the subscribers. This is @emph{not} the address to send subscription requests to. To subscribe to the mailing list, visit: -@uref{http://lists.gnu.org/mailman/listinfo/tramp-devel/, the +@uref{https://lists.gnu.org/mailman/listinfo/tramp-devel/, the @value{tramp} Mail Subscription Page}. @ifset installchapter @@ -2752,23 +3001,23 @@ Where is the latest @value{tramp}? @value{tramp} is available at the GNU URL: @noindent -@uref{ftp://ftp.gnu.org/gnu/tramp/} +@uref{https://ftp.gnu.org/gnu/tramp/} @noindent @value{tramp}'s GNU project page is located here: @noindent -@uref{http://savannah.gnu.org/projects/tramp/} +@uref{https://savannah.gnu.org/projects/tramp/} @item Which systems does it work on? -The package works successfully on Emacs 23, Emacs 24, and Emacs 25. +The package works successfully on Emacs 24, Emacs 25, and Emacs 26. While Unix and Unix-like systems are the primary remote targets, @value{tramp} has equal success connecting to other platforms, such as -MS Windows XP/Vista/7. +MS Windows 7/8/10. @item @@ -3063,10 +3312,22 @@ then set them with a hook as follows: @item Why is @file{~/.sh_history} file on the remote host growing? -Due to @command{ksh} saving tilde expansions triggered by -@value{tramp}, the history file is probably growing rapidly. To fix, -turn off saving history by putting this shell code in the -@file{.kshrc} file: +Due to the remote shell saving tilde expansions triggered by +@value{tramp}, the history file is probably growing rapidly. +@value{tramp} can suppress this behaviour with the user option +@code{tramp-histfile-override}. When set to @code{t}, environment +variable @env{HISTFILE} is unset, and environment variables +@env{HISTFILESIZE} @env{HISTSIZE} are set to 0. + +Alternatively, @code{tramp-histfile-override} could be a string. +Environment variable @env{HISTFILE} is set to this file name then. Be +careful when setting to @file{/dev/null}; this might result in +undesired results when using @command{bash} as remote shell. + +Another approach is to disable @value{tramp}'s handling of the +@env{HISTFILE} at all by setting @code{tramp-histfile-override} to +@code{nil}. In this case, saving history could be turned off by +putting this shell code in the @file{.bashrc} or @file{.kshrc} file: @example @group @@ -3112,7 +3373,7 @@ You can define default methods and user names for hosts, @end group @end lisp -The reduced typing: @kbd{C-x C-f @trampf{news.my.domain,/opt/news/etc}}. +The reduced typing: @kbd{C-x C-f @trampfn{-,news.my.domain,/opt/news/etc}}. @strong{Note} that there are some useful shortcuts already. Accessing your local host as @samp{root} user, is possible just by @kbd{C-x C-f @@ -3168,7 +3429,7 @@ Redefine another key sequence in Emacs for @kbd{C-x C-f}: (interactive) (find-file (read-file-name - "Find Tramp file: " + "Find @value{tramp} file: " "@trampfn{ssh,news@@news.my.domain,/opt/news/etc/}")))) @end group @end lisp @@ -3238,7 +3499,7 @@ The minibuffer expands for further editing. @item Use bookmarks: -Use bookmarks to save Tramp file names. +Use bookmarks to save @value{tramp} file names. @ifinfo @pxref{Bookmarks, , , emacs}. @end ifinfo @@ -3471,18 +3732,12 @@ handlers. @section Integrating with external Lisp packages @subsection File name completion. -For name completions in the minibuffer, @value{tramp} depends on the -last input character to decide whether to look for method name -completion or host name completion. For example, @kbd{C-x C-f -@value{prefix}ssh@value{postfixhop} @key{TAB}} is not entirely clear -if @option{ssh} is a method or a host name. But if the last input -character was either @key{TAB}, @key{SPACE} or @kbd{?}, then -@value{tramp} favors file name completion over host name completion. - -What about external packages using other characters to trigger file -name completions? They must somehow signal this to @value{tramp}. Use -the variable @code{non-essential} temporarily and bind it to -non-@code{nil} value. +Sometimes, it is not convenient to open a new connection to a remote +host, including entering the password and alike. For example, this is +nasty for packages providing file name completion. Such a package +could signal to @value{tramp}, that they don't want it to establish a +new connection. Use the variable @code{non-essential} temporarily and +bind it to non-@code{nil} value. @lisp @group @@ -3627,4 +3882,3 @@ strings from being written to @file{*trace-output*}. @c * Explain how tramp.el works in principle: open a shell on a remote @c host and then send commands to it. @c * Consistent small or capitalized words especially in menus. -@c * Make a unique declaration of @trampfn. diff --git a/doc/misc/trampver.texi b/doc/misc/trampver.texi index 70701aa3589..5d9dcc5635d 100644 --- a/doc/misc/trampver.texi +++ b/doc/misc/trampver.texi @@ -8,7 +8,7 @@ @c In the Tramp GIT, the version number is auto-frobbed from @c configure.ac, so you should edit that file and run @c "autoconf && ./configure" to change the version number. -@set trampver 2.3.2-pre +@set trampver 2.3.3-pre @c Other flags from configuration @set instprefix /usr/local @@ -27,6 +27,7 @@ @ifset unified @set prefix / +@set prefixwithspace / @set prefixhop @set postfix : @set postfixhop : @@ -36,6 +37,7 @@ @ifset separate @set prefix /[ +@set prefixwithspace / [ @set prefixhop [ @set postfix ] @set postfixhop / diff --git a/doc/misc/viper.texi b/doc/misc/viper.texi index 3e944d99e7f..745d5fadf62 100644 --- a/doc/misc/viper.texi +++ b/doc/misc/viper.texi @@ -1767,7 +1767,7 @@ Function used by the command @kbd{#c<move>} to spell. @item viper-glob-function The value of this variable is the function symbol used to expand wildcard symbols. This is platform-dependent. The default tries to set this variable -to work with most shells, MS Windows, OS/2, etc. However, if it +to work with most shells, MS Windows, etc. However, if it doesn't work the way you expect, you should write your own. Use @code{viper-glob-unix-files} and @code{viper-glob-mswindows-files} in @file{viper-util.el} as examples. diff --git a/etc/AUTHORS b/etc/AUTHORS index 9f951dfc1be..05a6d101dce 100644 --- a/etc/AUTHORS +++ b/etc/AUTHORS @@ -1211,7 +1211,7 @@ and changed diary.el tex-mode.el holiday.el cal-chinese.el diary-ins.el diary-insert.el cal-persian.el cal-islamic.el calendar.texi list-holidays.el -Edward O'Connor: wrote json.el +Theresa O'Connor: wrote json.el and changed erc.el erc-viper.el erc-log.el erc-track.el viper.el erc-backend.el erc-chess.el erc-dcc.el erc-ezbounce.el erc-goodies.el erc-list.el erc-macs.el erc-match.el erc-ring.el erc-services.el diff --git a/etc/HISTORY b/etc/HISTORY index 43790bb92bc..ad38b3262d2 100644 --- a/etc/HISTORY +++ b/etc/HISTORY @@ -209,6 +209,8 @@ GNU Emacs 24.5 (2015-04-10) emacs-24.5 GNU Emacs 25.1 (2016-09-16) emacs-25.1 +GNU Emacs 25.2 (2017-04-20) emacs-25.2 + ---------------------------------------------------------------------- This file is part of GNU Emacs. diff --git a/etc/MH-E-NEWS b/etc/MH-E-NEWS index 7e852afb714..6e1f4db1edf 100644 --- a/etc/MH-E-NEWS +++ b/etc/MH-E-NEWS @@ -13,7 +13,7 @@ Version 8.6 fixes composition errors in nmh 1.6. A components file is now generated that works with nmh 1.5 (partially closes SF #468). - + *** Error if mh-x-face-file is nil Ensure that `mh-x-face-file' is a string before trying to use it @@ -284,7 +284,7 @@ This has been fixed (closes SF #1565460). *** Errors Associated with mh-junk-background -The Spamassassin filter commands were used inconsistently and +The SpamAssassin filter commands were used inconsistently and incorrectly; if `mh-junk-background' were nil, not all of the updating would happen correctly. In the other back-ends such as bogofilter and SpamProbe, a value of t for `mh-junk-background' would cause the @@ -1147,9 +1147,9 @@ The -face suffix has been dropped from all face names. Items in swish indexes that aren't mail messages are now handled more gracefully. -*** Spamassassin Fixes +*** SpamAssassin Fixes -If you use spamassassin, there was an error when you tried to junk +If you use SpamAssassin, there was an error when you tried to junk mail if the option `mh-junk-background' was set. This has been fixed. *** Mairix Support diff --git a/etc/NEWS b/etc/NEWS index 5b5baff44e1..71a2da1b637 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -21,13 +21,6 @@ Temporary note: --- means no change in the manuals is needed. When you add a new item, use the appropriate mark if you are sure it applies, -+++ -** The version number of CC Mode has been changed from 5.33 to -5.32.99, although the software itself hasn't changed. This aims to -reduce confusion with the standalone CC Mode 5.33 (available from -http://cc-mode.sourceforge.net), which is a more mature version than -the one in Emacs 25.2. - * Installation Changes in Emacs 26.1 @@ -37,12 +30,21 @@ Use 'configure --with-gnutls=no' to build even when GnuTLS is missing. ** GnuTLS version 2.12.2 or later is now required, instead of merely version 2.6.6 or later. +** The new option 'configure --with-mailutils' causes Emacs to rely on +GNU Mailutils 'movemail' to retrieve email. By default, the Emacs +build procedure continues to build and install a limited and insecure +'movemail' substitute. Although --with-mailutils is recommended, it +is not yet the default due to backward-compatibility concerns. + ** The new option 'configure --enable-gcc-warnings=warn-only' causes GCC to issue warnings without stopping the build. This behavior is now the default in developer builds. As before, use '--disable-gcc-warnings' to suppress GCC's warnings, and '--enable-gcc-warnings' to stop the build if GCC issues warnings. +** When GCC warnings are enabled, '--enable-check-lisp-object-type' is +now enabled by default when configuring. + +++ ** The Emacs server now has socket-launching support. This allows socket based activation, where an external process like systemd can @@ -65,18 +67,30 @@ emacs-version and erc-cmd-SV functions, and the leave the following variables nil: emacs-build-system, emacs-build-time, erc-emacs-build-time. +** The configure option '--with-gameuser' now defaults to 'no', +as this appears to be the most common configuration in practice. +When it is 'no', the shared game directory and the auxiliary program +update-game-score are no longer needed and are not installed. + ** Emacs no longer works on IRIX. We expect that Emacs users are not affected by this, as SGI stopped supporting IRIX in December 2013. * Startup Changes in Emacs 26.1 -** New option '--new-daemon'. This is the same as '--daemon', except ++++ +** New option '--fg-daemon'. This is the same as '--daemon', except it runs in the foreground and does not fork. This is intended for modern init systems such as systemd, which manage many of the traditional -aspects of daemon behavior themselves. '--old-daemon' is now an alias +aspects of daemon behavior themselves. '--bg-daemon' is now an alias for '--daemon'. +** New option '--module-assertions'. If the user supplies this +option, Emacs will perform expensive correctness checks when dealing +with dynamic modules. This is intended for module authors that wish +to verify that their module conforms to the module requirements. The +option makes Emacs abort if a module-related assertion triggers. + +++ ** Emacs now supports 24-bit colors on capable text terminals Terminal is automatically initialized to use 24-bit colors if the @@ -86,6 +100,11 @@ required capabilities are found in terminfo. See the FAQ node * Changes in Emacs 26.1 ++++ +** The function 'assoc' now takes an optional third argument 'testfn'. +This argument, when non-nil, is used for comparison instead of +'equal'. + ** The variable 'emacs-version' no longer includes the build number. This is now stored separately in a new variable, 'emacs-build-number'. @@ -115,6 +134,22 @@ given file is on a case-insensitive filesystem. of curved quotes for 'electric-quote-mode', allowing user to choose the types of quotes to be used. +** The new user option 'electric-quote-context-sensitive' makes +'electric-quote-mode' context sensitive. If it is non-nil, you can +type an ASCII apostrophe to insert an opening or closing quote, +depending on context. Emacs will replace the apostrophe by an opening +quote character at the beginning of the buffer, the beginning of a +line, after a whitespace character, and after an opening parenthesis; +and it will replace the apostrophe by a closing quote character in all +other cases. + +** The new variable 'electric-quote-inhibit-functions' controls when +to disable electric quoting based on context. Major modes can add +functions to this list; Emacs will temporarily disable +'electric-quote-mode' whenever any of the functions returns non-nil. +This can be used by major modes that derive from 'text-mode' but allow +inline code segments, such as 'markdown-mode'. + +++ ** The new user variable 'dired-omit-case-fold' allows the user to customize the case-sensitivity of dired-omit-mode. It defaults to @@ -131,8 +166,8 @@ you can disable the feature by adding '(inhibit-double-buffering . t) -to default-frame-parameters. Or inject this parameter into the -selected frame by evaluating this form: +to default-frame-alist. Or inject this parameter into the selected +frame by evaluating this form: (modify-frame-parameters nil '((inhibit-double-buffering . t))) @@ -161,6 +196,10 @@ of a parenthetical grouping or string-delimiter: the default value nil keeps point at the end of the region, setting it to non-nil moves point to the beginning of the region. ++++ +** The new user option 'mouse-drag-and-drop-region' allows to drag the +entire region of text to another place or another buffer. + +++ ** The new user option 'confirm-kill-processes' allows the user to skip a confirmation prompt for killing subprocesses when exiting @@ -302,6 +341,15 @@ questions, with a handy way to display help texts. all call stack frames in a Lisp backtrace buffer as lists. Both debug.el and edebug.el have been updated to heed to this variable. +--- +** Values in call stack frames are now displayed using 'cl-prin1'. +The old behaviour of using 'prin1' can be restored by customizing the +new option 'debugger-print-function'. + ++++ +** NUL bytes in strings copied to the system clipboard are now +replaced with "\0". + +++ ** The new variable 'x-ctrl-keysym' has been added to the existing roster of X keysyms. It can be used in combination with another @@ -321,13 +369,131 @@ substituted by a home directory by writing it as "/foo:/:/~/file". settings of 'scroll-margin' up to half the window size, instead of always restricting the margin to a quarter of the window. ++++ +** Emacs can scroll horizontally using mouse, touchpad, and trackbar. +You can enable this by customizing 'mwheel-tilt-scroll-p'. If you +want to reverse the direction of the scroll, customize +'mwheel-flip-direction'. + +++ ** Emacsclient has a new option -u/--suppress-output. The option suppresses display of return values from the server process. +--- +** New user option 'dig-program-options' and extended functionality +for DNS-querying functions 'nslookup-host', 'dns-lookup-host', +and 'run-dig'. Each function now accepts an optional name server +argument interactively (with a prefix argument) and non-interactively. + ++++ +** Emacsclient has a new option -T/--tramp. +This helps with using a local Emacs session as the server for a remote +emacsclient. With appropriate setup, one can now set the EDITOR +environment variable on a remote machine to emacsclient, and +use the local Emacs to edit remote files via Tramp. See the node +"emacsclient Options" in the user manual for the details. + ++++ +** 'describe-key-briefly' now ignores mouse movement events. + ++++ +** The new variable 'eval-expression-print-maximum-character' prevents +large integers from being displayed as characters. + +** Two new commands for finding the source code of Emacs Lisp +libraries: 'find-library-other-window' and 'find-library-other-frame'. + ++++ +** The new variable 'display-raw-bytes-as-hex' allows to change the +display of raw bytes from octal to hex. + +** You can now provide explicit field numbers in format specifiers. +For example, '(format "%2$s %1$s" "X" "Y")' produces "Y X". + +** 'comment-indent-function' values may now return a cons to specify a +range of indentation. + ++++ +** Emacs now supports optional display of line numbers in the buffer. +This is similar to what linum-mode provides, but much faster and +doesn't usurp the display margin for the line numbers. Customize the +buffer-local variable 'display-line-numbers' to activate this optional +display. If set to t, Emacs will display the number of each line +before the line. If set to 'relative', Emacs will display the line +number relative to the line showing point, with that line's number +displayed as absolute. If set to 'visual', Emacs will display a +relative number for every screen line, i.e. it will count screen lines +rather than buffer lines. The default is nil, which doesn't display +the line numbers. + +In 'relative' and 'visual' modes, the variable +'display-line-numbers-current-absolute' controls what number is +displayed for the line showing point. By default, this variable's +value is t, which means display the absolute line number for the line +showing point. Customizing this variable to a nil value will cause +Emacs to show zero instead, which preserves horizontal space of the +window in large buffers. + +Line numbers are not displayed at all in minibuffer windows and in +tooltips, as they are not useful there. + +The new face 'line-number' is used to display the line numbers. The +new face 'line-number-current-line' can be customized to display the +current line's number differently from all the other line numbers; by +default these two faces are identical. + +You can also customize the new variable 'display-line-numbers-width' to +specify a fixed minimal with of the area allocated to line-number +display. The default is nil, meaning that Emacs will dynamically +calculate the area width, enlarging or shrinking it as needed. +Setting it to a non-negative integer specifies that as the minimal +width; selecting a value that is large enough to display all line +numbers in a buffer will then keep the line-number display area of +constant width at all times, if that is desired. + +Lisp programs can disable line-number display for a particular screen +line by putting the 'display-line-numbers-disable' text property or +overlay property on the first character of that screen line. This is +intended for add-on packages that need a finer control of the display. + +Lisp programs that need to know how much screen estate is used up for +line-number display in a window can use the new function +'line-number-display-width'. + +Linum mode and all similar packages are henceforth becoming obsolete. +Users and developers are encouraged to switch to this new feature +instead. + * Editing Changes in Emacs 26.1 ++++ +** New variable 'column-number-indicator-zero-based'. +Traditionally, in Column Number mode, the displayed column number +counts from zero starting at the left margin of the window. This +behavior is now controlled by 'column-number-indicator-zero-based'. +If you would prefer for the displayed column number to count from one, +you may set this variable to nil. (Behind the scenes, there is now a +new mode line construct, '%C', which operates exactly as '%c' does +except that it counts from one.) + ++++ +** New single-line horizontal scrolling mode. +The 'auto-hscroll-mode' variable can now have a new special value, +'current-line', which causes only the line where the cursor is +displayed to be horizontally scrolled when lines are truncated on +display and point moves outside the left or right window margin. + ++++ +** New mode line constructs '%o' and '%q', and user option +'mode-line-percent-position'. '%o' displays the "degree of travel" of +the window through the buffer. Unlike the default '%p', this +percentage approaches 100% as the window approaches the end of the +buffer. '%q' displays the percentage offsets of both the start and +the end of the window, e.g. "5-17%". The new option +'mode-line-percent-position' makes it easier to switch between '%p', +'%P', and these new constructs. + +++ ** Two new user options 'list-matching-lines-jump-to-current-line' and 'list-matching-lines-current-line-face' to show highlighted the current @@ -351,16 +517,64 @@ same as in modes where the character is not whitespace. Instead of only checking the modification time, Emacs now also checks the file's actual content before prompting the user. -** Title case characters are properly converted to upper case. -'upcase', 'upcase-region' et al. convert title case characters (such -as the single character "Dz") into their upper case form (such as "DZ"). -As a downside, 'capitalize' and 'upcase-initials' produce awkward -words where first character is upper rather than title case, e.g., -"DŽungla" instead of "Džungla". +** Various casing improvements. + +*** 'upcase', 'upcase-region' et al. convert title case characters +(such as Dz) into their upper case form (such as DZ). + +*** 'capitalize', 'upcase-initials' et al. make use of title-case forms +of initial characters (correctly producing for example Džungla instead +of incorrect DŽungla). + +*** Characters which turn into multiple ones when cased are correctly handled. +For example, fi ligature is converted to FI when upper cased. + +*** Greek small sigma is correctly handled when at the end of the word. +Strings such as ΌΣΟΣ are now correctly converted to Όσος when +capitalized instead of incorrect Όσοσ (compare lowercase sigma at the +end of the word). + +** Emacs can now auto-save buffers to visited files in a more robust +manner via the new mode 'auto-save-visited-mode'. Unlike +'auto-save-visited-file-name', this mode uses the normal saving +procedure and therefore obeys saving hooks. +'auto-save-visited-file-name' is now obsolete. + ++++ +** New behavior of 'mark-defun' implemented +Prefix argument selects that many (or that many more) defuns. +Negative prefix arg flips the direction of selection. Also, +'mark-defun' between defuns correctly selects N following defuns (or +-N previous for negative arguments). Finally, comments preceding the +defun are selected unless they are separated from the defun by a blank +line. + +** New command 'replace-buffer-contents'. +This command replaces the contents of the accessible portion of the +current buffer with the contents of the accessible portion of a +different buffer while keeping point, mark, markers, and text +properties as intact as possible. * Changes in Specialized Modes and Packages in Emacs 26.1 +** Dired +You can now use '`?`' in 'dired-do-shell-command'; as ' ? ', it gets replaced +by the current file name. + +*** html2text is now marked obsolete. + +*** smerge-refine-regions can refine regions in separate buffers + +*** Info menu and index completion uses substring completion by default. +This can be customized via the info-menu category in +completion-category-override. + ++++ +*** The ancestor buffer is shown by default in 3way merges. +A new option ediff-show-ancestor and a new toggle +ediff-toggle-show-ancestor. + ** TeX: Add luatex and xetex as alternatives to pdftex ** Electric-Buffer-menu @@ -462,8 +676,6 @@ where to place point after C-c M-r and C-c M-s. --- *** Messages from CMake are now recognized. -** Dired - +++ *** A new option 'dired-always-read-filesystem' default to nil. If non-nil, buffers visiting files are reverted before search them; @@ -523,6 +735,20 @@ replaced by the real images asynchronously, which will also now respect width/height HTML specs (unless they specify widths/heights bigger than the current window). +--- +*** The 'w' command on links is now 'shr-maybe-probe-and-copy-url'. +'shr-copy-url' now only copies the url at point; users who wish to +avoid accidentally accessing remote links may rebind 'w' and 'u' in +'eww-link-keymap' to it. + + +** Ido + +*** The commands 'find-alternate-file-other-window', +'dired-other-window', 'dired-other-frame', and +'display-buffer-other-window' are now remapped to Ido equivalents if +Ido mode is active. + ** Images +++ @@ -622,8 +848,30 @@ In 'visual-line-mode' it will look for the true beginning of a header while in non-'visual-line-mode' it will move the point to the indented header's value. +** Package + ++++ +*** The new variable 'package-gnupghome-dir' has been added to control +where the GnuPG home directory (used for signature verification) is +located and whether GnuPG's option "--homedir" is used or not. + +--- +*** Deleting a package no longer respects 'delete-by-moving-to-trash'. + ** Tramp ++++ +*** The method part of remote file names is mandatory now. A valid +remote file name starts with "/method:host:" or "/method:user@host:". + ++++ +*** The new pseudo method "-" is a marker for the default method. +"/-::" is the shortest remote file name then. + ++++ +*** The command 'tramp-change-syntax' allows to choose an alternative +remote file name syntax. + +++ *** New connection method "sg", which supports editing files under a different group ID. @@ -650,8 +898,15 @@ initialization files. --- ** 'auto-revert-use-notify' is set back to t in 'global-auto-revert-mode'. +** JS mode + --- -** JS mode now sets 'comment-multi-line' to t. +*** JS mode now sets 'comment-multi-line' to t. + +--- +*** New variable 'js-indent-align-list-continuation', when set to nil, +will not align continuations of bracketed lists, but will indent them +by the fixed width 'js-indent-level'. ** CSS mode @@ -668,6 +923,11 @@ pseudo-element, with the default being guessed from context). By default the information is looked up on the Mozilla Developer Network, but this can be customized using 'css-lookup-url-format'. +--- +*** CSS colors are fontified using the color they represent as the +background. For instance, #ff0000 would be fontified with a red +background. + +++ ** Emacs now supports character name escape sequences in character and string literals. The syntax variants \N{character name} and @@ -725,6 +985,10 @@ This is done with the help of 'c-or-c++-mode' function which analyses contents of the buffer to determine whether it's a C or C++ source file. +--- +** New DNS mode command 'dns-mode-ipv6-to-nibbles' to convert IPv6 addresses +to a format suitable for reverse lookup zone files. + ** Flymake +++ @@ -738,12 +1002,28 @@ processes on exit. ** New library 'xdg' with utilities for some XDG standards and specs. +** HTML + ++++ +*** A new submode of 'html-mode', 'mhtml-mode', is now the default +mode for *.html files. This mode handles indentation, +fontification, and commenting for embedded JavaScript and CSS. + +** New minor mode 'pixel-scroll-mode' provides smooth pixel-level scrolling. + * Incompatible Lisp Changes in Emacs 26.1 +++ -** Resizing a frame no longer runs 'window-configuration-change-hook'. -Put your function on 'window-size-change-functions' instead. +*** Command 'dired-mark-extension' now automatically prepends a '.' to the +extension when not present. The new command 'dired-mark-suffix' behaves +similarly but it doesn't prepend a '.'. + ++++ +** Certain cond/pcase/cl-case forms are now compiled using a faster jump +table implementation. This uses a new bytecode op 'switch', which isn't +compatible with previous Emacs versions. This functionality can be disabled +by setting 'byte-compile-cond-use-jump-table' to nil. ** 'C-up', 'C-down', 'C-left' and 'C-right' are now defined in term mode to send the same escape sequences that xterm does. This makes @@ -768,6 +1048,7 @@ of not providing replacement pairs via the history. *** make-variable-frame-local. Variables cannot be frame-local any more. *** From subr.el: window-dot, set-window-dot, read-input, show-buffer, eval-current-buffer, string-to-int +*** icomplete-prospects-length. *** All the default-FOO variables that hold the default value of the FOO variable. Use 'default-value' and 'setq-default' to access and change FOO, respectively. The exhaustive list of removed variables is: @@ -803,9 +1084,36 @@ Unicode horizontal whitespace as defined in the Unicode Technical Standard #18. If you only want to match space and tab, use [ \t] instead. ++++ +** 'min' and 'max' no longer round their results. Formerly, they +returned a floating-point value if any argument was floating-point, +which was sometimes numerically incorrect. For example, on a 64-bit +host (max 1e16 10000000000000001) now returns its second argument +instead of its first. + ++++ +** The variable 'old-style-backquotes' has been made internal and +renamed to 'lread--old-style-backquotes'. No user code should use +this variable. + ++++ +** Module functions are now implemented slightly differently; in +particular, the function 'internal--module-call' has been removed. +Code that depends on undocumented internals of the module system might +break. + * Lisp Changes in Emacs 26.1 +** New function 'seq-set-equal-p' to check if SEQUENCE1 and SEQUENCE2 +contain the same elements, regardless of the order. + ++++ +** Emacs now supports records for user-defined types, via the new +functions 'make-record', 'record', and 'recordp'. Records are now +used internally to represent cl-defstruct and defclass instances, for +example. + +++ ** 'save-some-buffers' now uses 'save-some-buffers-default-predicate' to decide which buffers to ask about, if the PRED argument is nil. @@ -843,21 +1151,6 @@ If no insurmountable problems before next release, it can stay that way. ** 'gnutls-boot' now takes a parameter ':complete-negotiation' that says that negotiation should complete even on non-blocking sockets. -+++ -** New functions 'window-pixel-width-before-size-change' and -'window-pixel-height-before-size-change' support detecting which -window changed size when 'window-size-change-functions' are run. - -+++ -** New function 'display-buffer-reuse-mode-window' is an action function -suitable for use in 'display-buffer-alist'. For example, to avoid creating -a new window when opening man pages when there's already one, use -(add-to-list 'display-buffer-alist - '("\\`\\*Man .*\\*\\'" . - (display-buffer-reuse-mode-window - (inhibit-same-window . nil) - (mode . Man-mode)))) - --- ** There is now a new variable 'flyspell-sort-corrections-function' that allows changing the way corrections are sorted. @@ -902,6 +1195,30 @@ interpreting consecutive runs of numerical characters as numbers, and compares their numerical values. According to this predicate, "foo2.png" is smaller than "foo12.png". +--- +** Numeric comparisons and 'logb' no longer return incorrect answers +due to internal rounding errors. For example, (< most-positive-fixnum +(+ 1.0 most-positive-fixnum)) now correctly returns t on 64-bit hosts. + +--- +** The functions 'ffloor', 'fceiling', 'ftruncate' and 'fround' now +accept only floating-point arguments, as per their documentation. +Formerly, they quietly accepted integer arguments and sometimes +returned nonsensical answers, e.g., (< N (ffloor N)) could return t. + +--- +** On hosts like GNU/Linux x86-64 where a 'long double' fraction +contains at least EMACS_INT_WIDTH - 3 bits, 'format' no longer returns +incorrect answers due to internal rounding errors when formatting +Emacs integers with %e, %f, or %g conversions. For example, on these +hosts (eql N (string-to-number (format "%.0f" N))) now returns t for +all Emacs integers N. + +--- +** Calls that accept floating-point integers (for use on hosts with +limited integer range) now signal an error if arguments are not +integral. For example (decode-char 'ascii 0.5) now signals an error. + +++ ** The new function 'char-from-name' converts a Unicode name string to the corresponding character code. @@ -973,8 +1290,129 @@ that does not exist. operating recursively and when some other process deletes the directory or its files before 'delete-directory' gets to them. ++++ +*** New error type 'user-search-failed' like 'search-failed' but +avoids debugger like 'user-error'. + ++++ +** The function 'line-number-at-pos' now takes a second optional +argument 'absolute'. If this parameter is nil, the default, this +function keeps on returning the line number taking potential narrowing +into account. If this parameter is non-nil, the function ignores +narrowing and returns the absolute line number. + ** Changes in Frame- and Window- Handling ++++ +*** Resizing a frame no longer runs 'window-configuration-change-hook'. +'window-size-change-functions' should be used instead. + ++++ +*** The new function 'frame-size-changed-p' can tell whether a frame has +been resized since the last time 'window-size-change-functions' has been +run. + ++++ +*** The function 'frame-geometry' now also returns the width of a +frame's outer border. + ++++ +*** New frame parameters and changed semantics for older ones + ++++ +**** 'z-group' positions a frame above or below all others. + ++++ +**** 'min-width' and 'min-height' specify the absolute minimum size of a +frame. + ++++ +**** 'parent-frame' makes a frame the child frame of another Emacs +frame. The section "Child Frames" in the Elisp manual describes the +intrinsics of that relationship. + ++++ +**** 'delete-before' triggers deletion of one frame before that of +another. + ++++ +**** 'mouse-wheel-frame' specifies another frame whose windows shall be +scrolled instead. + ++++ +**** 'no-other-frame' has 'next-frame' and 'previous-frame' skip this +frame. + ++++ +**** 'skip-taskbar' removes a frame's icon from the taskbar and has +Alt-<TAB> skip this frame. + ++++ +**** 'no-focus-on-map' avoids that a frame gets input focus when mapped. + ++++ +**** 'no-accept-focus' means that a frame does not want to get input +focus via the mouse. + ++++ +**** 'undecorated' removes the window manager decorations from a frame. + ++++ +**** 'override-redirect' tells the window manager to disregard this +frame. + ++++ +**** 'width' and 'height' allow to specify pixel values and ratios now. + ++++ +**** 'left' and 'top' allow to specify ratios now. + ++++ +**** 'keep-ratio' preserves size and position of child frames when their +parent frame is resized. + ++++ +**** 'no-special-glyphs' suppresses display of truncation and +continuation glyphs in a frame. + ++++ +**** 'auto-hide-function' and 'minibuffer-exit' handle auto hiding of +frames and exiting from minibuffer individually. + ++++ +**** 'fit-frame-to-buffer-margins' and 'fit-frame-to-buffer-sizes' +handle fitting a frame to its buffer individually. + ++++ +**** 'drag-internal-border', 'drag-with-header-line', +'drag-with-mode-line', 'snap-width', 'top-visible' and 'bottom-visible' +allow to drag and resize frames with the mouse. + +*** The new function 'frame-list-z-order' returns a list of all frames +in Z (stacking) order. + ++++ +*** The function 'x-focus-frame' optionally tries to not activate its +frame. + ++++ +*** The variable 'focus-follows-mouse' has a third meaningful value +'auto-raise' to indicate that the window manager automatically raises a +frame when the mouse pointer enters it. + ++++ +*** The new function 'frame-restack' puts a frame above or below +another on the display. + ++++ +*** The new face 'internal-border' specifies the background of a frame's +internal border. + ++++ +*** The NORECORD argument of 'select-window' now has a meaningful value +'mark-for-redisplay' which is like any other non-nil value but marks +WINDOW for redisplay. + +++ *** Support for side windows is now official. The display action function 'display-buffer-in-side-window' will display its buffer in a @@ -993,14 +1431,51 @@ section "Atomic Windows" in the Elisp manual. *** New 'display-buffer' alist entry 'window-parameters' allows to assign window parameters to the window used for displaying the buffer. ++++ +*** New function 'display-buffer-reuse-mode-window' is an action function +suitable for use in 'display-buffer-alist'. For example, to avoid creating +a new window when opening man pages when there's already one, use +(add-to-list 'display-buffer-alist + '("\\`\\*Man .*\\*\\'" . + (display-buffer-reuse-mode-window + (inhibit-same-window . nil) + (mode . Man-mode)))) + +++ *** New window parameter 'no-delete-other-window' prevents that its window gets deleted by 'delete-other-windows'. ++++ +*** New window parameters 'mode-line-format' and 'header-line-format' +allow to override the buffer-local formats for this window. + +++ *** New command 'window-swap-states' swaps the states of two live windows. ++++ +*** New functions 'window-pixel-width-before-size-change' and +'window-pixel-height-before-size-change' support detecting which +window changed size when 'window-size-change-functions' are run. + ++++ +*** The new function 'window-lines-pixel-dimensions' returns the pixel +dimensions of a window's text lines. + ++++ +*** The new function 'window-largest-empty-rectangle' returns the +dimensions of the largest rectangular area not occupying any text in a +window's body. + ++++ +*** The semantics of 'mouse-autoselect-window' has changed slightly. +For details see the section "Mouse Window Auto-selection" in the Elisp +manual. + +--- +** 'tcl-auto-fill-mode' is now declared obsolete. Its functionality +can be replicated simply by setting 'comment-auto-fill-only-comments'. + * Changes in Emacs 26.1 on Non-Free Operating Systems @@ -1043,6 +1518,9 @@ This is in contrast to the default action on POSIX Systems, where it causes the receiving process to terminate with a core dump if no debugger has been attached to it. +** 'set-mouse-position' and 'set-mouse-absolute-pixel-position' work +on macOS. + ---------------------------------------------------------------------- This file is part of GNU Emacs. diff --git a/etc/NEWS.25 b/etc/NEWS.25 index c5e95d37c84..539e56e42a0 100644 --- a/etc/NEWS.25 +++ b/etc/NEWS.25 @@ -17,38 +17,37 @@ with a prefix argument or by typing C-u C-h C-n. * Changes in Emacs 25.2 -This is a bug-fix release with (almost) no new features. ---- +This is mainly a bug-fix release, but there are some other changes. + ** 'find-library', 'help-function-def' and 'help-variable-def' now run 'find-function-after-hook'. -+++ ** New basic face 'fixed-pitch-serif', for a fixed-width font with serifs. -The 'Info-quoted' and 'tex-verbatim' faces now default to inheriting -from it. +The 'Info-quoted' and 'tex-verbatim' faces inherit from it by default. ---- -** New variable 'use-default-font-for-symbols' for backward compatibility. -This variable allows to get back pre-Emacs 25 behavior whereby the +** New variable 'use-default-font-for-symbols', for backward compatibility. +This variable allows you to get back pre-Emacs 25 behavior where the font for displaying symbol and punctuation characters was always -selected according to your fontset setup. Emacs 25 by default tries -to use the default face's font for such characters, disregarding the -fontsets if the default font supports these characters. Set this -variable to nil to disable the new behavior and get back the old -behavior. +selected according to your fontset setup. By default, Emacs 25 tries +to use the default face's font for such characters, if it supports +them, disregarding the fontsets. Set this variable to nil to disable +this and get back the old behavior. -+++ ** 'electric-quote-mode' is no longer suppressed in a buffer whose -whose coding system cannot represent curved quote characters. +coding system cannot represent curved quote characters. Instead, users can deal with the unrepresentable characters in the usual way when they save the buffer. ---- ** New variable 'inhibit-compacting-font-caches'. Set this variable to a non-nil value to speed up display of characters -using large fonts, at the price of a larger memory footprint of the -Emacs session. +using large fonts, at the price of a larger memory footprint. + +** The version number of CC Mode has been changed from 5.33 to +5.32.99, although the software itself hasn't changed. This aims to +reduce confusion with the standalone CC Mode 5.33 (available from +http://cc-mode.sourceforge.net), which is a more mature version than +the one included in Emacs 25.2. * Installation Changes in Emacs 25.1 diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index 38df7b2bd87..f8399dbf1e8 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -1,17 +1,1368 @@ ORG NEWS -- history of user-visible changes. -*- mode: org; coding: utf-8 -*- #+LINK: doc http://orgmode.org/worg/doc.html#%s -#+LINK: git http://orgmode.org/w/?p=org-mode.git;a=commit;h=%s +#+LINK: git http://orgmode.org/cgit.cgi/org-mode.git/commit/?id=%s Copyright (C) 2012-2017 Free Software Foundation, Inc. See the end of the file for license conditions. -Please send Org bug reports to emacs-orgmode@gnu.org. +Please send Org bug reports to mailto:emacs-orgmode@gnu.org. -* Version 8.2.3 +* Version 9.0 ** Incompatible changes +*** Emacs 23 support has been dropped + +From now on, Org expects at least Emacs 24.3, although Emacs 24.4 or +above is suggested. + +*** XEmacs support has been dropped + +Incomplete compatibility layer with XEmacs has been removed. If you +want to take over maintenance of this compatibility, please contact +our mailing list. + +*** New syntax for export blocks + +Export blocks are explicitly marked as such at the syntax level to +disambiguate their parsing from special blocks. The new syntax is + +#+BEGIN_SRC org +,#+BEGIN_EXPORT backend +... +,#+END_EXPORT +#+END_SRC + +instead of + +#+BEGIN_SRC org +,#+BEGIN_backend +... +,#+END_backend +#+END_SRC + +As a consequence, =INCLUDE= keywords syntax is modified, e.g., + +#+BEGIN_SRC org +,#+INCLUDE: "file.org" HTML +#+END_SRC + +becomes + +#+BEGIN_SRC org +,#+INCLUDE: "file.org" export html +#+END_SRC + +The following function repairs export blocks and =INCLUDE= keywords +using previous syntax: + +#+BEGIN_SRC emacs-lisp +(defun org-repair-export-blocks () + "Repair export blocks and INCLUDE keywords in current buffer." + (interactive) + (when (eq major-mode 'org-mode) + (let ((case-fold-search t) + (back-end-re (regexp-opt + '("HTML" "ASCII" "LATEX" "ODT" "MARKDOWN" "MD" "ORG" + "MAN" "BEAMER" "TEXINFO" "GROFF" "KOMA-LETTER") + t))) + (org-with-wide-buffer + (goto-char (point-min)) + (let ((block-re (concat "^[ \t]*#\\+BEGIN_" back-end-re))) + (save-excursion + (while (re-search-forward block-re nil t) + (let ((element (save-match-data (org-element-at-point)))) + (when (eq (org-element-type element) 'special-block) + (save-excursion + (goto-char (org-element-property :end element)) + (save-match-data (search-backward "_")) + (forward-char) + (insert "EXPORT") + (delete-region (point) (line-end-position))) + (replace-match "EXPORT \\1" nil nil nil 1)))))) + (let ((include-re + (format "^[ \t]*#\\+INCLUDE: .*?%s[ \t]*$" back-end-re))) + (while (re-search-forward include-re nil t) + (let ((element (save-match-data (org-element-at-point)))) + (when (and (eq (org-element-type element) 'keyword) + (string= (org-element-property :key element) "INCLUDE")) + (replace-match "EXPORT \\1" nil nil nil 1))))))))) +#+END_SRC + +Moreover, ~:export-block~ keyword used in ~org-export-define-backend~ and +~org-export-define-derived-backend~ is no longer used and needs to be +removed. + +*** Footnotes + +**** [1]-like constructs are not valid footnotes + +Using =[1]= as a footnote was already discouraged in the manual, since +it introduced too many false-positives in many Org documents. These +constructs are now unsupported. + +If you used =[N]= in some of your documents, consider turning them into +=[fn:N]=. + +**** /Org Footnote/ library doesn't handle non-Org buffers + +Commands for footnotes in an Org document no longer try to do +something in non-Org ones. If you need to have footnotes there, +consider using the =footnote.el= library, shipped with Emacs. + +In particular, ~org-footnote-tag-for-non-org-mode-files~ no longer +exists. + +*** ~org-file-apps~ no longer accepts S-expressions as commands + +The variable now accepts functions of two arguments instead of plain +S-expressions. Replacing an S-expression with an appropriate function +is straightforward. For example + +: ("pdf" . (foo)) + +becomes + +: ("pdf" . (lambda (file link) (foo))) + +*** The ~{{{modification-time}}}~ macro can get time via =vc= + +The modification time will be determined via =vc.el= if the second +argument is non-nil. See the manual for details. + +*** Preparation and completion functions in publishing projects change signature + +Preparation and completion functions are now called with an argument, +which is the project property list. It used to be dynamically scoped +through the ~project-plist~ variable. + +*** Old Babel header properties are no longer supported + +Using header arguments as property names is no longer possible. As +such, the following + +#+BEGIN_EXAMPLE +,* Headline +:PROPERTIES: +:exports: code +:var: a=1 b=2 +:var+: c=3 +:END: +#+END_EXAMPLE + +should be written instead + +#+BEGIN_EXAMPLE +,* Headline +:PROPERTIES: +:header-args: :exports code +:header-args: :var a=1 b=2 +:header-args+: :var c=3 +:END: +#+END_EXAMPLE + +Please note that, however, old properties were defined at the source +block definition. Current ones are defined where the block is called. + +** New features + +*** ~org-eww~ has been moved into core +*** New org-protocol key=value syntax + +Org-protocol can now handle query-style parameters such as: + +#+begin_example +org-protocol://store-link?url=http:%2F%2Flocalhost%2Findex.html&title=The%20title +org-protocol://capture?template=x&title=Hello&body=World&url=http:%2F%2Fexample.com +#+end_example + +Old-style links such as +: org-protocol://store-link:/http:%2F%2Flocalhost%2Findex.html/The%20title +continue to be supported. + +If you have defined your own handler functions for +~org-protocol-protocol-alist~, change them to accept either a property +list (for new-style links) or a string (for old-style links). Use +~org-protocol-parse-parameters~ to convert old-style links into property +lists. + +*** New Org linter library + +~org-lint~ can check syntax and report common issues in Org documents. + +*** New option ~date-tree-last~ for ~org-agenda-insert-diary-strategy~ + +When ~org-agenda-insert-diary-strategy~ is set to ~date-tree-last~, diary +entries are added to last in the date tree. + +*** New ~vbar~ entity + +~\vbar~ or ~\vbar{}~ will be exported unconditionally as a =|=, +unlike to existing ~\vert~, which is expanded as ~|~ when using +a HTML derived export back-end. + +*** Export + +**** New =#+latex_compiler= keyword to set LaTeX compiler. + +PDFLaTeX, XeLaTeX, and LuaLaTeX are supported. See the manual for +details. + +**** New option ~org-export-with-broken-links~ + +This option tells the export process how to behave when encountering +a broken internal link. See its docstring for more information. + +**** Attributes support in custom language environments for LaTeX export + +Custom language environments for LaTeX export can now define the +string to be inserted during export, using attributes to indicate the +position of the elements. See variable ~org-latex-custom-lang-environments~ +for more details. + +**** New Texinfo ~options~ attribute on special blocks + +Using ~:options~ as a Texinfo attribute, it is possible to add +information to custom environments. See manual for details. + +**** New HTML ~id~ attributes on special, example and quote blocks + +If the block has a =#+NAME:= attribute assigned, then the HTML element +will have an ~id~ attribute with that name in the HTML export. This +enables one to create links to these elements in other places, e.g., +~<a href="#name">text</a>~. + +**** Listings with captions are now numbered in HTML export + +The class associated to the numbering is "listing-number". If you +don't want these blocks to be numbered, as it was the case until now, +You may want to add ~.listing-number { display: none; }~ to the CSS +used. + +**** Line Numbering in SRC/EXAMPLE blocks support arbitrary start number + +The ~-n~ option to ~SRC~ and ~EXAMPLE~ blocks can now take a numeric +argument to specify the staring line number for the source or example +block. The ~+n~ option can now take a numeric argument that will be +added to the last line number from the previous block as the starting +point for the SRC/EXAMPLE block. + +#+BEGIN_SRC org +,#+BEGIN_SRC emacs-lisp -n 20 +;; this will export with line number 20 +(message "This is line 21") +,#+END_SRC +,#+BEGIN_SRC emacs-lisp +n 10 +;; This will be listed as line 31 +(message "This is line 32") +,#+END_SRC +#+END_SRC + +**** Allow toggling center for images in LaTeX export + +With the global variable ~org-latex-images-centered~ or the local +attribute ~:center~ it is now possible to center an image in LaTeX +export. + +**** Default CSS class ~org-svg~ for SVG images in HTML export + +SVG images exported in HTML are now by default assigned a CSS class +~org-svg~ if no CSS class is specified with the ~:class~ attribute. By +default, the CSS styling of class ~org-svg~ specifies an image width of +90\thinsp{}% of the container the image. + +**** Markdown footnote export customization + +Variables ~org-md-footnotes-section~ and ~org-md-footnote-format~ +introduced for =ox-md.el=. Both new variables define template strings +which can be used to customize the format of the exported footnotes +section and individual footnotes, respectively. + +*** Babel + +**** Blocks with coderefs labels can now be evaluated + +The labels are removed prior to evaluating the block. + +**** Support for Lua language +**** Support for SLY in Lisp blocks + +See ~org-babel-lisp-eval-fn~ to activate it. + +**** Support for Stan language + +New ob-stan.el library. + +Evaluating a Stan block can produce two different results. + +1. Dump the source code contents to a file. + + This file can then be used as a variable in other blocks, which + allows interfaces like RStan to use the model. + +2. Compile the contents to a model file. + + This provides access to the CmdStan interface. To use this, set + ~org-babel-stan-cmdstan-directory~ and provide a ~:file~ argument + that does not end in ".stan". + +For more information and usage examples, visit +http://orgmode.org/worg/org-contrib/babel/languages/ob-doc-stan.html + +**** Support for Oracle databases via ~sqlplus~ + +=ob-sql= library supports running SQL blocks against an Oracle +database using ~sqlplus~. Use with properties like this (all +mandatory): + +#+BEGIN_EXAMPLE +:engine oracle +:dbhost <host.com> +:dbport <1521> +:dbuser <username> +:database <database> +:dbpassword <secret> +#+END_EXAMPLE + +**** Improved support to Microsoft SQL Server via ~sqlcmd~ + +=ob-sql= library removes support to the ~msosql~ engine which uses the +deprecated ~osql~ command line tool, and replaces it with ~mssql~ +engine which uses the ~sqlcmd~ command line tool. Use with properties +like this: + +#+BEGIN_EXAMPLE +:engine mssql +:dbhost <host.com> +:dbuser <username> +:dbpassword <secret> +:database <database> +#+END_EXAMPLE + +If you want to use the *trusted connection* feature, omit *both* the +=dbuser= and =dbpassword= properties and add =cmdline -E= to the properties. + +If your Emacs is running in a Cygwin environment, the =ob-sql= library +can pass the converted path to the =sqlcmd= tool. + +**** Improved support of header arguments for postgresql + +The postgresql engine in a sql code block supports now ~:dbport~ nd +~:dbpassword~ as header arguments. + +**** Support for additional plantuml output formats + +The support for output formats of [[http://plantuml.com/][plantuml]] has been extended to now +include: + +All Diagrams: +- png :: +- svg :: +- eps :: +- pdf :: +- vdx :: +- txt :: ASCII art +- utxt :: ASCII art using unicode characters + +Class Diagrams: +- xmi :: +- html :: + +State Diagrams: +- scxml :: + +The output formats are determined by the file extension specified +using the :file property, e.g.: + +#+begin_src plantuml :file diagram.png +@startuml +Alice -> Bob: Authentication Request +Bob --> Alice: Authentication Response + +Alice -> Bob: Another authentication Request +Alice <-- Bob: another authentication Response +@enduml +#+end_src + +Please note that *pdf* *does not work out of the box* and needs additional +setup in addition to plantuml. See [[http://plantuml.com/pdf.html]] for +details and setup information. + +*** Rewrite of radio lists + +Radio lists, i.e, Org plain lists in foreign buffers, have been +rewritten to be on par with Radio tables. You can use a large set of +parameters to control how a given list should be rendered. See manual +for details. + +*** org-bbdb-anniversaries-future + +Used like ~org-bbdb-anniversaries~, it provides a few days warning for +upcoming anniversaries (default: 7 days). + +*** Clear non-repeated SCHEDULED upon repeating a task + +If the task is repeated, and therefore done at least one, scheduling +information is no longer relevant. It is therefore removed. + +See [[git:481719fbd5751aaa9c672b762cb43aea8ee986b0][commit message]] for more information. + +*** Support for ISO week trees + +ISO week trees are an alternative date tree format that orders entries +by ISO week and not by month. + +For example: + +: * 2015 +: ** 2015-W35 +: ** 2015-W36 +: *** 2015-08-31 Monday + +They are supported in org-capture via ~file+weektree~ and +~file+weektree+prompt~ target specifications. + +*** Accept ~:indent~ parameter when capturing column view + +When defining a "columnview" dynamic block, it is now possible to add +an :indent parameter, much like the one in the clock table. + +On the other hand, stars no longer appear in an ITEM field. + +*** Columns view + +**** ~org-columns~ accepts a prefix argument + +When called with a prefix argument, ~org-columns~ apply to the whole +buffer unconditionally. + +**** New variable : ~org-agenda-view-columns-initially~ + +The variable used to be a ~defvar~, it is now a ~defcustom~. + +**** Allow custom summaries + +It is now possible to add new summary types, or override those +provided by Org by customizing ~org-columns-summary-types~, which see. + +**** Allow multiple summaries for any property + +Columns can now summarize the same property using different summary +types. + +*** Preview LaTeX snippets in buffers not visiting files +*** New option ~org-attach-commit~ + +When non-nil, commit attachments with git, assuming the document is in +a git repository. + +*** Allow conditional case-fold searches in ~org-occur~ + +When set to ~smart~, the new variable ~org-occur-case-fold-search~ allows +to mimic =isearch.el=: if the regexp searched contains any upper case +character (or character class), the search is case sensitive. +Otherwise, it is case insensitive. + +*** More robust repeated =ox-latex= footnote handling + +Repeated footnotes are now numbered by referring to a label in the +first footnote. + +*** The ~org-block~ face is inherited by ~src-blocks~ + +This works also when =org-src-fontify-natively= is non-nil. It is also +possible to specify per-languages faces. See =org-src-block-faces= and +the manual for details. + +*** Links are now customizable + +Links can now have custom colors, tooltips, keymaps, display behavior, +etc. Links are now centralized in ~org-link-parameters~. + +** New functions + +*** ~org-next-line-empty-p~ + +It replaces the deprecated ~next~ argument to ~org-previous-line-empty-p~. + +*** ~org-show-children~ + +It is a faster implementation of ~outline-show-children~. + +** Removed functions + +*** ~org-agenda-filter-by-tag-refine~ has been removed. + +Use ~org-agenda-filter-by-tag~ instead. + +*** ~org-agenda-todayp~ is deprecated. + +Use ~org-agenda-today-p~ instead. + +*** ~org-babel-get-header~ is removed. + +Use ~org-babel--get-vars~ or ~assq~ instead, as applicable. + +*** ~org-babel-trim~ is deprecated. + +Use ~org-trim~ instead. + +*** ~org-element-remove-indentation~ is deprecated. + +Use ~org-remove-indentation~ instead. + +*** ~org-image-file-name-regexp~ is deprecated + +Use ~image-file-name-regexp~ instead. +The never-used-in-core ~extensions~ argument has been dropped. + +*** ~org-list-parse-list~ is deprecated + +Use ~org-list-to-lisp~ instead. + +*** ~org-on-heading-p~ is deprecated + +A comment to this effect was in the source code since 7.8.03, but +now a byte-compiler warning will be generated as well. + +*** ~org-table-p~ is deprecated + +Use ~org-at-table-p~ instead. + +*** ~org-table-recognize-table.el~ is deprecated + +It was not called by any org code since 2010. + +*** Various reimplementations of cl-lib functions are deprecated + +The affected functions are: +- ~org-count~ +- ~org-remove-if~ +- ~org-remove-if-not~ +- ~org-reduce~ +- ~org-every~ +- ~org-some~ + +Additionally, ~org-sublist~ is deprecated in favor of ~cl-subseq~. Note +the differences in indexing conventions: ~org-sublist~ is 1-based and +end-inclusive; ~cl-subseq~ is 0-based and end-exclusive. + +** Removed options + +*** Remove all options related to ~ido~ or ~iswitchb~ + +This includes ~org-completion-use-iswitchb~ and ~org-completion-use-ido~. +Instead Org uses regular functions, e.g., ~completion-read~ so as to +let those libraries operate. + +*** Remove ~org-list-empty-line-terminates-plain-lists~ + +Two consecutive blank lines always terminate all levels of current +plain list. + +*** ~fixltx2e~ is removed from ~org-latex-default-packages-alist~ + +fixltx2e is obsolete, see LaTeX News 22. + +** Miscellaneous +*** Add Icelandic smart quotes +*** Allow multiple receiver locations in radio tables and lists +*** Allow angular links within link descriptions + +It is now allowed to write, e.g., +~[[http:orgmode.org][<file:unicorn.png>]]~ as an equivalent to +~[[http:orgmode.org][file:unicorn.png]]~. The advantage of the former +is that spaces are allowed within the path. + +*** Beamer export back-ends uses ~org-latex-prefer-user-labels~ +*** ~:preparation-function~ called earlier during publishing + +Functions in this list are called before any file is associated to the +current project. Thus, they can be used to generate to be published +Org files. + +*** Function ~org-remove-indentation~ changes. + +The new algorithm doesn't remove TAB characters not used for +indentation. + +*** Secure placeholders in capture templates + +Placeholders in capture templates are no longer expanded recursively. +However, ~%(...)~ constructs are expanded very late, so you can fill +the contents of the S-exp with the replacement text of non-interactive +placeholders. As before, interactive ones are still expanded as the +very last step, so the previous statement doesn't apply to them. + +Note that only ~%(...)~ placeholders initially present in the +template, or introduced using a file placeholder, i.e., ~%[...]~ are +expanded. This prevents evaluating potentially malicious code when +another placeholder, e.g., ~%i~ expands to a S-exp. + +*** Links stored by ~org-gnus-store-link~ in nnir groups + +Since gnus nnir groups are temporary, ~org-gnus-store-link~ now refers +to the article's original group. + +*** ~org-babel-check-confirm-evaluate~ is now a function instead of a macro + +The calling convention has changed. + +*** HTML export table row customization changes + +Variable ~org-html-table-row-tags~ has been split into +~org-html-table-row-open-tag~ and ~org-html-table-row-close-tag~. +Both new variables can be either a string or a function which will be +called with 6 parameters. + +*** =ITEM= special property returns headline without stars +*** Rename ~org-insert-columns-dblock~ into ~org-columns-insert-dblock~ + +The previous name is, for the time being, kept as an obsolete alias. + +*** ~org-trim~ can preserve leading indentation. + +When setting a new optional argument to a non-nil value, ~org-trim~ +preserves leading indentation while removing blank lines at the +beginning of the string. The behavior is identical for white space at +the end of the string. + +*** Function ~org-info-export~ changes. + +HTML links created from certain info links now point to =gnu.org= URL's rather +than just to local files. For example info links such as =info:emacs#List +Buffers= used to be converted to HTML links like this: + +: <a href="emacs.html#List-Buffers">emacs#List Buffers</a> + +where local file =emacs.html= is referenced. +For most folks this file does not exist. +Thus the new behavior is to generate this HTML link instead: + +: <a href="http://www.gnu.org/software/emacs/manual/html_mono/emacs.html#List-Buffers">emacs#List Buffers</a> + +All emacs related info links are similarly translated plus few other +=gnu.org= manuals. + +*** Repeaters with a ~++~ interval and a time can be shifted to later today + +Previously, if a recurring task had a timestamp of +~<2016-01-01 Fri 20:00 ++1d>~ and was completed on =2016-01-02= at +=08:00=, the task would skip =2016-01-02= and would be rescheduled for +=2016-01-03=. Timestamps with ~++~ cookies and a specific time will +now shift to the first possible future occurrence, even if the +occurrence is later the same day the task is completed. (Timestamps +already in the future are still shifted one time further into the +future.) + +*** ~org-mobile-action-alist~ is now a defconst + +It used to be a defcustom, with a warning that it shouldn't be +modified anyway. + +*** ~file+emacs~ and ~file+sys~ link types are deprecated + +They are still supported in Org 9.0 but will eventually be removed in +a later release. Use ~file~ link type along with universal arguments +to force opening it in either Emacs or with system application. + +*** New defcustom ~org-babel-J-command~ stores the j command +*** New defalias ~org-babel-execute:j~ + +Allows J source blocks be indicated by letter j. Previously the +indication letter was solely J. + +*** ~org-open-line~ ignores tables at the very beginning of the buffer + +When ~org-special-ctrl-o~ is non-nil, it is impractical to create +a blank line above a table at the beginning of the document. Now, as +a special case, ~org-open-line~ behaves normally in this situation. + +*** ~org-babel-hash-show-time~ is now customizable + +The experimental variable used to be more or less confidential, as +a ~defvar~. + +*** New ~:format~ property to parsed links + +It defines the format of the original link. Possible values are: +~plain~, ~bracket~ and ~angle~. + +* Version 8.3 + +** Incompatible changes + +*** Properties drawers syntax changes + +Properties drawers are now required to be located right after a +headline and its planning line, when applicable. + +It will break some documents as TODO states changes were sometimes +logged before the property drawer. + +The following function will repair them: + +#+BEGIN_SRC emacs-lisp +(defun org-repair-property-drawers () + "Fix properties drawers in current buffer. +Ignore non Org buffers." + (when (eq major-mode 'org-mode) + (org-with-wide-buffer + (goto-char (point-min)) + (let ((case-fold-search t) + (inline-re (and (featurep 'org-inlinetask) + (concat (org-inlinetask-outline-regexp) + "END[ \t]*$")))) + (org-map-entries + (lambda () + (unless (and inline-re (org-looking-at-p inline-re)) + (save-excursion + (let ((end (save-excursion (outline-next-heading) (point)))) + (forward-line) + (when (org-looking-at-p org-planning-line-re) (forward-line)) + (when (and (< (point) end) + (not (org-looking-at-p org-property-drawer-re)) + (save-excursion + (and (re-search-forward org-property-drawer-re end t) + (eq (org-element-type + (save-match-data (org-element-at-point))) + 'drawer)))) + (insert (delete-and-extract-region + (match-beginning 0) + (min (1+ (match-end 0)) end))) + (unless (bolp) (insert "\n")))))))))))) +#+END_SRC + +*** Using "COMMENT" is now equivalent to commenting with "#" + +If you used "COMMENT" in headlines to prevent a subtree from being +exported, you can still do it but all information within the subtree +is now commented out, i.e. no #+OPTIONS line will be parsed or taken +into account when exporting. + +If you want to exclude a headline from export while using its contents +for setting options, use =:noexport:= (see =org-export-exclude-tags=.) + +*** =#+CATEGORY= keywords no longer apply partially to document + +It was possible to use several such keywords and have them apply to +the text below until the next one, but strongly deprecated since Org +5.14 (2008). + +=#+CATEGORY= keywords are now global to the document. You can use node +properties to set category for a subtree, e.g., + +#+BEGIN_SRC org +,* Headline + :PROPERTIES: + :CATEGORY: some category + :END: +#+END_SRC + +*** New variable to control visibility when revealing a location + +~org-show-following-heading~, ~org-show-siblings~, ~org-show-entry-below~ +and ~org-show-hierarchy-above~ no longer exist. Instead, visibility is +controlled through a single variable: ~org-show-context-detail~, which +see. + +*** Replace disputed keys again when reading a date + +~org-replace-disputed-keys~ has been ignored when reading date since +version 8.1, but the former behavior is restored again. + +Keybinding for reading date can be customized with a new variable +~org-read-date-minibuffer-local-map~. + +*** No default title is provided when =TITLE= keyword is missing + +Skipping =TITLE= keyword no longer provides the current file name, or +buffer name, as the title. Instead, simply ignore the title. + +*** Default bindings of =C-c C-n= and =C-c C-p= changed + +The key sequences =C-c C-n= and =C-c C-p= are now bound to +~org-next-visible-heading~ and ~org-previous-visible-heading~ +respectively, rather than the =outline-mode= versions of these +functions. The Org version of these functions skips over inline tasks +(and even-level headlines when ~org-odd-levels-only~ is set). + +*** ~org-element-context~ no longer return objects in keywords + +~org-element-context~ used to return objects on some keywords, i.e., +=TITLE=, =DATE= and =AUTHOR=. It now returns only the keyword. + +*** ~org-timer-default-timer~ type changed from number to string + +If you have, in your configuration, something like =(setq +org-timer-default-timer 10)= replace it with =(setq +org-timer-default-timer "10")=. + +*** Functions signature changes + +The following functions require an additional argument. See their +docstring for more information. + +- ~org-export-collect-footnote-definitions~ +- ~org-html-format-headline-function~ +- ~org-html-format-inlinetask-function~ +- ~org-latex-format-headline-function~ +- ~org-latex-format-inlinetask-function~ +- ~org-link-search~ + +** New features + +*** Default lexical evaluation of emacs-lisp src blocks + +Emacs-lisp src blocks in babel are now evaluated using lexical +scoping. There is a new header to control this behavior. + +The default results in an eval with lexical scoping. +:lexical yes + +This turns lexical scoping off in the eval (the former behavior). +:lexical no + +This uses the lexical environment with x=42 in the eval. +:lexical '((x . 42)) + +*** Behavior of ~org-return~ changed + +If point is before or after the headline title, insert a new line +without changing the headline. + +*** Hierarchies of tags + +The functionality of nesting tags in hierarchies is added to org-mode. +This is the generalization of what was previously called "Tag groups" +in the manual. That term is now changed to "Tag hierarchy". + +The following in-buffer definition: + +#+BEGIN_SRC org + ,#+TAGS: [ Group : SubOne SubTwo ] + ,#+TAGS: [ SubOne : SubOne1 SubOne2 ] + ,#+TAGS: [ SubTwo : SubTwo1 SubTwo2 ] +#+END_SRC + +Should be seen as the following tree of tags: + +- Group + - SubOne + - SubOne1 + - SubOne2 + - SubTwo + - SubTwo1 + - SubTwo2 + +Searching for "Group" should return all tags defined above. Filtering +on SubOne filters also it's sub-tags. Etc. + +There is no limit on the depth for the tag hierarchy. + +*** Additional syntax for non-unique grouptags + +Additional syntax is defined for grouptags if the tags in the group +don't have to be distinct on a heading. + +Grouptags had to previously be defined with { }. This syntax is +already used for exclusive tags and Grouptags need their own, +non-exclusive syntax. This behaviour is achieved with [ ]. Note: { } +can still be used also for Grouptags but then only one of the given +tags can be used on the headline at the same time. Example: + +[ group : sub1 sub2 ] + +#+BEGIN_SRC org +,* Test :sub1:sub2: +#+END_SRC + +This is a more general case than the already existing syntax for +grouptags; { }. + +*** Define regular expression patterns as tags + +Tags can be defined as grouptags with regular expressions as +"sub-tags". + +The regular expressions in the group must be marked up within { }. +Example use: + +: #+TAGS: [ Project : {P@.+} ] + +Searching for the tag Project will now list all tags also including +regular expression matches for P@.+. This is good for example for +projects tagged with a common identifier, i.e. P@2014_OrgTags. + +*** Filtering in the agenda on grouptags (Tag hierarchies) + +Filtering in the agenda on grouptags filters all of the related tags. +Except if a filter is applied with a (double) prefix-argument. + +Filtering in the agenda on subcategories does not filter the "above" +levels anymore. + +If a grouptag contains a regular expression the regular expression +is also used as a filter. + +*** Minor refactoring of ~org-agenda-filter-by-tag~ + +Now uses the argument ARG and optional argument exclude instead of +strip and narrow. ARG because the argument has multiple purposes and +makes more sense than strip now. The term "narrowing" is changed to +exclude. + +The main purpose is for the function to make more logical sense when +filtering on tags now when tags can be structured in hierarchies. + +*** Babel: support for sed scripts + +Thanks to Bjarte Johansen for this feature. + +*** Babel: support for Processing language + +New ob-processing.el library. + +This library implements necessary functions for implementing editing +of Processing code blocks, viewing the resulting sketches in an +external viewer, and HTML export of the sketches. + +Check the documentation for more details. + +Thanks to Jarmo Hurri for this feature. + +*** New behaviour for ~org-toggle-latex-fragment~ + +The new behaviour is the following: + +- With a double prefix argument or with a single prefix argument when + point is before the first headline, toggle overlays in the whole + buffer; + +- With a single prefix argument, toggle overlays in the current + subtree; + +- On latex code, toggle overlay at point; + +- Otherwise, toggle overlays in the current section. + +*** Additional markup with =#+INCLUDE= keyword + +The content of the included file can now be optionally marked up, for +instance as HTML. See the documentation for details. + +*** File links with =#+INCLUDE= keyword + +Objects can be extracted via =#+INCLUDE= using file links. It is +possible to include only the contents of the object. See manual for +more information. + +*** Drawers do not need anymore to be referenced in =#+DRAWERS= + +One can use a drawer without listing it in the =#+DRAWERS= keyword, +which is now obsolete. As a consequence, this change also deprecates +~org-drawers~ variable. + +*** ~org-edit-special~ can edit export blocks + +Using C-c ' on an export block now opens a sub-editing buffer. Major +mode in that buffer is determined by export backend name (e.g., +"latex" \to "latex-mode"). You can define exceptions to this rule by +configuring ~org-src-lang-modes~, which see. + +*** Additional =:hline= processing to ob-shell + +If the argument =:hlines yes= is present in a babel call, an optional +argument =:hlines-string= can be used to define a string to use as a +representation for the lisp symbol ='hline= in the shell program. The +default is =hline=. + +*** Markdown export supports switches in source blocks + +For example, it is now possible to number lines using the =-n= switch in +a source block. + +*** New option in ASCII export + +Plain lists can have an extra margin by setting ~org-ascii-list-margin~ +variable to an appropriate integer. + +*** New blocks in ASCII export + +ASCII export now supports =#+BEGIN_JUSTIFYRIGHT= and =#+BEGIN_JUSTIFYLEFT= +blocks. See documentation for details. + +*** More back-end specific publishing options + +The number of publishing options specific to each back-end has been +increased. See manual for details. + +*** Export inline source blocks + +Inline source code was used to be removed upon exporting. They are +now handled as standard code blocks, i.e., the source code can appear +in the output, depending on the parameters. + +*** Extend ~org-export-first-sibling-p~ and ~org-export-last-sibling-p~ + +These functions now support any element or object, not only headlines. + +*** New function: ~org-export-table-row-in-header-p~ + +*** New function: ~org-export-get-reference~ + +*** New function: ~org-element-lineage~ + +This function deprecates ~org-export-get-genealogy~. It also provides +more features. See docstring for details. + +*** New function: ~org-element-copy~ + +*** New filter: ~org-export-filter-body-functions~ + +Functions in this filter are applied on the body of the exported +document, before wrapping it within the template. + +*** New :environment parameter when exporting example blocks to LaTeX + +: #+ATTR_LATEX: :environment myverbatim +: #+BEGIN_EXAMPLE +: This sentence is false. +: #+END_EXAMPLE + +will be exported using =@samp(myverbatim)= instead of =@samp(verbatim)=. + +*** Various improvements on radio tables + +Radio tables feature now relies on Org's export framework ("ox.el"). +~:no-escape~ parameter no longer exists, but additional global +parameters are now supported: ~:raw~, ~:backend~. Moreover, there are new +parameters specific to some pre-defined translators, e.g., +~:environment~ and ~:booktabs~ for ~orgtbl-to-latex~. See translators +docstrings (including ~orgtbl-to-generic~) for details. + +*** Non-floating minted listings in Latex export + +It is not possible to specify =#+attr_latex: :float nil= in conjunction +with source blocks exported by the minted package. + +*** Field formulas can now create columns as needed + +Previously, evaluating formulas that referenced out-of-bounds columns +would throw an error. A new variable ~org-table-formula-create-columns~ +was added to adjust this behavior. It is now possible to silently add +new columns, to do so with a warning or to explicitly ask the user +each time. + +*** ASCII plot + +Ability to plot values in a column through ASCII-art bars. See manual +for details. + +*** New hook: ~org-archive-hook~ + +This hook is called after successfully archiving a subtree, with point +on the original subtree, not yet deleted. + +*** New option: ~org-attach-archive-delete~ + +When non-nil, attachments from archived subtrees are removed. + +*** New option: ~org-latex-caption-above~ + +This variable generalizes ~org-latex-table-caption-above~, which is now +deprecated. In addition to tables, it applies to source blocks, +special blocks and images. See docstring for more information. + +*** New option: ~org-latex-prefer-user-labels~ + +See the docstring for more information. + +*** Export unnumbered headlines + +Headlines, for which the property ~UNNUMBERED~ is non-nil, are now +exported without section numbers irrespective of their levels. The +property is inherited by children. + +*** Tables can be sorted with an arbitrary function + +It is now possible to specify a function, both programmatically, +through a new optional argument, and interactively with ~f~ or ~F~ keys, +to sort a table. + +*** Table of contents can be local to a section + +The ~TOC~ keywords now accepts an optional ~local~ parameter. See manual +for details. + +*** Countdown timers can now be paused + +~org-timer-pause-time~ now pauses and restarts both relative and +countdown timers. + +*** New option ~only-window~ for ~org-agenda-window-setup~ + +When ~org-agenda-window-setup~ is set to ~only-window~, the agenda is +displayed as the sole window of the current frame. + +*** ~{{{date}}}~ macro supports optional formatting argument + +It is now possible to supply and optional formatting argument to +~{{{date}}}~. See manual for details. + +*** ~{{{property}}}~ macro supports optional search argument + +It is now possible to supply an optional search option to +~{{{property}}}~ in order to retrieve remote properties optional. See +manual for details. + +*** New option ~org-export-with-title~ + +It is possible to suppress the title insertion with ~#+OPTIONS: +title:nil~ or globally using the variable ~org-export-with-title~. + +*** New entities family: "\_ " + +"\_ " are used to insert up to 20 contiguous spaces in various +back-ends. In particular, this family can be used to introduce +leading spaces within table cells. + +*** New MathJax configuration options + +Org uses the MathJax CDN by default. See the manual and the docstring +of ~org-html-mathjax-options~ for details. + +*** New behaviour in `org-export-options-alist' + +When defining a back-end, it is now possible to specify to give +`parse' behaviour on a keyword. It is equivalent to call +`org-element-parse-secondary-string' on the value. + +However, parsed =KEYWORD= is automatically associated to an +=:EXPORT_KEYWORD:= property, which can be used to override the keyword +value during a subtree export. Moreover, macros are expanded in such +keywords and properties. + +*** Viewport support in html export + +Viewport for mobile-optimized website is now automatically inserted +when exporting to html. See ~org-html-viewport~ for details. + +*** New ~#+SUBTITLE~ export keyword + +Org can typeset a subtitle in some export backends. See the manual +for details. + +*** Remotely edit a footnote definition + +Calling ~org-edit-footnote-reference~ (C-c ') on a footnote reference +allows to edit its definition, as long as it is not anonymous, in a +dedicated buffer. It works even if buffer is currently narrowed. + +*** New function ~org-delete-indentation~ bound to ~M-^~ + +Work as ~delete-indentation~ unless at heading, in which case text is +added to headline text. + +*** Support for images in Texinfo export + +~Texinfo~ back-end now handles images. See the manual for details. + +*** Support for captions in Texinfo export + +Tables and source blocks can now have captions. Additionally, lists +of tables and lists of listings can be inserted in the document with +=#+TOC= keyword. + +*** Countdown timer support hh:mm:ss format + +In addition to setting countdown timers in minutes, they can also be +set using the hh:mm:ss format. + +*** Extend ~org-clone-subtree-with-time-shift~ + +~org-clone-subtree-with-time-shift~ now accepts 0 as an argument for the +number of clones, which removes the repeater from the original subtree +and creates one shifted, repeating clone. + +*** New time block for clock tables: ~untilnow~ + +It encompasses all past closed clocks. + +*** Support for the ~polyglossia~ LaTeX package + +See the docstring of ~org-latex-classes~ and +~org-latex-guess-polyglossia-language~ for details. + +*** None-floating tables, graphics and blocks can have captions + +*** `org-insert-heading' can be forced to insert top-level headline + +** Removed functions + +*** Removed function ~org-translate-time~ + +Use ~org-timestamp-translate~ instead. + +*** Removed function ~org-beamer-insert-options-template~ + +This function inserted a Beamer specific template at point or in +current subtree. Use ~org-export-insert-default-template~ instead, as +it provides more features and covers all export back-ends. It is also +accessible from the export dispatcher. + +*** Removed function ~org-timer-cancel-timer~ + +~org-timer-stop~ now stops both relative and countdown timers. + +*** Removed function ~org-export-solidify-link-text~ + +This function, being non-bijective, introduced bug in internal +references. Use ~org-export-get-reference~ instead. + +*** Removed function ~org-end-of-meta-data-and-drawers~ + +The function is superseded by ~org-end-of-meta-data~, called with an +optional argument. + +*** Removed functions ~org-table-colgroup-line-p~, ~org-table-cookie-line-p~ + +These functions were left-over from pre 8.0 era. They are not correct +anymore. Since they are not needed, they have no replacement. + +** Removed options + +*** ~org-list-empty-line-terminates-plain-lists~ is deprecated + +It will be kept in code base until next release, for backward +compatibility. + +If you need to separate consecutive lists with blank lines, always use +two of them, as if this option was nil (default value). + +*** ~org-export-with-creator~ is a boolean + +Special ~comment~ value is no longer allowed. It is possible to use a +body filter to add comments about the creator at the end of the +document instead. + +*** Removed option =org-html-use-unicode-chars= + +Setting this to non-nil was problematic as it converted characters +everywhere in the buffer, possibly corrupting URLs. + +*** Removed option =org-babel-sh-command= + +This undocumented option defaulted to the value of =shell-file-name= at +the time of loading =ob-shell=. The new behaviour is to use the value +of =shell-file-name= directly when the shell langage is =shell=. To chose +a different shell, either customize =shell-file-name= or bind this +variable locally. + +*** Removed option =org-babel-sh-var-quote-fmt= + +This undocumented option was supposed to provide different quoting +styles when changing the shell type. Changing the shell type can now +be done directly from the source block and the quoting style has to be +compatible across all shells, so a customization doesn't make sense +anymore. The chosen hard coded quoting style conforms to POSIX. + +*** Removed option ~org-insert-labeled-timestamps-at-point~ + +Setting this option to anything else that the default value (nil) +would create invalid planning info. This dangerous option is now +removed. + +*** Removed option ~org-koma-letter-use-title~ + +Use org-export-with-title instead. See also below. + +*** Removed option ~org-entities-ascii-explanatory~ + +This variable has no effect since Org 8.0. + +*** Removed option ~org-table-error-on-row-ref-crossing-hline~ + +This variable has no effect since August 2009. + +*** Removed MathML-related options from ~org-html-mathjax-options~ + +MathJax automatically chooses the best display technology based on the +end-users browser. You may force initial usage of MathML via +~org-html-mathjax-template~ or by setting the ~path~ property of +~org-html-mathjax-options~. + +*** Removed comment-related filters + +~org-export-filter-comment-functions~ and +~org-export-filter-comment-block-functions~ variables do not exist +anymore. + +** Miscellaneous + +*** Strip all meta data from ITEM special property + +ITEM special property does not contain TODO, priority or tags anymore. + +*** File names in links accept are now compatible with URI syntax + +Absolute file names can now start with =///= in addition to =/=. E.g., +=[[file:///home/me/unicorn.jpg]]=. + +*** Footnotes in included files are now local to the file + +As a consequence, it is possible to include multiple Org files with +footnotes in a master document without being concerned about footnote +labels colliding. + +*** Mailto links now use regular URI syntax + +This change deprecates old Org syntax for mailto links: +=mailto:user@domain::Subject=. + +*** =QUOTE= keywords do not exist anymore + +=QUOTE= keywords have been deprecated since Org 8.2. + +*** Select tests to perform with the build system + +The build system has been enhanced to allow test selection with a +regular expression by defining =BTEST_RE= during the test invocation. +This is especially useful during bisection to find just when a +particular test failure was introduced. + +*** Exact heading search for external links ignore spaces and cookies + +Exact heading search for links now ignore spaces and cookies. This is +the case for links of the form ~file:projects.org::*task title~, as well +as links of the form ~file:projects.org::some words~ when +~org-link-search-must-match-exact-headline~ is not nil. + +*** ~org-latex-hyperref-template~, ~org-latex-title-command~ formatting + +New formatting keys are supported. See the respective docstrings. +Note, ~org-latex-hyperref-template~ has a new default value. + +*** ~float, wasysym, marvosym~ are removed from ~org-latex-default-packages-alist~ + +If you require any of these package add them to your preamble via +~org-latex-packages-alist~. Org also uses default LaTeX ~\tolerance~ now. + +*** When exporting, throw an error on unresolved id/fuzzy links and code refs + +This helps spotting wrong links. + +* Version 8.2 + +** Incompatible changes +*** =ob-sh.el= renamed to =ob-shell= +This may require two changes in user config. + +1. In =org-babel-do-load-languages=, change =(sh . t)= to =(shell . t)=. +2. Edit =local.mk= files to change the value of =BTEST_OB_LANGUAGES= + to remove "sh" and include "shell". + *** Combine org-mac-message.el and org-mac-link-grabber into org-mac-link.el Please remove calls to =(require 'org-mac-message)= and =(require @@ -171,6 +1522,18 @@ then inline code snippets will be wrapped into the formatting string. - =org-screenshot.el= by Max Mikhanosha :: an utility to handle screenshots easily from Org, using the external tool [[http://freecode.com/projects/scrot][scrot]]. +** Miscellaneous + +*** "QUOTE" keywords in headlines are deprecated + +"QUOTE" keywords are an undocumented feature in Org. When a headline +starts with the keyword "QUOTE", its contents are parsed as +a ~quote-section~ and treated as an example block. You can achieve +the same with example blocks. + +This feature is deprecated and will be removed in the next Org +release. + * Version 8.0.1 ** Installation @@ -1021,6 +2384,13 @@ consistent with using the `:' key in agenda view. You can now use `=' for [[doc::org-columns][org-columns]]. ** =org-float= is now obsolete, use =diary-float= instead +** No GPL manual anymore + +There used to be a GPL version of the Org manual, but this is not the +case anymore, the Free Software Foundation does not permit this. + +The GNU FDL license is now included in the manual directly. + ** Enhanced compatibility with Emacs 22 and XEmacs Thanks to Achim for his work on enhancing Org's compatibility with @@ -1058,7 +2428,7 @@ See http://orgmode.org/elpa/ | =C-c C-x E= | =E= | [[doc::org-inc-effort][org-inc-effort]] | | | =#= | [[doc::org-toggle-comment][org-toggle-comment]] | | | =:= | [[doc::org-columns][org-columns]] | - | | =W= | Set =APPT_WARNTIME= | + | | =W= | Set =APPT_WARNTIME= | | =k= | | [[doc::org-agenda-capture][org-agenda-capture]] | | C-c , | , | [[doc::org-priority][org-priority]] | @@ -1225,7 +2595,7 @@ See http://orgmode.org/elpa/ **** New =todo-unblocked= and =nottodo-unblocked= skip conditions - See the [[http://orgmode.org/w/?p%3Dorg-mode.git%3Ba%3Dcommit%3Bh%3Df426da][git commit]] for more explanations. + See the [[http://orgmode.org/cgit.cgi/org-mode.git/commit/?id=f426da][git commit]] for more explanations. **** Allow category filtering in the agenda @@ -1542,7 +2912,7 @@ See http://orgmode.org/elpa/ Thanks to Carsten for implementing this. **** ODT: Add support for ODT export in org-bbdb.el -**** ODT: Add support for indented tables (see [[http://orgmode.org/w/?p%3Dorg-mode.git%3Ba%3Dcommit%3Bh%3De9fd33][this commit]] for details) +**** ODT: Add support for indented tables (see [[http://orgmode.org/cgit.cgi/org-mode.git/commit/?id=e9fd33][this commit]] for details) **** ODT: Improve the conversion from ODT to other formats **** ASCII: Swap the level-1/level-2 characters to underline the headlines **** Support for Chinese, simplified Chinese, Russian, Ukrainian and Japanese diff --git a/etc/PROBLEMS b/etc/PROBLEMS index 06dc9f5e450..3906ba53d2f 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS @@ -217,6 +217,28 @@ result in an endless loop. If you need Emacs to be able to recover from closing displays, compile it with the Lucid toolkit instead of GTK. +** Emacs compiled with GTK crashes at startup due to X protocol error. + +This is known to happen on elementary OS GNU/Linux systems. + +The error message is: + + X protocol error: BadMatch (invalid parameter attributes) on protocol request 140 + When compiled with GTK, Emacs cannot recover from X disconnects. + This is a GTK bug: https://bugzilla.gnome.org/show_bug.cgi?id=85715 + For details, see etc/PROBLEMS. + Fatal error 6: Aborted + +followed by a C backtrace. (Sometimes the offending protocol request +number is 139.) + +The relevant bug report is here: + + https://bugs.launchpad.net/elementaryos/+bug/1355274 + +A workaround is to set XLIB_SKIP_ARGB_VISUALS=1 in the environment +before starting Emacs, or run Emacs as root. + ** Emacs crashes when you try to view a file with complex characters. For example, the etc/HELLO file (as shown by C-h h). @@ -323,12 +345,17 @@ or set the variable 'cannot-suspend' to a non-nil value. *** movemail compiled with POP support can't connect to the POP server. -Make sure that the 'pop' entry in /etc/services, or in the services -NIS map if your machine uses NIS, has the same port number as the -entry on the POP server. A common error is for the POP server to be -listening on port 110, the assigned port for the POP3 protocol, while -the client is trying to connect on port 109, the assigned port for the -old POP protocol. +This problem can occur if you do not configure --with-mailutils, +and don't have GNU Mailutils installed. Then Emacs uses its own +version of movemail, which doesn't support secure POP connections. +To solve this, install GNU Mailutils. + +Also, make sure that the 'pop' entry in /etc/services, or in the +services NIS map if your machine uses NIS, has the same port number as +the entry on the POP server. A common error is for the POP server to +be listening on port 110, the assigned port for the POP3 protocol, +while the client is trying to connect on port 109, the assigned port +for the old POP protocol. *** RMAIL gets error getting new mail. @@ -464,6 +491,34 @@ problem by adding this to your .cshrc file: stty -icrnl -onlcr -echo susp ^Z endif +*** In Shell buffers using ksh, resizing a window inserts random characters. + +The characters come from the PS2 prompt, but they are not followed by +a newline, which messes up the next command you type. This strange +effect is caused by Emacs 25 and later telling the shell that its +screen size changed. + +To work around the problem, customize the option +'window-adjust-process-window-size-function' to "Do not adjust process +window sizes" (Lisp value 'ignore'). + +*** In Inferior Python mode, input is echoed and native completion doesn't work. +<https://debbugs.gnu.org/cgi/bugreport.cgi?bug=25753> + +This happens when python uses a libedit based readline module, which +is the default on macOS. This can be worked around by installing a +GNU readline based module instead, for example, using setuptools + + sudo easy_install gnureadline + +And then rename the system's readline so that it won't be loaded: + + cd /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload + mv readline.so readline.so.bak + +See <https://pypi.python.org/pypi/gnureadline> for more details on +installation. + *** Emacs startup on GNU/Linux systems (and possibly other systems) is slow. This can happen if the system is misconfigured and Emacs can't get the @@ -740,6 +795,40 @@ The solution is to install the appropriate fonts on your machine. For instance if you are editing a text with a lot of math symbols, then installing a font like 'Symbola' should solve this problem. +Another reason for slow display is reportedly the nerd-fonts +installation, even when Symbola is installed as well. Uninstalling +nerd-fonts was reported to solve the problem in that case. + +** Emacs running on GNU/Linux system with the m17n library Ver.1.7.1 or the +earlier version has a problem with rendering Bengali script. + +The problem can be fixed by installing the newer version of the m17n +library (if any), or by following this procedure: + +1. Locate the file BENG-OTF.flt installed on your system as part of the +m17n library. Usually it is under the directory /usr/share/m17n. + +2. Apply the following patch to BENG-OTF.flt + +------------------------------------------------------------ +diff --git a/FLT/BENG-OTF.flt b/FLT/BENG-OTF.flt +index 45cc554..0cc5e76 100644 +--- a/FLT/BENG-OTF.flt ++++ b/FLT/BENG-OTF.flt +@@ -232,7 +232,7 @@ + (lang-forms + (cond + ("(.H)J" (1 :otf=beng=half+)) +- (".H" :otf=beng=blwf,half,vatu+) ++ (".+H" :otf=beng=blwf,half,vatu+) + ("." =))) + + (post +------------------------------------------------------------ + +If you can't modify that file directly, copy it to the directory +~/.m17n.d/ (create it if it doesn't exist), and apply the patch. + * Internationalization problems ** M-{ does not work on a Spanish PC keyboard. @@ -1005,6 +1094,13 @@ incompatibility of the Gnome terminal with Xterm, which also affects other programs using the Xterm mouse interface. A problem report has been filed. +*** Gnome: GPaste clipboard manager causes erratic behavior of 'yank' + +The symptom is that 'kill-line' followed by 'yank' often (but not +always) doesn't insert the whitespace of the killed and yanked line. + +The solution is to set the GPaste "trim items" option to OFF. + *** KDE: When running on KDE, colors or fonts are not as specified for Emacs, or messed up. @@ -2371,6 +2467,10 @@ middle button press. In such cases, setting the wheel press to "scroll" sometimes works if you press the button twice. Trying a generic mouse driver might help. +One particular situation where this happens is when you have +"Microsoft Intellipoint" installed, which runs the program +ipoint.exe. The fix is reportedly to uninstall this software. + ** Scrolling the mouse wheel on MS-Windows always scrolls the top window. This is another common problem with mouse drivers. Instead of @@ -2416,17 +2516,6 @@ please call support for your X-server and see if you can get a fix. If you do, please send it to bug-gnu-emacs@gnu.org so we can list it here. -* Runtime problems specific to Mac OS X - -** On Mac OS X, file-name-case-insensitive-p may be unreliable - -The implementation of that function on Mac OS X uses pathconf with the -_PC_CASE_SENSITIVE flag. There have been reports that this use of -pathconf does not work reliably. If you have a problem, please -recompile Emacs with -D DARWIN_OS_CASE_SENSITIVE_FIXME=1 or --D DARWIN_OS_CASE_SENSITIVE_FIXME=2, and file a bug report saying -whether this fixed your problem. - * Build-time problems ** Configuration diff --git a/etc/TODO b/etc/TODO index 71704f07cfd..af2f41bf966 100644 --- a/etc/TODO +++ b/etc/TODO @@ -139,7 +139,7 @@ things in their .emacs. case to make sure it stays fixed. Or pick your favorite programming major-mode, and write a test for its indentation. Or a version control backend, and write a test for its status parser. Etc. -See test/automated for examples. +See the 'test' directory for examples. * Small but important fixes needed in existing features: diff --git a/etc/org/OrgOdtStyles.xml b/etc/org/OrgOdtStyles.xml index f41d9840cbe..1a8edee99b4 100644 --- a/etc/org/OrgOdtStyles.xml +++ b/etc/org/OrgOdtStyles.xml @@ -109,33 +109,53 @@ </style:style> <style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text"> <style:text-properties fo:font-size="115%" fo:font-weight="bold" style:font-size-asian="115%" style:font-weight-asian="bold" style:font-size-complex="115%" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Heading_20_1_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_1" style:list-style-name=""> </style:style> <style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text"> <style:text-properties fo:font-size="14pt" fo:font-style="italic" fo:font-weight="bold" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-weight-asian="bold" style:font-size-complex="14pt" style:font-style-complex="italic" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Heading_20_2_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_2" style:list-style-name=""> </style:style> <style:style style:name="Heading_20_3" style:display-name="Heading 3" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="3" style:class="text"> <style:text-properties fo:font-size="14pt" fo:font-weight="bold" style:font-size-asian="14pt" style:font-weight-asian="bold" style:font-size-complex="14pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Heading_20_3_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_3" style:list-style-name=""> </style:style> <style:style style:name="Heading_20_4" style:display-name="Heading 4" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="4" style:class="text"> <style:text-properties fo:font-size="85%" fo:font-style="italic" fo:font-weight="bold" style:font-size-asian="85%" style:font-style-asian="italic" style:font-weight-asian="bold" style:font-size-complex="85%" style:font-style-complex="italic" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Heading_20_4_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_4" style:list-style-name=""> </style:style> <style:style style:name="Heading_20_5" style:display-name="Heading 5" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="5" style:class="text"> <style:text-properties fo:font-size="85%" fo:font-weight="bold" style:font-size-asian="85%" style:font-weight-asian="bold" style:font-size-complex="85%" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Heading_20_5_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_5" style:list-style-name=""> </style:style> <style:style style:name="Heading_20_6" style:display-name="Heading 6" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="6" style:class="text"> <style:text-properties fo:font-size="75%" fo:font-weight="bold" style:font-size-asian="75%" style:font-weight-asian="bold" style:font-size-complex="75%" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Heading_20_6_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_6" style:list-style-name=""> </style:style> <style:style style:name="Heading_20_7" style:display-name="Heading 7" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="7" style:class="text"> <style:text-properties fo:font-size="75%" fo:font-weight="bold" style:font-size-asian="75%" style:font-weight-asian="bold" style:font-size-complex="75%" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Heading_20_7_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_7" style:list-style-name=""> </style:style> <style:style style:name="Heading_20_8" style:display-name="Heading 8" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="8" style:class="text"> <style:text-properties fo:font-size="75%" fo:font-weight="bold" style:font-size-asian="75%" style:font-weight-asian="bold" style:font-size-complex="75%" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Heading_20_8_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_8" style:list-style-name=""> </style:style> <style:style style:name="Heading_20_9" style:display-name="Heading 9" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="9" style:class="text"> <style:text-properties fo:font-size="75%" fo:font-weight="bold" style:font-size-asian="75%" style:font-weight-asian="bold" style:font-size-complex="75%" style:font-weight-complex="bold"/> </style:style> + <style:style style:name="Heading_20_9_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_9" style:list-style-name=""> + </style:style> <style:style style:name="Heading_20_10" style:display-name="Heading 10" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="10" style:class="text"> <style:text-properties fo:font-size="75%" fo:font-weight="bold" style:font-size-asian="75%" style:font-weight-asian="bold" style:font-size-complex="75%" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Heading_20_10_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_10" style:list-style-name=""> </style:style> <style:style style:name="Heading_20_1.title" style:display-name="Heading 1.title" style:family="paragraph" style:parent-style-name="Heading_20_1"> <style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/> diff --git a/etc/org/library-of-babel.org b/etc/org/library-of-babel.org new file mode 100644 index 00000000000..0098e726397 --- /dev/null +++ b/etc/org/library-of-babel.org @@ -0,0 +1,584 @@ +#+title: The Library of Babel +#+author: Org-mode People +#+STARTUP: hideblocks + +* Introduction + +The Library of Babel is an extensible collection of ready-made and +easily-shortcut-callable source-code blocks for handling common tasks. +Org-babel comes pre-populated with the source-code blocks located in +this file. It is possible to add source-code blocks from any org-mode +file to the library by calling =(org-babel-lob-ingest +"path/to/file.org")=. + +This file is included in worg mainly less for viewing through the web +interface, and more for contribution through the worg git repository. +If you have code snippets that you think others may find useful please +add them to this file and [[file:~/src/worg/worg-git.org::contribute-to-worg][contribute them]] to worg. + +The raw Org-mode text of this file can be downloaded at +[[repofile:contrib/babel/library-of-babel.org][library-of-babel.org]] + +* Simple + +A collection of simple utility functions: + +#+name: echo +#+begin_src emacs-lisp :var input="echo'd" + input +#+end_src + +* File I/O + +** Reading and writing files + +Read the contents of the file at =file=. The =:results vector= and +=:results scalar= header arguments can be used to read the contents of +file as either a table or a string. + +#+name: read +#+begin_src emacs-lisp :var file="" :var format="" + (if (string= format "csv") + (with-temp-buffer + (org-table-import (expand-file-name file) nil) + (org-table-to-lisp)) + (with-temp-buffer + (insert-file-contents (expand-file-name file)) + (buffer-string))) +#+end_src + +Write =data= to a file at =file=. If =data= is a list, then write it +as a table in traditional Org-mode table syntax. + +#+name: write +#+begin_src emacs-lisp :var data="" :var file="" :var ext='() + (flet ((echo (r) (if (stringp r) r (format "%S" r)))) + (with-temp-file file + (case (and (listp data) + (or ext (intern (file-name-extension file)))) + ('tsv (insert (orgtbl-to-tsv data '(:fmt echo)))) + ('csv (insert (orgtbl-to-csv data '(:fmt echo)))) + (t (org-babel-insert-result data))))) + nil +#+end_src + +** Remote files + +*** json + +Read local or remote file in [[http://www.json.org/][json]] format into emacs-lisp objects. + +#+name: json +#+begin_src emacs-lisp :var file='() :var url='() + (require 'json) + (cond + (file + (with-temp-filebuffer file + (goto-char (point-min)) + (json-read))) + (url + (require 'w3m) + (with-temp-buffer + (w3m-retrieve url) + (goto-char (point-min)) + (json-read)))) +#+end_src + +*** Google docs + +The following code blocks make use of the [[http://code.google.com/p/googlecl/][googlecl]] Google command line +tool. This tool provides functionality for accessing Google services +from the command line, and the following code blocks use /googlecl/ +for reading from and writing to Google docs with Org-mode code blocks. + +**** Read a document from Google docs + +The =google= command seems to be throwing "Moved Temporarily" errors +when trying to download textual documents, but this is working fine +for spreadsheets. + +#+name: gdoc-read +#+begin_src emacs-lisp :var title="example" :var format="csv" + (let* ((file (concat title "." format)) + (cmd (format "google docs get --format %S --title %S" format title))) + (message cmd) (message (shell-command-to-string cmd)) + (prog1 (if (string= format "csv") + (with-temp-buffer + (org-table-import (shell-quote-argument file) '(4)) + (org-table-to-lisp)) + (with-temp-buffer + (insert-file-contents (shell-quote-argument file)) + (buffer-string))) + (delete-file file))) +#+end_src + +For example, a line like the following can be used to read the +contents of a spreadsheet named =num-cells= into a table. +: #+call: gdoc-read(title="num-cells"") + +A line like the following can be used to read the contents of a +document as a string. + +: #+call: gdoc-read(title="loremi", :format "txt") + +**** Write a document to a Google docs + +Write =data= to a google document named =title=. If =data= is tabular +it will be saved to a spreadsheet, otherwise it will be saved as a +normal document. + +#+name: gdoc-write +#+begin_src emacs-lisp :var title="babel-upload" :var data=fibs(n=10) :results silent + (let* ((format (if (listp data) "csv" "txt")) + (tmp-file (make-temp-file "org-babel-google-doc" nil (concat "." format))) + (cmd (format "google docs upload --title %S %S" title tmp-file))) + (with-temp-file tmp-file + (insert + (if (listp data) + (orgtbl-to-csv + data '(:fmt (lambda (el) (if (stringp el) el (format "%S" el))))) + (if (stringp data) data (format "%S" data))))) + (message cmd) + (prog1 (shell-command-to-string cmd) (delete-file tmp-file))) +#+end_src + +example usage +: #+name: fibs +: #+begin_src emacs-lisp :var n=8 +: (flet ((fib (m) (if (< m 2) 1 (+ (fib (- m 1)) (fib (- m 2)))))) +: (mapcar (lambda (el) (list el (fib el))) (number-sequence 0 (- n 1)))) +: #+end_src +: +: #+call: gdoc-write(title="fibs", data=fibs(n=10)) + +* Plotting code + +** R + +Plot column 2 (y axis) against column 1 (x axis). Columns 3 and +beyond, if present, are ignored. + +#+name: R-plot +#+begin_src R :var data=R-plot-example-data +plot(data) +#+end_src + +#+tblname: R-plot-example-data +| 1 | 2 | +| 2 | 4 | +| 3 | 9 | +| 4 | 16 | +| 5 | 25 | + +#+call: R-plot(data=R-plot-example-data) + +#+resname: R-plot(data=R-plot-example-data) +: nil + +** Gnuplot + +* Org reference + +** Headline references + +#+name: headline +#+begin_src emacs-lisp :var headline=top :var file='() + (save-excursion + (when file (get-file-buffer file)) + (org-open-link-from-string (org-make-link-string headline)) + (save-restriction + (org-narrow-to-subtree) + (buffer-string))) +#+end_src + +#+call: headline(headline="headline references") + +* Tables + +** LaTeX Table Export + +*** booktabs + +This source block can be used to wrap a table in the latex =booktabs= +environment. The source block adds a =toprule= and =bottomrule= (so +don't use =hline= at the top or bottom of the table). The =hline= +after the header is replaced with a =midrule=. + +Note that this function bypasses the Org-mode LaTeX exporter and calls +=orgtbl-to-generic= to create the output table. This means that the +entries in the table are not translated from Org-mode to LaTeX. + +It takes the following arguments -- all but the first two are +optional. + +| arg | description | +|-------+--------------------------------------------| +| table | a reference to the table | +| align | alignment string | +| env | optional environment, default to "tabular" | +| width | optional width specification string | + +#+name: booktabs +#+begin_src emacs-lisp :var table='((:head) hline (:body)) :var align='() :var env="tabular" :var width='() :noweb yes :results latex + (flet ((to-tab (tab) + (orgtbl-to-generic + (mapcar (lambda (lis) + (if (listp lis) + (mapcar (lambda (el) + (if (stringp el) + el + (format "%S" el))) lis) + lis)) tab) + (list :lend " \\\\" :sep " & " :hline "\\hline")))) + (org-fill-template + " + \\begin{%env}%width%align + \\toprule + %table + \\bottomrule + \\end{%env}\n" + (list + (cons "env" (or env "table")) + (cons "width" (if width (format "{%s}" width) "")) + (cons "align" (if align (format "{%s}" align) "")) + (cons "table" + ;; only use \midrule if it looks like there are column headers + (if (equal 'hline (second table)) + (concat (to-tab (list (first table))) + "\n\\midrule\n" + (to-tab (cddr table))) + (to-tab table)))))) +#+end_src + +*** longtable + +This block can be used to wrap a table in the latex =longtable= +environment, it takes the following arguments -- all but the first two +are optional. + +| arg | description | +|-----------+-------------------------------------------------------------| +| table | a reference to the table | +| align | optional alignment string | +| width | optional width specification string | +| hline | the string to use as hline separator, defaults to "\\hline" | +| head | optional "head" string | +| firsthead | optional "firsthead" string | +| foot | optional "foot" string | +| lastfoot | optional "lastfoot" string | + +#+name: longtable +#+begin_src emacs-lisp :var table='((:table)) :var align='() :var width='() :var hline="\\hline" :var firsthead='() :var head='() :var foot='() :var lastfoot='() :noweb yes :results latex + (org-fill-template + " + \\begin{longtable}%width%align + %firsthead + %head + %foot + %lastfoot + + %table + \\end{longtable}\n" + (list + (cons "width" (if width (format "{%s}" width) "")) + (cons "align" (if align (format "{%s}" align) "")) + (cons "firsthead" (if firsthead (concat firsthead "\n\\endfirsthead\n") "")) + (cons "head" (if head (concat head "\n\\endhead\n") "")) + (cons "foot" (if foot (concat foot "\n\\endfoot\n") "")) + (cons "lastfoot" (if lastfoot (concat lastfoot "\n\\endlastfoot\n") "")) + (cons "table" (orgtbl-to-generic + (mapcar (lambda (lis) + (if (listp lis) + (mapcar (lambda (el) + (if (stringp el) + el + (format "%S" el))) lis) + lis)) table) + (list :lend " \\\\" :sep " & " :hline hline))))) +#+end_src + +*** booktabs-notes + +This source block builds on [[booktabs]]. It accepts two additional +arguments, both of which are optional. + +#+tblname: arguments +| arg | description | +|--------+------------------------------------------------------| +| notes | an org-mode table with footnotes | +| lspace | if non-nil, insert =addlinespace= after =bottomrule= | + +An example footnote to the =arguments= table specifies the column +span. Note the use of LaTeX, rather than Org-mode, markup. + +#+tblname: arguments-notes +| \multicolumn{2}{l}{This is a footnote to the \emph{arguments} table.} | + +#+name: booktabs-notes +#+begin_src emacs-lisp :var table='((:head) hline (:body)) :var notes='() :var align='() :var env="tabular" :var width='() :var lspace='() :noweb yes :results latex + (flet ((to-tab (tab) + (orgtbl-to-generic + (mapcar (lambda (lis) + (if (listp lis) + (mapcar (lambda (el) + (if (stringp el) + el + (format "%S" el))) lis) + lis)) tab) + (list :lend " \\\\" :sep " & " :hline "\\hline")))) + (org-fill-template + " + \\begin{%env}%width%align + \\toprule + %table + \\bottomrule%spacer + %notes + \\end{%env}\n" + (list + (cons "env" (or env "table")) + (cons "width" (if width (format "{%s}" width) "")) + (cons "align" (if align (format "{%s}" align) "")) + (cons "spacer" (if lspace "\\addlinespace" "")) + (cons "table" + ;; only use \midrule if it looks like there are column headers + (if (equal 'hline (second table)) + (concat (to-tab (list (first table))) + "\n\\midrule\n" + (to-tab (cddr table))) + (to-tab table))) + (cons "notes" (if notes (to-tab notes) "")) + ))) +#+end_src + +** Elegant lisp for transposing a matrix + +#+tblname: transpose-example +| 1 | 2 | 3 | +| 4 | 5 | 6 | + +#+name: transpose +#+begin_src emacs-lisp :var table=transpose-example + (apply #'mapcar* #'list table) +#+end_src + +#+resname: +| 1 | 4 | +| 2 | 5 | +| 3 | 6 | + +** Convert every element of a table to a string + +#+tblname: hetero-table +| 1 | 2 | 3 | +| a | b | c | + +#+name: all-to-string +#+begin_src emacs-lisp :var tbl='() + (defun all-to-string (tbl) + (if (listp tbl) + (mapcar #'all-to-string tbl) + (if (stringp tbl) + tbl + (format "%s" tbl)))) + (all-to-string tbl) +#+end_src + +#+begin_src emacs-lisp :var tbl=hetero-table + (mapcar (lambda (row) (mapcar (lambda (cell) (stringp cell)) row)) tbl) +#+end_src + +#+name: +| nil | nil | nil | +| t | t | t | + +#+begin_src emacs-lisp :var tbl=all-to-string(hetero-table) + (mapcar (lambda (row) (mapcar (lambda (cell) (stringp cell)) row)) tbl) +#+end_src + +#+name: +| t | t | t | +| t | t | t | + +* Misc + +** File-specific Version Control logging + :PROPERTIES: + :AUTHOR: Luke Crook + :END: + +This function will attempt to retrieve the entire commit log for the +file associated with the current buffer and insert this log into the +export. The function uses the Emacs VC commands to interface to the +local version control system, but has only been tested to work with +Git. 'limit' is currently unsupported. + +#+name: vc-log +#+headers: :var limit=-1 +#+headers: :var buf=(buffer-name (current-buffer)) +#+begin_src emacs-lisp + ;; Most of this code is copied from vc.el vc-print-log + (require 'vc) + (when (vc-find-backend-function + (vc-backend (buffer-file-name (get-buffer buf))) 'print-log) + (let ((limit -1) + (vc-fileset nil) + (backend nil) + (files nil)) + (with-current-buffer (get-buffer buf) + (setq vc-fileset (vc-deduce-fileset t)) ; FIXME: Why t? --Stef + (setq backend (car vc-fileset)) + (setq files (cadr vc-fileset))) + (with-temp-buffer + (let ((status (vc-call-backend + backend 'print-log files (current-buffer)))) + (when (and (processp status) ; Make sure status is a process + (= 0 (process-exit-status status))) ; which has not terminated + (while (not (eq 'exit (process-status status))) + (sit-for 1 t))) + (buffer-string))))) +#+end_src + +** Trivial python code blocks + +#+name: python-identity +#+begin_src python :var a=1 +a +#+end_src + +#+name: python-add +#+begin_src python :var a=1 :var b=2 +a + b +#+end_src + +** Arithmetic + +#+name: lob-add +#+begin_src emacs-lisp :var a=0 :var b=0 + (+ a b) +#+end_src + +#+name: lob-minus +#+begin_src emacs-lisp :var a=0 :var b=0 + (- a b) +#+end_src + +#+name: lob-times +#+begin_src emacs-lisp :var a=0 :var b=0 + (* a b) +#+end_src + +#+name: lob-div +#+begin_src emacs-lisp :var a=0 :var b=0 + (/ a b) +#+end_src + +* GANTT Charts + +The =elispgantt= source block was sent to the mailing list by Eric +Fraga. It was modified slightly by Tom Dye. + +#+name: elispgantt +#+begin_src emacs-lisp :var table=gantttest + (let ((dates "") + (entries (nthcdr 2 table)) + (milestones "") + (nmilestones 0) + (ntasks 0) + (projecttime 0) + (tasks "") + (xlength 1)) + (message "Initial: %s\n" table) + (message "Entries: %s\n" entries) + (while entries + (let ((entry (first entries))) + (if (listp entry) + (let ((id (first entry)) + (type (nth 1 entry)) + (label (nth 2 entry)) + (task (nth 3 entry)) + (dependencies (nth 4 entry)) + (start (nth 5 entry)) + (duration (nth 6 entry)) + (end (nth 7 entry)) + (alignment (nth 8 entry))) + (if (> start projecttime) (setq projecttime start)) + (if (string= type "task") + (let ((end (+ start duration)) + (textposition (+ start (/ duration 2))) + (flush "")) + (if (string= alignment "left") + (progn + (setq textposition start) + (setq flush "[left]")) + (if (string= alignment "right") + (progn + (setq textposition end) + (setq flush "[right]")))) + (setq tasks + (format "%s \\gantttask{%s}{%s}{%d}{%d}{%d}{%s}\n" + tasks label task start end textposition flush)) + (setq ntasks (+ 1 ntasks)) + (if (> end projecttime) + (setq projecttime end))) + (if (string= type "milestone") + (progn + (setq milestones + (format + "%s \\ganttmilestone{$\\begin{array}{c}\\mbox{%s}\\\\ \\mbox{%s}\\end{array}$}{%d}\n" + milestones label task start)) + (setq nmilestones (+ 1 nmilestones))) + (if (string= type "date") + (setq dates (format "%s \\ganttdateline{%s}{%d}\n" + dates label start)) + (message "Ignoring entry with type %s\n" type))))) + (message "Ignoring non-list entry %s\n" entry)) ; end if list entry + (setq entries (cdr entries)))) ; end while entries left + (format "\\pgfdeclarelayer{background} + \\pgfdeclarelayer{foreground} + \\pgfsetlayers{background,foreground} + \\renewcommand{\\ganttprojecttime}{%d} + \\renewcommand{\\ganttntasks}{%d} + \\noindent + \\begin{tikzpicture}[y=-0.75cm,x=0.75\\textwidth] + \\begin{pgfonlayer}{background} + \\draw[very thin, red!10!white] (0,1+\\ganttntasks) grid [ystep=0.75cm,xstep=1/\\ganttprojecttime] (1,0); + \\draw[\\ganttdatelinecolour] (0,0) -- (1,0); + \\draw[\\ganttdatelinecolour] (0,1+\\ganttntasks) -- (1,1+\\ganttntasks); + \\end{pgfonlayer} + %s + %s + %s + \\end{tikzpicture}" projecttime ntasks tasks milestones dates)) +#+end_src + +* Available languages + :PROPERTIES: + :AUTHOR: Bastien + :END: + +** From Org's core + +| Language | Identifier | Language | Identifier | +|------------+------------+----------------+------------| +| Asymptote | asymptote | Awk | awk | +| Emacs Calc | calc | C | C | +| C++ | C++ | Clojure | clojure | +| CSS | css | ditaa | ditaa | +| Graphviz | dot | Emacs Lisp | emacs-lisp | +| gnuplot | gnuplot | Haskell | haskell | +| Javascript | js | LaTeX | latex | +| Ledger | ledger | Lisp | lisp | +| Lilypond | lilypond | MATLAB | matlab | +| Mscgen | mscgen | Objective Caml | ocaml | +| Octave | octave | Org-mode | org | +| | | Perl | perl | +| Plantuml | plantuml | Python | python | +| R | R | Ruby | ruby | +| Sass | sass | Scheme | scheme | +| GNU Screen | screen | shell | sh | +| SQL | sql | SQLite | sqlite | + +** From Org's contrib/babel/langs + +- ob-oz.el, by Torsten Anders and Eric Schulte +- ob-fomus.el, by Torsten Anders diff --git a/etc/refcards/orgcard.tex b/etc/refcards/orgcard.tex index b12ae7be592..0170a18abce 100644 --- a/etc/refcards/orgcard.tex +++ b/etc/refcards/orgcard.tex @@ -1,6 +1,6 @@ % Reference Card for Org Mode -\def\orgversionnumber{8.2} -\def\versionyear{2014} % latest update +\def\orgversionnumber{9.0.9} +\def\versionyear{2017} % latest update \input emacsver.tex %**start of header @@ -312,10 +312,11 @@ \section{Structure Editing} \key{turn item/line into headline}{C-c *} \key{promote/demote heading}{M-LEFT/RIGHT} \metax{promote/demote current subtree}{M-S-LEFT/RIGHT} -\metax{move subtree/list item up/down}{M-S-UP/DOWN} +\metax{move subtree/list item up/down}{M-UP/DOWN} +\metax{move the line at point up/down}{M-S-UP/DOWN} \metax{sort subtree/region/plain-list}{C-c \^{}} \metax{clone a subtree}{C-c C-x c} -\metax{copy visible text}{C-c C-x v} +\metax{copy visible parts of the region}{C-c C-x v} \metax{kill/copy subtree}{C-c C-x C-w/M-w} \metax{yank subtree}{C-c C-x C-y or C-y} \metax{narrow buffer to subtree / widen}{C-x n s/w} @@ -333,7 +334,6 @@ \section{Filtering and Sparse Trees} \key{construct a sparse tree by various criteria}{C-c /} \key{view TODO's in sparse tree}{C-c / t/T} \key{global TODO list in agenda mode}{C-c a t \noteone} -\key{time sorted view of current org file}{C-c a L} \section{Tables} @@ -375,7 +375,6 @@ \section{Tables} \metax{cut/copy/paste rectangular region}{C-c C-x C-w/M-w/C-y} %\key{copy rectangular region}{C-c C-x M-w} %\key{paste rectangular region}{C-c C-x C-y} -\key{fill paragraph across selected cells}{C-c C-q} {\bf Miscellaneous} @@ -574,7 +573,6 @@ \section{Agenda Views} \key{match tags, TODO kwds, properties}{C-c a m \noteone} \key{match only in TODO entries}{C-c a M \noteone} \key{find stuck projects}{C-c a \# \noteone} -\key{show timeline of current org file}{C-c a L \noteone} \key{configure custom commands}{C-c a C \noteone} %\key{configure stuck projects}{C-c a ! \noteone} \key{agenda for date at cursor}{C-c C-o} @@ -661,8 +659,11 @@ \section{Exporting and Publishing} \key{export/publish dispatcher}{C-c C-e} -\key{export visible part only}{C-c C-e v} -\key{insert template of export options}{C-c C-e t} +\key{toggle asynchronous export}{C-c C-e C-a} +\key{toggle body/visible only export}{C-c C-e C-b/v} +\key{toggle subtree export}{C-c C-e C-s} +\key{insert template of export options}{C-c C-e \#} + \key{toggle fixed width for entry or region}{C-c :} \key{toggle pretty display of scripts, entities}{C-c C-x {\tt\char`\\}} @@ -690,6 +691,5 @@ \section{Notes} \bye % Local variables: -% compile-command: "tex refcard" +% compile-command: "pdftex orgcard" % End: - diff --git a/etc/remacs-buffer.gdb b/etc/remacs-buffer.gdb index 9659ccdc644..48e9a5dac1b 100644 --- a/etc/remacs-buffer.gdb +++ b/etc/remacs-buffer.gdb @@ -105,8 +105,6 @@ define ybuffer-list while $alist != $qnil set $this = ((struct Lisp_Cons *) $ptr)->car set $alist = ((struct Lisp_Cons *) $ptr)->u.cdr - ygetptr $alist - set $alist = $ptr # Vbuffer_alist elts are pairs of the form (name . buffer) ygetptr $this @@ -136,6 +134,8 @@ define ybuffer-list end set $i++ + ygetptr $alist + set $alist = $ptr end end document ybuffer-list diff --git a/etc/remacs.desktop b/etc/remacs.desktop index 5cdb8fd2d59..6bdb92d0455 100644 --- a/etc/remacs.desktop +++ b/etc/remacs.desktop @@ -3,10 +3,10 @@ Name=Remacs GenericName=Text Editor Comment=Edit text MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++; -Exec=remacs %F -Icon=remacs +Exec=emacs %F +Icon=emacs Type=Application Terminal=false Categories=Development;TextEditor; -StartupWMClass=remacs +StartupWMClass=emacs Keywords=Text;Editor; diff --git a/etc/remacs.service b/etc/remacs.service index f0299b33af6..f9e8b05c2b5 100644 --- a/etc/remacs.service +++ b/etc/remacs.service @@ -4,12 +4,12 @@ ## to use absolute file names for the executables. [Unit] Description=remacs text editor -Documentation=info:remacs man:remacs(1) https://gnu.org/software/emacs/ +Documentation=info:remacs man:emacs(1) https://gnu.org/software/emacs/ [Service] Type=simple -ExecStart=remacs --new-daemon -ExecStop=remacsclient --eval "(kill-emacs)" +ExecStart=emacs --fg-daemon +ExecStop=emacsclient --eval "(kill-emacs)" Environment=SSH_AUTH_SOCK=%t/keyring/ssh Restart=on-failure diff --git a/etc/schema/od-manifest-schema-v1.2-os.rnc b/etc/schema/od-manifest-schema-v1.2-os.rnc new file mode 100644 index 00000000000..87f84d1ea87 --- /dev/null +++ b/etc/schema/od-manifest-schema-v1.2-os.rnc @@ -0,0 +1,88 @@ +# Open Document Format for Office Applications (OpenDocument) Version 1.2 +# OASIS Standard, 29 September 2011 +# Manifest Relax-NG Schema +# Source: http://docs.oasis-open.org/office/v1.2/os/ +# Copyright (c) OASIS Open 2002-2011, 2013. All Rights Reserved. +# +# All capitalized terms in the following text have the meanings assigned to them +# in the OASIS Intellectual Property Rights Policy (the "OASIS IPR Policy"). The +# full Policy may be found at the OASIS website. +# +# This document and translations of it may be copied and furnished to others, and +# derivative works that comment on or otherwise explain it or assist in its +# implementation may be prepared, copied, published, and distributed, in whole or +# in part, without restriction of any kind, provided that the above copyright +# notice and this section are included on all such copies and derivative works. +# However, this document itself may not be modified in any way, including by +# removing the copyright notice or references to OASIS, except as needed for the +# purpose of developing any document or deliverable produced by an OASIS +# Technical Committee (in which case the rules applicable to copyrights, as set +# forth in the OASIS IPR Policy, must be followed) or as required to translate it +# into languages other than English. +# +# The limited permissions granted above are perpetual and will not be revoked by +# OASIS or its successors or assigns. +# +# This document and the information contained herein is provided on an "AS IS" +# basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +# LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT +# INFRINGE ANY OWNERSHIP RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR +# FITNESS FOR A PARTICULAR PURPOSE. + +namespace manifest = + "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" + +start = manifest +manifest = element manifest:manifest { manifest-attlist, file-entry+ } +manifest-attlist = attribute manifest:version { "1.2" } +file-entry = + element manifest:file-entry { file-entry-attlist, encryption-data? } +file-entry-attlist = + attribute manifest:full-path { \string } + & attribute manifest:size { nonNegativeInteger }? + & attribute manifest:media-type { \string } + & attribute manifest:preferred-view-mode { + "edit" | "presentation-slide-show" | "read-only" | namespacedToken + }? + & attribute manifest:version { \string }? +encryption-data = + element manifest:encryption-data { + encryption-data-attlist, + algorithm, + start-key-generation?, + key-derivation + } +encryption-data-attlist = + attribute manifest:checksum-type { "SHA1/1K" | anyURI } + & attribute manifest:checksum { base64Binary } +algorithm = + element manifest:algorithm { algorithm-attlist, anyElements } +algorithm-attlist = + attribute manifest:algorithm-name { "Blowfish CFB" | anyURI } + & attribute manifest:initialisation-vector { base64Binary } +anyAttListOrElements = + attribute * { text }*, + anyElements +anyElements = + element * { + mixed { anyAttListOrElements } + }* +key-derivation = + element manifest:key-derivation { key-derivation-attlist, empty } +key-derivation-attlist = + attribute manifest:key-derivation-name { "PBKDF2" | anyURI } + & attribute manifest:salt { base64Binary } + & attribute manifest:iteration-count { nonNegativeInteger } + & attribute manifest:key-size { nonNegativeInteger }? +start-key-generation = + element manifest:start-key-generation { + start-key-generation-attlist, empty + } +start-key-generation-attlist = + attribute manifest:start-key-generation-name { "SHA1" | anyURI } + & attribute manifest:key-size { nonNegativeInteger }? +base64Binary = xsd:base64Binary +namespacedToken = xsd:QName { pattern = "[^:]+:[^:]+" } +nonNegativeInteger = xsd:nonNegativeInteger +\string = xsd:string +anyURI = xsd:anyURI diff --git a/etc/schema/od-schema-v1.2-os.rnc b/etc/schema/od-schema-v1.2-os.rnc new file mode 100644 index 00000000000..8d679d62e4e --- /dev/null +++ b/etc/schema/od-schema-v1.2-os.rnc @@ -0,0 +1,6280 @@ +# Open Document Format for Office Applications (OpenDocument) Version 1.2 +# OASIS Standard, 29 September 2011 +# Relax-NG Schema +# Source: http://docs.oasis-open.org/office/v1.2/os/ +# Copyright (c) OASIS Open 2002-2011, 2013. All Rights Reserved. +# +# All capitalized terms in the following text have the meanings assigned to them +# in the OASIS Intellectual Property Rights Policy (the "OASIS IPR Policy"). The +# full Policy may be found at the OASIS website. +# +# This document and translations of it may be copied and furnished to others, and +# derivative works that comment on or otherwise explain it or assist in its +# implementation may be prepared, copied, published, and distributed, in whole or +# in part, without restriction of any kind, provided that the above copyright +# notice and this section are included on all such copies and derivative works. +# However, this document itself may not be modified in any way, including by +# removing the copyright notice or references to OASIS, except as needed for the +# purpose of developing any document or deliverable produced by an OASIS +# Technical Committee (in which case the rules applicable to copyrights, as set +# forth in the OASIS IPR Policy, must be followed) or as required to translate it +# into languages other than English. +# +# The limited permissions granted above are perpetual and will not be revoked by +# OASIS or its successors or assigns. +# +# This document and the information contained herein is provided on an "AS IS" +# basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +# LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT +# INFRINGE ANY OWNERSHIP RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR +# FITNESS FOR A PARTICULAR PURPOSE. + +namespace anim = "urn:oasis:names:tc:opendocument:xmlns:animation:1.0" +namespace chart = "urn:oasis:names:tc:opendocument:xmlns:chart:1.0" +namespace config = "urn:oasis:names:tc:opendocument:xmlns:config:1.0" +namespace db = "urn:oasis:names:tc:opendocument:xmlns:database:1.0" +namespace dc = "http://purl.org/dc/elements/1.1/" +namespace dr3d = "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" +namespace draw = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" +namespace fo = + "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" +namespace form = "urn:oasis:names:tc:opendocument:xmlns:form:1.0" +namespace grddl = "http://www.w3.org/2003/g/data-view#" +namespace math = "http://www.w3.org/1998/Math/MathML" +namespace meta = "urn:oasis:names:tc:opendocument:xmlns:meta:1.0" +namespace number = "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" +namespace office = "urn:oasis:names:tc:opendocument:xmlns:office:1.0" +namespace presentation = + "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" +namespace script = "urn:oasis:names:tc:opendocument:xmlns:script:1.0" +namespace smil = + "urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" +namespace style = "urn:oasis:names:tc:opendocument:xmlns:style:1.0" +namespace svg = + "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" +namespace table = "urn:oasis:names:tc:opendocument:xmlns:table:1.0" +namespace text = "urn:oasis:names:tc:opendocument:xmlns:text:1.0" +namespace xforms = "http://www.w3.org/2002/xforms" +namespace xhtml = "http://www.w3.org/1999/xhtml" +namespace xlink = "http://www.w3.org/1999/xlink" + +office-process-content = attribute office:process-content { boolean }? +start = + office-document + | office-document-content + | office-document-styles + | office-document-meta + | office-document-settings +office-document = + element office:document { + office-document-attrs, + office-document-common-attrs, + office-meta, + office-settings, + office-scripts, + office-font-face-decls, + office-styles, + office-automatic-styles, + office-master-styles, + office-body + } +office-document-content = + element office:document-content { + office-document-common-attrs, + office-scripts, + office-font-face-decls, + office-automatic-styles, + office-body + } +office-document-styles = + element office:document-styles { + office-document-common-attrs, + office-font-face-decls, + office-styles, + office-automatic-styles, + office-master-styles + } +office-document-meta = + element office:document-meta { + office-document-common-attrs, office-meta + } +office-document-settings = + element office:document-settings { + office-document-common-attrs, office-settings + } +office-document-common-attrs = + attribute office:version { "1.2" } + & attribute grddl:transformation { + list { anyIRI* } + }? +office-document-attrs = attribute office:mimetype { \string } +office-meta = element office:meta { office-meta-content-strict }? +office-meta-content-strict = office-meta-data* +office-body = element office:body { office-body-content } +office-body-content = + element office:text { + office-text-attlist, + office-text-content-prelude, + office-text-content-main, + office-text-content-epilogue + } + | element office:drawing { + office-drawing-attlist, + office-drawing-content-prelude, + office-drawing-content-main, + office-drawing-content-epilogue + } + | element office:presentation { + office-presentation-attlist, + office-presentation-content-prelude, + office-presentation-content-main, + office-presentation-content-epilogue + } + | element office:spreadsheet { + office-spreadsheet-attlist, + office-spreadsheet-content-prelude, + office-spreadsheet-content-main, + office-spreadsheet-content-epilogue + } + | element office:chart { + office-chart-attlist, + office-chart-content-prelude, + office-chart-content-main, + office-chart-content-epilogue + } + | element office:image { + office-image-attlist, + office-image-content-prelude, + office-image-content-main, + office-image-content-epilogue + } + | office-database +office-text-content-prelude = + office-forms, text-tracked-changes, text-decls, table-decls +office-text-content-main = + text-content* + | (text-page-sequence, (shape)*) +text-content = + text-h + | text-p + | text-list + | text-numbered-paragraph + | table-table + | text-section + | text-soft-page-break + | text-table-of-content + | text-illustration-index + | text-table-index + | text-object-index + | text-user-index + | text-alphabetical-index + | text-bibliography + | shape + | change-marks +office-text-content-epilogue = table-functions +office-text-attlist = + attribute text:global { boolean }? + & attribute text:use-soft-page-breaks { boolean }? +office-drawing-attlist = empty +office-drawing-content-prelude = text-decls, table-decls +office-drawing-content-main = draw-page* +office-drawing-content-epilogue = table-functions +office-presentation-attlist = empty +office-presentation-content-prelude = + text-decls, table-decls, presentation-decls +office-presentation-content-main = draw-page* +office-presentation-content-epilogue = + presentation-settings, table-functions +office-spreadsheet-content-prelude = + table-tracked-changes?, text-decls, table-decls +table-decls = + table-calculation-settings?, + table-content-validations?, + table-label-ranges? +office-spreadsheet-content-main = table-table* +office-spreadsheet-content-epilogue = table-functions +table-functions = + table-named-expressions?, + table-database-ranges?, + table-data-pilot-tables?, + table-consolidation?, + table-dde-links? +office-chart-attlist = empty +office-chart-content-prelude = text-decls, table-decls +office-chart-content-main = chart-chart +office-chart-content-epilogue = table-functions +office-image-attlist = empty +office-image-content-prelude = empty +office-image-content-main = draw-frame +office-image-content-epilogue = empty +office-settings = element office:settings { config-config-item-set+ }? +config-config-item-set = + element config:config-item-set { + config-config-item-set-attlist, config-items + } +config-items = + (config-config-item + | config-config-item-set + | config-config-item-map-named + | config-config-item-map-indexed)+ +config-config-item-set-attlist = attribute config:name { \string } +config-config-item = + element config:config-item { config-config-item-attlist, text } +config-config-item-attlist = + attribute config:name { \string } + & attribute config:type { + "boolean" + | "short" + | "int" + | "long" + | "double" + | "string" + | "datetime" + | "base64Binary" + } +config-config-item-map-indexed = + element config:config-item-map-indexed { + config-config-item-map-indexed-attlist, + config-config-item-map-entry+ + } +config-config-item-map-indexed-attlist = + attribute config:name { \string } +config-config-item-map-entry = + element config:config-item-map-entry { + config-config-item-map-entry-attlist, config-items + } +config-config-item-map-entry-attlist = + attribute config:name { \string }? +config-config-item-map-named = + element config:config-item-map-named { + config-config-item-map-named-attlist, config-config-item-map-entry+ + } +config-config-item-map-named-attlist = attribute config:name { \string } +office-scripts = + element office:scripts { office-script*, office-event-listeners? }? +office-script = + element office:script { + office-script-attlist, + mixed { anyElements } + } +office-script-attlist = attribute script:language { \string } +office-font-face-decls = + element office:font-face-decls { style-font-face* }? +office-styles = + element office:styles { + styles + & style-default-style* + & style-default-page-layout? + & text-outline-style? + & text-notes-configuration* + & text-bibliography-configuration? + & text-linenumbering-configuration? + & draw-gradient* + & svg-linearGradient* + & svg-radialGradient* + & draw-hatch* + & draw-fill-image* + & draw-marker* + & draw-stroke-dash* + & draw-opacity* + & style-presentation-page-layout* + & table-table-template* + }? +office-automatic-styles = + element office:automatic-styles { styles & style-page-layout* }? +office-master-styles = + element office:master-styles { + style-master-page* & style-handout-master? & draw-layer-set? + }? +styles = + style-style* + & text-list-style* + & number-number-style* + & number-currency-style* + & number-percentage-style* + & number-date-style* + & number-time-style* + & number-boolean-style* + & number-text-style* +office-meta-data = + element meta:generator { \string } + | element dc:title { \string } + | element dc:description { \string } + | element dc:subject { \string } + | element meta:keyword { \string } + | element meta:initial-creator { \string } + | dc-creator + | element meta:printed-by { \string } + | element meta:creation-date { dateTime } + | dc-date + | element meta:print-date { dateTime } + | element meta:template { + attribute xlink:type { "simple" }, + attribute xlink:href { anyIRI }, + attribute xlink:actuate { "onRequest" }?, + attribute xlink:title { \string }?, + attribute meta:date { dateTime }? + } + | element meta:auto-reload { + (attribute xlink:type { "simple" }, + attribute xlink:href { anyIRI }, + attribute xlink:show { "replace" }?, + attribute xlink:actuate { "onLoad" }?)?, + attribute meta:delay { duration }? + } + | element meta:hyperlink-behaviour { + attribute office:target-frame-name { targetFrameName }?, + attribute xlink:show { "new" | "replace" }? + } + | element dc:language { language } + | element meta:editing-cycles { nonNegativeInteger } + | element meta:editing-duration { duration } + | element meta:document-statistic { + attribute meta:page-count { nonNegativeInteger }?, + attribute meta:table-count { nonNegativeInteger }?, + attribute meta:draw-count { nonNegativeInteger }?, + attribute meta:image-count { nonNegativeInteger }?, + attribute meta:ole-object-count { nonNegativeInteger }?, + attribute meta:object-count { nonNegativeInteger }?, + attribute meta:paragraph-count { nonNegativeInteger }?, + attribute meta:word-count { nonNegativeInteger }?, + attribute meta:character-count { nonNegativeInteger }?, + attribute meta:frame-count { nonNegativeInteger }?, + attribute meta:sentence-count { nonNegativeInteger }?, + attribute meta:syllable-count { nonNegativeInteger }?, + attribute meta:non-whitespace-character-count { + nonNegativeInteger + }?, + attribute meta:row-count { nonNegativeInteger }?, + attribute meta:cell-count { nonNegativeInteger }? + } + | element meta:user-defined { + attribute meta:name { \string }, + ((attribute meta:value-type { "float" }, + double) + | (attribute meta:value-type { "date" }, + dateOrDateTime) + | (attribute meta:value-type { "time" }, + duration) + | (attribute meta:value-type { "boolean" }, + boolean) + | (attribute meta:value-type { "string" }, + \string) + | text) + } +dc-creator = element dc:creator { \string } +dc-date = element dc:date { dateTime } +text-h = + element text:h { + heading-attrs, + paragraph-attrs, + text-number?, + paragraph-content-or-hyperlink* + } +heading-attrs = + attribute text:outline-level { positiveInteger } + & attribute text:restart-numbering { boolean }? + & attribute text:start-value { nonNegativeInteger }? + & attribute text:is-list-header { boolean }? +text-number = element text:number { \string } +text-p = + element text:p { paragraph-attrs, paragraph-content-or-hyperlink* } +paragraph-attrs = + attribute text:style-name { styleNameRef }? + & attribute text:class-names { styleNameRefs }? + & attribute text:cond-style-name { styleNameRef }? + & (xml-id, + attribute text:id { NCName }?)? + & common-in-content-meta-attlist? +text-page-sequence = element text:page-sequence { text-page+ } +text-page = element text:page { text-page-attlist, empty } +text-page-attlist = attribute text:master-page-name { styleNameRef } +text-list = + element text:list { + text-list-attr, text-list-header?, text-list-item* + } +text-list-attr = + attribute text:style-name { styleNameRef }? + & attribute text:continue-numbering { boolean }? + & attribute text:continue-list { IDREF }? + & xml-id? +text-list-item = + element text:list-item { text-list-item-attr, text-list-item-content } +text-list-item-content = + text-number?, (text-p | text-h | text-list | text-soft-page-break)* +text-list-item-attr = + attribute text:start-value { nonNegativeInteger }? + & attribute text:style-override { styleNameRef }? + & xml-id? +text-list-header = + element text:list-header { + text-list-header-attr, text-list-item-content + } +text-list-header-attr = xml-id? +text-numbered-paragraph = + element text:numbered-paragraph { + text-numbered-paragraph-attr, text-number?, (text-p | text-h) + } +text-numbered-paragraph-attr = + attribute text:list-id { NCName } + & attribute text:level { positiveInteger }? + & (attribute text:style-name { styleNameRef }, + attribute text:continue-numbering { boolean }, + attribute text:start-value { nonNegativeInteger })? + & xml-id? +text-section = + element text:section { + text-section-attlist, + (text-section-source | text-section-source-dde | empty), + text-content* + } +text-section-attlist = + common-section-attlist + & (attribute text:display { "true" | "none" } + | (attribute text:display { "condition" }, + attribute text:condition { \string }) + | empty) +common-section-attlist = + attribute text:style-name { styleNameRef }? + & attribute text:name { \string } + & attribute text:protected { boolean }? + & attribute text:protection-key { \string }? + & attribute text:protection-key-digest-algorithm { anyIRI }? + & xml-id? +text-section-source = + element text:section-source { text-section-source-attr } +text-section-source-attr = + (attribute xlink:type { "simple" }, + attribute xlink:href { anyIRI }, + attribute xlink:show { "embed" }?)? + & attribute text:section-name { \string }? + & attribute text:filter-name { \string }? +text-section-source-dde = office-dde-source +text-tracked-changes = + element text:tracked-changes { + text-tracked-changes-attr, text-changed-region* + }? +text-tracked-changes-attr = attribute text:track-changes { boolean }? +text-changed-region = + element text:changed-region { + text-changed-region-attr, text-changed-region-content + } +text-changed-region-attr = + xml-id, + attribute text:id { NCName }? +text-changed-region-content = + element text:insertion { office-change-info } + | element text:deletion { office-change-info, text-content* } + | element text:format-change { office-change-info } +change-marks = + element text:change { change-mark-attr } + | element text:change-start { change-mark-attr } + | element text:change-end { change-mark-attr } +change-mark-attr = attribute text:change-id { IDREF } +text-soft-page-break = element text:soft-page-break { empty } +text-decls = + element text:variable-decls { text-variable-decl* }?, + element text:sequence-decls { text-sequence-decl* }?, + element text:user-field-decls { text-user-field-decl* }?, + element text:dde-connection-decls { text-dde-connection-decl* }?, + text-alphabetical-index-auto-mark-file? +paragraph-content-or-hyperlink = paragraph-content | text-a +paragraph-content = + text + | element text:s { + attribute text:c { nonNegativeInteger }? + } + | element text:tab { text-tab-attr } + | element text:line-break { empty } + | text-soft-page-break + | element text:span { + attribute text:style-name { styleNameRef }?, + attribute text:class-names { styleNameRefs }?, + paragraph-content-or-hyperlink* + } + | element text:meta { + text-meta-attlist, paragraph-content-or-hyperlink* + } + | (text-bookmark | text-bookmark-start | text-bookmark-end) + | element text:reference-mark { + attribute text:name { \string } + } + | (element text:reference-mark-start { + attribute text:name { \string } + } + | element text:reference-mark-end { + attribute text:name { \string } + }) + | element text:note { + text-note-class, + attribute text:id { \string }?, + element text:note-citation { + attribute text:label { \string }?, + text + }, + element text:note-body { text-content* } + } + | element text:ruby { + attribute text:style-name { styleNameRef }?, + element text:ruby-base { paragraph-content-or-hyperlink* }, + element text:ruby-text { + attribute text:style-name { styleNameRef }?, + text + } + } + | (office-annotation | office-annotation-end) + | change-marks + | shape + | element text:date { text-date-attlist, text } + | element text:time { text-time-attlist, text } + | element text:page-number { text-page-number-attlist, text } + | element text:page-continuation { + text-page-continuation-attlist, text + } + | element text:sender-firstname { common-field-fixed-attlist, text } + | element text:sender-lastname { common-field-fixed-attlist, text } + | element text:sender-initials { common-field-fixed-attlist, text } + | element text:sender-title { common-field-fixed-attlist, text } + | element text:sender-position { common-field-fixed-attlist, text } + | element text:sender-email { common-field-fixed-attlist, text } + | element text:sender-phone-private { + common-field-fixed-attlist, text + } + | element text:sender-fax { common-field-fixed-attlist, text } + | element text:sender-company { common-field-fixed-attlist, text } + | element text:sender-phone-work { common-field-fixed-attlist, text } + | element text:sender-street { common-field-fixed-attlist, text } + | element text:sender-city { common-field-fixed-attlist, text } + | element text:sender-postal-code { common-field-fixed-attlist, text } + | element text:sender-country { common-field-fixed-attlist, text } + | element text:sender-state-or-province { + common-field-fixed-attlist, text + } + | element text:author-name { common-field-fixed-attlist, text } + | element text:author-initials { common-field-fixed-attlist, text } + | element text:chapter { text-chapter-attlist, text } + | element text:file-name { text-file-name-attlist, text } + | element text:template-name { text-template-name-attlist, text } + | element text:sheet-name { text } + | element text:variable-set { + (common-field-name-attlist + & common-field-formula-attlist + & common-value-and-type-attlist + & common-field-display-value-none-attlist + & common-field-data-style-name-attlist), + text + } + | element text:variable-get { + (common-field-name-attlist + & common-field-display-value-formula-attlist + & common-field-data-style-name-attlist), + text + } + | element text:variable-input { + (common-field-name-attlist + & common-field-description-attlist + & common-value-type-attlist + & common-field-display-value-none-attlist + & common-field-data-style-name-attlist), + text + } + | element text:user-field-get { + (common-field-name-attlist + & common-field-display-value-formula-none-attlist + & common-field-data-style-name-attlist), + text + } + | element text:user-field-input { + (common-field-name-attlist + & common-field-description-attlist + & common-field-data-style-name-attlist), + text + } + | element text:sequence { + (common-field-name-attlist + & common-field-formula-attlist + & common-field-num-format-attlist + & text-sequence-ref-name), + text + } + | element text:expression { + (common-field-formula-attlist + & common-value-and-type-attlist? + & common-field-display-value-formula-attlist + & common-field-data-style-name-attlist), + text + } + | element text:text-input { common-field-description-attlist, text } + | element text:initial-creator { common-field-fixed-attlist, text } + | element text:creation-date { + (common-field-fixed-attlist + & common-field-data-style-name-attlist + & attribute text:date-value { dateOrDateTime }?), + text + } + | element text:creation-time { + (common-field-fixed-attlist + & common-field-data-style-name-attlist + & attribute text:time-value { timeOrDateTime }?), + text + } + | element text:description { common-field-fixed-attlist, text } + | element text:user-defined { + (common-field-fixed-attlist + & attribute text:name { \string } + & common-field-data-style-name-attlist + & attribute office:value { double }? + & attribute office:date-value { dateOrDateTime }? + & attribute office:time-value { duration }? + & attribute office:boolean-value { boolean }? + & attribute office:string-value { \string }?), + text + } + | element text:print-time { + (common-field-fixed-attlist + & common-field-data-style-name-attlist + & attribute text:time-value { time }?), + text + } + | element text:print-date { + (common-field-fixed-attlist + & common-field-data-style-name-attlist + & attribute text:date-value { date }?), + text + } + | element text:printed-by { common-field-fixed-attlist, text } + | element text:title { common-field-fixed-attlist, text } + | element text:subject { common-field-fixed-attlist, text } + | element text:keywords { common-field-fixed-attlist, text } + | element text:editing-cycles { common-field-fixed-attlist, text } + | element text:editing-duration { + (common-field-fixed-attlist + & common-field-data-style-name-attlist + & attribute text:duration { duration }?), + text + } + | element text:modification-time { + (common-field-fixed-attlist + & common-field-data-style-name-attlist + & attribute text:time-value { time }?), + text + } + | element text:modification-date { + (common-field-fixed-attlist + & common-field-data-style-name-attlist + & attribute text:date-value { date }?), + text + } + | element text:creator { common-field-fixed-attlist, text } + | element text:page-count + | text:paragraph-count + | text:word-count + | text:character-count + | text:table-count + | text:image-count + | text:object-count { + common-field-num-format-attlist, text + } + | element text:database-display { + text-database-display-attlist, text + } + | element text:database-next { text-database-next-attlist } + | element text:database-row-select { + text-database-row-select-attlist + } + | element text:database-row-number { + (common-field-database-table + & common-field-num-format-attlist + & attribute text:value { nonNegativeInteger }?), + text + } + | element text:database-name { common-field-database-table, text } + | element text:page-variable-set { + text-set-page-variable-attlist, text + } + | element text:page-variable-get { + text-get-page-variable-attlist, text + } + | element text:placeholder { text-placeholder-attlist, text } + | element text:conditional-text { + text-conditional-text-attlist, text + } + | element text:hidden-text { text-hidden-text-attlist, text } + | element text:reference-ref | text:bookmark-ref { + text-common-ref-content & text-bookmark-ref-content + } + | element text:note-ref { + text-common-ref-content & text-note-ref-content + } + | element text:sequence-ref { + text-common-ref-content & text-sequence-ref-content + } + | element text:script { + ((attribute xlink:type { "simple" }, + attribute xlink:href { anyIRI }) + | text) + & attribute script:language { \string }? + } + | element text:execute-macro { + attribute text:name { \string }?, + office-event-listeners?, + text + } + | element text:hidden-paragraph { + text-hidden-paragraph-attlist, text + } + | element text:dde-connection { + attribute text:connection-name { \string }, + text + } + | element text:measure { + attribute text:kind { "value" | "unit" | "gap" }, + text + } + | element text:table-formula { + (common-field-formula-attlist + & common-field-display-value-formula-attlist + & common-field-data-style-name-attlist), + text + } + | element text:meta-field { + text-meta-field-attlist, paragraph-content-or-hyperlink* + } + | element text:toc-mark-start { text-toc-mark-start-attrs } + | element text:toc-mark-end { text-id } + | element text:toc-mark { + attribute text:string-value { \string }, + text-outline-level + } + | element text:user-index-mark-start { + text-id, text-outline-level, text-index-name + } + | element text:user-index-mark-end { text-id } + | element text:user-index-mark { + attribute text:string-value { \string }, + text-outline-level, + text-index-name + } + | element text:alphabetical-index-mark-start { + text-id, text-alphabetical-index-mark-attrs + } + | element text:alphabetical-index-mark-end { text-id } + | element text:alphabetical-index-mark { + attribute text:string-value { \string }, + text-alphabetical-index-mark-attrs + } + | element text:bibliography-mark { + attribute text:bibliography-type { text-bibliography-types }, + attribute text:identifier + | text:address + | text:annote + | text:author + | text:booktitle + | text:chapter + | text:edition + | text:editor + | text:howpublished + | text:institution + | text:journal + | text:month + | text:note + | text:number + | text:organizations + | text:pages + | text:publisher + | text:school + | text:series + | text:title + | text:report-type + | text:volume + | text:year + | text:url + | text:custom1 + | text:custom2 + | text:custom3 + | text:custom4 + | text:custom5 + | text:isbn + | text:issn { \string }*, + text + } + | element presentation:header { empty } + | element presentation:footer { empty } + | element presentation:date-time { empty } +text-tab-attr = attribute text:tab-ref { nonNegativeInteger }? +text-a = + element text:a { + text-a-attlist, office-event-listeners?, paragraph-content* + } +text-a-attlist = + attribute office:name { \string }? + & attribute office:title { \string }? + & attribute xlink:type { "simple" } + & attribute xlink:href { anyIRI } + & attribute xlink:actuate { "onRequest" }? + & attribute office:target-frame-name { targetFrameName }? + & attribute xlink:show { "new" | "replace" }? + & attribute text:style-name { styleNameRef }? + & attribute text:visited-style-name { styleNameRef }? +text-meta-attlist = common-in-content-meta-attlist? & xml-id? +text-bookmark = element text:bookmark { text-bookmark-attlist, empty } +text-bookmark-start = + element text:bookmark-start { text-bookmark-start-attlist, empty } +text-bookmark-end = + element text:bookmark-end { text-bookmark-end-attlist, empty } +text-bookmark-attlist = + attribute text:name { \string } + & xml-id? +text-bookmark-start-attlist = + attribute text:name { \string } + & xml-id? + & common-in-content-meta-attlist? +text-bookmark-end-attlist = attribute text:name { \string } +text-note-class = attribute text:note-class { "footnote" | "endnote" } +text-date-attlist = + (common-field-fixed-attlist & common-field-data-style-name-attlist) + & attribute text:date-value { dateOrDateTime }? + & attribute text:date-adjust { duration }? +text-time-attlist = + (common-field-fixed-attlist & common-field-data-style-name-attlist) + & attribute text:time-value { timeOrDateTime }? + & attribute text:time-adjust { duration }? +text-page-number-attlist = + (common-field-num-format-attlist & common-field-fixed-attlist) + & attribute text:page-adjust { integer }? + & attribute text:select-page { "previous" | "current" | "next" }? +text-page-continuation-attlist = + attribute text:select-page { "previous" | "next" } + & attribute text:string-value { \string }? +text-chapter-attlist = + attribute text:display { + "name" + | "number" + | "number-and-name" + | "plain-number-and-name" + | "plain-number" + } + & attribute text:outline-level { nonNegativeInteger } +text-file-name-attlist = + attribute text:display { + "full" | "path" | "name" | "name-and-extension" + }? + & common-field-fixed-attlist +text-template-name-attlist = + attribute text:display { + "full" | "path" | "name" | "name-and-extension" | "area" | "title" + }? +text-variable-decl = + element text:variable-decl { + common-field-name-attlist, common-value-type-attlist + } +text-user-field-decl = + element text:user-field-decl { + common-field-name-attlist, + common-field-formula-attlist?, + common-value-and-type-attlist + } +text-sequence-decl = + element text:sequence-decl { text-sequence-decl-attlist } +text-sequence-decl-attlist = + common-field-name-attlist + & attribute text:display-outline-level { nonNegativeInteger } + & attribute text:separation-character { character }? +text-sequence-ref-name = attribute text:ref-name { \string }? +common-field-database-table = + common-field-database-table-attlist, common-field-database-name +common-field-database-name = + attribute text:database-name { \string }? + | form-connection-resource +common-field-database-table-attlist = + attribute text:table-name { \string } + & attribute text:table-type { "table" | "query" | "command" }? +text-database-display-attlist = + common-field-database-table + & common-field-data-style-name-attlist + & attribute text:column-name { \string } +text-database-next-attlist = + common-field-database-table + & attribute text:condition { \string }? +text-database-row-select-attlist = + common-field-database-table + & attribute text:condition { \string }? + & attribute text:row-number { nonNegativeInteger }? +text-set-page-variable-attlist = + attribute text:active { boolean }? + & attribute text:page-adjust { integer }? +text-get-page-variable-attlist = common-field-num-format-attlist +text-placeholder-attlist = + attribute text:placeholder-type { + "text" | "table" | "text-box" | "image" | "object" + } + & common-field-description-attlist +text-conditional-text-attlist = + attribute text:condition { \string } + & attribute text:string-value-if-true { \string } + & attribute text:string-value-if-false { \string } + & attribute text:current-value { boolean }? +text-hidden-text-attlist = + attribute text:condition { \string } + & attribute text:string-value { \string } + & attribute text:is-hidden { boolean }? +text-common-ref-content = + text + & attribute text:ref-name { \string }? +text-bookmark-ref-content = + attribute text:reference-format { + common-ref-format-values + | "number-no-superior" + | "number-all-superior" + | "number" + }? +text-note-ref-content = + attribute text:reference-format { common-ref-format-values }? + & text-note-class +text-sequence-ref-content = + attribute text:reference-format { + common-ref-format-values + | "category-and-value" + | "caption" + | "value" + }? +common-ref-format-values = "page" | "chapter" | "direction" | "text" +text-hidden-paragraph-attlist = + attribute text:condition { \string } + & attribute text:is-hidden { boolean }? +text-meta-field-attlist = xml-id & common-field-data-style-name-attlist +common-value-type-attlist = attribute office:value-type { valueType } +common-value-and-type-attlist = + (attribute office:value-type { "float" }, + attribute office:value { double }) + | (attribute office:value-type { "percentage" }, + attribute office:value { double }) + | (attribute office:value-type { "currency" }, + attribute office:value { double }, + attribute office:currency { \string }?) + | (attribute office:value-type { "date" }, + attribute office:date-value { dateOrDateTime }) + | (attribute office:value-type { "time" }, + attribute office:time-value { duration }) + | (attribute office:value-type { "boolean" }, + attribute office:boolean-value { boolean }) + | (attribute office:value-type { "string" }, + attribute office:string-value { \string }?) +common-field-fixed-attlist = attribute text:fixed { boolean }? +common-field-name-attlist = attribute text:name { variableName } +common-field-description-attlist = + attribute text:description { \string }? +common-field-display-value-none-attlist = + attribute text:display { "value" | "none" }? +common-field-display-value-formula-none-attlist = + attribute text:display { "value" | "formula" | "none" }? +common-field-display-value-formula-attlist = + attribute text:display { "value" | "formula" }? +common-field-formula-attlist = attribute text:formula { \string }? +common-field-data-style-name-attlist = + attribute style:data-style-name { styleNameRef }? +common-field-num-format-attlist = common-num-format-attlist? +text-toc-mark-start-attrs = text-id, text-outline-level +text-outline-level = attribute text:outline-level { positiveInteger }? +text-id = attribute text:id { \string } +text-index-name = attribute text:index-name { \string } +text-alphabetical-index-mark-attrs = + attribute text:key1 { \string }? + & attribute text:key2 { \string }? + & attribute text:string-value-phonetic { \string }? + & attribute text:key1-phonetic { \string }? + & attribute text:key2-phonetic { \string }? + & attribute text:main-entry { boolean }? +text-bibliography-types = + "article" + | "book" + | "booklet" + | "conference" + | "custom1" + | "custom2" + | "custom3" + | "custom4" + | "custom5" + | "email" + | "inbook" + | "incollection" + | "inproceedings" + | "journal" + | "manual" + | "mastersthesis" + | "misc" + | "phdthesis" + | "proceedings" + | "techreport" + | "unpublished" + | "www" +text-index-body = element text:index-body { index-content-main* } +index-content-main = text-content | text-index-title +text-index-title = + element text:index-title { + common-section-attlist, index-content-main* + } +text-table-of-content = + element text:table-of-content { + common-section-attlist, + text-table-of-content-source, + text-index-body + } +text-table-of-content-source = + element text:table-of-content-source { + text-table-of-content-source-attlist, + text-index-title-template?, + text-table-of-content-entry-template*, + text-index-source-styles* + } +text-table-of-content-source-attlist = + attribute text:outline-level { positiveInteger }? + & attribute text:use-outline-level { boolean }? + & attribute text:use-index-marks { boolean }? + & attribute text:use-index-source-styles { boolean }? + & attribute text:index-scope { "document" | "chapter" }? + & attribute text:relative-tab-stop-position { boolean }? +text-table-of-content-entry-template = + element text:table-of-content-entry-template { + text-table-of-content-entry-template-attlist, + text-table-of-content-children* + } +text-table-of-content-children = + text-index-entry-chapter + | text-index-entry-page-number + | text-index-entry-text + | text-index-entry-span + | text-index-entry-tab-stop + | text-index-entry-link-start + | text-index-entry-link-end +text-table-of-content-entry-template-attlist = + attribute text:outline-level { positiveInteger } + & attribute text:style-name { styleNameRef } +text-illustration-index = + element text:illustration-index { + common-section-attlist, + text-illustration-index-source, + text-index-body + } +text-illustration-index-source = + element text:illustration-index-source { + text-illustration-index-source-attrs, + text-index-title-template?, + text-illustration-index-entry-template? + } +text-illustration-index-source-attrs = + text-index-scope-attr + & text-relative-tab-stop-position-attr + & attribute text:use-caption { boolean }? + & attribute text:caption-sequence-name { \string }? + & attribute text:caption-sequence-format { + "text" | "category-and-value" | "caption" + }? +text-index-scope-attr = + attribute text:index-scope { "document" | "chapter" }? +text-relative-tab-stop-position-attr = + attribute text:relative-tab-stop-position { boolean }? +text-illustration-index-entry-template = + element text:illustration-index-entry-template { + text-illustration-index-entry-content + } +text-illustration-index-entry-content = + text-illustration-index-entry-template-attrs, + (text-index-entry-chapter + | text-index-entry-page-number + | text-index-entry-text + | text-index-entry-span + | text-index-entry-tab-stop)* +text-illustration-index-entry-template-attrs = + attribute text:style-name { styleNameRef } +text-table-index = + element text:table-index { + common-section-attlist, text-table-index-source, text-index-body + } +text-table-index-source = + element text:table-index-source { + text-illustration-index-source-attrs, + text-index-title-template?, + text-table-index-entry-template? + } +text-table-index-entry-template = + element text:table-index-entry-template { + text-illustration-index-entry-content + } +text-object-index = + element text:object-index { + common-section-attlist, text-object-index-source, text-index-body + } +text-object-index-source = + element text:object-index-source { + text-object-index-source-attrs, + text-index-title-template?, + text-object-index-entry-template? + } +text-object-index-source-attrs = + text-index-scope-attr + & text-relative-tab-stop-position-attr + & attribute text:use-spreadsheet-objects { boolean }? + & attribute text:use-math-objects { boolean }? + & attribute text:use-draw-objects { boolean }? + & attribute text:use-chart-objects { boolean }? + & attribute text:use-other-objects { boolean }? +text-object-index-entry-template = + element text:object-index-entry-template { + text-illustration-index-entry-content + } +text-user-index = + element text:user-index { + common-section-attlist, text-user-index-source, text-index-body + } +text-user-index-source = + element text:user-index-source { + text-user-index-source-attr, + text-index-title-template?, + text-user-index-entry-template*, + text-index-source-styles* + } +text-user-index-source-attr = + text-index-scope-attr + & text-relative-tab-stop-position-attr + & attribute text:use-index-marks { boolean }? + & attribute text:use-index-source-styles { boolean }? + & attribute text:use-graphics { boolean }? + & attribute text:use-tables { boolean }? + & attribute text:use-floating-frames { boolean }? + & attribute text:use-objects { boolean }? + & attribute text:copy-outline-levels { boolean }? + & attribute text:index-name { \string } +text-user-index-entry-template = + element text:user-index-entry-template { + text-user-index-entry-template-attrs, + (text-index-entry-chapter + | text-index-entry-page-number + | text-index-entry-text + | text-index-entry-span + | text-index-entry-tab-stop)* + } +text-user-index-entry-template-attrs = + attribute text:outline-level { positiveInteger } + & attribute text:style-name { styleNameRef } +text-alphabetical-index = + element text:alphabetical-index { + common-section-attlist, + text-alphabetical-index-source, + text-index-body + } +text-alphabetical-index-source = + element text:alphabetical-index-source { + text-alphabetical-index-source-attrs, + text-index-title-template?, + text-alphabetical-index-entry-template* + } +text-alphabetical-index-source-attrs = + text-index-scope-attr + & text-relative-tab-stop-position-attr + & attribute text:ignore-case { boolean }? + & attribute text:main-entry-style-name { styleNameRef }? + & attribute text:alphabetical-separators { boolean }? + & attribute text:combine-entries { boolean }? + & attribute text:combine-entries-with-dash { boolean }? + & attribute text:combine-entries-with-pp { boolean }? + & attribute text:use-keys-as-entries { boolean }? + & attribute text:capitalize-entries { boolean }? + & attribute text:comma-separated { boolean }? + & attribute fo:language { languageCode }? + & attribute fo:country { countryCode }? + & attribute fo:script { scriptCode }? + & attribute style:rfc-language-tag { language }? + & attribute text:sort-algorithm { \string }? +text-alphabetical-index-auto-mark-file = + element text:alphabetical-index-auto-mark-file { + attribute xlink:type { "simple" }, + attribute xlink:href { anyIRI } + } +text-alphabetical-index-entry-template = + element text:alphabetical-index-entry-template { + text-alphabetical-index-entry-template-attrs, + (text-index-entry-chapter + | text-index-entry-page-number + | text-index-entry-text + | text-index-entry-span + | text-index-entry-tab-stop)* + } +text-alphabetical-index-entry-template-attrs = + attribute text:outline-level { "1" | "2" | "3" | "separator" } + & attribute text:style-name { styleNameRef } +text-bibliography = + element text:bibliography { + common-section-attlist, text-bibliography-source, text-index-body + } +text-bibliography-source = + element text:bibliography-source { + text-index-title-template?, text-bibliography-entry-template* + } +text-bibliography-entry-template = + element text:bibliography-entry-template { + text-bibliography-entry-template-attrs, + (text-index-entry-span + | text-index-entry-tab-stop + | text-index-entry-bibliography)* + } +text-bibliography-entry-template-attrs = + attribute text:bibliography-type { text-bibliography-types } + & attribute text:style-name { styleNameRef } +text-index-source-styles = + element text:index-source-styles { + attribute text:outline-level { positiveInteger }, + text-index-source-style* + } +text-index-source-style = + element text:index-source-style { + attribute text:style-name { styleName }, + empty + } +text-index-title-template = + element text:index-title-template { + attribute text:style-name { styleNameRef }?, + text + } +text-index-entry-chapter = + element text:index-entry-chapter { + attribute text:style-name { styleNameRef }?, + text-index-entry-chapter-attrs + } +text-index-entry-chapter-attrs = + attribute text:display { + "name" + | "number" + | "number-and-name" + | "plain-number" + | "plain-number-and-name" + }? + & attribute text:outline-level { positiveInteger }? +text-index-entry-text = + element text:index-entry-text { + attribute text:style-name { styleNameRef }? + } +text-index-entry-page-number = + element text:index-entry-page-number { + attribute text:style-name { styleNameRef }? + } +text-index-entry-span = + element text:index-entry-span { + attribute text:style-name { styleNameRef }?, + text + } +text-index-entry-bibliography = + element text:index-entry-bibliography { + text-index-entry-bibliography-attrs + } +text-index-entry-bibliography-attrs = + attribute text:style-name { styleNameRef }? + & attribute text:bibliography-data-field { + "address" + | "annote" + | "author" + | "bibliography-type" + | "booktitle" + | "chapter" + | "custom1" + | "custom2" + | "custom3" + | "custom4" + | "custom5" + | "edition" + | "editor" + | "howpublished" + | "identifier" + | "institution" + | "isbn" + | "issn" + | "journal" + | "month" + | "note" + | "number" + | "organizations" + | "pages" + | "publisher" + | "report-type" + | "school" + | "series" + | "title" + | "url" + | "volume" + | "year" + } +text-index-entry-tab-stop = + element text:index-entry-tab-stop { + attribute text:style-name { styleNameRef }?, + text-index-entry-tab-stop-attrs + } +text-index-entry-tab-stop-attrs = + attribute style:leader-char { character }? + & (attribute style:type { "right" } + | (attribute style:type { "left" }, + attribute style:position { length })) +text-index-entry-link-start = + element text:index-entry-link-start { + attribute text:style-name { styleNameRef }? + } +text-index-entry-link-end = + element text:index-entry-link-end { + attribute text:style-name { styleNameRef }? + } +table-table = + element table:table { + table-table-attlist, + table-title?, + table-desc?, + table-table-source?, + office-dde-source?, + table-scenario?, + office-forms?, + table-shapes?, + table-columns-and-groups, + table-rows-and-groups, + table-named-expressions? + } +table-columns-and-groups = + (table-table-column-group | table-columns-no-group)+ +table-columns-no-group = + (table-columns, (table-table-header-columns, table-columns?)?) + | (table-table-header-columns, table-columns?) +table-columns = table-table-columns | table-table-column+ +table-rows-and-groups = (table-table-row-group | table-rows-no-group)+ +table-rows-no-group = + (table-rows, (table-table-header-rows, table-rows?)?) + | (table-table-header-rows, table-rows?) +table-rows = + table-table-rows | (text-soft-page-break?, table-table-row)+ +table-table-attlist = + attribute table:name { \string }? + & attribute table:style-name { styleNameRef }? + & attribute table:template-name { \string }? + & attribute table:use-first-row-styles { boolean }? + & attribute table:use-last-row-styles { boolean }? + & attribute table:use-first-column-styles { boolean }? + & attribute table:use-last-column-styles { boolean }? + & attribute table:use-banding-rows-styles { boolean }? + & attribute table:use-banding-columns-styles { boolean }? + & attribute table:protected { boolean }? + & attribute table:protection-key { \string }? + & attribute table:protection-key-digest-algorithm { anyIRI }? + & attribute table:print { boolean }? + & attribute table:print-ranges { cellRangeAddressList }? + & xml-id? + & attribute table:is-sub-table { boolean }? +table-title = element table:title { text } +table-desc = element table:desc { text } +table-table-row = + element table:table-row { + table-table-row-attlist, + (table-table-cell | table-covered-table-cell)+ + } +table-table-row-attlist = + attribute table:number-rows-repeated { positiveInteger }? + & attribute table:style-name { styleNameRef }? + & attribute table:default-cell-style-name { styleNameRef }? + & attribute table:visibility { table-visibility-value }? + & xml-id? +table-visibility-value = "visible" | "collapse" | "filter" +table-table-cell = + element table:table-cell { + table-table-cell-attlist, + table-table-cell-attlist-extra, + table-table-cell-content + } +table-covered-table-cell = + element table:covered-table-cell { + table-table-cell-attlist, table-table-cell-content + } +table-table-cell-content = + table-cell-range-source?, + office-annotation?, + table-detective?, + text-content* +table-table-cell-attlist = + attribute table:number-columns-repeated { positiveInteger }? + & attribute table:style-name { styleNameRef }? + & attribute table:content-validation-name { \string }? + & attribute table:formula { \string }? + & common-value-and-type-attlist? + & attribute table:protect { boolean }? + & attribute table:protected { boolean }? + & xml-id? + & common-in-content-meta-attlist? +table-table-cell-attlist-extra = + attribute table:number-columns-spanned { positiveInteger }? + & attribute table:number-rows-spanned { positiveInteger }? + & attribute table:number-matrix-columns-spanned { positiveInteger }? + & attribute table:number-matrix-rows-spanned { positiveInteger }? +table-table-column = + element table:table-column { table-table-column-attlist, empty } +table-table-column-attlist = + attribute table:number-columns-repeated { positiveInteger }? + & attribute table:style-name { styleNameRef }? + & attribute table:visibility { table-visibility-value }? + & attribute table:default-cell-style-name { styleNameRef }? + & xml-id? +table-table-header-columns = + element table:table-header-columns { table-table-column+ } +table-table-columns = + element table:table-columns { table-table-column+ } +table-table-column-group = + element table:table-column-group { + table-table-column-group-attlist, table-columns-and-groups + } +table-table-column-group-attlist = attribute table:display { boolean }? +table-table-header-rows = + element table:table-header-rows { + (text-soft-page-break?, table-table-row)+ + } +table-table-rows = + element table:table-rows { (text-soft-page-break?, table-table-row)+ } +table-table-row-group = + element table:table-row-group { + table-table-row-group-attlist, table-rows-and-groups + } +table-table-row-group-attlist = attribute table:display { boolean }? +cellAddress = + xsd:string { + pattern = "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+" + } +cellRangeAddress = + xsd:string { + pattern = + "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+(:($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+)?" + } + | xsd:string { + pattern = + "($?([^\. ']+|'([^']|'')+'))?\.$?[0-9]+:($?([^\. ']+|'([^']|'')+'))?\.$?[0-9]+" + } + | xsd:string { + pattern = + "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+:($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+" + } +cellRangeAddressList = + xsd:string + >> dc:description [ + 'Value is a space separated list of "cellRangeAddress" patterns' + ] +table-table-source = + element table:table-source { + table-table-source-attlist, table-linked-source-attlist, empty + } +table-table-source-attlist = + attribute table:mode { "copy-all" | "copy-results-only" }? + & attribute table:table-name { \string }? +table-linked-source-attlist = + attribute xlink:type { "simple" } + & attribute xlink:href { anyIRI } + & attribute xlink:actuate { "onRequest" }? + & attribute table:filter-name { \string }? + & attribute table:filter-options { \string }? + & attribute table:refresh-delay { duration }? +table-scenario = + element table:scenario { table-scenario-attlist, empty } +table-scenario-attlist = + attribute table:scenario-ranges { cellRangeAddressList } + & attribute table:is-active { boolean } + & attribute table:display-border { boolean }? + & attribute table:border-color { color }? + & attribute table:copy-back { boolean }? + & attribute table:copy-styles { boolean }? + & attribute table:copy-formulas { boolean }? + & attribute table:comment { \string }? + & attribute table:protected { boolean }? +table-shapes = element table:shapes { shape+ } +table-cell-range-source = + element table:cell-range-source { + table-table-cell-range-source-attlist, + table-linked-source-attlist, + empty + } +table-table-cell-range-source-attlist = + attribute table:name { \string } + & attribute table:last-column-spanned { positiveInteger } + & attribute table:last-row-spanned { positiveInteger } +table-detective = + element table:detective { table-highlighted-range*, table-operation* } +table-operation = + element table:operation { table-operation-attlist, empty } +table-operation-attlist = + attribute table:name { + "trace-dependents" + | "remove-dependents" + | "trace-precedents" + | "remove-precedents" + | "trace-errors" + } + & attribute table:index { nonNegativeInteger } +table-highlighted-range = + element table:highlighted-range { + (table-highlighted-range-attlist + | table-highlighted-range-attlist-invalid), + empty + } +table-highlighted-range-attlist = + attribute table:cell-range-address { cellRangeAddress }? + & attribute table:direction { + "from-another-table" | "to-another-table" | "from-same-table" + } + & attribute table:contains-error { boolean }? +table-highlighted-range-attlist-invalid = + attribute table:marked-invalid { boolean } +office-spreadsheet-attlist = + attribute table:structure-protected { boolean }?, + attribute table:protection-key { \string }?, + attribute table:protection-key-digest-algorithm { anyIRI }? +table-calculation-settings = + element table:calculation-settings { + table-calculation-setting-attlist, + table-null-date?, + table-iteration? + } +table-calculation-setting-attlist = + attribute table:case-sensitive { boolean }? + & attribute table:precision-as-shown { boolean }? + & attribute table:search-criteria-must-apply-to-whole-cell { + boolean + }? + & attribute table:automatic-find-labels { boolean }? + & attribute table:use-regular-expressions { boolean }? + & attribute table:use-wildcards { boolean }? + & attribute table:null-year { positiveInteger }? +table-null-date = + element table:null-date { + attribute table:value-type { "date" }?, + attribute table:date-value { date }?, + empty + } +table-iteration = + element table:iteration { + attribute table:status { "enable" | "disable" }?, + attribute table:steps { positiveInteger }?, + attribute table:maximum-difference { double }?, + empty + } +table-content-validations = + element table:content-validations { table-content-validation+ } +table-content-validation = + element table:content-validation { + table-validation-attlist, + table-help-message?, + (table-error-message | (table-error-macro, office-event-listeners))? + } +table-validation-attlist = + attribute table:name { \string } + & attribute table:condition { \string }? + & attribute table:base-cell-address { cellAddress }? + & attribute table:allow-empty-cell { boolean }? + & attribute table:display-list { + "none" | "unsorted" | "sort-ascending" + }? +table-help-message = + element table:help-message { + attribute table:title { \string }?, + attribute table:display { boolean }?, + text-p* + } +table-error-message = + element table:error-message { + attribute table:title { \string }?, + attribute table:display { boolean }?, + attribute table:message-type { + "stop" | "warning" | "information" + }?, + text-p* + } +table-error-macro = + element table:error-macro { + attribute table:execute { boolean }? + } +table-label-ranges = element table:label-ranges { table-label-range* } +table-label-range = + element table:label-range { table-label-range-attlist, empty } +table-label-range-attlist = + attribute table:label-cell-range-address { cellRangeAddress } + & attribute table:data-cell-range-address { cellRangeAddress } + & attribute table:orientation { "column" | "row" } +table-named-expressions = + element table:named-expressions { + (table-named-range | table-named-expression)* + } +table-named-range = + element table:named-range { table-named-range-attlist, empty } +table-named-range-attlist = + attribute table:name { \string }, + attribute table:cell-range-address { cellRangeAddress }, + attribute table:base-cell-address { cellAddress }?, + attribute table:range-usable-as { + "none" + | list { + ("print-range" | "filter" | "repeat-row" | "repeat-column")+ + } + }? +table-named-expression = + element table:named-expression { + table-named-expression-attlist, empty + } +table-named-expression-attlist = + attribute table:name { \string }, + attribute table:expression { \string }, + attribute table:base-cell-address { cellAddress }? +table-database-ranges = + element table:database-ranges { table-database-range* } +table-database-range = + element table:database-range { + table-database-range-attlist, + (table-database-source-sql + | table-database-source-table + | table-database-source-query)?, + table-filter?, + table-sort?, + table-subtotal-rules? + } +table-database-range-attlist = + attribute table:name { \string }? + & attribute table:is-selection { boolean }? + & attribute table:on-update-keep-styles { boolean }? + & attribute table:on-update-keep-size { boolean }? + & attribute table:has-persistent-data { boolean }? + & attribute table:orientation { "column" | "row" }? + & attribute table:contains-header { boolean }? + & attribute table:display-filter-buttons { boolean }? + & attribute table:target-range-address { cellRangeAddress } + & attribute table:refresh-delay { boolean }? +table-database-source-sql = + element table:database-source-sql { + table-database-source-sql-attlist, empty + } +table-database-source-sql-attlist = + attribute table:database-name { \string } + & attribute table:sql-statement { \string } + & attribute table:parse-sql-statement { boolean }? +table-database-source-query = + element table:database-source-table { + table-database-source-table-attlist, empty + } +table-database-source-table-attlist = + attribute table:database-name { \string } + & attribute table:database-table-name { \string } +table-database-source-table = + element table:database-source-query { + table-database-source-query-attlist, empty + } +table-database-source-query-attlist = + attribute table:database-name { \string } + & attribute table:query-name { \string } +table-sort = element table:sort { table-sort-attlist, table-sort-by+ } +table-sort-attlist = + attribute table:bind-styles-to-content { boolean }? + & attribute table:target-range-address { cellRangeAddress }? + & attribute table:case-sensitive { boolean }? + & attribute table:language { languageCode }? + & attribute table:country { countryCode }? + & attribute table:script { scriptCode }? + & attribute table:rfc-language-tag { language }? + & attribute table:algorithm { \string }? + & attribute table:embedded-number-behavior { + "alpha-numeric" | "integer" | "double" + }? +table-sort-by = element table:sort-by { table-sort-by-attlist, empty } +table-sort-by-attlist = + attribute table:field-number { nonNegativeInteger } + & attribute table:data-type { + "text" | "number" | "automatic" | \string + }? + & attribute table:order { "ascending" | "descending" }? +table-subtotal-rules = + element table:subtotal-rules { + table-subtotal-rules-attlist, + table-sort-groups?, + table-subtotal-rule* + } +table-subtotal-rules-attlist = + attribute table:bind-styles-to-content { boolean }? + & attribute table:case-sensitive { boolean }? + & attribute table:page-breaks-on-group-change { boolean }? +table-sort-groups = + element table:sort-groups { table-sort-groups-attlist, empty } +table-sort-groups-attlist = + attribute table:data-type { + "text" | "number" | "automatic" | \string + }? + & attribute table:order { "ascending" | "descending" }? +table-subtotal-rule = + element table:subtotal-rule { + table-subtotal-rule-attlist, table-subtotal-field* + } +table-subtotal-rule-attlist = + attribute table:group-by-field-number { nonNegativeInteger } +table-subtotal-field = + element table:subtotal-field { table-subtotal-field-attlist, empty } +table-subtotal-field-attlist = + attribute table:field-number { nonNegativeInteger } + & attribute table:function { + "average" + | "count" + | "countnums" + | "max" + | "min" + | "product" + | "stdev" + | "stdevp" + | "sum" + | "var" + | "varp" + | \string + } +table-filter = + element table:filter { + table-filter-attlist, + (table-filter-condition | table-filter-and | table-filter-or) + } +table-filter-attlist = + attribute table:target-range-address { cellRangeAddress }? + & attribute table:condition-source { "self" | "cell-range" }? + & attribute table:condition-source-range-address { cellRangeAddress }? + & attribute table:display-duplicates { boolean }? +table-filter-and = + element table:filter-and { + (table-filter-or | table-filter-condition)+ + } +table-filter-or = + element table:filter-or { + (table-filter-and | table-filter-condition)+ + } +table-filter-condition = + element table:filter-condition { + table-filter-condition-attlist, table-filter-set-item* + } +table-filter-condition-attlist = + attribute table:field-number { nonNegativeInteger } + & attribute table:value { \string | double } + & attribute table:operator { \string } + & attribute table:case-sensitive { \string }? + & attribute table:data-type { "text" | "number" }? +table-filter-set-item = + element table:filter-set-item { + attribute table:value { \string }, + empty + } +table-data-pilot-tables = + element table:data-pilot-tables { table-data-pilot-table* } +table-data-pilot-table = + element table:data-pilot-table { + table-data-pilot-table-attlist, + (table-database-source-sql + | table-database-source-table + | table-database-source-query + | table-source-service + | table-source-cell-range)?, + table-data-pilot-field+ + } +table-data-pilot-table-attlist = + attribute table:name { \string } + & attribute table:application-data { \string }? + & attribute table:grand-total { "none" | "row" | "column" | "both" }? + & attribute table:ignore-empty-rows { boolean }? + & attribute table:identify-categories { boolean }? + & attribute table:target-range-address { cellRangeAddress } + & attribute table:buttons { cellRangeAddressList }? + & attribute table:show-filter-button { boolean }? + & attribute table:drill-down-on-double-click { boolean }? +table-source-cell-range = + element table:source-cell-range { + table-source-cell-range-attlist, table-filter? + } +table-source-cell-range-attlist = + attribute table:cell-range-address { cellRangeAddress } +table-source-service = + element table:source-service { table-source-service-attlist, empty } +table-source-service-attlist = + attribute table:name { \string } + & attribute table:source-name { \string } + & attribute table:object-name { \string } + & attribute table:user-name { \string }? + & attribute table:password { \string }? +table-data-pilot-field = + element table:data-pilot-field { + table-data-pilot-field-attlist, + table-data-pilot-level?, + table-data-pilot-field-reference?, + table-data-pilot-groups? + } +table-data-pilot-field-attlist = + attribute table:source-field-name { \string } + & (attribute table:orientation { + "row" | "column" | "data" | "hidden" + } + | (attribute table:orientation { "page" }, + attribute table:selected-page { \string })) + & attribute table:is-data-layout-field { \string }? + & attribute table:function { + "auto" + | "average" + | "count" + | "countnums" + | "max" + | "min" + | "product" + | "stdev" + | "stdevp" + | "sum" + | "var" + | "varp" + | \string + }? + & attribute table:used-hierarchy { integer }? +table-data-pilot-level = + element table:data-pilot-level { + table-data-pilot-level-attlist, + table-data-pilot-subtotals?, + table-data-pilot-members?, + table-data-pilot-display-info?, + table-data-pilot-sort-info?, + table-data-pilot-layout-info? + } +table-data-pilot-level-attlist = attribute table:show-empty { boolean }? +table-data-pilot-subtotals = + element table:data-pilot-subtotals { table-data-pilot-subtotal* } +table-data-pilot-subtotal = + element table:data-pilot-subtotal { + table-data-pilot-subtotal-attlist, empty + } +table-data-pilot-subtotal-attlist = + attribute table:function { + "auto" + | "average" + | "count" + | "countnums" + | "max" + | "min" + | "product" + | "stdev" + | "stdevp" + | "sum" + | "var" + | "varp" + | \string + } +table-data-pilot-members = + element table:data-pilot-members { table-data-pilot-member* } +table-data-pilot-member = + element table:data-pilot-member { + table-data-pilot-member-attlist, empty + } +table-data-pilot-member-attlist = + attribute table:name { \string } + & attribute table:display { boolean }? + & attribute table:show-details { boolean }? +table-data-pilot-display-info = + element table:data-pilot-display-info { + table-data-pilot-display-info-attlist, empty + } +table-data-pilot-display-info-attlist = + attribute table:enabled { boolean } + & attribute table:data-field { \string } + & attribute table:member-count { nonNegativeInteger } + & attribute table:display-member-mode { "from-top" | "from-bottom" } +table-data-pilot-sort-info = + element table:data-pilot-sort-info { + table-data-pilot-sort-info-attlist, empty + } +table-data-pilot-sort-info-attlist = + ((attribute table:sort-mode { "data" }, + attribute table:data-field { \string }) + | attribute table:sort-mode { "none" | "manual" | "name" }) + & attribute table:order { "ascending" | "descending" } +table-data-pilot-layout-info = + element table:data-pilot-layout-info { + table-data-pilot-layout-info-attlist, empty + } +table-data-pilot-layout-info-attlist = + attribute table:layout-mode { + "tabular-layout" + | "outline-subtotals-top" + | "outline-subtotals-bottom" + } + & attribute table:add-empty-lines { boolean } +table-data-pilot-field-reference = + element table:data-pilot-field-reference { + table-data-pilot-field-reference-attlist + } +table-data-pilot-field-reference-attlist = + attribute table:field-name { \string } + & ((attribute table:member-type { "named" }, + attribute table:member-name { \string }) + | attribute table:member-type { "previous" | "next" }) + & attribute table:type { + "none" + | "member-difference" + | "member-percentage" + | "member-percentage-difference" + | "running-total" + | "row-percentage" + | "column-percentage" + | "total-percentage" + | "index" + } +table-data-pilot-groups = + element table:data-pilot-groups { + table-data-pilot-groups-attlist, table-data-pilot-group+ + } +table-data-pilot-groups-attlist = + attribute table:source-field-name { \string } + & (attribute table:date-start { dateOrDateTime | "auto" } + | attribute table:start { double | "auto" }) + & (attribute table:date-end { dateOrDateTime | "auto" } + | attribute table:end { double | "auto" }) + & attribute table:step { double } + & attribute table:grouped-by { + "seconds" + | "minutes" + | "hours" + | "days" + | "months" + | "quarters" + | "years" + } +table-data-pilot-group = + element table:data-pilot-group { + table-data-pilot-group-attlist, table-data-pilot-group-member+ + } +table-data-pilot-group-attlist = attribute table:name { \string } +table-data-pilot-group-member = + element table:data-pilot-group-member { + table-data-pilot-group-member-attlist + } +table-data-pilot-group-member-attlist = attribute table:name { \string } +table-consolidation = + element table:consolidation { table-consolidation-attlist, empty } +table-consolidation-attlist = + attribute table:function { + "average" + | "count" + | "countnums" + | "max" + | "min" + | "product" + | "stdev" + | "stdevp" + | "sum" + | "var" + | "varp" + | \string + } + & attribute table:source-cell-range-addresses { cellRangeAddressList } + & attribute table:target-cell-address { cellAddress } + & attribute table:use-labels { "none" | "row" | "column" | "both" }? + & attribute table:link-to-source-data { boolean }? +table-dde-links = element table:dde-links { table-dde-link+ } +table-tracked-changes = + element table:tracked-changes { + table-tracked-changes-attlist, + (table-cell-content-change + | table-insertion + | table-deletion + | table-movement)* + } +table-tracked-changes-attlist = + attribute table:track-changes { boolean }? +table-insertion = + element table:insertion { + table-insertion-attlist, + common-table-change-attlist, + office-change-info, + table-dependencies?, + table-deletions? + } +table-insertion-attlist = + attribute table:type { "row" | "column" | "table" } + & attribute table:position { integer } + & attribute table:count { positiveInteger }? + & attribute table:table { integer }? +table-dependencies = element table:dependencies { table-dependency+ } +table-dependency = + element table:dependency { + attribute table:id { \string }, + empty + } +table-deletions = + element table:deletions { + (table-cell-content-deletion | table-change-deletion)+ + } +table-cell-content-deletion = + element table:cell-content-deletion { + attribute table:id { \string }?, + table-cell-address?, + table-change-track-table-cell? + } +table-change-deletion = + element table:change-deletion { + attribute table:id { \string }?, + empty + } +table-deletion = + element table:deletion { + table-deletion-attlist, + common-table-change-attlist, + office-change-info, + table-dependencies?, + table-deletions?, + table-cut-offs? + } +table-deletion-attlist = + attribute table:type { "row" | "column" | "table" } + & attribute table:position { integer } + & attribute table:table { integer }? + & attribute table:multi-deletion-spanned { integer }? +table-cut-offs = + element table:cut-offs { + table-movement-cut-off+ + | (table-insertion-cut-off, table-movement-cut-off*) + } +table-insertion-cut-off = + element table:insertion-cut-off { + table-insertion-cut-off-attlist, empty + } +table-insertion-cut-off-attlist = + attribute table:id { \string } + & attribute table:position { integer } +table-movement-cut-off = + element table:movement-cut-off { + table-movement-cut-off-attlist, empty + } +table-movement-cut-off-attlist = + attribute table:position { integer } + | (attribute table:start-position { integer }, + attribute table:end-position { integer }) +table-movement = + element table:movement { + common-table-change-attlist, + table-source-range-address, + table-target-range-address, + office-change-info, + table-dependencies?, + table-deletions? + } +table-source-range-address = + element table:source-range-address { + common-table-range-attlist, empty + } +table-target-range-address = + element table:target-range-address { + common-table-range-attlist, empty + } +common-table-range-attlist = + common-table-cell-address-attlist + | common-table-cell-range-address-attlist +common-table-cell-address-attlist = + attribute table:column { integer }, + attribute table:row { integer }, + attribute table:table { integer } +common-table-cell-range-address-attlist = + attribute table:start-column { integer }, + attribute table:start-row { integer }, + attribute table:start-table { integer }, + attribute table:end-column { integer }, + attribute table:end-row { integer }, + attribute table:end-table { integer } +table-change-track-table-cell = + element table:change-track-table-cell { + table-change-track-table-cell-attlist, text-p* + } +table-change-track-table-cell-attlist = + attribute table:cell-address { cellAddress }? + & attribute table:matrix-covered { boolean }? + & attribute table:formula { \string }? + & attribute table:number-matrix-columns-spanned { positiveInteger }? + & attribute table:number-matrix-rows-spanned { positiveInteger }? + & common-value-and-type-attlist? +table-cell-content-change = + element table:cell-content-change { + common-table-change-attlist, + table-cell-address, + office-change-info, + table-dependencies?, + table-deletions?, + table-previous + } +table-cell-address = + element table:cell-address { + common-table-cell-address-attlist, empty + } +table-previous = + element table:previous { + attribute table:id { \string }?, + table-change-track-table-cell + } +common-table-change-attlist = + attribute table:id { \string } + & attribute table:acceptance-state { + "accepted" | "rejected" | "pending" + }? + & attribute table:rejecting-change-id { \string }? +style-handout-master = + element style:handout-master { + common-presentation-header-footer-attlist, + style-handout-master-attlist, + shape* + } +style-handout-master-attlist = + attribute presentation:presentation-page-layout-name { styleNameRef }? + & attribute style:page-layout-name { styleNameRef } + & attribute draw:style-name { styleNameRef }? +draw-layer-set = element draw:layer-set { draw-layer* } +draw-layer = + element draw:layer { draw-layer-attlist, svg-title?, svg-desc? } +draw-layer-attlist = + attribute draw:name { \string } + & attribute draw:protected { boolean }? + & attribute draw:display { "always" | "screen" | "printer" | "none" }? +draw-page = + element draw:page { + common-presentation-header-footer-attlist, + draw-page-attlist, + svg-title?, + svg-desc?, + draw-layer-set?, + office-forms?, + shape*, + (presentation-animations | animation-element)?, + presentation-notes? + } +draw-page-attlist = + attribute draw:name { \string }? + & attribute draw:style-name { styleNameRef }? + & attribute draw:master-page-name { styleNameRef } + & attribute presentation:presentation-page-layout-name { + styleNameRef + }? + & (xml-id, + attribute draw:id { NCName }?)? + & attribute draw:nav-order { IDREFS }? +common-presentation-header-footer-attlist = + attribute presentation:use-header-name { \string }? + & attribute presentation:use-footer-name { \string }? + & attribute presentation:use-date-time-name { \string }? +shape = shape-instance | draw-a +shape-instance = + draw-rect + | draw-line + | draw-polyline + | draw-polygon + | draw-regular-polygon + | draw-path + | draw-circle + | draw-ellipse + | draw-g + | draw-page-thumbnail + | draw-frame + | draw-measure + | draw-caption + | draw-connector + | draw-control + | dr3d-scene + | draw-custom-shape +draw-rect = + element draw:rect { + draw-rect-attlist, + common-draw-position-attlist, + common-draw-size-attlist, + common-draw-shape-with-text-and-styles-attlist, + common-draw-caption-id-attlist, + svg-title?, + svg-desc?, + office-event-listeners?, + draw-glue-point*, + draw-text + } +draw-rect-attlist = + attribute draw:corner-radius { nonNegativeLength }? + | (attribute svg:rx { nonNegativeLength }?, + attribute svg:ry { nonNegativeLength }?) +draw-line = + element draw:line { + draw-line-attlist, + common-draw-shape-with-text-and-styles-attlist, + common-draw-caption-id-attlist, + svg-title?, + svg-desc?, + office-event-listeners?, + draw-glue-point*, + draw-text + } +draw-line-attlist = + attribute svg:x1 { coordinate } + & attribute svg:y1 { coordinate } + & attribute svg:x2 { coordinate } + & attribute svg:y2 { coordinate } +draw-polyline = + element draw:polyline { + common-draw-points-attlist, + common-draw-position-attlist, + common-draw-size-attlist, + common-draw-viewbox-attlist, + common-draw-shape-with-text-and-styles-attlist, + common-draw-caption-id-attlist, + svg-title?, + svg-desc?, + office-event-listeners?, + draw-glue-point*, + draw-text + } +common-draw-points-attlist = attribute draw:points { points } +draw-polygon = + element draw:polygon { + common-draw-points-attlist, + common-draw-position-attlist, + common-draw-size-attlist, + common-draw-viewbox-attlist, + common-draw-shape-with-text-and-styles-attlist, + common-draw-caption-id-attlist, + svg-title?, + svg-desc?, + office-event-listeners?, + draw-glue-point*, + draw-text + } +draw-regular-polygon = + element draw:regular-polygon { + draw-regular-polygon-attlist, + common-draw-position-attlist, + common-draw-size-attlist, + common-draw-shape-with-text-and-styles-attlist, + common-draw-caption-id-attlist, + svg-title?, + svg-desc?, + office-event-listeners?, + draw-glue-point*, + draw-text + } +draw-regular-polygon-attlist = + (attribute draw:concave { "false" } + | (attribute draw:concave { "true" }, + draw-regular-polygon-sharpness-attlist)) + & attribute draw:corners { positiveInteger } +draw-regular-polygon-sharpness-attlist = + attribute draw:sharpness { percent } +draw-path = + element draw:path { + common-draw-path-data-attlist, + common-draw-position-attlist, + common-draw-size-attlist, + common-draw-viewbox-attlist, + common-draw-shape-with-text-and-styles-attlist, + common-draw-caption-id-attlist, + svg-title?, + svg-desc?, + office-event-listeners?, + draw-glue-point*, + draw-text + } +common-draw-path-data-attlist = attribute svg:d { pathData } +draw-circle = + element draw:circle { + ((draw-circle-attlist, common-draw-circle-ellipse-pos-attlist) + | (common-draw-position-attlist, common-draw-size-attlist)), + common-draw-circle-ellipse-attlist, + common-draw-shape-with-text-and-styles-attlist, + common-draw-caption-id-attlist, + svg-title?, + svg-desc?, + office-event-listeners?, + draw-glue-point*, + draw-text + } +common-draw-circle-ellipse-pos-attlist = + attribute svg:cx { coordinate }, + attribute svg:cy { coordinate } +draw-circle-attlist = attribute svg:r { length } +common-draw-circle-ellipse-attlist = + attribute draw:kind { "full" | "section" | "cut" | "arc" }? + & attribute draw:start-angle { angle }? + & attribute draw:end-angle { angle }? +draw-ellipse = + element draw:ellipse { + ((draw-ellipse-attlist, common-draw-circle-ellipse-pos-attlist) + | (common-draw-position-attlist, common-draw-size-attlist)), + common-draw-circle-ellipse-attlist, + common-draw-shape-with-text-and-styles-attlist, + common-draw-caption-id-attlist, + svg-title?, + svg-desc?, + office-event-listeners?, + draw-glue-point*, + draw-text + } +draw-ellipse-attlist = + attribute svg:rx { length }, + attribute svg:ry { length } +draw-connector = + element draw:connector { + draw-connector-attlist, + common-draw-shape-with-text-and-styles-attlist, + common-draw-caption-id-attlist, + common-draw-viewbox-attlist, + svg-title?, + svg-desc?, + office-event-listeners?, + draw-glue-point*, + draw-text + } +draw-connector-attlist = + attribute draw:type { "standard" | "lines" | "line" | "curve" }? + & (attribute svg:x1 { coordinate }, + attribute svg:y1 { coordinate })? + & attribute draw:start-shape { IDREF }? + & attribute draw:start-glue-point { nonNegativeInteger }? + & (attribute svg:x2 { coordinate }, + attribute svg:y2 { coordinate })? + & attribute draw:end-shape { IDREF }? + & attribute draw:end-glue-point { nonNegativeInteger }? + & attribute draw:line-skew { + list { length, (length, length?)? } + }? + & attribute svg:d { pathData }? +draw-caption = + element draw:caption { + draw-caption-attlist, + common-draw-position-attlist, + common-draw-size-attlist, + common-draw-shape-with-text-and-styles-attlist, + common-draw-caption-id-attlist, + svg-title?, + svg-desc?, + office-event-listeners?, + draw-glue-point*, + draw-text + } +draw-caption-attlist = + (attribute draw:caption-point-x { coordinate }, + attribute draw:caption-point-y { coordinate })? + & attribute draw:corner-radius { nonNegativeLength }? +draw-measure = + element draw:measure { + draw-measure-attlist, + common-draw-shape-with-text-and-styles-attlist, + common-draw-caption-id-attlist, + svg-title?, + svg-desc?, + office-event-listeners?, + draw-glue-point*, + draw-text + } +draw-measure-attlist = + attribute svg:x1 { coordinate } + & attribute svg:y1 { coordinate } + & attribute svg:x2 { coordinate } + & attribute svg:y2 { coordinate } +draw-control = + element draw:control { + draw-control-attlist, + common-draw-position-attlist, + common-draw-size-attlist, + common-draw-shape-with-text-and-styles-attlist, + common-draw-caption-id-attlist, + svg-title?, + svg-desc?, + draw-glue-point* + } +draw-control-attlist = attribute draw:control { IDREF } +draw-page-thumbnail = + element draw:page-thumbnail { + draw-page-thumbnail-attlist, + common-draw-position-attlist, + common-draw-size-attlist, + presentation-shape-attlist, + common-draw-shape-with-styles-attlist, + common-draw-caption-id-attlist, + svg-title?, + svg-desc? + } +draw-page-thumbnail-attlist = + attribute draw:page-number { positiveInteger }? +draw-g = + element draw:g { + draw-g-attlist, + common-draw-z-index-attlist, + common-draw-name-attlist, + common-draw-id-attlist, + common-draw-style-name-attlist, + common-text-spreadsheet-shape-attlist, + common-draw-caption-id-attlist, + svg-title?, + svg-desc?, + office-event-listeners?, + draw-glue-point*, + shape* + } +draw-g-attlist = attribute svg:y { coordinate }? +common-draw-name-attlist = attribute draw:name { \string }? +common-draw-caption-id-attlist = attribute draw:caption-id { IDREF }? +common-draw-position-attlist = + attribute svg:x { coordinate }?, + attribute svg:y { coordinate }? +common-draw-size-attlist = + attribute svg:width { length }?, + attribute svg:height { length }? +common-draw-transform-attlist = attribute draw:transform { \string }? +common-draw-viewbox-attlist = + attribute svg:viewBox { + list { integer, integer, integer, integer } + } +common-draw-style-name-attlist = + (attribute draw:style-name { styleNameRef }?, + attribute draw:class-names { styleNameRefs }?) + | (attribute presentation:style-name { styleNameRef }?, + attribute presentation:class-names { styleNameRefs }?) +common-draw-text-style-name-attlist = + attribute draw:text-style-name { styleNameRef }? +common-draw-layer-name-attlist = attribute draw:layer { \string }? +common-draw-id-attlist = + (xml-id, + attribute draw:id { NCName }?)? +common-draw-z-index-attlist = + attribute draw:z-index { nonNegativeInteger }? +common-text-spreadsheet-shape-attlist = + attribute table:end-cell-address { cellAddress }? + & attribute table:end-x { coordinate }? + & attribute table:end-y { coordinate }? + & attribute table:table-background { boolean }? + & common-text-anchor-attlist +common-text-anchor-attlist = + attribute text:anchor-type { + "page" | "frame" | "paragraph" | "char" | "as-char" + }? + & attribute text:anchor-page-number { positiveInteger }? +draw-text = (text-p | text-list)* +common-draw-shape-with-styles-attlist = + common-draw-z-index-attlist, + common-draw-id-attlist, + common-draw-layer-name-attlist, + common-draw-style-name-attlist, + common-draw-transform-attlist, + common-draw-name-attlist, + common-text-spreadsheet-shape-attlist +common-draw-shape-with-text-and-styles-attlist = + common-draw-shape-with-styles-attlist, + common-draw-text-style-name-attlist +draw-glue-point = + element draw:glue-point { draw-glue-point-attlist, empty } +draw-glue-point-attlist = + attribute draw:id { nonNegativeInteger } + & attribute svg:x { distance | percent } + & attribute svg:y { distance | percent } + & attribute draw:align { + "top-left" + | "top" + | "top-right" + | "left" + | "center" + | "right" + | "bottom-left" + | "bottom-right" + }? + & attribute draw:escape-direction { + "auto" + | "left" + | "right" + | "up" + | "down" + | "horizontal" + | "vertical" + } +svg-title = element svg:title { text } +svg-desc = element svg:desc { text } +draw-frame = + element draw:frame { + common-draw-shape-with-text-and-styles-attlist, + common-draw-position-attlist, + common-draw-rel-size-attlist, + common-draw-caption-id-attlist, + presentation-shape-attlist, + draw-frame-attlist, + (draw-text-box + | draw-image + | draw-object + | draw-object-ole + | draw-applet + | draw-floating-frame + | draw-plugin + | table-table)*, + office-event-listeners?, + draw-glue-point*, + draw-image-map?, + svg-title?, + svg-desc?, + (draw-contour-polygon | draw-contour-path)? + } +common-draw-rel-size-attlist = + common-draw-size-attlist, + attribute style:rel-width { percent | "scale" | "scale-min" }?, + attribute style:rel-height { percent | "scale" | "scale-min" }? +draw-frame-attlist = attribute draw:copy-of { \string }? +draw-text-box = + element draw:text-box { draw-text-box-attlist, text-content* } +draw-text-box-attlist = + attribute draw:chain-next-name { \string }? + & attribute draw:corner-radius { nonNegativeLength }? + & attribute fo:min-height { length | percent }? + & attribute fo:min-width { length | percent }? + & attribute fo:max-height { length | percent }? + & attribute fo:max-width { length | percent }? + & (xml-id, + attribute text:id { NCName }?)? +draw-image = + element draw:image { + draw-image-attlist, + (common-draw-data-attlist | office-binary-data), + draw-text + } +common-draw-data-attlist = + attribute xlink:type { "simple" }, + attribute xlink:href { anyIRI }, + attribute xlink:show { "embed" }?, + attribute xlink:actuate { "onLoad" }? +office-binary-data = element office:binary-data { base64Binary } +draw-image-attlist = + attribute draw:filter-name { \string }? + & xml-id? +draw-object = + element draw:object { + draw-object-attlist, + (common-draw-data-attlist | office-document | math-math) + } +draw-object-ole = + element draw:object-ole { + draw-object-ole-attlist, + (common-draw-data-attlist | office-binary-data) + } +draw-object-attlist = + attribute draw:notify-on-update-of-ranges { + cellRangeAddressList | \string + }? + & xml-id? +draw-object-ole-attlist = + attribute draw:class-id { \string }? + & xml-id? +draw-applet = + element draw:applet { + draw-applet-attlist, common-draw-data-attlist?, draw-param* + } +draw-applet-attlist = + attribute draw:code { \string }? + & attribute draw:object { \string }? + & attribute draw:archive { \string }? + & attribute draw:may-script { boolean }? + & xml-id? +draw-plugin = + element draw:plugin { + draw-plugin-attlist, common-draw-data-attlist, draw-param* + } +draw-plugin-attlist = + attribute draw:mime-type { \string }? + & xml-id? +draw-param = element draw:param { draw-param-attlist, empty } +draw-param-attlist = + attribute draw:name { \string }? + & attribute draw:value { \string }? +draw-floating-frame = + element draw:floating-frame { + draw-floating-frame-attlist, common-draw-data-attlist + } +draw-floating-frame-attlist = + attribute draw:frame-name { \string }? + & xml-id? +draw-contour-polygon = + element draw:contour-polygon { + common-contour-attlist, + common-draw-size-attlist, + common-draw-viewbox-attlist, + common-draw-points-attlist, + empty + } +draw-contour-path = + element draw:contour-path { + common-contour-attlist, + common-draw-size-attlist, + common-draw-viewbox-attlist, + common-draw-path-data-attlist, + empty + } +common-contour-attlist = attribute draw:recreate-on-edit { boolean } +draw-a = element draw:a { draw-a-attlist, shape-instance } +draw-a-attlist = + attribute xlink:type { "simple" } + & attribute xlink:href { anyIRI } + & attribute xlink:actuate { "onRequest" }? + & attribute office:target-frame-name { targetFrameName }? + & attribute xlink:show { "new" | "replace" }? + & attribute office:name { \string }? + & attribute office:title { \string }? + & attribute office:server-map { boolean }? + & xml-id? +draw-image-map = + element draw:image-map { + (draw-area-rectangle | draw-area-circle | draw-area-polygon)* + } +draw-area-rectangle = + element draw:area-rectangle { + common-draw-area-attlist, + attribute svg:x { coordinate }, + attribute svg:y { coordinate }, + attribute svg:width { length }, + attribute svg:height { length }, + svg-title?, + svg-desc?, + office-event-listeners? + } +draw-area-circle = + element draw:area-circle { + common-draw-area-attlist, + attribute svg:cx { coordinate }, + attribute svg:cy { coordinate }, + attribute svg:r { length }, + svg-title?, + svg-desc?, + office-event-listeners? + } +draw-area-polygon = + element draw:area-polygon { + common-draw-area-attlist, + attribute svg:x { coordinate }, + attribute svg:y { coordinate }, + attribute svg:width { length }, + attribute svg:height { length }, + common-draw-viewbox-attlist, + common-draw-points-attlist, + svg-title?, + svg-desc?, + office-event-listeners? + } +common-draw-area-attlist = + (attribute xlink:type { "simple" }, + attribute xlink:href { anyIRI }, + attribute office:target-frame-name { targetFrameName }?, + attribute xlink:show { "new" | "replace" }?)? + & attribute office:name { \string }? + & attribute draw:nohref { "nohref" }? +dr3d-scene = + element dr3d:scene { + dr3d-scene-attlist, + common-draw-position-attlist, + common-draw-size-attlist, + common-draw-style-name-attlist, + common-draw-z-index-attlist, + common-draw-id-attlist, + common-draw-layer-name-attlist, + common-text-spreadsheet-shape-attlist, + common-dr3d-transform-attlist, + common-draw-caption-id-attlist, + svg-title?, + svg-desc?, + dr3d-light*, + shapes3d*, + draw-glue-point* + } +shapes3d = + dr3d-scene | dr3d-extrude | dr3d-sphere | dr3d-rotate | dr3d-cube +dr3d-scene-attlist = + attribute dr3d:vrp { vector3D }? + & attribute dr3d:vpn { vector3D }? + & attribute dr3d:vup { vector3D }? + & attribute dr3d:projection { "parallel" | "perspective" }? + & attribute dr3d:distance { length }? + & attribute dr3d:focal-length { length }? + & attribute dr3d:shadow-slant { angle }? + & attribute dr3d:shade-mode { + "flat" | "phong" | "gouraud" | "draft" + }? + & attribute dr3d:ambient-color { color }? + & attribute dr3d:lighting-mode { boolean }? +common-dr3d-transform-attlist = attribute dr3d:transform { \string }? +dr3d-light = element dr3d:light { dr3d-light-attlist, empty } +dr3d-light-attlist = + attribute dr3d:diffuse-color { color }? + & attribute dr3d:direction { vector3D } + & attribute dr3d:enabled { boolean }? + & attribute dr3d:specular { boolean }? +dr3d-cube = + element dr3d:cube { + dr3d-cube-attlist, + common-draw-z-index-attlist, + common-draw-id-attlist, + common-draw-layer-name-attlist, + common-draw-style-name-attlist, + common-dr3d-transform-attlist, + empty + } +dr3d-cube-attlist = + attribute dr3d:min-edge { vector3D }?, + attribute dr3d:max-edge { vector3D }? +dr3d-sphere = + element dr3d:sphere { + dr3d-sphere-attlist, + common-draw-z-index-attlist, + common-draw-id-attlist, + common-draw-layer-name-attlist, + common-draw-style-name-attlist, + common-dr3d-transform-attlist, + empty + } +dr3d-sphere-attlist = + attribute dr3d:center { vector3D }? + & attribute dr3d:size { vector3D }? +dr3d-extrude = + element dr3d:extrude { + common-draw-path-data-attlist, + common-draw-viewbox-attlist, + common-draw-id-attlist, + common-draw-z-index-attlist, + common-draw-layer-name-attlist, + common-draw-style-name-attlist, + common-dr3d-transform-attlist, + empty + } +dr3d-rotate = + element dr3d:rotate { + common-draw-viewbox-attlist, + common-draw-path-data-attlist, + common-draw-z-index-attlist, + common-draw-id-attlist, + common-draw-layer-name-attlist, + common-draw-style-name-attlist, + common-dr3d-transform-attlist, + empty + } +draw-custom-shape = + element draw:custom-shape { + draw-custom-shape-attlist, + common-draw-position-attlist, + common-draw-size-attlist, + common-draw-shape-with-text-and-styles-attlist, + common-draw-caption-id-attlist, + svg-title?, + svg-desc?, + office-event-listeners?, + draw-glue-point*, + draw-text, + draw-enhanced-geometry? + } +draw-custom-shape-attlist = + attribute draw:engine { namespacedToken }? + & attribute draw:data { \string }? +draw-enhanced-geometry = + element draw:enhanced-geometry { + draw-enhanced-geometry-attlist, draw-equation*, draw-handle* + } +draw-enhanced-geometry-attlist = + attribute draw:type { custom-shape-type }? + & attribute svg:viewBox { + list { integer, integer, integer, integer } + }? + & attribute draw:mirror-vertical { boolean }? + & attribute draw:mirror-horizontal { boolean }? + & attribute draw:text-rotate-angle { angle }? + & attribute draw:extrusion-allowed { boolean }? + & attribute draw:text-path-allowed { boolean }? + & attribute draw:concentric-gradient-fill-allowed { boolean }? + & attribute draw:extrusion { boolean }? + & attribute draw:extrusion-brightness { zeroToHundredPercent }? + & attribute draw:extrusion-depth { + list { length, double } + }? + & attribute draw:extrusion-diffusion { percent }? + & attribute draw:extrusion-number-of-line-segments { integer }? + & attribute draw:extrusion-light-face { boolean }? + & attribute draw:extrusion-first-light-harsh { boolean }? + & attribute draw:extrusion-second-light-harsh { boolean }? + & attribute draw:extrusion-first-light-level { zeroToHundredPercent }? + & attribute draw:extrusion-second-light-level { + zeroToHundredPercent + }? + & attribute draw:extrusion-first-light-direction { vector3D }? + & attribute draw:extrusion-second-light-direction { vector3D }? + & attribute draw:extrusion-metal { boolean }? + & attribute dr3d:shade-mode { + "flat" | "phong" | "gouraud" | "draft" + }? + & attribute draw:extrusion-rotation-angle { + list { angle, angle } + }? + & attribute draw:extrusion-rotation-center { vector3D }? + & attribute draw:extrusion-shininess { zeroToHundredPercent }? + & attribute draw:extrusion-skew { + list { double, angle } + }? + & attribute draw:extrusion-specularity { zeroToHundredPercent }? + & attribute dr3d:projection { "parallel" | "perspective" }? + & attribute draw:extrusion-viewpoint { point3D }? + & attribute draw:extrusion-origin { + list { extrusionOrigin, extrusionOrigin } + }? + & attribute draw:extrusion-color { boolean }? + & attribute draw:enhanced-path { \string }? + & attribute draw:path-stretchpoint-x { double }? + & attribute draw:path-stretchpoint-y { double }? + & attribute draw:text-areas { \string }? + & attribute draw:glue-points { \string }? + & attribute draw:glue-point-type { + "none" | "segments" | "rectangle" + }? + & attribute draw:glue-point-leaving-directions { \string }? + & attribute draw:text-path { boolean }? + & attribute draw:text-path-mode { "normal" | "path" | "shape" }? + & attribute draw:text-path-scale { "path" | "shape" }? + & attribute draw:text-path-same-letter-heights { boolean }? + & attribute draw:modifiers { \string }? +custom-shape-type = "non-primitive" | \string +point3D = + xsd:string { + pattern = + "\([ ]*-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))([ ]+-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))){2}[ ]*\)" + } +extrusionOrigin = + xsd:double { minInclusive = "-0.5" maxInclusive = "0.5" } +draw-equation = element draw:equation { draw-equation-attlist, empty } +draw-equation-attlist = + attribute draw:name { \string }? + & attribute draw:formula { \string }? +draw-handle = element draw:handle { draw-handle-attlist, empty } +draw-handle-attlist = + attribute draw:handle-mirror-vertical { boolean }? + & attribute draw:handle-mirror-horizontal { boolean }? + & attribute draw:handle-switched { boolean }? + & attribute draw:handle-position { \string } + & attribute draw:handle-range-x-minimum { \string }? + & attribute draw:handle-range-x-maximum { \string }? + & attribute draw:handle-range-y-minimum { \string }? + & attribute draw:handle-range-y-maximum { \string }? + & attribute draw:handle-polar { \string }? + & attribute draw:handle-radius-range-minimum { \string }? + & attribute draw:handle-radius-range-maximum { \string }? +presentation-shape-attlist = + attribute presentation:class { presentation-classes }? + & attribute presentation:placeholder { boolean }? + & attribute presentation:user-transformed { boolean }? +presentation-classes = + "title" + | "outline" + | "subtitle" + | "text" + | "graphic" + | "object" + | "chart" + | "table" + | "orgchart" + | "page" + | "notes" + | "handout" + | "header" + | "footer" + | "date-time" + | "page-number" +presentation-animations = + element presentation:animations { + (presentation-animation-elements | presentation-animation-group)* + } +presentation-animation-elements = + presentation-show-shape + | presentation-show-text + | presentation-hide-shape + | presentation-hide-text + | presentation-dim + | presentation-play +presentation-sound = + element presentation:sound { + presentation-sound-attlist, + attribute xlink:type { "simple" }, + attribute xlink:href { anyIRI }, + attribute xlink:actuate { "onRequest" }?, + attribute xlink:show { "new" | "replace" }?, + empty + } +presentation-sound-attlist = + attribute presentation:play-full { boolean }? + & xml-id? +presentation-show-shape = + element presentation:show-shape { + common-presentation-effect-attlist, presentation-sound? + } +common-presentation-effect-attlist = + attribute draw:shape-id { IDREF } + & attribute presentation:effect { presentationEffects }? + & attribute presentation:direction { presentationEffectDirections }? + & attribute presentation:speed { presentationSpeeds }? + & attribute presentation:delay { duration }? + & attribute presentation:start-scale { percent }? + & attribute presentation:path-id { \string }? +presentationEffects = + "none" + | "fade" + | "move" + | "stripes" + | "open" + | "close" + | "dissolve" + | "wavyline" + | "random" + | "lines" + | "laser" + | "appear" + | "hide" + | "move-short" + | "checkerboard" + | "rotate" + | "stretch" +presentationEffectDirections = + "none" + | "from-left" + | "from-top" + | "from-right" + | "from-bottom" + | "from-center" + | "from-upper-left" + | "from-upper-right" + | "from-lower-left" + | "from-lower-right" + | "to-left" + | "to-top" + | "to-right" + | "to-bottom" + | "to-upper-left" + | "to-upper-right" + | "to-lower-right" + | "to-lower-left" + | "path" + | "spiral-inward-left" + | "spiral-inward-right" + | "spiral-outward-left" + | "spiral-outward-right" + | "vertical" + | "horizontal" + | "to-center" + | "clockwise" + | "counter-clockwise" +presentationSpeeds = "slow" | "medium" | "fast" +presentation-show-text = + element presentation:show-text { + common-presentation-effect-attlist, presentation-sound? + } +presentation-hide-shape = + element presentation:hide-shape { + common-presentation-effect-attlist, presentation-sound? + } +presentation-hide-text = + element presentation:hide-text { + common-presentation-effect-attlist, presentation-sound? + } +presentation-dim = + element presentation:dim { + presentation-dim-attlist, presentation-sound? + } +presentation-dim-attlist = + attribute draw:shape-id { IDREF } + & attribute draw:color { color } +presentation-play = + element presentation:play { presentation-play-attlist, empty } +presentation-play-attlist = + attribute draw:shape-id { IDREF }, + attribute presentation:speed { presentationSpeeds }? +presentation-animation-group = + element presentation:animation-group { + presentation-animation-elements* + } +common-anim-attlist = + attribute presentation:node-type { + "default" + | "on-click" + | "with-previous" + | "after-previous" + | "timing-root" + | "main-sequence" + | "interactive-sequence" + }? + & attribute presentation:preset-id { \string }? + & attribute presentation:preset-sub-type { \string }? + & attribute presentation:preset-class { + "custom" + | "entrance" + | "exit" + | "emphasis" + | "motion-path" + | "ole-action" + | "media-call" + }? + & attribute presentation:master-element { IDREF }? + & attribute presentation:group-id { \string }? + & (xml-id, + attribute anim:id { NCName }?)? +presentation-event-listener = + element presentation:event-listener { + presentation-event-listener-attlist, presentation-sound? + } +presentation-event-listener-attlist = + attribute script:event-name { \string } + & attribute presentation:action { + "none" + | "previous-page" + | "next-page" + | "first-page" + | "last-page" + | "hide" + | "stop" + | "execute" + | "show" + | "verb" + | "fade-out" + | "sound" + | "last-visited-page" + } + & attribute presentation:effect { presentationEffects }? + & attribute presentation:direction { presentationEffectDirections }? + & attribute presentation:speed { presentationSpeeds }? + & attribute presentation:start-scale { percent }? + & (attribute xlink:type { "simple" }, + attribute xlink:href { anyIRI }, + attribute xlink:show { "embed" }?, + attribute xlink:actuate { "onRequest" }?)? + & attribute presentation:verb { nonNegativeInteger }? +presentation-decls = presentation-decl* +presentation-decl = + element presentation:header-decl { + presentation-header-decl-attlist, text + } + | element presentation:footer-decl { + presentation-footer-decl-attlist, text + } + | element presentation:date-time-decl { + presentation-date-time-decl-attlist, text + } +presentation-header-decl-attlist = + attribute presentation:name { \string } +presentation-footer-decl-attlist = + attribute presentation:name { \string } +presentation-date-time-decl-attlist = + attribute presentation:name { \string } + & attribute presentation:source { "fixed" | "current-date" } + & attribute style:data-style-name { styleNameRef }? +presentation-settings = + element presentation:settings { + presentation-settings-attlist, presentation-show* + }? +presentation-settings-attlist = + attribute presentation:start-page { \string }? + & attribute presentation:show { \string }? + & attribute presentation:full-screen { boolean }? + & attribute presentation:endless { boolean }? + & attribute presentation:pause { duration }? + & attribute presentation:show-logo { boolean }? + & attribute presentation:force-manual { boolean }? + & attribute presentation:mouse-visible { boolean }? + & attribute presentation:mouse-as-pen { boolean }? + & attribute presentation:start-with-navigator { boolean }? + & attribute presentation:animations { "enabled" | "disabled" }? + & attribute presentation:transition-on-click { + "enabled" | "disabled" + }? + & attribute presentation:stay-on-top { boolean }? + & attribute presentation:show-end-of-presentation-slide { boolean }? +presentation-show = + element presentation:show { presentation-show-attlist, empty } +presentation-show-attlist = + attribute presentation:name { \string } + & attribute presentation:pages { \string } +chart-chart = + element chart:chart { + chart-chart-attlist, + chart-title?, + chart-subtitle?, + chart-footer?, + chart-legend?, + chart-plot-area, + table-table? + } +chart-chart-attlist = + attribute chart:class { namespacedToken } + & common-draw-size-attlist + & attribute chart:column-mapping { \string }? + & attribute chart:row-mapping { \string }? + & attribute chart:style-name { styleNameRef }? + & (attribute xlink:type { "simple" }, + attribute xlink:href { anyIRI })? + & xml-id? +chart-title = element chart:title { chart-title-attlist, text-p? } +chart-title-attlist = + attribute table:cell-range { cellRangeAddressList }? + & common-draw-position-attlist + & attribute chart:style-name { styleNameRef }? +chart-subtitle = element chart:subtitle { chart-title-attlist, text-p? } +chart-footer = element chart:footer { chart-title-attlist, text-p? } +chart-legend = element chart:legend { chart-legend-attlist, text-p? } +chart-legend-attlist = + ((attribute chart:legend-position { + "start" | "end" | "top" | "bottom" + }, + attribute chart:legend-align { "start" | "center" | "end" }?) + | attribute chart:legend-position { + "top-start" | "bottom-start" | "top-end" | "bottom-end" + } + | empty) + & common-draw-position-attlist + & (attribute style:legend-expansion { "wide" | "high" | "balanced" } + | (attribute style:legend-expansion { "custom" }, + attribute style:legend-expansion-aspect-ratio { double }) + | empty) + & attribute chart:style-name { styleNameRef }? +chart-plot-area = + element chart:plot-area { + chart-plot-area-attlist, + dr3d-light*, + chart-axis*, + chart-series*, + chart-stock-gain-marker?, + chart-stock-loss-marker?, + chart-stock-range-line?, + chart-wall?, + chart-floor? + } +chart-plot-area-attlist = + common-draw-position-attlist + & common-draw-size-attlist + & attribute chart:style-name { styleNameRef }? + & attribute table:cell-range-address { cellRangeAddressList }? + & attribute chart:data-source-has-labels { + "none" | "row" | "column" | "both" + }? + & dr3d-scene-attlist + & common-dr3d-transform-attlist + & xml-id? +chart-wall = element chart:wall { chart-wall-attlist, empty } +chart-wall-attlist = + attribute svg:width { length }? + & attribute chart:style-name { styleNameRef }? +chart-floor = element chart:floor { chart-floor-attlist, empty } +chart-floor-attlist = + attribute svg:width { length }? + & attribute chart:style-name { styleNameRef }? +chart-axis = + element chart:axis { + chart-axis-attlist, chart-title?, chart-categories?, chart-grid* + } +chart-axis-attlist = + attribute chart:dimension { chart-dimension } + & attribute chart:name { \string }? + & attribute chart:style-name { styleNameRef }? +chart-dimension = "x" | "y" | "z" +chart-categories = + element chart:categories { + attribute table:cell-range-address { cellRangeAddressList }? + } +chart-grid = element chart:grid { chart-grid-attlist } +chart-grid-attlist = + attribute chart:class { "major" | "minor" }? + & attribute chart:style-name { styleNameRef }? +chart-series = + element chart:series { + chart-series-attlist, + chart-domain*, + chart-mean-value?, + chart-regression-curve*, + chart-error-indicator*, + chart-data-point*, + chart-data-label? + } +chart-series-attlist = + attribute chart:values-cell-range-address { cellRangeAddressList }? + & attribute chart:label-cell-address { cellRangeAddressList }? + & attribute chart:class { namespacedToken }? + & attribute chart:attached-axis { \string }? + & attribute chart:style-name { styleNameRef }? + & xml-id? +chart-domain = + element chart:domain { + attribute table:cell-range-address { cellRangeAddressList }? + } +chart-data-point = + element chart:data-point { + chart-data-point-attlist, chart-data-label? + } +chart-data-point-attlist = + attribute chart:repeated { positiveInteger }? + & attribute chart:style-name { styleNameRef }? + & xml-id? +chart-data-label = + element chart:data-label { chart-data-label-attlist, text-p? } +chart-data-label-attlist = + common-draw-position-attlist + & attribute chart:style-name { styleNameRef }? +chart-mean-value = + element chart:mean-value { chart-mean-value-attlist, empty } +chart-mean-value-attlist = attribute chart:style-name { styleNameRef }? +chart-error-indicator = + element chart:error-indicator { chart-error-indicator-attlist, empty } +chart-error-indicator-attlist = + attribute chart:style-name { styleNameRef }? + & attribute chart:dimension { chart-dimension } +chart-regression-curve = + element chart:regression-curve { + chart-regression-curve-attlist, chart-equation? + } +chart-regression-curve-attlist = + attribute chart:style-name { styleNameRef }? +chart-equation = + element chart:equation { chart-equation-attlist, text-p? } +chart-equation-attlist = + attribute chart:automatic-content { boolean }? + & attribute chart:display-r-square { boolean }? + & attribute chart:display-equation { boolean }? + & common-draw-position-attlist + & attribute chart:style-name { styleNameRef }? +chart-stock-gain-marker = + element chart:stock-gain-marker { common-stock-marker-attlist } +chart-stock-loss-marker = + element chart:stock-loss-marker { common-stock-marker-attlist } +chart-stock-range-line = + element chart:stock-range-line { common-stock-marker-attlist } +common-stock-marker-attlist = + attribute chart:style-name { styleNameRef }? +office-database = + element office:database { + db-data-source, + db-forms?, + db-reports?, + db-queries?, + db-table-presentations?, + db-schema-definition? + } +db-data-source = + element db:data-source { + db-data-source-attlist, + db-connection-data, + db-driver-settings?, + db-application-connection-settings? + } +db-data-source-attlist = empty +db-connection-data = + element db:connection-data { + db-connection-data-attlist, + (db-database-description | db-connection-resource), + db-login? + } +db-connection-data-attlist = empty +db-database-description = + element db:database-description { + db-database-description-attlist, + (db-file-based-database | db-server-database) + } +db-database-description-attlist = empty +db-file-based-database = + element db:file-based-database { db-file-based-database-attlist } +db-file-based-database-attlist = + attribute xlink:type { "simple" } + & attribute xlink:href { anyIRI } + & attribute db:media-type { \string } + & attribute db:extension { \string }? +db-server-database = + element db:server-database { db-server-database-attlist, empty } +db-server-database-attlist = + attribute db:type { namespacedToken } + & (db-host-and-port | db-local-socket-name) + & attribute db:database-name { \string }? +db-host-and-port = + attribute db:hostname { \string }, + attribute db:port { positiveInteger }? +db-local-socket-name = attribute db:local-socket { \string }? +db-connection-resource = + element db:connection-resource { + db-connection-resource-attlist, empty + } +db-connection-resource-attlist = + attribute xlink:type { "simple" }, + attribute xlink:href { anyIRI }, + attribute xlink:show { "none" }?, + attribute xlink:actuate { "onRequest" }? +db-login = element db:login { db-login-attlist, empty } +db-login-attlist = + (attribute db:user-name { \string } + | attribute db:use-system-user { boolean })? + & attribute db:is-password-required { boolean }? + & attribute db:login-timeout { positiveInteger }? +db-driver-settings = + element db:driver-settings { + db-driver-settings-attlist, + db-auto-increment?, + db-delimiter?, + db-character-set?, + db-table-settings? + } +db-driver-settings-attlist = + db-show-deleted + & attribute db:system-driver-settings { \string }? + & attribute db:base-dn { \string }? + & db-is-first-row-header-line + & attribute db:parameter-name-substitution { boolean }? +db-show-deleted = attribute db:show-deleted { boolean }? +db-is-first-row-header-line = + attribute db:is-first-row-header-line { boolean }? +db-auto-increment = + element db:auto-increment { db-auto-increment-attlist, empty } +db-auto-increment-attlist = + attribute db:additional-column-statement { \string }? + & attribute db:row-retrieving-statement { \string }? +db-delimiter = element db:delimiter { db-delimiter-attlist, empty } +db-delimiter-attlist = + attribute db:field { \string }? + & attribute db:string { \string }? + & attribute db:decimal { \string }? + & attribute db:thousand { \string }? +db-character-set = + element db:character-set { db-character-set-attlist, empty } +db-character-set-attlist = attribute db:encoding { textEncoding }? +db-table-settings = element db:table-settings { db-table-setting* } +db-table-setting = + element db:table-setting { + db-table-setting-attlist, db-delimiter?, db-character-set?, empty + } +db-table-setting-attlist = db-is-first-row-header-line, db-show-deleted +db-application-connection-settings = + element db:application-connection-settings { + db-application-connection-settings-attlist, + db-table-filter?, + db-table-type-filter?, + db-data-source-settings? + } +db-application-connection-settings-attlist = + attribute db:is-table-name-length-limited { boolean }? + & attribute db:enable-sql92-check { boolean }? + & attribute db:append-table-alias-name { boolean }? + & attribute db:ignore-driver-privileges { boolean }? + & attribute db:boolean-comparison-mode { + "equal-integer" + | "is-boolean" + | "equal-boolean" + | "equal-use-only-zero" + }? + & attribute db:use-catalog { boolean }? + & attribute db:max-row-count { integer }? + & attribute db:suppress-version-columns { boolean }? +db-table-filter = + element db:table-filter { + db-table-filter-attlist, + db-table-include-filter?, + db-table-exclude-filter? + } +db-table-filter-attlist = empty +db-table-include-filter = + element db:table-include-filter { + db-table-include-filter-attlist, db-table-filter-pattern+ + } +db-table-include-filter-attlist = empty +db-table-exclude-filter = + element db:table-exclude-filter { + db-table-exclude-filter-attlist, db-table-filter-pattern+ + } +db-table-exclude-filter-attlist = empty +db-table-filter-pattern = + element db:table-filter-pattern { + db-table-filter-pattern-attlist, \string + } +db-table-filter-pattern-attlist = empty +db-table-type-filter = + element db:table-type-filter { + db-table-type-filter-attlist, db-table-type* + } +db-table-type-filter-attlist = empty +db-table-type = element db:table-type { db-table-type-attlist, \string } +db-table-type-attlist = empty +db-data-source-settings = + element db:data-source-settings { + db-data-source-settings-attlist, db-data-source-setting+ + } +db-data-source-settings-attlist = empty +db-data-source-setting = + element db:data-source-setting { + db-data-source-setting-attlist, db-data-source-setting-value+ + } +db-data-source-setting-attlist = + attribute db:data-source-setting-is-list { boolean }? + & attribute db:data-source-setting-name { \string } + & attribute db:data-source-setting-type { + db-data-source-setting-types + } +db-data-source-setting-types = + "boolean" | "short" | "int" | "long" | "double" | "string" +db-data-source-setting-value = + element db:data-source-setting-value { + db-data-source-setting-value-attlist, \string + } +db-data-source-setting-value-attlist = empty +db-forms = + element db:forms { + db-forms-attlist, (db-component | db-component-collection)* + } +db-forms-attlist = empty +db-reports = + element db:reports { + db-reports-attlist, (db-component | db-component-collection)* + } +db-reports-attlist = empty +db-component-collection = + element db:component-collection { + db-component-collection-attlist, + common-db-object-name, + common-db-object-title, + common-db-object-description, + (db-component | db-component-collection)* + } +db-component-collection-attlist = empty +db-component = + element db:component { + db-component-attlist, + common-db-object-name, + common-db-object-title, + common-db-object-description, + (office-document | math-math)? + } +db-component-attlist = + (attribute xlink:type { "simple" }, + attribute xlink:href { anyIRI }, + attribute xlink:show { "none" }?, + attribute xlink:actuate { "onRequest" }?)? + & attribute db:as-template { boolean }? +db-queries = + element db:queries { + db-queries-attlist, (db-query | db-query-collection)* + } +db-queries-attlist = empty +db-query-collection = + element db:query-collection { + db-query-collection-attlist, + common-db-object-name, + common-db-object-title, + common-db-object-description, + (db-query | db-query-collection)* + } +db-query-collection-attlist = empty +db-query = + element db:query { + db-query-attlist, + common-db-object-name, + common-db-object-title, + common-db-object-description, + common-db-table-style-name, + db-order-statement?, + db-filter-statement?, + db-columns?, + db-update-table? + } +db-query-attlist = + attribute db:command { \string } + & attribute db:escape-processing { boolean }? +db-order-statement = + element db:order-statement { db-command, db-apply-command, empty } +db-filter-statement = + element db:filter-statement { db-command, db-apply-command, empty } +db-update-table = + element db:update-table { common-db-table-name-attlist } +db-table-presentations = + element db:table-representations { + db-table-presentations-attlist, db-table-presentation* + } +db-table-presentations-attlist = empty +db-table-presentation = + element db:table-representation { + db-table-presentation-attlist, + common-db-table-name-attlist, + common-db-object-title, + common-db-object-description, + common-db-table-style-name, + db-order-statement?, + db-filter-statement?, + db-columns? + } +db-table-presentation-attlist = empty +db-columns = element db:columns { db-columns-attlist, db-column+ } +db-columns-attlist = empty +db-column = + element db:column { + db-column-attlist, + common-db-object-name, + common-db-object-title, + common-db-object-description, + common-db-default-value + } +db-column-attlist = + attribute db:visible { boolean }? + & attribute db:style-name { styleNameRef }? + & attribute db:default-cell-style-name { styleNameRef }? +db-command = attribute db:command { \string } +db-apply-command = attribute db:apply-command { boolean }? +common-db-table-name-attlist = + attribute db:name { \string } + & attribute db:catalog-name { \string }? + & attribute db:schema-name { \string }? +common-db-object-name = attribute db:name { \string } +common-db-object-title = attribute db:title { \string }? +common-db-object-description = attribute db:description { \string }? +common-db-table-style-name = + attribute db:style-name { styleNameRef }? + & attribute db:default-row-style-name { styleNameRef }? +common-db-default-value = common-value-and-type-attlist? +db-schema-definition = + element db:schema-definition { + db-schema-definition-attlist, db-table-definitions + } +db-schema-definition-attlist = empty +db-table-definitions = + element db:table-definitions { + db-table-definitions-attlist, db-table-definition* + } +db-table-definitions-attlist = empty +db-table-definition = + element db:table-definition { + common-db-table-name-attlist, + db-table-definition-attlist, + db-column-definitions, + db-keys?, + db-indices? + } +db-table-definition-attlist = attribute db:type { \string }? +db-column-definitions = + element db:column-definitions { + db-column-definitions-attlist, db-column-definition+ + } +db-column-definitions-attlist = empty +db-column-definition = + element db:column-definition { + db-column-definition-attlist, common-db-default-value + } +db-column-definition-attlist = + attribute db:name { \string } + & attribute db:data-type { db-data-types }? + & attribute db:type-name { \string }? + & attribute db:precision { positiveInteger }? + & attribute db:scale { positiveInteger }? + & attribute db:is-nullable { "no-nulls" | "nullable" }? + & attribute db:is-empty-allowed { boolean }? + & attribute db:is-autoincrement { boolean }? +db-data-types = + "bit" + | "boolean" + | "tinyint" + | "smallint" + | "integer" + | "bigint" + | "float" + | "real" + | "double" + | "numeric" + | "decimal" + | "char" + | "varchar" + | "longvarchar" + | "date" + | "time" + | "timestmp" + | "binary" + | "varbinary" + | "longvarbinary" + | "sqlnull" + | "other" + | "object" + | "distinct" + | "struct" + | "array" + | "blob" + | "clob" + | "ref" +db-keys = element db:keys { db-keys-attlist, db-key+ } +db-keys-attlist = empty +db-key = element db:key { db-key-attlist, db-key-columns+ } +db-key-attlist = + attribute db:name { \string }? + & attribute db:type { "primary" | "unique" | "foreign" } + & attribute db:referenced-table-name { \string }? + & attribute db:update-rule { + "cascade" | "restrict" | "set-null" | "no-action" | "set-default" + }? + & attribute db:delete-rule { + "cascade" | "restrict" | "set-null" | "no-action" | "set-default" + }? +db-key-columns = + element db:key-columns { db-key-columns-attlist, db-key-column+ } +db-key-columns-attlist = empty +db-key-column = element db:key-column { db-key-column-attlist, empty } +db-key-column-attlist = + attribute db:name { \string }? + & attribute db:related-column-name { \string }? +db-indices = element db:indices { db-indices-attlist, db-index+ } +db-indices-attlist = empty +db-index = element db:index { db-index-attlist, db-index-columns+ } +db-index-attlist = + attribute db:name { \string } + & attribute db:catalog-name { \string }? + & attribute db:is-unique { boolean }? + & attribute db:is-clustered { boolean }? +db-index-columns = element db:index-columns { db-index-column+ } +db-index-column = + element db:index-column { db-index-column-attlist, empty } +db-index-column-attlist = + attribute db:name { \string } + & attribute db:is-ascending { boolean }? +office-forms = + element office:forms { + office-forms-attlist, (form-form | xforms-model)* + }? +office-forms-attlist = + attribute form:automatic-focus { boolean }? + & attribute form:apply-design-mode { boolean }? +form-form = + element form:form { + common-form-control-attlist, + form-form-attlist, + form-properties?, + office-event-listeners?, + (controls | form-form)*, + form-connection-resource? + } +form-form-attlist = + (attribute xlink:type { "simple" }, + attribute xlink:href { anyIRI }, + attribute xlink:actuate { "onRequest" }?)? + & attribute office:target-frame { targetFrameName }? + & attribute form:method { "get" | "post" | \string }? + & attribute form:enctype { \string }? + & attribute form:allow-deletes { boolean }? + & attribute form:allow-inserts { boolean }? + & attribute form:allow-updates { boolean }? + & attribute form:apply-filter { boolean }? + & attribute form:command-type { "table" | "query" | "command" }? + & attribute form:command { \string }? + & attribute form:datasource { anyIRI | \string }? + & attribute form:master-fields { \string }? + & attribute form:detail-fields { \string }? + & attribute form:escape-processing { boolean }? + & attribute form:filter { \string }? + & attribute form:ignore-result { boolean }? + & attribute form:navigation-mode { navigation }? + & attribute form:order { \string }? + & attribute form:tab-cycle { tab-cycles }? +navigation = "none" | "current" | "parent" +tab-cycles = "records" | "current" | "page" +form-connection-resource = + element form:connection-resource { + attribute xlink:href { anyIRI }, + empty + } +xforms-model = element xforms:model { anyAttListOrElements } +column-controls = + element form:text { form-text-attlist, common-form-control-content } + | element form:textarea { + form-textarea-attlist, common-form-control-content, text-p* + } + | element form:formatted-text { + form-formatted-text-attlist, common-form-control-content + } + | element form:number { + form-number-attlist, + common-numeric-control-attlist, + common-form-control-content, + common-linked-cell, + common-spin-button, + common-repeat, + common-delay-for-repeat + } + | element form:date { + form-date-attlist, + common-numeric-control-attlist, + common-form-control-content, + common-linked-cell, + common-spin-button, + common-repeat, + common-delay-for-repeat + } + | element form:time { + form-time-attlist, + common-numeric-control-attlist, + common-form-control-content, + common-linked-cell, + common-spin-button, + common-repeat, + common-delay-for-repeat + } + | element form:combobox { + form-combobox-attlist, common-form-control-content, form-item* + } + | element form:listbox { + form-listbox-attlist, common-form-control-content, form-option* + } + | element form:checkbox { + form-checkbox-attlist, common-form-control-content + } +controls = + column-controls + | element form:password { + form-password-attlist, common-form-control-content + } + | element form:file { form-file-attlist, common-form-control-content } + | element form:fixed-text { + form-fixed-text-attlist, common-form-control-content + } + | element form:button { + form-button-attlist, common-form-control-content + } + | element form:image { + form-image-attlist, common-form-control-content + } + | element form:radio { + form-radio-attlist, common-form-control-content + } + | element form:frame { + form-frame-attlist, common-form-control-content + } + | element form:image-frame { + form-image-frame-attlist, common-form-control-content + } + | element form:hidden { + form-hidden-attlist, common-form-control-content + } + | element form:grid { + form-grid-attlist, common-form-control-content, form-column* + } + | element form:value-range { + form-value-range-attlist, common-form-control-content + } + | element form:generic-control { + form-generic-control-attlist, common-form-control-content + } +form-text-attlist = + form-control-attlist, + common-current-value-attlist, + common-disabled-attlist, + common-maxlength-attlist, + common-printable-attlist, + common-readonly-attlist, + common-tab-attlist, + common-title-attlist, + common-value-attlist, + common-convert-empty-attlist, + common-data-field-attlist, + common-linked-cell +form-control-attlist = + common-form-control-attlist, + common-control-id-attlist, + xforms-bind-attlist +common-form-control-content = form-properties?, office-event-listeners? +form-textarea-attlist = + form-control-attlist, + common-current-value-attlist, + common-disabled-attlist, + common-maxlength-attlist, + common-printable-attlist, + common-readonly-attlist, + common-tab-attlist, + common-title-attlist, + common-value-attlist, + common-convert-empty-attlist, + common-data-field-attlist, + common-linked-cell +form-password-attlist = + form-control-attlist + & common-disabled-attlist + & common-maxlength-attlist + & common-printable-attlist + & common-tab-attlist + & common-title-attlist + & common-value-attlist + & common-convert-empty-attlist + & common-linked-cell + & attribute form:echo-char { character }? +form-file-attlist = + form-control-attlist, + common-current-value-attlist, + common-disabled-attlist, + common-maxlength-attlist, + common-printable-attlist, + common-readonly-attlist, + common-tab-attlist, + common-title-attlist, + common-value-attlist, + common-linked-cell +form-formatted-text-attlist = + form-control-attlist + & common-current-value-attlist + & common-disabled-attlist + & common-maxlength-attlist + & common-printable-attlist + & common-readonly-attlist + & common-tab-attlist + & common-title-attlist + & common-value-attlist + & common-convert-empty-attlist + & common-data-field-attlist + & common-linked-cell + & common-spin-button + & common-repeat + & common-delay-for-repeat + & attribute form:max-value { \string }? + & attribute form:min-value { \string }? + & attribute form:validation { boolean }? +common-numeric-control-attlist = + form-control-attlist, + common-disabled-attlist, + common-maxlength-attlist, + common-printable-attlist, + common-readonly-attlist, + common-tab-attlist, + common-title-attlist, + common-convert-empty-attlist, + common-data-field-attlist +form-number-attlist = + attribute form:value { double }? + & attribute form:current-value { double }? + & attribute form:min-value { double }? + & attribute form:max-value { double }? +form-date-attlist = + attribute form:value { date }? + & attribute form:current-value { date }? + & attribute form:min-value { date }? + & attribute form:max-value { date }? +form-time-attlist = + attribute form:value { time }? + & attribute form:current-value { time }? + & attribute form:min-value { time }? + & attribute form:max-value { time }? +form-fixed-text-attlist = + form-control-attlist + & for + & common-disabled-attlist + & label + & common-printable-attlist + & common-title-attlist + & attribute form:multi-line { boolean }? +form-combobox-attlist = + form-control-attlist + & common-current-value-attlist + & common-disabled-attlist + & dropdown + & common-maxlength-attlist + & common-printable-attlist + & common-readonly-attlist + & size + & common-tab-attlist + & common-title-attlist + & common-value-attlist + & common-convert-empty-attlist + & common-data-field-attlist + & list-source + & list-source-type + & common-linked-cell + & common-source-cell-range + & attribute form:auto-complete { boolean }? +form-item = element form:item { form-item-attlist, text } +form-item-attlist = label +form-listbox-attlist = + form-control-attlist + & common-disabled-attlist + & dropdown + & common-printable-attlist + & size + & common-tab-attlist + & common-title-attlist + & bound-column + & common-data-field-attlist + & list-source + & list-source-type + & common-linked-cell + & list-linkage-type + & common-source-cell-range + & attribute form:multiple { boolean }? + & attribute form:xforms-list-source { \string }? +list-linkage-type = + attribute form:list-linkage-type { + "selection" | "selection-indices" + }? +form-option = element form:option { form-option-attlist, text } +form-option-attlist = + current-selected, selected, label, common-value-attlist +form-button-attlist = + form-control-attlist + & button-type + & common-disabled-attlist + & label + & image-data + & common-printable-attlist + & common-tab-attlist + & target-frame + & target-location + & common-title-attlist + & common-value-attlist + & common-form-relative-image-position-attlist + & common-repeat + & common-delay-for-repeat + & attribute form:default-button { boolean }? + & attribute form:toggle { boolean }? + & attribute form:focus-on-click { boolean }? + & attribute form:xforms-submission { \string }? +form-image-attlist = + form-control-attlist, + button-type, + common-disabled-attlist, + image-data, + common-printable-attlist, + common-tab-attlist, + target-frame, + target-location, + common-title-attlist, + common-value-attlist +form-checkbox-attlist = + form-control-attlist + & common-disabled-attlist + & label + & common-printable-attlist + & common-tab-attlist + & common-title-attlist + & common-value-attlist + & common-data-field-attlist + & common-form-visual-effect-attlist + & common-form-relative-image-position-attlist + & common-linked-cell + & attribute form:current-state { states }? + & attribute form:is-tristate { boolean }? + & attribute form:state { states }? +states = "unchecked" | "checked" | "unknown" +form-radio-attlist = + form-control-attlist, + current-selected, + common-disabled-attlist, + label, + common-printable-attlist, + selected, + common-tab-attlist, + common-title-attlist, + common-value-attlist, + common-data-field-attlist, + common-form-visual-effect-attlist, + common-form-relative-image-position-attlist, + common-linked-cell +form-frame-attlist = + form-control-attlist, + common-disabled-attlist, + for, + label, + common-printable-attlist, + common-title-attlist +form-image-frame-attlist = + form-control-attlist, + common-disabled-attlist, + image-data, + common-printable-attlist, + common-readonly-attlist, + common-title-attlist, + common-data-field-attlist +form-hidden-attlist = form-control-attlist, common-value-attlist +form-grid-attlist = + form-control-attlist, + common-disabled-attlist, + common-printable-attlist, + common-tab-attlist, + common-title-attlist +form-column = + element form:column { form-column-attlist, column-controls+ } +form-column-attlist = + common-form-control-attlist, label, text-style-name +text-style-name = attribute form:text-style-name { styleNameRef }? +form-value-range-attlist = + form-control-attlist + & common-disabled-attlist + & common-printable-attlist + & common-tab-attlist + & common-title-attlist + & common-value-attlist + & common-linked-cell + & common-repeat + & common-delay-for-repeat + & attribute form:max-value { integer }? + & attribute form:min-value { integer }? + & attribute form:step-size { positiveInteger }? + & attribute form:page-step-size { positiveInteger }? + & attribute form:orientation { "horizontal" | "vertical" }? +form-generic-control-attlist = form-control-attlist +common-form-control-attlist = + attribute form:name { \string }? + & attribute form:control-implementation { namespacedToken }? +xforms-bind-attlist = attribute xforms:bind { \string }? +types = "submit" | "reset" | "push" | "url" +button-type = attribute form:button-type { types }? +common-control-id-attlist = + xml-id, + attribute form:id { NCName }? +current-selected = attribute form:current-selected { boolean }? +common-value-attlist = attribute form:value { \string }? +common-current-value-attlist = attribute form:current-value { \string }? +common-disabled-attlist = attribute form:disabled { boolean }? +dropdown = attribute form:dropdown { boolean }? +for = attribute form:for { \string }? +image-data = attribute form:image-data { anyIRI }? +label = attribute form:label { \string }? +common-maxlength-attlist = + attribute form:max-length { nonNegativeInteger }? +common-printable-attlist = attribute form:printable { boolean }? +common-readonly-attlist = attribute form:readonly { boolean }? +selected = attribute form:selected { boolean }? +size = attribute form:size { nonNegativeInteger }? +common-tab-attlist = + attribute form:tab-index { nonNegativeInteger }? + & attribute form:tab-stop { boolean }? +target-frame = attribute office:target-frame { targetFrameName }? +target-location = attribute xlink:href { anyIRI }? +common-title-attlist = attribute form:title { \string }? +common-form-visual-effect-attlist = + attribute form:visual-effect { "flat" | "3d" }? +common-form-relative-image-position-attlist = + attribute form:image-position { "center" }? + | (attribute form:image-position { + "start" | "end" | "top" | "bottom" + }, + attribute form:image-align { "start" | "center" | "end" }?) +bound-column = attribute form:bound-column { \string }? +common-convert-empty-attlist = + attribute form:convert-empty-to-null { boolean }? +common-data-field-attlist = attribute form:data-field { \string }? +list-source = attribute form:list-source { \string }? +list-source-type = + attribute form:list-source-type { + "table" + | "query" + | "sql" + | "sql-pass-through" + | "value-list" + | "table-fields" + }? +common-linked-cell = + attribute form:linked-cell { cellAddress | \string }? +common-source-cell-range = + attribute form:source-cell-range { cellRangeAddress | \string }? +common-spin-button = attribute form:spin-button { boolean }? +common-repeat = attribute form:repeat { boolean }? +common-delay-for-repeat = attribute form:delay-for-repeat { duration }? +form-properties = element form:properties { form-property+ } +form-property = + element form:property { + form-property-name, form-property-value-and-type-attlist + } + | element form:list-property { + form-property-name, form-property-type-and-value-list + } +form-property-name = attribute form:property-name { \string } +form-property-value-and-type-attlist = + common-value-and-type-attlist + | attribute office:value-type { "void" } +form-property-type-and-value-list = + (attribute office:value-type { "float" }, + element form:list-value { + attribute office:value { double } + }*) + | (attribute office:value-type { "percentage" }, + element form:list-value { + attribute office:value { double } + }*) + | (attribute office:value-type { "currency" }, + element form:list-value { + attribute office:value { double }, + attribute office:currency { \string }? + }*) + | (attribute office:value-type { "date" }, + element form:list-value { + attribute office:date-value { dateOrDateTime } + }*) + | (attribute office:value-type { "time" }, + element form:list-value { + attribute office:time-value { duration } + }*) + | (attribute office:value-type { "boolean" }, + element form:list-value { + attribute office:boolean-value { boolean } + }*) + | (attribute office:value-type { "string" }, + element form:list-value { + attribute office:string-value { \string } + }*) + | attribute office:value-type { "void" } +office-annotation = + element office:annotation { + office-annotation-attlist, + draw-caption-attlist, + common-draw-position-attlist, + common-draw-size-attlist, + common-draw-shape-with-text-and-styles-attlist, + dc-creator?, + dc-date?, + meta-date-string?, + (text-p | text-list)* + } +office-annotation-end = + element office:annotation-end { office-annotation-end-attlist } +office-annotation-attlist = + attribute office:display { boolean }? + & common-office-annotation-name-attlist? +office-annotation-end-attlist = common-office-annotation-name-attlist +common-office-annotation-name-attlist = + attribute office:name { \string } +meta-date-string = element meta:date-string { \string } +common-num-format-prefix-suffix-attlist = + attribute style:num-prefix { \string }?, + attribute style:num-suffix { \string }? +common-num-format-attlist = + attribute style:num-format { "1" | "i" | "I" | \string | empty } + | (attribute style:num-format { "a" | "A" }, + style-num-letter-sync-attlist) + | empty +style-num-letter-sync-attlist = + attribute style:num-letter-sync { boolean }? +office-change-info = + element office:change-info { dc-creator, dc-date, text-p* } +office-event-listeners = + element office:event-listeners { + (script-event-listener | presentation-event-listener)* + } +script-event-listener = + element script:event-listener { script-event-listener-attlist, empty } +script-event-listener-attlist = + attribute script:event-name { \string } + & attribute script:language { \string } + & (attribute script:macro-name { \string } + | (attribute xlink:type { "simple" }, + attribute xlink:href { anyIRI }, + attribute xlink:actuate { "onRequest" }?)) +math-math = element math:math { mathMarkup } +[ + dc:description [ + "To avoid inclusion of the complete MathML schema, anything is allowed within a math:math top-level element" + ] +] +mathMarkup = + (attribute * { text } + | text + | element * { mathMarkup })* +text-dde-connection-decl = + element text:dde-connection-decl { + text-dde-connection-decl-attlist, common-dde-connection-decl-attlist + } +text-dde-connection-decl-attlist = attribute office:name { \string } +common-dde-connection-decl-attlist = + attribute office:dde-application { \string } + & attribute office:dde-topic { \string } + & attribute office:dde-item { \string } + & attribute office:automatic-update { boolean }? +table-dde-link = + element table:dde-link { office-dde-source, table-table } +office-dde-source = + element office:dde-source { + office-dde-source-attlist, common-dde-connection-decl-attlist + } +office-dde-source-attlist = + attribute office:name { \string }? + & attribute office:conversion-mode { + "into-default-style-data-style" + | "into-english-number" + | "keep-text" + }? +animation-element = + element anim:animate { + common-anim-target-attlist, + common-anim-named-target-attlist, + common-anim-values-attlist, + common-anim-spline-mode-attlist, + common-spline-anim-value-attlist, + common-timing-attlist, + common-anim-add-accum-attlist + } + | element anim:set { + common-anim-target-attlist, + common-anim-named-target-attlist, + common-anim-set-values-attlist, + common-timing-attlist, + common-anim-add-accum-attlist + } + | element anim:animateMotion { + anim-animate-motion-attlist, + common-anim-target-attlist, + common-anim-named-target-attlist, + common-anim-add-accum-attlist, + common-anim-values-attlist, + common-timing-attlist, + common-spline-anim-value-attlist + } + | element anim:animateColor { + common-anim-target-attlist, + common-anim-named-target-attlist, + common-anim-add-accum-attlist, + common-anim-values-attlist, + common-anim-spline-mode-attlist, + common-spline-anim-value-attlist, + anim-animate-color-attlist, + common-timing-attlist + } + | element anim:animateTransform { + common-anim-target-attlist, + common-anim-named-target-attlist, + common-anim-add-accum-attlist, + common-anim-values-attlist, + anim-animate-transform-attlist, + common-timing-attlist + } + | element anim:transitionFilter { + common-anim-target-attlist, + common-anim-add-accum-attlist, + common-anim-values-attlist, + common-anim-spline-mode-attlist, + anim-transition-filter-attlist, + common-timing-attlist + } + | element anim:par { + common-anim-attlist, + common-timing-attlist, + common-endsync-timing-attlist, + animation-element* + } + | element anim:seq { + common-anim-attlist, + common-endsync-timing-attlist, + common-timing-attlist, + animation-element* + } + | element anim:iterate { + common-anim-attlist, + anim-iterate-attlist, + common-timing-attlist, + common-endsync-timing-attlist, + animation-element* + } + | element anim:audio { + common-anim-attlist, + anim-audio-attlist, + common-basic-timing-attlist + } + | element anim:command { + common-anim-attlist, + anim-command-attlist, + common-begin-end-timing-attlist, + common-anim-target-attlist, + element anim:param { + attribute anim:name { \string }, + attribute anim:value { \string } + }* + } +anim-animate-motion-attlist = + attribute svg:path { pathData }? + & attribute svg:origin { \string }? + & attribute smil:calcMode { + "discrete" | "linear" | "paced" | "spline" + }? +anim-animate-color-attlist = + attribute anim:color-interpolation { "rgb" | "hsl" }? + & attribute anim:color-interpolation-direction { + "clockwise" | "counter-clockwise" + }? +anim-animate-transform-attlist = + attribute svg:type { + "translate" | "scale" | "rotate" | "skewX" | "skewY" + } +anim-transition-filter-attlist = + attribute smil:type { \string } + & attribute smil:subtype { \string }? + & attribute smil:direction { "forward" | "reverse" }? + & attribute smil:fadeColor { color }? + & attribute smil:mode { "in" | "out" }? +common-anim-target-attlist = + attribute smil:targetElement { IDREF }? + & attribute anim:sub-item { \string }? +common-anim-named-target-attlist = + attribute smil:attributeName { \string } +common-anim-values-attlist = + attribute smil:values { \string }? + & attribute anim:formula { \string }? + & common-anim-set-values-attlist + & attribute smil:from { \string }? + & attribute smil:by { \string }? +common-anim-spline-mode-attlist = + attribute smil:calcMode { + "discrete" | "linear" | "paced" | "spline" + }? +common-spline-anim-value-attlist = + attribute smil:keyTimes { \string }? + & attribute smil:keySplines { \string }? +common-anim-add-accum-attlist = + attribute smil:accumulate { "none" | "sum" }? + & attribute smil:additive { "replace" | "sum" }? +common-anim-set-values-attlist = attribute smil:to { \string }? +common-begin-end-timing-attlist = + attribute smil:begin { \string }? + & attribute smil:end { \string }? +common-dur-timing-attlist = attribute smil:dur { \string }? +common-endsync-timing-attlist = + attribute smil:endsync { "first" | "last" | "all" | "media" | IDREF }? +common-repeat-timing-attlist = + attribute smil:repeatDur { \string }?, + attribute smil:repeatCount { nonNegativeDecimal | "indefinite" }? +nonNegativeDecimal = xsd:decimal { minInclusive = "0.0" } +common-fill-timing-attlist = + attribute smil:fill { + "remove" | "freeze" | "hold" | "auto" | "default" | "transition" + }? +common-fill-default-attlist = + attribute smil:fillDefault { + "remove" | "freeze" | "hold" | "transition" | "auto" | "inherit" + }? +common-restart-timing-attlist = + attribute smil:restart { + "never" | "always" | "whenNotActive" | "default" + }? +common-restart-default-attlist = + attribute smil:restartDefault { + "never" | "always" | "whenNotActive" | "inherit" + }? +common-time-manip-attlist = + attribute smil:accelerate { zeroToOneDecimal }? + & attribute smil:decelerate { zeroToOneDecimal }? + & attribute smil:autoReverse { boolean }? +zeroToOneDecimal = xsd:decimal { minInclusive = "0" maxInclusive = "1" } +common-basic-timing-attlist = + common-begin-end-timing-attlist, + common-dur-timing-attlist, + common-repeat-timing-attlist, + common-restart-timing-attlist, + common-restart-default-attlist, + common-fill-timing-attlist, + common-fill-default-attlist +common-timing-attlist = + common-basic-timing-attlist, common-time-manip-attlist +anim-iterate-attlist = + common-anim-target-attlist + & attribute anim:iterate-type { \string }? + & attribute anim:iterate-interval { duration }? +anim-audio-attlist = + attribute xlink:href { anyIRI }? + & attribute anim:audio-level { double }? +anim-command-attlist = attribute anim:command { \string } +style-style = + element style:style { + style-style-attlist, style-style-content, style-map* + } +common-in-content-meta-attlist = + attribute xhtml:about { URIorSafeCURIE }, + attribute xhtml:property { CURIEs }, + common-meta-literal-attlist +common-meta-literal-attlist = + attribute xhtml:datatype { CURIE }?, + attribute xhtml:content { \string }? +xml-id = attribute xml:id { ID } +style-style-attlist = + attribute style:name { styleName } + & attribute style:display-name { \string }? + & attribute style:parent-style-name { styleNameRef }? + & attribute style:next-style-name { styleNameRef }? + & attribute style:list-level { positiveInteger | empty }? + & attribute style:list-style-name { styleName | empty }? + & attribute style:master-page-name { styleNameRef }? + & attribute style:auto-update { boolean }? + & attribute style:data-style-name { styleNameRef }? + & attribute style:percentage-data-style-name { styleNameRef }? + & attribute style:class { \string }? + & attribute style:default-outline-level { positiveInteger | empty }? +style-map = element style:map { style-map-attlist, empty } +style-map-attlist = + attribute style:condition { \string } + & attribute style:apply-style-name { styleNameRef } + & attribute style:base-cell-address { cellAddress }? +style-default-style = + element style:default-style { style-style-content } +style-page-layout = + element style:page-layout { + style-page-layout-attlist, style-page-layout-content + } +style-page-layout-content = + style-page-layout-properties?, + style-header-style?, + style-footer-style? +style-page-layout-attlist = + attribute style:name { styleName } + & attribute style:page-usage { + "all" | "left" | "right" | "mirrored" + }? +style-header-style = + element style:header-style { style-header-footer-properties? } +style-footer-style = + element style:footer-style { style-header-footer-properties? } +style-default-page-layout = + element style:default-page-layout { style-page-layout-content } +style-master-page = + element style:master-page { + style-master-page-attlist, + (style-header, style-header-left?)?, + (style-footer, style-footer-left?)?, + draw-layer-set?, + office-forms?, + shape*, + animation-element?, + presentation-notes? + } +style-master-page-attlist = + attribute style:name { styleName } + & attribute style:display-name { \string }? + & attribute style:page-layout-name { styleNameRef } + & attribute draw:style-name { styleNameRef }? + & attribute style:next-style-name { styleNameRef }? +style-header = + element style:header { + common-style-header-footer-attlist, header-footer-content + } +style-footer = + element style:footer { + common-style-header-footer-attlist, header-footer-content + } +style-header-left = + element style:header-left { + common-style-header-footer-attlist, header-footer-content + } +style-footer-left = + element style:footer-left { + common-style-header-footer-attlist, header-footer-content + } +header-footer-content = + (text-tracked-changes, + text-decls, + (text-h + | text-p + | text-list + | table-table + | text-section + | text-table-of-content + | text-illustration-index + | text-table-index + | text-object-index + | text-user-index + | text-alphabetical-index + | text-bibliography + | text-index-title + | change-marks)*) + | (style-region-left?, style-region-center?, style-region-right?) +common-style-header-footer-attlist = + attribute style:display { boolean }? +style-region-left = element style:region-left { region-content } +style-region-center = element style:region-center { region-content } +style-region-right = element style:region-right { region-content } +region-content = text-p* +presentation-notes = + element presentation:notes { + common-presentation-header-footer-attlist, + presentation-notes-attlist, + office-forms, + shape* + } +presentation-notes-attlist = + attribute style:page-layout-name { styleNameRef }? + & attribute draw:style-name { styleNameRef }? +table-table-template = + element table:table-template { + table-table-template-attlist, + table-first-row?, + table-last-row?, + table-first-column?, + table-last-column?, + table-body, + table-even-rows?, + table-odd-rows?, + table-even-columns?, + table-odd-columns?, + table-background? + } +table-table-template-attlist = + attribute table:name { \string } + & attribute table:first-row-start-column { rowOrCol } + & attribute table:first-row-end-column { rowOrCol } + & attribute table:last-row-start-column { rowOrCol } + & attribute table:last-row-end-column { rowOrCol } +rowOrCol = "row" | "column" +table-first-row = + element table:first-row { common-table-template-attlist, empty } +table-last-row = + element table:last-row { common-table-template-attlist, empty } +table-first-column = + element table:first-column { common-table-template-attlist, empty } +table-last-column = + element table:last-column { common-table-template-attlist, empty } +table-body = element table:body { common-table-template-attlist, empty } +table-even-rows = + element table:even-rows { common-table-template-attlist, empty } +table-odd-rows = + element table:odd-rows { common-table-template-attlist, empty } +table-even-columns = + element table:even-columns { common-table-template-attlist, empty } +table-odd-columns = + element table:odd-columns { common-table-template-attlist, empty } +common-table-template-attlist = + attribute table:style-name { styleNameRef }, + attribute table:paragraph-style-name { styleNameRef }? +table-background = + element table:background { table-background-attlist, empty } +table-background-attlist = attribute table:style-name { styleNameRef } +style-font-face = + element style:font-face { + style-font-face-attlist, svg-font-face-src?, svg-definition-src? + } +style-font-face-attlist = + attribute svg:font-family { \string }? + & attribute svg:font-style { fontStyle }? + & attribute svg:font-variant { fontVariant }? + & attribute svg:font-weight { fontWeight }? + & attribute svg:font-stretch { + "normal" + | "ultra-condensed" + | "extra-condensed" + | "condensed" + | "semi-condensed" + | "semi-expanded" + | "expanded" + | "extra-expanded" + | "ultra-expanded" + }? + & attribute svg:font-size { positiveLength }? + & attribute svg:unicode-range { \string }? + & attribute svg:units-per-em { integer }? + & attribute svg:panose-1 { \string }? + & attribute svg:stemv { integer }? + & attribute svg:stemh { integer }? + & attribute svg:slope { integer }? + & attribute svg:cap-height { integer }? + & attribute svg:x-height { integer }? + & attribute svg:accent-height { integer }? + & attribute svg:ascent { integer }? + & attribute svg:descent { integer }? + & attribute svg:widths { \string }? + & attribute svg:bbox { \string }? + & attribute svg:ideographic { integer }? + & attribute svg:alphabetic { integer }? + & attribute svg:mathematical { integer }? + & attribute svg:hanging { integer }? + & attribute svg:v-ideographic { integer }? + & attribute svg:v-alphabetic { integer }? + & attribute svg:v-mathematical { integer }? + & attribute svg:v-hanging { integer }? + & attribute svg:underline-position { integer }? + & attribute svg:underline-thickness { integer }? + & attribute svg:strikethrough-position { integer }? + & attribute svg:strikethrough-thickness { integer }? + & attribute svg:overline-position { integer }? + & attribute svg:overline-thickness { integer }? + & attribute style:name { \string } + & attribute style:font-adornments { \string }? + & attribute style:font-family-generic { fontFamilyGeneric }? + & attribute style:font-pitch { fontPitch }? + & attribute style:font-charset { textEncoding }? +svg-font-face-src = + element svg:font-face-src { + (svg-font-face-uri | svg-font-face-name)+ + } +svg-font-face-uri = + element svg:font-face-uri { + common-svg-font-face-xlink-attlist, svg-font-face-format* + } +svg-font-face-format = + element svg:font-face-format { + attribute svg:string { \string }?, + empty + } +svg-font-face-name = + element svg:font-face-name { + attribute svg:name { \string }?, + empty + } +svg-definition-src = + element svg:definition-src { + common-svg-font-face-xlink-attlist, empty + } +common-svg-font-face-xlink-attlist = + attribute xlink:type { "simple" }, + attribute xlink:href { anyIRI }, + attribute xlink:actuate { "onRequest" }? +number-number-style = + element number:number-style { + common-data-style-attlist, + style-text-properties?, + number-text?, + (any-number, number-text?)?, + style-map* + } +any-number = number-number | number-scientific-number | number-fraction +number-number = + element number:number { + number-number-attlist, + common-decimal-places-attlist, + common-number-attlist, + number-embedded-text* + } +number-number-attlist = + attribute number:decimal-replacement { \string }? + & attribute number:display-factor { double }? +number-embedded-text = + element number:embedded-text { number-embedded-text-attlist, text } +number-embedded-text-attlist = attribute number:position { integer } +number-scientific-number = + element number:scientific-number { + number-scientific-number-attlist, + common-decimal-places-attlist, + common-number-attlist, + empty + } +number-scientific-number-attlist = + attribute number:min-exponent-digits { integer }? +number-fraction = + element number:fraction { + number-fraction-attlist, common-number-attlist, empty + } +number-fraction-attlist = + attribute number:min-numerator-digits { integer }? + & attribute number:min-denominator-digits { integer }? + & attribute number:denominator-value { integer }? +number-currency-style = + element number:currency-style { + common-data-style-attlist, + common-auto-reorder-attlist, + style-text-properties?, + number-text?, + ((number-and-text, currency-symbol-and-text?) + | (currency-symbol-and-text, number-and-text?))?, + style-map* + } +currency-symbol-and-text = number-currency-symbol, number-text? +number-and-text = number-number, number-text? +number-currency-symbol = + element number:currency-symbol { + number-currency-symbol-attlist, text + } +number-currency-symbol-attlist = + attribute number:language { languageCode }?, + attribute number:country { countryCode }?, + attribute number:script { scriptCode }?, + attribute number:rfc-language-tag { language }? +number-percentage-style = + element number:percentage-style { + common-data-style-attlist, + style-text-properties?, + number-text?, + number-and-text?, + style-map* + } +number-date-style = + element number:date-style { + common-data-style-attlist, + common-auto-reorder-attlist, + common-format-source-attlist, + style-text-properties?, + number-text?, + (any-date, number-text?)+, + style-map* + } +any-date = + number-day + | number-month + | number-year + | number-era + | number-day-of-week + | number-week-of-year + | number-quarter + | number-hours + | number-am-pm + | number-minutes + | number-seconds +number-day = + element number:day { + number-day-attlist, common-calendar-attlist, empty + } +number-day-attlist = attribute number:style { "short" | "long" }? +number-month = + element number:month { + number-month-attlist, common-calendar-attlist, empty + } +number-month-attlist = + attribute number:textual { boolean }? + & attribute number:possessive-form { boolean }? + & attribute number:style { "short" | "long" }? +number-year = + element number:year { + number-year-attlist, common-calendar-attlist, empty + } +number-year-attlist = attribute number:style { "short" | "long" }? +number-era = + element number:era { + number-era-attlist, common-calendar-attlist, empty + } +number-era-attlist = attribute number:style { "short" | "long" }? +number-day-of-week = + element number:day-of-week { + number-day-of-week-attlist, common-calendar-attlist, empty + } +number-day-of-week-attlist = + attribute number:style { "short" | "long" }? +number-week-of-year = + element number:week-of-year { common-calendar-attlist, empty } +number-quarter = + element number:quarter { + number-quarter-attlist, common-calendar-attlist, empty + } +number-quarter-attlist = attribute number:style { "short" | "long" }? +number-time-style = + element number:time-style { + number-time-style-attlist, + common-data-style-attlist, + common-format-source-attlist, + style-text-properties?, + number-text?, + (any-time, number-text?)+, + style-map* + } +any-time = number-hours | number-am-pm | number-minutes | number-seconds +number-time-style-attlist = + attribute number:truncate-on-overflow { boolean }? +number-hours = element number:hours { number-hours-attlist, empty } +number-hours-attlist = attribute number:style { "short" | "long" }? +number-minutes = + element number:minutes { number-minutes-attlist, empty } +number-minutes-attlist = attribute number:style { "short" | "long" }? +number-seconds = + element number:seconds { number-seconds-attlist, empty } +number-seconds-attlist = + attribute number:style { "short" | "long" }? + & attribute number:decimal-places { integer }? +number-am-pm = element number:am-pm { empty } +number-boolean-style = + element number:boolean-style { + common-data-style-attlist, + style-text-properties?, + number-text?, + (number-boolean, number-text?)?, + style-map* + } +number-boolean = element number:boolean { empty } +number-text-style = + element number:text-style { + common-data-style-attlist, + style-text-properties?, + number-text?, + (number-text-content, number-text?)*, + style-map* + } +number-text = element number:text { text } +number-text-content = element number:text-content { empty } +common-data-style-attlist = + attribute style:name { styleName } + & attribute style:display-name { \string }? + & attribute number:language { languageCode }? + & attribute number:country { countryCode }? + & attribute number:script { scriptCode }? + & attribute number:rfc-language-tag { language }? + & attribute number:title { \string }? + & attribute style:volatile { boolean }? + & attribute number:transliteration-format { \string }? + & attribute number:transliteration-language { countryCode }? + & attribute number:transliteration-country { countryCode }? + & attribute number:transliteration-style { + "short" | "medium" | "long" + }? +common-auto-reorder-attlist = + attribute number:automatic-order { boolean }? +common-format-source-attlist = + attribute number:format-source { "fixed" | "language" }? +common-decimal-places-attlist = + attribute number:decimal-places { integer }? +common-number-attlist = + attribute number:min-integer-digits { integer }? + & attribute number:grouping { boolean }? +common-calendar-attlist = + attribute number:calendar { + "gregorian" + | "gengou" + | "ROC" + | "hanja_yoil" + | "hanja" + | "hijri" + | "jewish" + | "buddhist" + | \string + }? +style-style-content = + (attribute style:family { "text" }, + style-text-properties?) + | (attribute style:family { "paragraph" }, + style-paragraph-properties?, + style-text-properties?) + | (attribute style:family { "section" }, + style-section-properties?) + | (attribute style:family { "ruby" }, + style-ruby-properties?) + | (attribute style:family { "table" }, + style-table-properties?) + | (attribute style:family { "table-column" }, + style-table-column-properties?) + | (attribute style:family { "table-row" }, + style-table-row-properties?) + | (attribute style:family { "table-cell" }, + style-table-cell-properties?, + style-paragraph-properties?, + style-text-properties?) + | (attribute style:family { "graphic" | "presentation" }, + style-graphic-properties?, + style-paragraph-properties?, + style-text-properties?) + | (attribute style:family { "drawing-page" }, + style-drawing-page-properties?) + | (attribute style:family { "chart" }, + style-chart-properties?, + style-graphic-properties?, + style-paragraph-properties?, + style-text-properties?) +text-linenumbering-configuration = + element text:linenumbering-configuration { + text-linenumbering-configuration-attlist, + text-linenumbering-separator? + } +text-linenumbering-configuration-attlist = + attribute text:number-lines { boolean }? + & common-num-format-attlist? + & attribute text:style-name { styleNameRef }? + & attribute text:increment { nonNegativeInteger }? + & attribute text:number-position { + "left" | "right" | "inner" | "outer" + }? + & attribute text:offset { nonNegativeLength }? + & attribute text:count-empty-lines { boolean }? + & attribute text:count-in-text-boxes { boolean }? + & attribute text:restart-on-page { boolean }? +text-linenumbering-separator = + element text:linenumbering-separator { + attribute text:increment { nonNegativeInteger }?, + text + } +text-notes-configuration = + element text:notes-configuration { text-notes-configuration-content } +text-notes-configuration-content = + text-note-class + & attribute text:citation-style-name { styleNameRef }? + & attribute text:citation-body-style-name { styleNameRef }? + & attribute text:default-style-name { styleNameRef }? + & attribute text:master-page-name { styleNameRef }? + & attribute text:start-value { nonNegativeInteger }? + & common-num-format-prefix-suffix-attlist + & common-num-format-attlist? + & attribute text:start-numbering-at { + "document" | "chapter" | "page" + }? + & attribute text:footnotes-position { + "text" | "page" | "section" | "document" + }? + & element text:note-continuation-notice-forward { text }? + & element text:note-continuation-notice-backward { text }? +text-bibliography-configuration = + element text:bibliography-configuration { + text-bibliography-configuration-attlist, text-sort-key* + } +text-bibliography-configuration-attlist = + attribute text:prefix { \string }? + & attribute text:suffix { \string }? + & attribute text:numbered-entries { boolean }? + & attribute text:sort-by-position { boolean }? + & attribute fo:language { languageCode }? + & attribute fo:country { countryCode }? + & attribute fo:script { scriptCode }? + & attribute style:rfc-language-tag { language }? + & attribute text:sort-algorithm { \string }? +text-sort-key = element text:sort-key { text-sort-key-attlist, empty } +text-sort-key-attlist = + attribute text:key { + "address" + | "annote" + | "author" + | "bibliography-type" + | "booktitle" + | "chapter" + | "custom1" + | "custom2" + | "custom3" + | "custom4" + | "custom5" + | "edition" + | "editor" + | "howpublished" + | "identifier" + | "institution" + | "isbn" + | "issn" + | "journal" + | "month" + | "note" + | "number" + | "organizations" + | "pages" + | "publisher" + | "report-type" + | "school" + | "series" + | "title" + | "url" + | "volume" + | "year" + }, + attribute text:sort-ascending { boolean }? +text-list-style = + element text:list-style { + text-list-style-attr, text-list-style-content* + } +text-list-style-attr = + attribute style:name { styleName } + & attribute style:display-name { \string }? + & attribute text:consecutive-numbering { boolean }? +text-list-style-content = + element text:list-level-style-number { + text-list-level-style-attr, + text-list-level-style-number-attr, + style-list-level-properties?, + style-text-properties? + } + | element text:list-level-style-bullet { + text-list-level-style-attr, + text-list-level-style-bullet-attr, + style-list-level-properties?, + style-text-properties? + } + | element text:list-level-style-image { + text-list-level-style-attr, + text-list-level-style-image-attr, + style-list-level-properties? + } +text-list-level-style-number-attr = + attribute text:style-name { styleNameRef }? + & common-num-format-attlist + & common-num-format-prefix-suffix-attlist + & attribute text:display-levels { positiveInteger }? + & attribute text:start-value { positiveInteger }? +text-list-level-style-bullet-attr = + attribute text:style-name { styleNameRef }? + & attribute text:bullet-char { character } + & common-num-format-prefix-suffix-attlist + & attribute text:bullet-relative-size { percent }? +text-list-level-style-image-attr = + common-draw-data-attlist | office-binary-data +text-list-level-style-attr = attribute text:level { positiveInteger } +text-outline-style = + element text:outline-style { + text-outline-style-attr, text-outline-level-style+ + } +text-outline-style-attr = attribute style:name { styleName } +text-outline-level-style = + element text:outline-level-style { + text-outline-level-style-attlist, + style-list-level-properties?, + style-text-properties? + } +text-outline-level-style-attlist = + attribute text:level { positiveInteger } + & attribute text:style-name { styleNameRef }? + & common-num-format-attlist + & common-num-format-prefix-suffix-attlist + & attribute text:display-levels { positiveInteger }? + & attribute text:start-value { positiveInteger }? +style-graphic-properties = + element style:graphic-properties { + style-graphic-properties-content-strict + } +style-graphic-properties-content-strict = + style-graphic-properties-attlist, + style-graphic-fill-properties-attlist, + style-graphic-properties-elements +style-drawing-page-properties = + element style:drawing-page-properties { + style-drawing-page-properties-content-strict + } +style-drawing-page-properties-content-strict = + style-graphic-fill-properties-attlist, + style-drawing-page-properties-attlist, + style-drawing-page-properties-elements +draw-gradient = + element draw:gradient { + common-draw-gradient-attlist, draw-gradient-attlist, empty + } +common-draw-gradient-attlist = + attribute draw:name { styleName }? + & attribute draw:display-name { \string }? + & attribute draw:style { gradient-style } + & attribute draw:cx { percent }? + & attribute draw:cy { percent }? + & attribute draw:angle { angle }? + & attribute draw:border { percent }? +gradient-style = + "linear" | "axial" | "radial" | "ellipsoid" | "square" | "rectangular" +draw-gradient-attlist = + attribute draw:start-color { color }? + & attribute draw:end-color { color }? + & attribute draw:start-intensity { zeroToHundredPercent }? + & attribute draw:end-intensity { zeroToHundredPercent }? +svg-linearGradient = + element svg:linearGradient { + common-svg-gradient-attlist, + attribute svg:x1 { coordinate | percent }?, + attribute svg:y1 { coordinate | percent }?, + attribute svg:x2 { coordinate | percent }?, + attribute svg:y2 { coordinate | percent }?, + svg-stop* + } +svg-radialGradient = + element svg:radialGradient { + common-svg-gradient-attlist, + attribute svg:cx { coordinate | percent }?, + attribute svg:cy { coordinate | percent }?, + attribute svg:r { coordinate | percent }?, + attribute svg:fx { coordinate | percent }?, + attribute svg:fy { coordinate | percent }?, + svg-stop* + } +svg-stop = + element svg:stop { + attribute svg:offset { double | percent }, + attribute svg:stop-color { color }?, + attribute svg:stop-opacity { double }? + } +common-svg-gradient-attlist = + attribute svg:gradientUnits { "objectBoundingBox" }? + & attribute svg:gradientTransform { \string }? + & attribute svg:spreadMethod { "pad" | "reflect" | "repeat" }? + & attribute draw:name { styleName } + & attribute draw:display-name { \string }? +draw-hatch = element draw:hatch { draw-hatch-attlist, empty } +draw-hatch-attlist = + attribute draw:name { styleName } + & attribute draw:display-name { \string }? + & attribute draw:style { "single" | "double" | "triple" } + & attribute draw:color { color }? + & attribute draw:distance { length }? + & attribute draw:rotation { angle }? +draw-fill-image = + element draw:fill-image { + draw-fill-image-attlist, + attribute xlink:type { "simple" }, + attribute xlink:href { anyIRI }, + attribute xlink:show { "embed" }?, + attribute xlink:actuate { "onLoad" }?, + empty + } +draw-fill-image-attlist = + attribute draw:name { styleName } + & attribute draw:display-name { \string }? + & attribute svg:width { length }? + & attribute svg:height { length }? +draw-opacity = + element draw:opacity { + common-draw-gradient-attlist, draw-opacity-attlist, empty + } +draw-opacity-attlist = + attribute draw:start { zeroToHundredPercent }?, + attribute draw:end { zeroToHundredPercent }? +draw-marker = + element draw:marker { + draw-marker-attlist, + common-draw-viewbox-attlist, + common-draw-path-data-attlist, + empty + } +draw-marker-attlist = + attribute draw:name { styleName } + & attribute draw:display-name { \string }? +draw-stroke-dash = + element draw:stroke-dash { draw-stroke-dash-attlist, empty } +draw-stroke-dash-attlist = + attribute draw:name { styleName } + & attribute draw:display-name { \string }? + & attribute draw:style { "rect" | "round" }? + & attribute draw:dots1 { integer }? + & attribute draw:dots1-length { length | percent }? + & attribute draw:dots2 { integer }? + & attribute draw:dots2-length { length | percent }? + & attribute draw:distance { length | percent }? +style-presentation-page-layout = + element style:presentation-page-layout { + attribute style:name { styleName }, + attribute style:display-name { \string }?, + presentation-placeholder* + } +presentation-placeholder = + element presentation:placeholder { + attribute presentation:object { presentation-classes }, + attribute svg:x { coordinate | percent }, + attribute svg:y { coordinate | percent }, + attribute svg:width { length | percent }, + attribute svg:height { length | percent }, + empty + } +style-page-layout-properties = + element style:page-layout-properties { + style-page-layout-properties-content-strict + } +style-page-layout-properties-content-strict = + style-page-layout-properties-attlist, + style-page-layout-properties-elements +style-page-layout-properties-attlist = + attribute fo:page-width { length }? + & attribute fo:page-height { length }? + & common-num-format-attlist? + & common-num-format-prefix-suffix-attlist + & attribute style:paper-tray-name { "default" | \string }? + & attribute style:print-orientation { "portrait" | "landscape" }? + & common-horizontal-margin-attlist + & common-vertical-margin-attlist + & common-margin-attlist + & common-border-attlist + & common-border-line-width-attlist + & common-padding-attlist + & common-shadow-attlist + & common-background-color-attlist + & attribute style:register-truth-ref-style-name { styleNameRef }? + & attribute style:print { + list { + ("headers" + | "grid" + | "annotations" + | "objects" + | "charts" + | "drawings" + | "formulas" + | "zero-values")* + } + }? + & attribute style:print-page-order { "ttb" | "ltr" }? + & attribute style:first-page-number { positiveInteger | "continue" }? + & attribute style:scale-to { percent }? + & attribute style:scale-to-pages { positiveInteger }? + & attribute style:table-centering { + "horizontal" | "vertical" | "both" | "none" + }? + & attribute style:footnote-max-height { length }? + & common-writing-mode-attlist + & attribute style:layout-grid-mode { "none" | "line" | "both" }? + & attribute style:layout-grid-standard-mode { boolean }? + & attribute style:layout-grid-base-height { length }? + & attribute style:layout-grid-ruby-height { length }? + & attribute style:layout-grid-lines { positiveInteger }? + & attribute style:layout-grid-base-width { length }? + & attribute style:layout-grid-color { color }? + & attribute style:layout-grid-ruby-below { boolean }? + & attribute style:layout-grid-print { boolean }? + & attribute style:layout-grid-display { boolean }? + & attribute style:layout-grid-snap-to { boolean }? +style-page-layout-properties-elements = + style-background-image & style-columns & style-footnote-sep +style-footnote-sep = + element style:footnote-sep { style-footnote-sep-attlist, empty }? +style-footnote-sep-attlist = + attribute style:width { length }?, + attribute style:rel-width { percent }?, + attribute style:color { color }?, + attribute style:line-style { lineStyle }?, + attribute style:adjustment { "left" | "center" | "right" }?, + attribute style:distance-before-sep { length }?, + attribute style:distance-after-sep { length }? +style-header-footer-properties = + element style:header-footer-properties { + style-header-footer-properties-content-strict + } +style-header-footer-properties-content-strict = + style-header-footer-properties-attlist, + style-header-footer-properties-elements +style-header-footer-properties-attlist = + attribute svg:height { length }? + & attribute fo:min-height { length }? + & common-horizontal-margin-attlist + & common-vertical-margin-attlist + & common-margin-attlist + & common-border-attlist + & common-border-line-width-attlist + & common-padding-attlist + & common-background-color-attlist + & common-shadow-attlist + & attribute style:dynamic-spacing { boolean }? +style-header-footer-properties-elements = style-background-image +style-text-properties = + element style:text-properties { style-text-properties-content-strict } +style-text-properties-content-strict = + style-text-properties-attlist, style-text-properties-elements +style-text-properties-elements = empty +style-text-properties-attlist = + attribute fo:font-variant { fontVariant }? + & attribute fo:text-transform { + "none" | "lowercase" | "uppercase" | "capitalize" + }? + & attribute fo:color { color }? + & attribute style:use-window-font-color { boolean }? + & attribute style:text-outline { boolean }? + & attribute style:text-line-through-type { lineType }? + & attribute style:text-line-through-style { lineStyle }? + & attribute style:text-line-through-width { lineWidth }? + & attribute style:text-line-through-color { "font-color" | color }? + & attribute style:text-line-through-text { \string }? + & attribute style:text-line-through-text-style { styleNameRef }? + & attribute style:text-position { + list { (percent | "super" | "sub"), percent? } + }? + & attribute style:font-name { \string }? + & attribute style:font-name-asian { \string }? + & attribute style:font-name-complex { \string }? + & attribute fo:font-family { \string }? + & attribute style:font-family-asian { \string }? + & attribute style:font-family-complex { \string }? + & attribute style:font-family-generic { fontFamilyGeneric }? + & attribute style:font-family-generic-asian { fontFamilyGeneric }? + & attribute style:font-family-generic-complex { fontFamilyGeneric }? + & attribute style:font-style-name { \string }? + & attribute style:font-style-name-asian { \string }? + & attribute style:font-style-name-complex { \string }? + & attribute style:font-pitch { fontPitch }? + & attribute style:font-pitch-asian { fontPitch }? + & attribute style:font-pitch-complex { fontPitch }? + & attribute style:font-charset { textEncoding }? + & attribute style:font-charset-asian { textEncoding }? + & attribute style:font-charset-complex { textEncoding }? + & attribute fo:font-size { positiveLength | percent }? + & attribute style:font-size-asian { positiveLength | percent }? + & attribute style:font-size-complex { positiveLength | percent }? + & attribute style:font-size-rel { length }? + & attribute style:font-size-rel-asian { length }? + & attribute style:font-size-rel-complex { length }? + & attribute style:script-type { + "latin" | "asian" | "complex" | "ignore" + }? + & attribute fo:letter-spacing { length | "normal" }? + & attribute fo:language { languageCode }? + & attribute style:language-asian { languageCode }? + & attribute style:language-complex { languageCode }? + & attribute fo:country { countryCode }? + & attribute style:country-asian { countryCode }? + & attribute style:country-complex { countryCode }? + & attribute fo:script { scriptCode }? + & attribute style:script-asian { scriptCode }? + & attribute style:script-complex { scriptCode }? + & attribute style:rfc-language-tag { language }? + & attribute style:rfc-language-tag-asian { language }? + & attribute style:rfc-language-tag-complex { language }? + & attribute fo:font-style { fontStyle }? + & attribute style:font-style-asian { fontStyle }? + & attribute style:font-style-complex { fontStyle }? + & attribute style:font-relief { "none" | "embossed" | "engraved" }? + & attribute fo:text-shadow { shadowType }? + & attribute style:text-underline-type { lineType }? + & attribute style:text-underline-style { lineStyle }? + & attribute style:text-underline-width { lineWidth }? + & attribute style:text-underline-color { "font-color" | color }? + & attribute style:text-overline-type { lineType }? + & attribute style:text-overline-style { lineStyle }? + & attribute style:text-overline-width { lineWidth }? + & attribute style:text-overline-color { "font-color" | color }? + & attribute style:text-overline-mode { lineMode }? + & attribute fo:font-weight { fontWeight }? + & attribute style:font-weight-asian { fontWeight }? + & attribute style:font-weight-complex { fontWeight }? + & attribute style:text-underline-mode { lineMode }? + & attribute style:text-line-through-mode { lineMode }? + & attribute style:letter-kerning { boolean }? + & attribute style:text-blinking { boolean }? + & common-background-color-attlist + & attribute style:text-combine { "none" | "letters" | "lines" }? + & attribute style:text-combine-start-char { character }? + & attribute style:text-combine-end-char { character }? + & attribute style:text-emphasize { + "none" + | list { + ("none" | "accent" | "dot" | "circle" | "disc"), + ("above" | "below") + } + }? + & attribute style:text-scale { percent }? + & attribute style:text-rotation-angle { angle }? + & attribute style:text-rotation-scale { "fixed" | "line-height" }? + & attribute fo:hyphenate { boolean }? + & attribute fo:hyphenation-remain-char-count { positiveInteger }? + & attribute fo:hyphenation-push-char-count { positiveInteger }? + & (attribute text:display { "true" } + | attribute text:display { "none" } + | (attribute text:display { "condition" }, + attribute text:condition { "none" }) + | empty) +fontVariant = "normal" | "small-caps" +fontFamilyGeneric = + "roman" | "swiss" | "modern" | "decorative" | "script" | "system" +fontPitch = "fixed" | "variable" +textEncoding = xsd:string { pattern = "[A-Za-z][A-Za-z0-9._\-]*" } +fontStyle = "normal" | "italic" | "oblique" +shadowType = "none" | \string +lineType = "none" | "single" | "double" +lineStyle = + "none" + | "solid" + | "dotted" + | "dash" + | "long-dash" + | "dot-dash" + | "dot-dot-dash" + | "wave" +lineWidth = + "auto" + | "normal" + | "bold" + | "thin" + | "medium" + | "thick" + | positiveInteger + | percent + | positiveLength +fontWeight = + "normal" + | "bold" + | "100" + | "200" + | "300" + | "400" + | "500" + | "600" + | "700" + | "800" + | "900" +lineMode = "continuous" | "skip-white-space" +style-paragraph-properties = + element style:paragraph-properties { + style-paragraph-properties-content-strict + } +style-paragraph-properties-content-strict = + style-paragraph-properties-attlist, + style-paragraph-properties-elements +style-paragraph-properties-attlist = + attribute fo:line-height { "normal" | nonNegativeLength | percent }? + & attribute style:line-height-at-least { nonNegativeLength }? + & attribute style:line-spacing { length }? + & attribute style:font-independent-line-spacing { boolean }? + & common-text-align + & attribute fo:text-align-last { "start" | "center" | "justify" }? + & attribute style:justify-single-word { boolean }? + & attribute fo:keep-together { "auto" | "always" }? + & attribute fo:widows { nonNegativeInteger }? + & attribute fo:orphans { nonNegativeInteger }? + & attribute style:tab-stop-distance { nonNegativeLength }? + & attribute fo:hyphenation-keep { "auto" | "page" }? + & attribute fo:hyphenation-ladder-count { + "no-limit" | positiveInteger + }? + & attribute style:register-true { boolean }? + & common-horizontal-margin-attlist + & attribute fo:text-indent { length | percent }? + & attribute style:auto-text-indent { boolean }? + & common-vertical-margin-attlist + & common-margin-attlist + & common-break-attlist + & common-background-color-attlist + & common-border-attlist + & common-border-line-width-attlist + & attribute style:join-border { boolean }? + & common-padding-attlist + & common-shadow-attlist + & common-keep-with-next-attlist + & attribute text:number-lines { boolean }? + & attribute text:line-number { nonNegativeInteger }? + & attribute style:text-autospace { "none" | "ideograph-alpha" }? + & attribute style:punctuation-wrap { "simple" | "hanging" }? + & attribute style:line-break { "normal" | "strict" }? + & attribute style:vertical-align { + "top" | "middle" | "bottom" | "auto" | "baseline" + }? + & common-writing-mode-attlist + & attribute style:writing-mode-automatic { boolean }? + & attribute style:snap-to-layout-grid { boolean }? + & common-page-number-attlist + & common-background-transparency-attlist +common-text-align = + attribute fo:text-align { + "start" | "end" | "left" | "right" | "center" | "justify" + }? +style-paragraph-properties-elements = + style-tab-stops & style-drop-cap & style-background-image +style-tab-stops = element style:tab-stops { style-tab-stop* }? +style-tab-stop = + element style:tab-stop { style-tab-stop-attlist, empty } +style-tab-stop-attlist = + attribute style:position { length } + & (attribute style:type { "left" | "center" | "right" }? + | (attribute style:type { "char" }, + style-tab-stop-char-attlist)) + & attribute style:leader-type { lineType }? + & attribute style:leader-style { lineStyle }? + & attribute style:leader-width { lineWidth }? + & attribute style:leader-color { "font-color" | color }? + & attribute style:leader-text { character }? + & attribute style:leader-text-style { styleNameRef }? +style-tab-stop-char-attlist = attribute style:char { character } +style-drop-cap = + element style:drop-cap { style-drop-cap-attlist, empty }? +style-drop-cap-attlist = + attribute style:length { "word" | positiveInteger }? + & attribute style:lines { positiveInteger }? + & attribute style:distance { length }? + & attribute style:style-name { styleNameRef }? +common-horizontal-margin-attlist = + attribute fo:margin-left { length | percent }?, + attribute fo:margin-right { length | percent }? +common-vertical-margin-attlist = + attribute fo:margin-top { nonNegativeLength | percent }?, + attribute fo:margin-bottom { nonNegativeLength | percent }? +common-margin-attlist = + attribute fo:margin { nonNegativeLength | percent }? +common-break-attlist = + attribute fo:break-before { "auto" | "column" | "page" }?, + attribute fo:break-after { "auto" | "column" | "page" }? +common-background-color-attlist = + attribute fo:background-color { "transparent" | color }? +style-background-image = + element style:background-image { + style-background-image-attlist, + (common-draw-data-attlist | office-binary-data | empty) + }? +style-background-image-attlist = + attribute style:repeat { "no-repeat" | "repeat" | "stretch" }? + & attribute style:position { + "left" + | "center" + | "right" + | "top" + | "bottom" + | list { horiBackPos, vertBackPos } + | list { vertBackPos, horiBackPos } + }? + & attribute style:filter-name { \string }? + & attribute draw:opacity { zeroToHundredPercent }? +horiBackPos = "left" | "center" | "right" +vertBackPos = "top" | "center" | "bottom" +common-border-attlist = + attribute fo:border { \string }?, + attribute fo:border-top { \string }?, + attribute fo:border-bottom { \string }?, + attribute fo:border-left { \string }?, + attribute fo:border-right { \string }? +common-border-line-width-attlist = + attribute style:border-line-width { borderWidths }?, + attribute style:border-line-width-top { borderWidths }?, + attribute style:border-line-width-bottom { borderWidths }?, + attribute style:border-line-width-left { borderWidths }?, + attribute style:border-line-width-right { borderWidths }? +borderWidths = list { positiveLength, positiveLength, positiveLength } +common-padding-attlist = + attribute fo:padding { nonNegativeLength }?, + attribute fo:padding-top { nonNegativeLength }?, + attribute fo:padding-bottom { nonNegativeLength }?, + attribute fo:padding-left { nonNegativeLength }?, + attribute fo:padding-right { nonNegativeLength }? +common-shadow-attlist = attribute style:shadow { shadowType }? +common-keep-with-next-attlist = + attribute fo:keep-with-next { "auto" | "always" }? +common-writing-mode-attlist = + attribute style:writing-mode { + "lr-tb" | "rl-tb" | "tb-rl" | "tb-lr" | "lr" | "rl" | "tb" | "page" + }? +common-page-number-attlist = + attribute style:page-number { positiveInteger | "auto" }? +common-background-transparency-attlist = + attribute style:background-transparency { zeroToHundredPercent }? +style-ruby-properties = + element style:ruby-properties { style-ruby-properties-content-strict } +style-ruby-properties-content-strict = + style-ruby-properties-attlist, style-ruby-properties-elements +style-ruby-properties-elements = empty +style-ruby-properties-attlist = + attribute style:ruby-position { "above" | "below" }? + & attribute style:ruby-align { + "left" + | "center" + | "right" + | "distribute-letter" + | "distribute-space" + }? +style-section-properties = + element style:section-properties { + style-section-properties-content-strict + } +style-section-properties-content-strict = + style-section-properties-attlist, style-section-properties-elements +style-section-properties-attlist = + common-background-color-attlist + & common-horizontal-margin-attlist + & attribute style:protect { boolean }? + & common-editable-attlist + & attribute text:dont-balance-text-columns { boolean }? + & common-writing-mode-attlist +style-section-properties-elements = + style-background-image & style-columns & text-notes-configuration* +style-columns = + element style:columns { + style-columns-attlist, style-column-sep?, style-column* + }? +style-columns-attlist = + attribute fo:column-count { positiveInteger } + & attribute fo:column-gap { length }? +style-column = element style:column { style-column-attlist } +style-column-attlist = + attribute style:rel-width { relativeLength } + & attribute fo:start-indent { length }? + & attribute fo:end-indent { length }? + & attribute fo:space-before { length }? + & attribute fo:space-after { length }? +style-column-sep = element style:column-sep { style-column-sep-attlist } +style-column-sep-attlist = + attribute style:style { + "none" | "solid" | "dotted" | "dashed" | "dot-dashed" + }? + & attribute style:width { length } + & attribute style:height { zeroToHundredPercent }? + & attribute style:vertical-align { "top" | "middle" | "bottom" }? + & attribute style:color { color }? +style-table-properties = + element style:table-properties { + style-table-properties-content-strict + } +style-table-properties-content-strict = + style-table-properties-attlist, style-table-properties-elements +style-table-properties-attlist = + attribute style:width { positiveLength }? + & attribute style:rel-width { percent }? + & attribute table:align { "left" | "center" | "right" | "margins" }? + & common-horizontal-margin-attlist + & common-vertical-margin-attlist + & common-margin-attlist + & common-page-number-attlist + & common-break-attlist + & common-background-color-attlist + & common-shadow-attlist + & common-keep-with-next-attlist + & attribute style:may-break-between-rows { boolean }? + & attribute table:border-model { "collapsing" | "separating" }? + & common-writing-mode-attlist + & attribute table:display { boolean }? +style-table-properties-elements = style-background-image +style-table-column-properties = + element style:table-column-properties { + style-table-column-properties-content-strict + } +style-table-column-properties-content-strict = + style-table-column-properties-attlist, + style-table-column-properties-elements +style-table-column-properties-elements = empty +style-table-column-properties-attlist = + attribute style:column-width { positiveLength }? + & attribute style:rel-column-width { relativeLength }? + & attribute style:use-optimal-column-width { boolean }? + & common-break-attlist +style-table-row-properties = + element style:table-row-properties { + style-table-row-properties-content-strict + } +style-table-row-properties-content-strict = + style-table-row-properties-attlist, + style-table-row-properties-elements +style-table-row-properties-attlist = + attribute style:row-height { positiveLength }? + & attribute style:min-row-height { nonNegativeLength }? + & attribute style:use-optimal-row-height { boolean }? + & common-background-color-attlist + & common-break-attlist + & attribute fo:keep-together { "auto" | "always" }? +style-table-row-properties-elements = style-background-image +style-table-cell-properties = + element style:table-cell-properties { + style-table-cell-properties-content-strict + } +style-table-cell-properties-content-strict = + style-table-cell-properties-attlist, + style-table-cell-properties-elements +style-table-cell-properties-attlist = + attribute style:vertical-align { + "top" | "middle" | "bottom" | "automatic" + }? + & attribute style:text-align-source { "fix" | "value-type" }? + & common-style-direction-attlist + & attribute style:glyph-orientation-vertical { + "auto" | "0" | "0deg" | "0rad" | "0grad" + }? + & common-writing-mode-attlist + & common-shadow-attlist + & common-background-color-attlist + & common-border-attlist + & attribute style:diagonal-tl-br { \string }? + & attribute style:diagonal-tl-br-widths { borderWidths }? + & attribute style:diagonal-bl-tr { \string }? + & attribute style:diagonal-bl-tr-widths { borderWidths }? + & common-border-line-width-attlist + & common-padding-attlist + & attribute fo:wrap-option { "no-wrap" | "wrap" }? + & common-rotation-angle-attlist + & attribute style:rotation-align { + "none" | "bottom" | "top" | "center" + }? + & attribute style:cell-protect { + "none" + | "hidden-and-protected" + | list { ("protected" | "formula-hidden")+ } + }? + & attribute style:print-content { boolean }? + & attribute style:decimal-places { nonNegativeInteger }? + & attribute style:repeat-content { boolean }? + & attribute style:shrink-to-fit { boolean }? +common-style-direction-attlist = + attribute style:direction { "ltr" | "ttb" }? +style-table-cell-properties-elements = style-background-image +common-rotation-angle-attlist = + attribute style:rotation-angle { angle }? +style-list-level-properties = + element style:list-level-properties { + style-list-level-properties-content-strict + } +style-list-level-properties-content-strict = + style-list-level-properties-attlist, + style-list-level-properties-elements +style-list-level-properties-attlist = + common-text-align + & attribute text:space-before { length }? + & attribute text:min-label-width { nonNegativeLength }? + & attribute text:min-label-distance { nonNegativeLength }? + & attribute style:font-name { \string }? + & attribute fo:width { positiveLength }? + & attribute fo:height { positiveLength }? + & common-vertical-rel-attlist + & common-vertical-pos-attlist + & attribute text:list-level-position-and-space-mode { + "label-width-and-position" | "label-alignment" + }? +style-list-level-properties-elements = style-list-level-label-alignment +style-list-level-label-alignment = + element style:list-level-label-alignment { + style-list-level-label-alignment-attlist, empty + }? +style-list-level-label-alignment-attlist = + attribute text:label-followed-by { "listtab" | "space" | "nothing" } + & attribute text:list-tab-stop-position { length }? + & attribute fo:text-indent { length }? + & attribute fo:margin-left { length }? +style-graphic-properties-attlist = + attribute draw:stroke { "none" | "dash" | "solid" }? + & attribute draw:stroke-dash { styleNameRef }? + & attribute draw:stroke-dash-names { styleNameRefs }? + & attribute svg:stroke-width { length }? + & attribute svg:stroke-color { color }? + & attribute draw:marker-start { styleNameRef }? + & attribute draw:marker-end { styleNameRef }? + & attribute draw:marker-start-width { length }? + & attribute draw:marker-end-width { length }? + & attribute draw:marker-start-center { boolean }? + & attribute draw:marker-end-center { boolean }? + & attribute svg:stroke-opacity { + xsd:double { minInclusive = "0" maxInclusive = "1" } + | zeroToHundredPercent + }? + & attribute draw:stroke-linejoin { + "miter" | "round" | "bevel" | "middle" | "none" + }? + & attribute svg:stroke-linecap { "butt" | "square" | "round" }? + & attribute draw:symbol-color { color }? + & attribute text:animation { + "none" | "scroll" | "alternate" | "slide" + }? + & attribute text:animation-direction { + "left" | "right" | "up" | "down" + }? + & attribute text:animation-start-inside { boolean }? + & attribute text:animation-stop-inside { boolean }? + & attribute text:animation-repeat { nonNegativeInteger }? + & attribute text:animation-delay { duration }? + & attribute text:animation-steps { length }? + & attribute draw:auto-grow-width { boolean }? + & attribute draw:auto-grow-height { boolean }? + & attribute draw:fit-to-size { boolean }? + & attribute draw:fit-to-contour { boolean }? + & attribute draw:textarea-vertical-align { + "top" | "middle" | "bottom" | "justify" + }? + & attribute draw:textarea-horizontal-align { + "left" | "center" | "right" | "justify" + }? + & attribute fo:wrap-option { "no-wrap" | "wrap" }? + & attribute style:shrink-to-fit { boolean }? + & attribute draw:color-mode { + "greyscale" | "mono" | "watermark" | "standard" + }? + & attribute draw:color-inversion { boolean }? + & attribute draw:luminance { zeroToHundredPercent }? + & attribute draw:contrast { percent }? + & attribute draw:gamma { percent }? + & attribute draw:red { signedZeroToHundredPercent }? + & attribute draw:green { signedZeroToHundredPercent }? + & attribute draw:blue { signedZeroToHundredPercent }? + & attribute draw:image-opacity { zeroToHundredPercent }? + & attribute draw:shadow { "visible" | "hidden" }? + & attribute draw:shadow-offset-x { length }? + & attribute draw:shadow-offset-y { length }? + & attribute draw:shadow-color { color }? + & attribute draw:shadow-opacity { zeroToHundredPercent }? + & attribute draw:start-line-spacing-horizontal { distance }? + & attribute draw:start-line-spacing-vertical { distance }? + & attribute draw:end-line-spacing-horizontal { distance }? + & attribute draw:end-line-spacing-vertical { distance }? + & attribute draw:line-distance { distance }? + & attribute draw:guide-overhang { length }? + & attribute draw:guide-distance { distance }? + & attribute draw:start-guide { length }? + & attribute draw:end-guide { length }? + & attribute draw:placing { "below" | "above" }? + & attribute draw:parallel { boolean }? + & attribute draw:measure-align { + "automatic" | "left-outside" | "inside" | "right-outside" + }? + & attribute draw:measure-vertical-align { + "automatic" | "above" | "below" | "center" + }? + & attribute draw:unit { + "automatic" + | "mm" + | "cm" + | "m" + | "km" + | "pt" + | "pc" + | "inch" + | "ft" + | "mi" + }? + & attribute draw:show-unit { boolean }? + & attribute draw:decimal-places { nonNegativeInteger }? + & attribute draw:caption-type { + "straight-line" | "angled-line" | "angled-connector-line" + }? + & attribute draw:caption-angle-type { "fixed" | "free" }? + & attribute draw:caption-angle { angle }? + & attribute draw:caption-gap { distance }? + & attribute draw:caption-escape-direction { + "horizontal" | "vertical" | "auto" + }? + & attribute draw:caption-escape { length | percent }? + & attribute draw:caption-line-length { length }? + & attribute draw:caption-fit-line-length { boolean }? + & attribute dr3d:horizontal-segments { nonNegativeInteger }? + & attribute dr3d:vertical-segments { nonNegativeInteger }? + & attribute dr3d:edge-rounding { percent }? + & attribute dr3d:edge-rounding-mode { "correct" | "attractive" }? + & attribute dr3d:back-scale { percent }? + & attribute dr3d:depth { length }? + & attribute dr3d:backface-culling { "enabled" | "disabled" }? + & attribute dr3d:end-angle { angle }? + & attribute dr3d:close-front { boolean }? + & attribute dr3d:close-back { boolean }? + & attribute dr3d:lighting-mode { "standard" | "double-sided" }? + & attribute dr3d:normals-kind { "object" | "flat" | "sphere" }? + & attribute dr3d:normals-direction { "normal" | "inverse" }? + & attribute dr3d:texture-generation-mode-x { + "object" | "parallel" | "sphere" + }? + & attribute dr3d:texture-generation-mode-y { + "object" | "parallel" | "sphere" + }? + & attribute dr3d:texture-kind { "luminance" | "intensity" | "color" }? + & attribute dr3d:texture-filter { "enabled" | "disabled" }? + & attribute dr3d:texture-mode { "replace" | "modulate" | "blend" }? + & attribute dr3d:ambient-color { color }? + & attribute dr3d:emissive-color { color }? + & attribute dr3d:specular-color { color }? + & attribute dr3d:diffuse-color { color }? + & attribute dr3d:shininess { percent }? + & attribute dr3d:shadow { "visible" | "hidden" }? + & common-draw-rel-size-attlist + & attribute fo:min-width { length | percent }? + & attribute fo:min-height { length | percent }? + & attribute fo:max-height { length | percent }? + & attribute fo:max-width { length | percent }? + & common-horizontal-margin-attlist + & common-vertical-margin-attlist + & common-margin-attlist + & attribute style:print-content { boolean }? + & attribute style:protect { + "none" + | list { ("content" | "position" | "size")+ } + }? + & attribute style:horizontal-pos { + "left" + | "center" + | "right" + | "from-left" + | "inside" + | "outside" + | "from-inside" + }? + & attribute svg:x { coordinate }? + & attribute style:horizontal-rel { + "page" + | "page-content" + | "page-start-margin" + | "page-end-margin" + | "frame" + | "frame-content" + | "frame-start-margin" + | "frame-end-margin" + | "paragraph" + | "paragraph-content" + | "paragraph-start-margin" + | "paragraph-end-margin" + | "char" + }? + & common-vertical-pos-attlist + & common-vertical-rel-attlist + & common-text-anchor-attlist + & common-border-attlist + & common-border-line-width-attlist + & common-padding-attlist + & common-shadow-attlist + & common-background-color-attlist + & common-background-transparency-attlist + & common-editable-attlist + & attribute style:wrap { + "none" + | "left" + | "right" + | "parallel" + | "dynamic" + | "run-through" + | "biggest" + }? + & attribute style:wrap-dynamic-threshold { nonNegativeLength }? + & attribute style:number-wrapped-paragraphs { + "no-limit" | positiveInteger + }? + & attribute style:wrap-contour { boolean }? + & attribute style:wrap-contour-mode { "full" | "outside" }? + & attribute style:run-through { "foreground" | "background" }? + & attribute style:flow-with-text { boolean }? + & attribute style:overflow-behavior { + "clip" | "auto-create-new-frame" + }? + & attribute style:mirror { + "none" + | "vertical" + | horizontal-mirror + | list { "vertical", horizontal-mirror } + | list { horizontal-mirror, "vertical" } + }? + & attribute fo:clip { "auto" | clipShape }? + & attribute draw:wrap-influence-on-position { + "iterative" | "once-concurrent" | "once-successive" + }? + & common-writing-mode-attlist + & attribute draw:frame-display-scrollbar { boolean }? + & attribute draw:frame-display-border { boolean }? + & attribute draw:frame-margin-horizontal { nonNegativePixelLength }? + & attribute draw:frame-margin-vertical { nonNegativePixelLength }? + & attribute draw:visible-area-left { nonNegativeLength }? + & attribute draw:visible-area-top { nonNegativeLength }? + & attribute draw:visible-area-width { positiveLength }? + & attribute draw:visible-area-height { positiveLength }? + & attribute draw:draw-aspect { + "content" | "thumbnail" | "icon" | "print-view" + }? + & attribute draw:ole-draw-aspect { nonNegativeInteger }? +style-graphic-fill-properties-attlist = + attribute draw:fill { + "none" | "solid" | "bitmap" | "gradient" | "hatch" + }? + & attribute draw:fill-color { color }? + & attribute draw:secondary-fill-color { color }? + & attribute draw:fill-gradient-name { styleNameRef }? + & attribute draw:gradient-step-count { nonNegativeInteger }? + & attribute draw:fill-hatch-name { styleNameRef }? + & attribute draw:fill-hatch-solid { boolean }? + & attribute draw:fill-image-name { styleNameRef }? + & attribute style:repeat { "no-repeat" | "repeat" | "stretch" }? + & attribute draw:fill-image-width { length | percent }? + & attribute draw:fill-image-height { length | percent }? + & attribute draw:fill-image-ref-point-x { percent }? + & attribute draw:fill-image-ref-point-y { percent }? + & attribute draw:fill-image-ref-point { + "top-left" + | "top" + | "top-right" + | "left" + | "center" + | "right" + | "bottom-left" + | "bottom" + | "bottom-right" + }? + & attribute draw:tile-repeat-offset { + list { zeroToHundredPercent, ("horizontal" | "vertical") } + }? + & attribute draw:opacity { zeroToHundredPercent }? + & attribute draw:opacity-name { styleNameRef }? + & attribute svg:fill-rule { "nonzero" | "evenodd" }? +style-graphic-properties-elements = + text-list-style? & style-background-image & style-columns +common-vertical-pos-attlist = + attribute style:vertical-pos { + "top" | "middle" | "bottom" | "from-top" | "below" + }?, + attribute svg:y { coordinate }? +common-vertical-rel-attlist = + attribute style:vertical-rel { + "page" + | "page-content" + | "frame" + | "frame-content" + | "paragraph" + | "paragraph-content" + | "char" + | "line" + | "baseline" + | "text" + }? +common-editable-attlist = attribute style:editable { boolean }? +horizontal-mirror = + "horizontal" | "horizontal-on-odd" | "horizontal-on-even" +clipShape = + xsd:string { + pattern = + "rect\([ ]*((-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)))|(auto))([ ]*,[ ]*((-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))))|(auto)){3}[ ]*\)" + } +nonNegativePixelLength = + xsd:string { pattern = "([0-9]+(\.[0-9]*)?|\.[0-9]+)(px)" } +style-chart-properties = + element style:chart-properties { + style-chart-properties-content-strict + } +style-chart-properties-content-strict = + style-chart-properties-attlist, style-chart-properties-elements +style-chart-properties-elements = empty +style-chart-properties-attlist = + attribute chart:scale-text { boolean }? + & attribute chart:three-dimensional { boolean }? + & attribute chart:deep { boolean }? + & attribute chart:right-angled-axes { boolean }? + & (attribute chart:symbol-type { "none" } + | attribute chart:symbol-type { "automatic" } + | (attribute chart:symbol-type { "named-symbol" }, + attribute chart:symbol-name { + "square" + | "diamond" + | "arrow-down" + | "arrow-up" + | "arrow-right" + | "arrow-left" + | "bow-tie" + | "hourglass" + | "circle" + | "star" + | "x" + | "plus" + | "asterisk" + | "horizontal-bar" + | "vertical-bar" + }) + | (attribute chart:symbol-type { "image" }, + element chart:symbol-image { + attribute xlink:href { anyIRI } + }) + | empty) + & attribute chart:symbol-width { nonNegativeLength }? + & attribute chart:symbol-height { nonNegativeLength }? + & attribute chart:sort-by-x-values { boolean }? + & attribute chart:vertical { boolean }? + & attribute chart:connect-bars { boolean }? + & attribute chart:gap-width { integer }? + & attribute chart:overlap { integer }? + & attribute chart:group-bars-per-axis { boolean }? + & attribute chart:japanese-candle-stick { boolean }? + & attribute chart:interpolation { + "none" | "cubic-spline" | "b-spline" + }? + & attribute chart:spline-order { positiveInteger }? + & attribute chart:spline-resolution { positiveInteger }? + & attribute chart:pie-offset { nonNegativeInteger }? + & attribute chart:angle-offset { angle }? + & attribute chart:hole-size { percent }? + & attribute chart:lines { boolean }? + & attribute chart:solid-type { + "cuboid" | "cylinder" | "cone" | "pyramid" + }? + & attribute chart:stacked { boolean }? + & attribute chart:percentage { boolean }? + & attribute chart:treat-empty-cells { + "use-zero" | "leave-gap" | "ignore" + }? + & attribute chart:link-data-style-to-source { boolean }? + & attribute chart:logarithmic { boolean }? + & attribute chart:maximum { double }? + & attribute chart:minimum { double }? + & attribute chart:origin { double }? + & attribute chart:interval-major { double }? + & attribute chart:interval-minor-divisor { positiveInteger }? + & attribute chart:tick-marks-major-inner { boolean }? + & attribute chart:tick-marks-major-outer { boolean }? + & attribute chart:tick-marks-minor-inner { boolean }? + & attribute chart:tick-marks-minor-outer { boolean }? + & attribute chart:reverse-direction { boolean }? + & attribute chart:display-label { boolean }? + & attribute chart:text-overlap { boolean }? + & attribute text:line-break { boolean }? + & attribute chart:label-arrangement { + "side-by-side" | "stagger-even" | "stagger-odd" + }? + & common-style-direction-attlist + & common-rotation-angle-attlist + & attribute chart:data-label-number { + "none" | "value" | "percentage" | "value-and-percentage" + }? + & attribute chart:data-label-text { boolean }? + & attribute chart:data-label-symbol { boolean }? + & element chart:label-separator { text-p }? + & attribute chart:label-position { labelPositions }? + & attribute chart:label-position-negative { labelPositions }? + & attribute chart:visible { boolean }? + & attribute chart:auto-position { boolean }? + & attribute chart:auto-size { boolean }? + & attribute chart:mean-value { boolean }? + & attribute chart:error-category { + "none" + | "variance" + | "standard-deviation" + | "percentage" + | "error-margin" + | "constant" + | "standard-error" + | "cell-range" + }? + & attribute chart:error-percentage { double }? + & attribute chart:error-margin { double }? + & attribute chart:error-lower-limit { double }? + & attribute chart:error-upper-limit { double }? + & attribute chart:error-upper-indicator { boolean }? + & attribute chart:error-lower-indicator { boolean }? + & attribute chart:error-lower-range { cellRangeAddressList }? + & attribute chart:error-upper-range { cellRangeAddressList }? + & attribute chart:series-source { "columns" | "rows" }? + & attribute chart:regression-type { + "none" | "linear" | "logarithmic" | "exponential" | "power" + }? + & attribute chart:axis-position { "start" | "end" | double }? + & attribute chart:axis-label-position { + "near-axis" + | "near-axis-other-side" + | "outside-start" + | "outside-end" + }? + & attribute chart:tick-mark-position { + "at-labels" | "at-axis" | "at-labels-and-axis" + }? + & attribute chart:include-hidden-cells { boolean }? +labelPositions = + "avoid-overlap" + | "center" + | "top" + | "top-right" + | "right" + | "bottom-right" + | "bottom" + | "bottom-left" + | "left" + | "top-left" + | "inside" + | "outside" + | "near-origin" +style-drawing-page-properties-attlist = + attribute presentation:transition-type { + "manual" | "automatic" | "semi-automatic" + }? + & attribute presentation:transition-style { + "none" + | "fade-from-left" + | "fade-from-top" + | "fade-from-right" + | "fade-from-bottom" + | "fade-from-upperleft" + | "fade-from-upperright" + | "fade-from-lowerleft" + | "fade-from-lowerright" + | "move-from-left" + | "move-from-top" + | "move-from-right" + | "move-from-bottom" + | "move-from-upperleft" + | "move-from-upperright" + | "move-from-lowerleft" + | "move-from-lowerright" + | "uncover-to-left" + | "uncover-to-top" + | "uncover-to-right" + | "uncover-to-bottom" + | "uncover-to-upperleft" + | "uncover-to-upperright" + | "uncover-to-lowerleft" + | "uncover-to-lowerright" + | "fade-to-center" + | "fade-from-center" + | "vertical-stripes" + | "horizontal-stripes" + | "clockwise" + | "counterclockwise" + | "open-vertical" + | "open-horizontal" + | "close-vertical" + | "close-horizontal" + | "wavyline-from-left" + | "wavyline-from-top" + | "wavyline-from-right" + | "wavyline-from-bottom" + | "spiralin-left" + | "spiralin-right" + | "spiralout-left" + | "spiralout-right" + | "roll-from-top" + | "roll-from-left" + | "roll-from-right" + | "roll-from-bottom" + | "stretch-from-left" + | "stretch-from-top" + | "stretch-from-right" + | "stretch-from-bottom" + | "vertical-lines" + | "horizontal-lines" + | "dissolve" + | "random" + | "vertical-checkerboard" + | "horizontal-checkerboard" + | "interlocking-horizontal-left" + | "interlocking-horizontal-right" + | "interlocking-vertical-top" + | "interlocking-vertical-bottom" + | "fly-away" + | "open" + | "close" + | "melt" + }? + & attribute presentation:transition-speed { presentationSpeeds }? + & attribute smil:type { \string }? + & attribute smil:subtype { \string }? + & attribute smil:direction { "forward" | "reverse" }? + & attribute smil:fadeColor { color }? + & attribute presentation:duration { duration }? + & attribute presentation:visibility { "visible" | "hidden" }? + & attribute draw:background-size { "full" | "border" }? + & attribute presentation:background-objects-visible { boolean }? + & attribute presentation:background-visible { boolean }? + & attribute presentation:display-header { boolean }? + & attribute presentation:display-footer { boolean }? + & attribute presentation:display-page-number { boolean }? + & attribute presentation:display-date-time { boolean }? +style-drawing-page-properties-elements = presentation-sound? +\string = xsd:string +date = xsd:date +time = xsd:time +dateTime = xsd:dateTime +duration = xsd:duration +integer = xsd:integer +nonNegativeInteger = xsd:nonNegativeInteger +positiveInteger = xsd:positiveInteger +double = xsd:double +anyURI = xsd:anyURI +base64Binary = xsd:base64Binary +ID = xsd:ID +IDREF = xsd:IDREF +IDREFS = xsd:IDREFS +NCName = xsd:NCName +boolean = "true" | "false" +dateOrDateTime = xsd:date | xsd:dateTime +timeOrDateTime = xsd:time | xsd:dateTime +language = xsd:language +countryCode = xsd:token { pattern = "[A-Za-z0-9]{1,8}" } +languageCode = xsd:token { pattern = "[A-Za-z]{1,8}" } +scriptCode = xsd:token { pattern = "[A-Za-z0-9]{1,8}" } +character = xsd:string { length = "1" } +length = + xsd:string { + pattern = + "-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px))" + } +nonNegativeLength = + xsd:string { + pattern = + "([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px))" + } +positiveLength = + xsd:string { + pattern = + "([0-9]*[1-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px))" + } +percent = xsd:string { pattern = "-?([0-9]+(\.[0-9]*)?|\.[0-9]+)%" } +zeroToHundredPercent = + xsd:string { + pattern = "([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)%" + } +signedZeroToHundredPercent = + xsd:string { + pattern = "-?([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)%" + } +relativeLength = xsd:string { pattern = "[0-9]+\*" } +coordinate = length +distance = length +color = xsd:string { pattern = "#[0-9a-fA-F]{6}" } +angle = xsd:string +CURIE = + xsd:string { pattern = "(([\i-[:]][\c-[:]]*)?:)?.+" minLength = "1" } +CURIEs = list { CURIE+ } +SafeCURIE = + xsd:string { + pattern = "\[(([\i-[:]][\c-[:]]*)?:)?.+\]" + minLength = "3" + } +URIorSafeCURIE = anyURI | SafeCURIE +styleName = xsd:NCName +styleNameRef = xsd:NCName | empty +styleNameRefs = list { xsd:NCName* } +variableName = xsd:string +targetFrameName = "_self" | "_blank" | "_parent" | "_top" | \string +valueType = + "float" + | "time" + | "date" + | "percentage" + | "currency" + | "boolean" + | "string" +points = + xsd:string { pattern = "-?[0-9]+,-?[0-9]+([ ]+-?[0-9]+,-?[0-9]+)*" } +pathData = xsd:string +vector3D = + xsd:string { + pattern = + "\([ ]*-?([0-9]+(\.[0-9]*)?|\.[0-9]+)([ ]+-?([0-9]+(\.[0-9]*)?|\.[0-9]+)){2}[ ]*\)" + } +namespacedToken = xsd:QName { pattern = "[^:]+:[^:]+" } +anyIRI = + xsd:anyURI + >> dc:description [ + "An IRI-reference as defined in [RFC3987]. See ODF 1.2 Part 1 section 18.3." + ] +anyAttListOrElements = + attribute * { text }*, + anyElements +anyElements = + element * { + mixed { anyAttListOrElements } + }* diff --git a/etc/schema/schemas.xml b/etc/schema/schemas.xml index d217d6edfb3..97b29617c79 100644 --- a/etc/schema/schemas.xml +++ b/etc/schema/schemas.xml @@ -55,4 +55,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. --> <typeId id="XHTML" uri="xhtml.rnc"/> <typeId id="DocBook" uri="docbook.rnc"/> <typeId id="RDF" uri="rdfxml.rnc"/> + + <documentElement prefix="office" typeId="OpenDocument"/> + <documentElement prefix="manifest" localName="manifest" typeId="OpenDocument Manifest"/> + <typeId id="OpenDocument" uri="od-schema-v1.2-os.rnc"/> + <typeId id="OpenDocument Manifest" uri="od-manifest-schema-v1.2-os.rnc"/> + </locatingRules> diff --git a/etc/themes/leuven-theme.el b/etc/themes/leuven-theme.el index a633962fe79..c15bd41bf81 100644 --- a/etc/themes/leuven-theme.el +++ b/etc/themes/leuven-theme.el @@ -461,7 +461,7 @@ Semantic, and Ansi-Color faces are included -- and much more...") `(info-xref ((,class (:underline t :foreground "#006DAF")))) ; unvisited cross-references `(info-xref-visited ((,class (:underline t :foreground "magenta4")))) ; previously visited cross-references `(light-symbol-face ((,class (:background "#FFFFA0")))) - `(linum ((,class (:foreground "#9A9A9A" :background "#EDEDED")))) + `(linum ((,class (:inherit (default shadow) :foreground "#9A9A9A" :background "#EDEDED")))) `(log-view-file ((,class (:foreground "#0000CC" :background "#EAF2F5")))) `(lui-button-face ((,class ,link))) `(lui-highlight-face ((,class (:box '(:line-width 1 :color "#CC0000") :foreground "#CC0000" :background "#FFFF88")))) ; my nickname diff --git a/etc/themes/manoj-dark-theme.el b/etc/themes/manoj-dark-theme.el index 87a2af74f10..bbfeb83d53e 100644 --- a/etc/themes/manoj-dark-theme.el +++ b/etc/themes/manoj-dark-theme.el @@ -602,6 +602,18 @@ jarring angry fruit salad look to reduce eye fatigue.") '(paren-no-match-face ((t (:bold t :background "white" :foreground "red")))) '(query-replace ((t (:foreground "brown4" :background "palevioletred2")))) '(region ((t (:background "blue3")))) + + `(realgud-overlay-arrow1 ((t (:foreground "medium sea green")))) + `(realgud-overlay-arrow2 ((t (:foreground "white")))) + `(realgud-overlay-arrow3 ((t (:foreground "indian red")))) + `(realgud-bp-enabled-face ((t (:inherit error)))) + `(realgud-bp-disabled-face ((t (:underline t)))) + `(realgud-bp-line-enabled-face ((t (:foreground "orange")))) + `(realgud-bp-line-disabled-face ((t (:underline t)))) + `(realgud-file-name ((t (:foreground "cyan")))) + `(realgud-line-number ((t (:foreground "yellow")))) + `(realgud-backtrace-number ((t (:foreground "yellow" :weight bold)))))) + '(scroll-bar ((t (:background "grey75" :foreground "WhiteSmoke")))) '(secondary-selection ((t (:background "SkyBlue4")))) '(semantic-dirty-token-face ((t (:background "lightyellow")))) diff --git a/etc/themes/tsdh-dark-theme.el b/etc/themes/tsdh-dark-theme.el index cd94a71bd38..4f48854d449 100644 --- a/etc/themes/tsdh-dark-theme.el +++ b/etc/themes/tsdh-dark-theme.el @@ -118,6 +118,16 @@ '(outline-6 ((t (:foreground "light salmon" :weight bold)))) '(outline-7 ((t (:foreground "pale goldenrod" :weight bold)))) '(outline-8 ((t (:foreground "OliveDrab1" :weight bold)))) + `(realgud-overlay-arrow1 ((t (:foreground "medium spring green")))) + `(realgud-overlay-arrow2 ((t (:foreground "OliveDrab1")))) + `(realgud-overlay-arrow3 ((t (:foreground "light salmon")))) + `(realgud-bp-enabled-face ((t (:inherit error)))) + `(realgud-bp-disabled-face ((t (:foreground "gray35")))) + `(realgud-bp-line-enabled-face ((t (:foreground "light salmon")))) + `(realgud-bp-line-disabled-face ((t (:foreground "medium spring green")))) + `(realgud-file-name ((t (:foreground "dark khaki")))) + `(realgud-line-number ((t (:foreground "cyan3")))) + `(realgud-backtrace-number ((t (:foreground "cyan3" :weight bold)))))) '(rcirc-my-nick ((t (:foreground "SpringGreen1" :weight bold))) t) '(rcirc-other-nick ((t (:foreground "dodger blue"))) t) '(rcirc-track-keyword ((t (:foreground "DodgerBlue" :weight bold))) t) diff --git a/etc/themes/wheatgrass-theme.el b/etc/themes/wheatgrass-theme.el index 291e839d3bc..9ec532d9baa 100644 --- a/etc/themes/wheatgrass-theme.el +++ b/etc/themes/wheatgrass-theme.el @@ -68,7 +68,18 @@ of green, brown, and blue.") `(message-header-subject ((,class (:foreground "pale turquoise")))) `(message-header-to ((,class (:foreground "pale green")))) `(message-cited-text ((,class (:foreground "SpringGreen3")))) - `(message-separator ((,class (:foreground "deep sky blue")))))) + `(message-separator ((,class (:foreground "deep sky blue")))) + ;; Realgud faces + `(realgud-overlay-arrow1 ((,class (:foreground "SpringGreen3")))) + `(realgud-overlay-arrow2 ((,class (:foreground "white")))) + `(realgud-overlay-arrow3 ((,class (:foreground "wheat")))) + `(realgud-bp-enabled-face ((,class (:inherit error)))) + `(realgud-bp-disabled-face ((,class (:foreground "dark slate gray")))) + `(realgud-bp-line-enabled-face ((,class (:underline "SpringGreen3")))) + `(realgud-bp-line-disabled-face ((,class (:underline "salmon")))) + `(realgud-file-name ((,class (:foreground "dark khaki")))) + `(realgud-line-number ((,class (:foreground "dark cyan")))) + `(realgud-backtrace-number ((,class (:foreground "dark cyan" :weight bold)))))) (provide-theme 'wheatgrass) diff --git a/etc/themes/whiteboard-theme.el b/etc/themes/whiteboard-theme.el index 5e2f466acc4..0192289a5bc 100644 --- a/etc/themes/whiteboard-theme.el +++ b/etc/themes/whiteboard-theme.el @@ -83,6 +83,16 @@ `(outline-4 ((,class (:foreground "RoyalBlue")))) `(outline-5 ((,class (:foreground "DeepSkyBlue")))) `(primary-selection ((,class (:background "blue3")))) + `(realgud-overlay-arrow1 ((,class (:foreground "DarkGreen")))) + `(realgud-overlay-arrow2 ((,class (:foreground "DarkOliveGreen")))) + `(realgud-overlay-arrow3 ((,class (:foreground "gray60")))) + `(realgud-bp-disabled-face ((,class (:foreground "gray60")))) + `(realgud-bp-line-enabled-face ((,class (:underline "red")))) + `(realgud-bp-line-disabled-face ((,class (:underline "gray60")))) + `(realgud-file-name ((,class :foreground "DarkGreen"))) + `(realgud-line-number ((,class :foreground "blue3"))) + `(realgud-backtrace-number ((,class :foreground "blue3" :weight bold))) + `(region ((,class (:background "SkyBlue1")))) `(show-paren-match-face ((,class (:background "dodgerblue1" :foreground "white")))) `(show-paren-mismatch-face ((,class (:background "red1" :foreground "white")))) diff --git a/etc/tutorials/TUTORIAL b/etc/tutorials/TUTORIAL index 40e1cf8480d..3419c63c1fb 100644 --- a/etc/tutorials/TUTORIAL +++ b/etc/tutorials/TUTORIAL @@ -12,6 +12,7 @@ write that in full each time, we'll use the following abbreviations: Important note: to end the Emacs session, type C-x C-c. (Two characters.) To quit a partially entered command, type C-g. +To stop the tutorial, type C-x k, then <Return> at the prompt. The characters ">>" at the left margin indicate directions for you to try using a command. For instance: <<Blank lines inserted around following line by help-with-tutorial>> diff --git a/etc/tutorials/TUTORIAL.he b/etc/tutorials/TUTORIAL.he index fefc780d644..49997164630 100644 --- a/etc/tutorials/TUTORIAL.he +++ b/etc/tutorials/TUTORIAL.he @@ -12,6 +12,7 @@ הערה חשובה: כדי לצאת מ־Emacs יש להקיש C-x C-c (שני תוים, משמאל לימין). כדי להפסיק פקודה באמצע ההקשה, יש להקיש C-g. +כדי להפסיק שיעור זה, יש להקיש C-x k, ואז <Return> בתשובה לשאלה. המחרוזת ">>" בקצה הימני מסמנת הוראות עבורכם כדי לנסות להשתמש בפקודה כלשהי. לדוגמה: <<שורות ריקות תתווספנה סביב השורה הבאה ע״י help-with-tutorial>> diff --git a/etc/tutorials/TUTORIAL.it b/etc/tutorials/TUTORIAL.it index 4e010cb9fbe..0f5039de24b 100644 --- a/etc/tutorials/TUTORIAL.it +++ b/etc/tutorials/TUTORIAL.it @@ -15,9 +15,11 @@ le seguenti abbreviazioni: <ESC> per indicare il tasto ESC. Nota importante: per chiudere una sessione di lavoro di Emacs usa C-x -C-c (due caratteri). Per annullare un comando inserito parzialmente -usa C-g. I caratteri “>>” posti al margine sinistro indicano le -direttive per provare a usare un comando. Per esempio: +C-c (due caratteri). +Per annullare un comando inserito parzialmente usa C-g. +Per terminare l'esercitazione, usa C-x k quindi <Invio> al prompt. +I caratteri “>>” posti al margine sinistro indicano le direttive per +provare a usare un comando. Per esempio: <<Blank lines inserted here by startup of help-with-tutorial>> [Spaziatura inserita a scopo didattico. Il testo continua sotto] >> Adesso premi C-v (vedi schermata successiva) per spostarti alla diff --git a/etc/tutorials/TUTORIAL.sv b/etc/tutorials/TUTORIAL.sv index 4001748376f..30608c56883 100644 --- a/etc/tutorials/TUTORIAL.sv +++ b/etc/tutorials/TUTORIAL.sv @@ -12,6 +12,8 @@ ALT eller EDIT). Vi använder här följande förkortningar: Viktigt: För att avsluta Emacs trycker du C-x C-c (två tecken). För att avsluta kommandon som inte skrivits in fullt, tryck C-g. +För att avsluta användarhandledningen, tryck C-x k och sedan <Return> +vid prompten. Tecknen ">>" i vänstermarginalen anger att du kan prova ett kommando. Till exempel: <<Tomma rader sätts in runt nästa rad när help-with-tutorial aktiveras>> @@ -234,6 +236,7 @@ texten. Om din mus har ett rullningshjul kan även den användas för att rulla texten. + * OM EMACS SLUTAR SVARA ----------------------- @@ -290,8 +293,6 @@ tas bort. >> Slå C-x 1 och se hur dokumentationsfönstret nu försvinner. -Kommandot skiljer sig lite från andra kommandon du har lärt dig -eftersom det består av två tecken. Det startar med tecknet KONTROLL-x. Det finns många kommandon som startar med KONTROLL-x och många av dem har med filer, skärmbilder och liknande saker att göra. Dessa kommandon är två, tre eller fyra tecken långa. @@ -342,6 +343,19 @@ skärmbredd, så kommer den att visas med ett fortsättningstecken. >> Tryck <Return> för att sätta in radbrytningen du tog bort. +<Return>-tangenten är speciell. Genom att trycka på den kan mer göras +än att bara sätta in en ny rad. Beroende på texten runt om kring kan +blanktecken matas in så att när du börjar skriva på den nya raden är +den indragen som raden ovanför. Vi kallar detta beteende (när ett +tryck på en tangent leder till mer än att det aktuella tecknet matas +in) "elektriskt". + +>> Här är ett exempel på när <Return> är elektrisk. + Tryck <Return> vid slutet på denna rad. + +Du bör se att efter att den nya raden satts in, sätter Emacs in +blanktecken så att markören flyttas fram under "T" i "Tryck". + Tänk på att de flesta Emacs-kommandon kan ta numeriska argument. Detta gäller också texttecken. Genom att repetera ett texttecken kommer det skrivas flera gånger. @@ -405,13 +419,11 @@ raderar så många rader OCH innehållet i dem. Detta är alltså inte bara en repetition av kommandot. C-u 2 C-k raderar två rader samt de tomma raderna, medan C-k två gånger inte kommer att göra det. -Att sätta in borttagen text kallas att "återhämta" den (yanking). -(Tänk på det som att du rycker, eller drar, tillbaka någon text som -tagits bort.) Du kan antingen hämta tillbaka borttagen text till samma -plats som där den blev borttagen, eller så kan du sätta in den på en -annan plats i texten du redigerar eller till och med i en helt annan -fil. Du kan också hämta tillbaka samma text flera gånger så att du får -flera kopior av den. Några andra textredigerare kallar "ta bort" och +Du kan antingen hämta tillbaka borttagen text till samma plats som där +den blev borttagen, eller så kan du sätta in den på en annan plats i +texten du redigerar eller till och med i en helt annan fil. Du kan +också hämta tillbaka samma text flera gånger så att du får flera +kopior av den. Några andra textredigerare kallar "ta bort" och "återhämta" att "klippa ut" respektive "klistra in" (Se ordlistan i Emacs-manualen) @@ -499,7 +511,7 @@ med när du sparar filen kommer Emacs att behålla originalet under ett nytt namn, som backup, ifall du senare ångrar alltihop. Om du tittar nästan längst ner på skärmbilden så kommer du se en rad -som börjar med minustecken, och som startar med "--:-- TUTORIAL.sv" +som börjar med minustecken, och som startar med "-:--- TUTORIAL.sv" eller något snarlikt. Denna del av skärmbilden visar normalt namnet på filen du besöker. Just nu besöker du din personlig kopia av vägledningen till Emacs, vilken heter "TUTORIAL.sv". Vilken fil du än @@ -592,8 +604,7 @@ Mestadels är buffertens namn densamma som filens namn (utan katalogdel.) Det är dock inte alltid så. Bufferlistan du skapar med C-x C-b visar alltid namnen på varje buffert. -All text du ser i ett Emacsfönster är alltid del av någon buffert. En -del buffertar är inte knutna till någon fil, till exempel bufferten +En del buffertar är inte knutna till någon fil, till exempel bufferten "*Buffer List*". Det är den buffert som innehåller buffertlistan som skapades med C-x C-b. Bufferten "*Messages*" motsvarar inte heller någon fil. Den innehåller de meddelanden som visas på den nedersta @@ -685,9 +696,9 @@ avsluta bägge argumenten med <Return>. >> Flytta markören till den blanka raden två rader under denna rad. Skriv M-x repl s<Return>förändrad<Return>ändrad<Return>. - Lägg märke till hur den här raden har blivit förändrad. Du har - ersatt ordet f-ö-r-ä-n-d-r-a-d med "ändrad" på alla platser där - ordet förekom, från markören och nedåt. + Lägg märke till hur den här raden har blivit uppdaterad. Du har + ersatt ordet "förändrad" med "ändrad" på alla platser där ordet + förekom, från markören och nedåt. * SPARAUTOMATIK @@ -703,8 +714,8 @@ sätt kommer Emacs radera autosparfilen. Om maskinen kraschar kan du återfå dina automatiskt sparade ändringar genom att finna filen på vanlig sätt (filen du redigerade, inte -autosparfilen) och skriva M-x recover-file<Return>. När Emacs vill ha -bekräftelse svarar du yes<Return> för att återställa filen. +autosparfilen) och skriva M-x recover-this-file <Return>. När Emacs +vill ha bekräftelse svarar du yes<Return> för att återställa filen. * EKOOMRÅDE @@ -722,7 +733,7 @@ skärmbilden. Raden precis över ekoområdet kallas "lägesrad" (mode line). Den ser ungefär ut så här: ---:** TUTORIAL 63% L749 (Fundamental)----------------------- + -:**- TUTORIAL 63% L749 (Fundamental) Raden innehåller information om Emacs och texten du redigerar. @@ -774,6 +785,7 @@ annorlunda. För att få fram dokumentationen för det läge du är i nu kan du skriva C-h m. +>> Flytta markören till raden efter denna rad. >> Använd C-l C-l för att få denna rad överst på skärmbilden. >> Skriv C-h m och se hur Text-läget skiljer sig från Fundamental-läget. @@ -902,10 +914,11 @@ ordlista över Emacs-termer. gjorde när du lämnade det. Du kan fortsätta att använda C-x o för att byta mellan de två -fönstren. Det valda fönstret, där de flesta redigeringarna äger rum, är -det med den tydligaste markören, som blinkar när du inte skriver. De -andra fönstren har sin egen markörposition. Om du kör Emacs under ett -fönstersystem, ritas dessa markörer som en tom ruta som inte blinkar.. +fönstren. Det "valda fönstret", där de flesta redigeringarna äger rum, +är det med den tydligaste markören, som blinkar när du inte skriver. +De andra fönstren har sin egen markörposition. Om du kör Emacs under +ett fönstersystem, ritas dessa markörer som en tom ruta som inte +blinkar. Kommandot C-M-v är bra när du redigerar text i ett fönster och använder det andra fönstret för referenser. Utan att lämna det valda @@ -944,6 +957,7 @@ filer: >> Skriv C-x o för att gå tillbaka till det övre fönstret och C-x 1 för att bli kvitt det nedre igen. + * MULTIPLA RAMAR ---------------- @@ -953,20 +967,21 @@ etc. Det som Emacs kallar för ram kallar de flesta andra program för fönster. Flera grafiska ramar kan visas på skärmen samtidigt. På en textterminal kan bara en ram visas åt gången. ->> Skriv M-x make-frame <Return>. +>> Skriv C-x 5 2. En ny ram visas på din skärm. Du kan göra allt du gjorde i den första ramen i den här nya ramen. Det finns inget speciellt med den första ramen. ->> Skriv M-x delete-frame <Return>. - Ta bort den valda ramen. +>> Skriv C-x 5 0. + Detta tar bort den valda ramen. Du kan också ta bort ramen genom den vanliga metod som tillhandahålls av fönstersystemet (ofta klickar man på knappen med symbolen "X" i något av de övre hörnen.) Om den sista ramen tas bort på det här sättet så avlutas Emacs. + * REKURSIVA REDIGERINGSNIVÅER ----------------------------- @@ -990,13 +1005,13 @@ under rekursiv redigering. * MER HJÄLP ----------- -I denna vägledning har vi försökt inkludera precis så mycket -information att du kan börja använda Emacs. Det finns så många -möjligheter i Emacs att det skulle vara omöjligt att förklara alla -här. Men du VILL säkert lära dig mer om Emacs eftersom den har många -goda egenskaper. Emacs tillhandahåller kommandon för att läsa all -dokumentation. Dessa hjälpkommandon startas med teckenkombinationen -C-h. +I denna vägledning har vi försökt få med precis så mycket information +att du kan börja använda Emacs. Det finns så många möjligheter i Emacs +att det skulle vara omöjligt att förklara alla här. Men du vill säkert +lära dig mer om Emacs eftersom den har många goda egenskaper. Emacs +tillhandahåller kommandon för att läsa all dokumentation. Dessa +hjälpkommandon startas med tecknet KONTROLL-h, som kallas för +hjälptecknet. För att använda hjälpen skriver du C-h följt av ett tecken för den hjälp du behöver. Om du verkligen är helt villrådig kan du trycka C-h @@ -1020,8 +1035,9 @@ Detta ger dig namnet på funktionen. Eftersom funktionerna har beskrivande namn kan de också fungera som en enkel dokumentation, tillräckligt för att påminna dig om kommandon du redan lärt dig. -Flerteckenskommandon, så som C-x C-s och (om du inte har META, EDIT -eller ALT tangenten) <ESC> v, är också tillåtna efter C-h c. +Flerteckenskommandon, så som C-x C-s och <ESC>v (i stället för M-v, om +du inte har META, EDIT eller ALT tangenten) är också tillåtna efter +C-h c. För att få mer information om ett kommando kan du använda C-h k istället för C-h c. @@ -1045,18 +1061,18 @@ Ett liknande kommando, C-h v, visar dokumentationen för de variabler som du kan ändra värde på för att anpassa Emacs beteende. Du måste ange namnet på variabeln när Emacs frågar efter den. - C-h a Kommando-apropå (Command Apropos). Skriv in ett + C-h a Kommando-apropå (Command Apropos). Skriv in ett nyckelord och Emacs listar all kommandon vars namn - innehåller det nyckelordet. Alla dessa - kommandon kan aktiveras med META-x. För några - kommandon listas också de kombinationer bestående av - en eller två tecken som kör det kommandot. + innehåller det nyckelordet. Alla dessa kommandon kan + aktiveras med META-x. För några kommandon listas också + en sekvens av en eller flera tecken som kör det + kommandot. ->> Skriv C-h a file<Return>. +>> Skriv C-h a file <Return>. Detta visar i ett annat fönster en lista över alla M-x kommandon där -"file" förekommer i kommandonamnet. Du kommer se teckenkommandon som -C-x C-f listade bredvid motsvarande kommandonamn, t.ex. find-file. +"file" förekommer i namnet. Du kommer se teckenkommandon som C-x C-f +listade bredvid motsvarande kommandonamn, t.ex. find-file. >> Tryck C-M-v för att rulla texten i hjälpfönstret. Gör det några gånger. @@ -1068,7 +1084,7 @@ C-x C-f listade bredvid motsvarande kommandonamn, t.ex. find-file. där du kan läsa hjälpen för de paket som är installerade i ditt system. Slå m emacs <Return> för att läsa Emacs-manualen. Om du aldrig tidigare har - använt dig av Info, skriv ? och Emacs tar dig på en + använt dig av Info, skriv h och Emacs tar dig på en guidad tur över Infolägets (Info-mode) möjligheter. När du väl har tagit dig igenom den här användarhandledningen så är det direktmanualen som är @@ -1079,7 +1095,7 @@ C-x C-f listade bredvid motsvarande kommandonamn, t.ex. find-file. ---------------- Du kan lära dig mer om Emacs genom att läsa dess manual, antingen i -bokform eller on-line i Info (använd Hjälp-menyn eller skriv F10 h r). +bokform eller on-line i Info (använd Hjälp-menyn eller skriv C-h r). Två finesser som du kan komma att gilla speciellt är komplettering (completion), som spar tangenttryckningar, och dired, som förenklar filhantering. @@ -1097,6 +1113,7 @@ Emacs-manualen i noden "Dired". Manualen beskriver även många andra Emacs funktioner. + * SLUTORD --------- diff --git a/lib-src/Makefile.in b/lib-src/Makefile.in index cb4a5144c89..acf9a357cfc 100644 --- a/lib-src/Makefile.in +++ b/lib-src/Makefile.in @@ -52,7 +52,6 @@ C_SWITCH_MACHINE=@C_SWITCH_MACHINE@ PROFILING_CFLAGS = @PROFILING_CFLAGS@ WARN_CFLAGS = @WARN_CFLAGS@ WERROR_CFLAGS = @WERROR_CFLAGS@ -UPDATE_MANIFEST = @UPDATE_MANIFEST@ # Program name transformation. TRANSFORM = @program_transform_name@ @@ -113,6 +112,9 @@ bindir=@bindir@ # --libexecdir option to '../configure'. libexecdir=@libexecdir@ +# Nonempty if Emacs can assume Mailutils is installed. +with_mailutils=@with_mailutils@ + # Directory for local state files for all programs. localstatedir=@localstatedir@ @@ -145,9 +147,15 @@ abs_top_srcdir=@abs_top_srcdir@ # to '../configure'. archlibdir=@archlibdir@ -gamedir=@gamedir@ +# User or group of the auxiliary program update-game-score, which is +# installed on platforms with a game directory shared by multiple users. +# On other platforms Emacs can update the score files itself. gameuser=@gameuser@ gamegroup=@gamegroup@ +# Where to install game score files, if gameuser or gamegroup is nonempty. +gamedir=@gamedir@ +# Nonempty if and only if a shared gamedir is used. +use_gamedir=$(gameuser)$(gamegroup) # ==================== Utility Programs for the Build ================= @@ -170,14 +178,15 @@ INSTALLABLES = etags${EXEEXT} ctags${EXEEXT} remacsclient${EXEEXT} $(CLIENTW) \ # Things that Emacs runs internally, or during the build process, # which should not be installed in bindir. -UTILITIES = profile${EXEEXT} movemail${EXEEXT} hexl${EXEEXT} \ - update-game-score${EXEEXT} +UTILITIES = profile${EXEEXT} hexl${EXEEXT} \ + $(if $(with_mailutils), , movemail${EXEEXT}) \ + $(and $(use_gamedir), update-game-score${EXEEXT}) DONT_INSTALL= make-docfile${EXEEXT} # Like UTILITIES, but they're not system-dependent, and should not be # deleted by the distclean target. -SCRIPTS= rcs2log $(UPDATE_MANIFEST) +SCRIPTS= rcs2log # All files that are created by the linker, i.e., whose names end in ${EXEEXT}. EXE_FILES = ${INSTALLABLES} ${UTILITIES} ${DONT_INSTALL} @@ -252,7 +261,7 @@ all: ${EXE_FILES} ${SCRIPTS} .PHONY: all need-blessmail maybe-blessmail -LOADLIBES = ../lib/libgnu.a $(LIBS_SYSTEM) $(RUST_LIB) +LOADLIBES = ../lib/libgnu.a $(LIBS_SYSTEM) $(RUST_LIB) $(EXE_FILES): ../lib/libgnu.a $(RUST_ARCHIVE) ## Only used if we need blessmail, but no harm in always defining. @@ -276,10 +285,9 @@ need-blessmail: blessmail maybe-blessmail: $(BLESSMAIL_TARGET) ## Install the internal utilities. Until they are installed, we can -## just run them directly from lib-src. -## If the chown/chmod commands fail, that is not a big deal. -## update-game-score will detect at runtime that it is not setuid, -## and handle things accordingly. +## just run them directly from lib-src. When installing, do not give +## up if chown or chgrp fails, as the package responsible for +## installing Emacs can fix this problem later. $(DESTDIR)${archlibdir}: all @echo @echo "Installing utilities run internally by Emacs." @@ -291,28 +299,26 @@ $(DESTDIR)${archlibdir}: all "$(DESTDIR)${archlibdir}/$$file" || exit; \ done ; \ fi - umask 022 && ${MKDIR_P} "$(DESTDIR)${gamedir}" && \ + ifneq (,$(use_gamedir)) + umask 022 && ${MKDIR_P} "$(DESTDIR)${gamedir}" touch "$(DESTDIR)${gamedir}/snake-scores" \ "$(DESTDIR)${gamedir}/tetris-scores" -ifneq ($(gameuser),) - if chown ${gameuser} \ - "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}" && \ - chmod u+s,go-r \ - "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}"; \ - then \ - chown ${gameuser} "$(DESTDIR)${gamedir}" && \ - chmod u=rwx,g=rx,o=rx "$(DESTDIR)${gamedir}"; \ - fi -else ifneq ($(gamegroup),) - if chgrp ${gamegroup} \ - "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}" && \ - chmod g+s,o-r \ - "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}"; \ - then \ - chgrp ${gamegroup} "$(DESTDIR)${gamedir}" && \ - chmod u=rwx,g=rwx,o=rx "$(DESTDIR)${gamedir}"; \ - fi -endif + ifneq (,$(gameuser)) + -chown ${gameuser} \ + "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}" \ + "$(DESTDIR)${gamedir}" && \ + chmod u+s,go-r \ + "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}" && \ + chmod u=rwx,g=rx,o=rx "$(DESTDIR)${gamedir}" + else + -chgrp ${gamegroup} \ + "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}" \ + "$(DESTDIR)${gamedir}" && \ + chmod g+s,o-r \ + "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}" && \ + chmod u=rwx,g=rwx,o=rx "$(DESTDIR)${gamedir}" + endif + endif exp_archlibdir=`cd "$(DESTDIR)${archlibdir}" && /bin/pwd` && \ if [ "$$exp_archlibdir" != "`cd ${srcdir} && /bin/pwd`" ]; then \ for file in ${SCRIPTS}; do \ diff --git a/lib-src/ebrowse.c b/lib-src/ebrowse.c index ef5339e9b7d..c8ec14cf74d 100644 --- a/lib-src/ebrowse.c +++ b/lib-src/ebrowse.c @@ -20,21 +20,21 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> #include <stddef.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <assert.h> #include <getopt.h> +#include <flexmember.h> +#include <min-max.h> +#include <unlocked-io.h> + /* The SunOS compiler doesn't have SEEK_END. */ #ifndef SEEK_END #define SEEK_END 2 #endif -#include <flexmember.h> -#include <min-max.h> - /* Files are read in chunks of this number of bytes. */ enum { READ_CHUNK_SIZE = 100 * 1024 }; @@ -3057,8 +3057,7 @@ class_definition (struct sym *containing, int tag, int flags, int nested) MATCH until we see something like `;' or `{'. */ while (!LOOKING_AT3 (';', YYEOF, '{')) MATCH (); - done = 1; - + FALLTHROUGH; case '{': done = 1; break; @@ -3182,7 +3181,7 @@ declaration (int flags) free (id); return; } - + FALLTHROUGH; case '=': /* Assumed to be the start of an initialization in this context. */ diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 7b735dfb05d..f1d4e8976da 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c @@ -73,7 +73,6 @@ char *w32_getenv (const char *); #include <stdarg.h> #include <ctype.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> #include <getopt.h> @@ -84,6 +83,8 @@ char *w32_getenv (const char *); #include <signal.h> #include <errno.h> +#include <unlocked-io.h> + #ifndef VERSION #define VERSION "unspecified" #endif @@ -149,6 +150,9 @@ const char *socket_name = NULL; /* If non-NULL, the filename of the authentication file. */ const char *server_file = NULL; +/* If non-NULL, the tramp prefix emacs must use to find the files. */ +const char *tramp_prefix = NULL; + /* PID of the Emacs server process. */ int emacs_pid = 0; @@ -178,6 +182,7 @@ struct option longopts[] = { "server-file", required_argument, NULL, 'f' }, { "display", required_argument, NULL, 'd' }, { "parent-id", required_argument, NULL, 'p' }, + { "tramp", required_argument, NULL, 'T' }, { 0, 0, 0, 0 } }; @@ -204,7 +209,7 @@ char *get_current_dir_name (void); /* Return the current working directory. Returns NULL on errors. Any other returned value must be freed with free. This is used only when get_current_dir_name is not defined on the system. */ -char* +char * get_current_dir_name (void) { char *buf; @@ -468,14 +473,15 @@ static void decode_options (int argc, char **argv) { alternate_editor = egetenv ("ALTERNATE_EDITOR"); + tramp_prefix = egetenv ("EMACSCLIENT_TRAMP"); while (1) { int opt = getopt_long_only (argc, argv, #ifndef NO_SOCKETS_IN_FILE_SYSTEM - "VHnequa:s:f:d:F:tc", + "VHnequa:s:f:d:F:tcT:", #else - "VHnequa:f:d:F:tc", + "VHnequa:f:d:F:tcT:", #endif longopts, 0); @@ -554,6 +560,10 @@ decode_options (int argc, char **argv) frame_parameters = optarg; break; + case 'T': + tramp_prefix = optarg; + break; + default: message (true, "Try '%s --help' for more information\n", progname); exit (EXIT_FAILURE); @@ -654,6 +664,9 @@ The following OPTIONS are accepted:\n\ Editor to fallback to if the server is not running\n" " If EDITOR is the empty string, start Emacs in daemon\n\ mode and try connecting again\n" +"-T PREFIX, --tramp=PREFIX\n\ + PREFIX to prepend to filenames sent by emacsclient\n\ + for locating files remotely via Tramp\n" "\n\ Report bugs with M-x report-emacs-bug.\n"); exit (EXIT_SUCCESS); @@ -1687,7 +1700,10 @@ main (int argc, char **argv) } } send_to_emacs (emacs_socket, "-dir "); + if (tramp_prefix) + quote_argument (emacs_socket, tramp_prefix); quote_argument (emacs_socket, cwd); + free (cwd); send_to_emacs (emacs_socket, "/"); send_to_emacs (emacs_socket, " "); @@ -1791,6 +1807,8 @@ main (int argc, char **argv) #endif send_to_emacs (emacs_socket, "-file "); + if (tramp_prefix && file_name_absolute_p (argv[i])) + quote_argument (emacs_socket, tramp_prefix); quote_argument (emacs_socket, argv[i]); send_to_emacs (emacs_socket, " "); } diff --git a/lib-src/etags.c b/lib-src/etags.c index b8beab94d33..032339c21e3 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c @@ -114,6 +114,7 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4"; #include <errno.h> #include <fcntl.h> #include <binary-io.h> +#include <unlocked-io.h> #include <c-ctype.h> #include <c-strcase.h> @@ -365,6 +366,7 @@ static void readline (linebuffer *, FILE *); static long readline_internal (linebuffer *, FILE *, char const *); static bool nocase_tail (const char *); static void get_tag (char *, char **); +static void get_lispy_tag (char *); static void analyze_regex (char *); static void free_regexps (void); @@ -1150,7 +1152,7 @@ main (int argc, char **argv) case 'c': /* Backward compatibility: support obsolete --ignore-case-regexp. */ optarg = concat (optarg, "i", ""); /* memory leak here */ - /* FALLTHRU */ + FALLTHROUGH; case 'r': argbuffer[current_arg].arg_type = at_regexp; argbuffer[current_arg].what = optarg; @@ -1185,7 +1187,7 @@ main (int argc, char **argv) case 't': typedefs = true; break; case 'T': typedefs = typedefs_or_cplusplus = true; break; case 'u': update = true; break; - case 'v': vgrind_style = true; /*FALLTHRU*/ + case 'v': vgrind_style = true; FALLTHROUGH; case 'x': cxref_style = true; break; case 'w': no_warnings = true; break; default: @@ -1411,7 +1413,7 @@ get_compressor_from_suffix (char *file, char **extptr) for (compr = compressors; compr->suffix != NULL; compr++) if (streq (compr->suffix, suffix)) return compr; - break; /* do it only once: not really a loop */ + break; /* do it only once: not really a loop */ if (extptr != NULL) *extptr = ++suffix; } while (*suffix != '\0'); @@ -2432,7 +2434,7 @@ enum sym_type st_none, st_C_objprot, st_C_objimpl, st_C_objend, st_C_gnumacro, - st_C_ignore, st_C_attribute, + st_C_ignore, st_C_attribute, st_C_enum_bf, st_C_javastruct, st_C_operator, st_C_class, st_C_template, @@ -2481,6 +2483,7 @@ DEFUN, 0, st_C_gnumacro SYSCALL, 0, st_C_gnumacro ENTRY, 0, st_C_gnumacro PSEUDO, 0, st_C_gnumacro +ENUM_BF, 0, st_C_enum_bf # These are defined inside C functions, so currently they are not met. # EXFUN used in glibc, DEFVAR_* in emacs. #EXFUN, 0, st_C_gnumacro @@ -2488,46 +2491,48 @@ PSEUDO, 0, st_C_gnumacro %] and replace lines between %< and %> with its output, then: - remove the #if characterset check - - make in_word_set static and not inline. */ + - remove any #line directives + - make in_word_set static and not inline + - remove any 'register' qualifications from variable decls. */ /*%<*/ /* C code produced by gperf version 3.0.1 */ -/* Command-line: gperf -m 5 */ +/* Command-line: gperf -m 5 */ /* Computed positions: -k'2-3' */ struct C_stab_entry { const char *name; int c_ext; enum sym_type type; }; -/* maximum key range = 33, duplicates = 0 */ +/* maximum key range = 34, duplicates = 0 */ static int hash (const char *str, int len) { static char const asso_values[] = { - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 3, - 26, 35, 35, 35, 35, 35, 35, 35, 27, 35, - 35, 35, 35, 24, 0, 35, 35, 35, 35, 0, - 35, 35, 35, 35, 35, 1, 35, 16, 35, 6, - 23, 0, 0, 35, 22, 0, 35, 35, 5, 0, - 0, 15, 1, 35, 6, 35, 8, 19, 35, 16, - 4, 5, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35 + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 3, + 27, 36, 36, 36, 36, 36, 36, 36, 26, 36, + 36, 36, 36, 25, 0, 0, 36, 36, 36, 0, + 36, 36, 36, 36, 36, 1, 36, 16, 36, 6, + 23, 0, 0, 36, 22, 0, 36, 36, 5, 0, + 0, 15, 1, 36, 6, 36, 8, 19, 36, 16, + 4, 5, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36 }; int hval = len; @@ -2535,7 +2540,7 @@ hash (const char *str, int len) { default: hval += asso_values[(unsigned char) str[2]]; - /*FALLTHROUGH*/ + FALLTHROUGH; case 2: hval += asso_values[(unsigned char) str[1]]; break; @@ -2548,11 +2553,11 @@ in_word_set (register const char *str, register unsigned int len) { enum { - TOTAL_KEYWORDS = 33, + TOTAL_KEYWORDS = 34, MIN_WORD_LENGTH = 2, MAX_WORD_LENGTH = 15, MIN_HASH_VALUE = 2, - MAX_HASH_VALUE = 34 + MAX_HASH_VALUE = 35 }; static struct C_stab_entry wordlist[] = @@ -2587,8 +2592,9 @@ in_word_set (register const char *str, register unsigned int len) {"undef", 0, st_C_define}, {"package", (C_JAVA & ~C_PLPL), st_C_ignore}, {"__attribute__", 0, st_C_attribute}, - {"SYSCALL", 0, st_C_gnumacro}, {"ENTRY", 0, st_C_gnumacro}, + {"SYSCALL", 0, st_C_gnumacro}, + {"ENUM_BF", 0, st_C_enum_bf}, {"PSEUDO", 0, st_C_gnumacro}, {"DEFUN", 0, st_C_gnumacro} }; @@ -2625,6 +2631,11 @@ C_symtype (char *str, int len, int c_ext) */ static bool inattribute; /* looking at an __attribute__ construct */ +/* Ignoring ENUM_BF (type) + * + */ +static bool in_enum_bf; /* inside parentheses following ENUM_BF */ + /* * C functions and variables are recognized using a simple * finite automaton. fvdef is its state variable. @@ -2865,6 +2876,15 @@ consider_token (char *str, int len, int c, int *c_extp, return false; } + /* + * Skip ENUM_BF + */ + if (toktype == st_C_enum_bf && definedef == dnone) + { + in_enum_bf = true; + return false; + } + /* * Advance the definedef state machine. */ @@ -2969,7 +2989,7 @@ consider_token (char *str, int len, int c, int *c_extp, *c_extp = (*c_extp | C_PLPL) & ~C_AUTO; if (toktype == st_C_template) break; - /* FALLTHRU */ + FALLTHROUGH; case st_C_struct: case st_C_enum: if (parlev == 0 @@ -3132,7 +3152,7 @@ consider_token (char *str, int len, int c, int *c_extp, default: break; } - /* FALLTHRU */ + FALLTHROUGH; case fvnameseen: if (len >= 10 && strneq (str+len-10, "::operator", 10)) { @@ -3343,7 +3363,7 @@ C_entries (int c_ext, FILE *inf) case '\0': /* Hmmm, something went wrong. */ CNL (); - /* FALLTHRU */ + FALLTHROUGH; case '\'': inchar = false; break; @@ -3470,7 +3490,8 @@ C_entries (int c_ext, FILE *inf) && templatelev == 0 && (definedef != dnone || structdef != scolonseen) - && !inattribute) + && !inattribute + && !in_enum_bf) { if (midtoken) { @@ -3783,7 +3804,7 @@ C_entries (int c_ext, FILE *inf) || (members && plainc && instruct)) make_C_tag (true); /* a function */ - /* FALLTHRU */ + FALLTHROUGH; default: fvextern = false; fvdef = fvnone; @@ -3793,7 +3814,7 @@ C_entries (int c_ext, FILE *inf) else token.valid = false; } /* switch (fvdef) */ - /* FALLTHRU */ + FALLTHROUGH; default: if (!instruct) typdef = tnone; @@ -3881,7 +3902,7 @@ C_entries (int c_ext, FILE *inf) || (globals && bracelev == 0 && (!fvextern || declarations))) make_C_tag (false); /* a variable */ - /* FALLTHRU */ + FALLTHROUGH; default: fvdef = fvnone; } @@ -3914,7 +3935,7 @@ C_entries (int c_ext, FILE *inf) fvdef = fignore; break; } - /* FALLTHRU */ + FALLTHROUGH; case foperator: fvdef = fstartlist; break; @@ -3933,6 +3954,12 @@ C_entries (int c_ext, FILE *inf) inattribute = false; break; } + if (in_enum_bf) + { + if (--parlev == 0) + in_enum_bf = false; + break; + } if (definedef != dnone) break; if (objdef == ocatseen && parlev == 1) @@ -3998,7 +4025,7 @@ C_entries (int c_ext, FILE *inf) } } make_C_tag (true); /* a function */ - /* FALLTHRU */ + FALLTHROUGH; case fignore: fvdef = fvnone; break; @@ -4091,7 +4118,7 @@ C_entries (int c_ext, FILE *inf) if ((members && bracelev == 1) || (globals && bracelev == 0 && (!fvextern || declarations))) make_C_tag (false); /* a variable */ - /* FALLTHRU */ + FALLTHROUGH; default: fvdef = vignore; } @@ -4118,7 +4145,7 @@ C_entries (int c_ext, FILE *inf) objdef = omethodsign; break; } - /* FALLTHRU */ + FALLTHROUGH; resetfvdef: case '#': case '~': case '&': case '%': case '/': case '|': case '^': case '!': case '.': case '?': @@ -5295,7 +5322,7 @@ L_getit (void) /* Ok, then skip "(" before name in (defstruct (foo)) */ dbp = skip_spaces (dbp); } - get_tag (dbp, NULL); + get_lispy_tag (dbp); } static void @@ -5497,14 +5524,14 @@ Scheme_functions (FILE *inf) if (strneq (bp, "(def", 4) || strneq (bp, "(DEF", 4)) { bp = skip_non_spaces (bp+4); - /* Skip over open parens and white space. Don't continue past - '\0'. */ - while (*bp && notinname (*bp)) + /* Skip over open parens and white space. + Don't continue past '\0' or '='. */ + while (*bp && notinname (*bp) && *bp != '=') bp++; - get_tag (bp, NULL); + get_lispy_tag (bp); } if (LOOKING_AT (bp, "(SET!") || LOOKING_AT (bp, "(set!")) - get_tag (bp, NULL); + get_lispy_tag (bp); } } @@ -6303,7 +6330,7 @@ add_regex (char *regexp_pattern, language *lang) break; case 's': single_line = true; - /* FALLTHRU */ + FALLTHROUGH; case 'm': multi_line = true; need_filebuf = true; @@ -6539,6 +6566,22 @@ get_tag (register char *bp, char **namepp) *namepp = savenstr (bp, cp - bp); } +/* Similar to get_tag, but include '=' as part of the tag. */ +static void +get_lispy_tag (register char *bp) +{ + register char *cp = bp; + + if (*bp != '\0') + { + /* Go till you get to white space or a syntactic break */ + for (cp = bp + 1; !notinname (*cp) || *cp == '='; cp++) + continue; + make_tag (bp, cp - bp, true, + lb.buffer, cp - lb.buffer + 1, lineno, linecharno); + } +} + /* * Read a line of text from `stream' into `lbp', excluding the * newline or CR-NL, if any. Return the number of characters read from diff --git a/lib-src/hexl.c b/lib-src/hexl.c index 319ce8bc890..d949af08902 100644 --- a/lib-src/hexl.c +++ b/lib-src/hexl.c @@ -22,11 +22,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> #include <inttypes.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> #include <binary-io.h> +#include <unlocked-io.h> static char *progname; diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c index 47afd7ffde6..f714040835a 100644 --- a/lib-src/make-docfile.c +++ b/lib-src/make-docfile.c @@ -39,10 +39,14 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <stdarg.h> #include <stddef.h> #include <stdint.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> +#include <binary-io.h> +#include <intprops.h> +#include <min-max.h> +#include <unlocked-io.h> + #ifdef WINDOWSNT /* Defined to be sys_fopen in ms-w32.h, but only #ifdef emacs, so this is really just insurance. */ @@ -50,10 +54,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <direct.h> #endif /* WINDOWSNT */ -#include <binary-io.h> -#include <intprops.h> -#include <min-max.h> - #ifdef DOS_NT /* Defined to be sys_chdir in ms-w32.h, but only #ifdef emacs, so this is really just insurance. */ @@ -850,8 +850,7 @@ scan_c_stream (FILE *infile) bool defvarperbufferflag = false; bool defvarflag = false; enum global_type type = INVALID; - static char *name; - static ptrdiff_t name_size; + static char name[sizeof input_buffer]; if (c != '\n' && c != '\r') { @@ -972,22 +971,13 @@ scan_c_stream (FILE *infile) if (c < 0) goto eof; input_buffer[i++] = c; + if (sizeof input_buffer <= i) + fatal ("identifier too long"); c = getc (infile); } while (! (c == ',' || c == ' ' || c == '\t' || c == '\n' || c == '\r')); input_buffer[i] = '\0'; - - if (name_size <= i) - { - free (name); - name_size = i + 1; - ptrdiff_t doubled; - if (! INT_MULTIPLY_WRAPV (name_size, 2, &doubled) - && doubled <= SIZE_MAX) - name_size = doubled; - name = xmalloc (name_size); - } memcpy (name, input_buffer, i + 1); if (type == SYMBOL) diff --git a/lib-src/movemail.c b/lib-src/movemail.c index 7c076a251dd..8791916286b 100644 --- a/lib-src/movemail.c +++ b/lib-src/movemail.c @@ -59,7 +59,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <sys/types.h> #include <sys/stat.h> #include <sys/file.h> -#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <time.h> @@ -69,6 +68,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <fcntl.h> #include <signal.h> #include <string.h> + +#include <unlocked-io.h> + #include "syswait.h" #include "remacs-lib.h" #ifdef MAIL_USE_POP diff --git a/lib-src/ntlib.c b/lib-src/ntlib.c index 8742f1ad2f4..bda59fa1a82 100644 --- a/lib-src/ntlib.c +++ b/lib-src/ntlib.c @@ -50,8 +50,6 @@ struct timezone }; #endif -void gettimeofday (struct timeval *, struct timezone *); - #define MAXPATHLEN _MAX_PATH /* Emulate sleep...we could have done this with a define, but that @@ -229,29 +227,6 @@ getpass (const char * prompt) return NULL; } -/* This is needed because lib/gettime.c calls gettimeofday, which MSVC - doesn't have. Copied from w32.c. */ -void -gettimeofday (struct timeval *tv, struct timezone *tz) -{ - struct _timeb tb; - _ftime (&tb); - - tv->tv_sec = tb.time; - tv->tv_usec = tb.millitm * 1000L; - /* Implementation note: _ftime sometimes doesn't update the dstflag - according to the new timezone when the system timezone is - changed. We could fix that by using GetSystemTime and - GetTimeZoneInformation, but that doesn't seem necessary, since - Emacs always calls gettimeofday with the 2nd argument NULL (see - current_emacs_time). */ - if (tz) - { - tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */ - tz->tz_dsttime = tb.dstflag; /* type of dst correction */ - } -} - int fchown (int fd, unsigned uid, unsigned gid) { diff --git a/lib-src/profile.c b/lib-src/profile.c index 253f00e2d80..f4ab45c1718 100644 --- a/lib-src/profile.c +++ b/lib-src/profile.c @@ -34,11 +34,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> #include <inttypes.h> -#include <stdio.h> #include <stdlib.h> #include <intprops.h> #include <systime.h> +#include <unlocked-io.h> static struct timespec TV1; static int watch_not_started = 1; /* flag */ diff --git a/lib-src/update-game-score.c b/lib-src/update-game-score.c index eccff0aab31..87684060fcc 100644 --- a/lib-src/update-game-score.c +++ b/lib-src/update-game-score.c @@ -39,7 +39,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <limits.h> #include <string.h> #include <stdlib.h> -#include <stdio.h> #include <time.h> #include <pwd.h> #include <ctype.h> @@ -47,6 +46,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <sys/stat.h> #include <getopt.h> +#include <unlocked-io.h> + #ifdef WINDOWSNT #include "ntlib.h" #endif diff --git a/lib-src/update-game-score.exe.manifest b/lib-src/update-game-score.exe.manifest deleted file mode 100644 index 1db836bec6b..00000000000 --- a/lib-src/update-game-score.exe.manifest +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> - <v3:trustInfo xmlns:v3="urn:schemas-microsoft-com:asm.v3"> - <v3:security> - <v3:requestedPrivileges> - <v3:requestedExecutionLevel level="asInvoker" /> - </v3:requestedPrivileges> - </v3:security> - </v3:trustInfo> -</assembly> diff --git a/lib/Makefile.am b/lib/Makefile.am deleted file mode 100644 index e6d90ddd102..00000000000 --- a/lib/Makefile.am +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright 2016-2017 Free Software Foundation, Inc. - -# This file is part of GNU Emacs. - -# GNU Emacs is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# GNU Emacs is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. - -# GNU Emacs assumes GNU Make. -AUTOMAKE_OPTIONS = -Wno-portability - -BUILT_SOURCES = -CLEANFILES = -EXTRA_DIST = -MOSTLYCLEANDIRS = -MOSTLYCLEANFILES = -noinst_LIBRARIES = -SUFFIXES = - -AM_CFLAGS = $(PROFILING_CFLAGS) $(GNULIB_WARN_CFLAGS) $(WERROR_CFLAGS) -DEFAULT_INCLUDES = -I. -I$(top_srcdir)/lib -I../src -I$(top_srcdir)/src - -if BUILDING_FOR_WINDOWSNT -include ../nt/gnulib.mk -else -include gnulib.mk - -libgnu_a_SOURCES += openat-die.c save-cwd.c -endif - -if HYBRID_MALLOC_LIB -noinst_LIBRARIES += libegnu.a -endif - -libegnu_a_SOURCES = $(libgnu_a_SOURCES) -libegnu_a_LIBADD = $(patsubst %.o,e-%.o,$(libgnu_a_LIBADD)) -EXTRA_libegnu_a_SOURCES = $(EXTRA_libgnu_a_SOURCES) -libegnu_a_SHORTNAME = e -libegnu_a_CPPFLAGS = -Demacs -MOSTLYCLEANFILES += libegnu.a - -.PHONY: bootstrap-clean - -bootstrap-clean: maintainer-clean diff --git a/lib/Makefile.in b/lib/Makefile.in new file mode 100644 index 00000000000..ee41ea3e55e --- /dev/null +++ b/lib/Makefile.in @@ -0,0 +1,127 @@ +### @configure_input@ + +# Copyright 2017 Free Software Foundation, Inc. + +# This file is part of GNU Emacs. + +# GNU Emacs is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# GNU Emacs is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. + +srcdir = @srcdir@ +VPATH = @srcdir@ + +# Variables substituted by 'configure', and not autogenerated in gnulib.mk, +# or needed before gnulib.mk is included. +abs_top_srcdir = @abs_top_srcdir@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +all: +.PHONY: all + +# 'make' verbosity. +AM_V_AR = $(am__v_AR_@AM_V@) +am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) +am__v_AR_0 = @echo " AR " $@; +am__v_AR_1 = + +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = + +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = + +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = + +ALL_CFLAGS= \ + $(C_SWITCH_SYSTEM) $(C_SWITCH_MACHINE) $(DEPFLAGS) \ + $(GNULIB_WARN_CFLAGS) $(WERROR_CFLAGS) $(PROFILING_CFLAGS) $(CFLAGS) \ + -I. -I../src -I$(srcdir) -I$(srcdir)/../src \ + $(if $(patsubst e-%,,$(notdir $<)),,-Demacs) + +SYSTEM_TYPE = @SYSTEM_TYPE@ +ifeq ($(SYSTEM_TYPE),windows-nt) + include $(srcdir)/../nt/gnulib-cfg.mk +endif +include gnulib.mk +ifneq ($(SYSTEM_TYPE),windows-nt) + libgnu_a_SOURCES += openat-die.c save-cwd.c +endif + +DEPDIR = deps +ifeq ($(AUTO_DEPEND),yes) + DEPFLAGS = -MMD -MF $(DEPDIR)/$*.d -MP + -include $(ALLOBJS:%.o=$(DEPDIR)/%.d) +else + DEPFLAGS = +endif + +.PRECIOUS: ../config.status Makefile +../config.status: $(top_srcdir)/configure.ac $(top_srcdir)/m4/*.m4 + $(MAKE) -C .. $(notdir $@) +Makefile: ../config.status $(srcdir)/Makefile.in + $(MAKE) -C .. src/$@ + +libgnu_a_OBJECTS = $(gl_LIBOBJS) \ + $(patsubst %.c,%.o,$(filter %.c,$(libgnu_a_SOURCES))) +libegnu_a_OBJECTS = $(patsubst %.o,e-%.o,$(libgnu_a_OBJECTS)) + +$(libegnu_a_OBJECTS) $(libgnu_a_OBJECTS): $(BUILT_SOURCES) + +.c.o: + $(AM_V_CC)$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $< +e-%.o: %.c + $(AM_V_CC)$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -Demacs -o $@ $< + +all: libgnu.a $(if $(HYBRID_MALLOC),libegnu.a) + +libgnu.a: $(libgnu_a_OBJECTS) + $(AM_V_at)rm -f $@ + $(AM_V_AR)$(AR) $(ARFLAGS) $@ $(libgnu_a_OBJECTS) + $(AM_V_at)$(RANLIB) $@ + +libegnu.a: $(libegnu_a_OBJECTS) + $(AM_V_at)rm -f $@ + $(AM_V_AR)$(AR) $(ARFLAGS) $@ $(libegnu_a_OBJECTS) + $(AM_V_at)$(RANLIB) $@ + +ETAGS = ../lib-src/etags$(EXEEXT) +$(ETAGS): + $(MAKE) -C $(dir $@) $(notdir $@) +tagsfiles= $(wildcard $(srcdir)/*.[ch]) +tags: TAGS +TAGS: $(ETAGS) $(tagsfiles) + $(ETAGS) $(tagsfiles) +.PHONY: $(ETAGS) tags + +clean: + rm -f *.[ao] *-t \#* $(DEPDIR)/* +mostlyclean: clean + rm -f $(filter-out %-t,$(MOSTLYCLEANFILES)) +distclean bootstrap-clean: mostlyclean + rm -f Makefile + rm -fr $(DEPDIR) +maintainer-clean: distclean + rm -f TAGS gnulib.mk +.PHONY: mostlyclean clean distclean bootstrap-clean maintainer-clean + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/build-aux/snippet/_Noreturn.h b/lib/_Noreturn.h similarity index 100% rename from build-aux/snippet/_Noreturn.h rename to lib/_Noreturn.h diff --git a/build-aux/snippet/arg-nonnull.h b/lib/arg-nonnull.h similarity index 100% rename from build-aux/snippet/arg-nonnull.h rename to lib/arg-nonnull.h diff --git a/build-aux/snippet/c++defs.h b/lib/c++defs.h similarity index 100% rename from build-aux/snippet/c++defs.h rename to lib/c++defs.h diff --git a/lib/count-leading-zeros.c b/lib/count-leading-zeros.c new file mode 100644 index 00000000000..d0c0704f582 --- /dev/null +++ b/lib/count-leading-zeros.c @@ -0,0 +1,3 @@ +#include <config.h> +#define COUNT_LEADING_ZEROS_INLINE _GL_EXTERN_INLINE +#include "count-leading-zeros.h" diff --git a/lib/count-leading-zeros.h b/lib/count-leading-zeros.h new file mode 100644 index 00000000000..e197137e66e --- /dev/null +++ b/lib/count-leading-zeros.h @@ -0,0 +1,114 @@ +/* count-leading-zeros.h -- counts the number of leading 0 bits in a word. + Copyright (C) 2012-2017 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Eric Blake. */ + +#ifndef COUNT_LEADING_ZEROS_H +#define COUNT_LEADING_ZEROS_H 1 + +#include <limits.h> +#include <stdlib.h> + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef COUNT_LEADING_ZEROS_INLINE +# define COUNT_LEADING_ZEROS_INLINE _GL_INLINE +#endif + +/* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN, + expand to code that computes the number of leading zeros of the local + variable 'x' of type TYPE (an unsigned integer type) and return it + from the current function. */ +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ + return x ? BUILTIN (x) : CHAR_BIT * sizeof x; +#elif _MSC_VER +# pragma intrinsic _BitScanReverse +# pragma intrinsic _BitScanReverse64 +# define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ + do \ + { \ + unsigned long result; \ + return MSC_BUILTIN (&result, x) ? result : CHAR_BIT * sizeof x; \ + } \ + while (0) +#else +# define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ + do \ + { \ + int count; \ + unsigned int leading_32; \ + if (! x) \ + return CHAR_BIT * sizeof x; \ + for (count = 0; \ + (leading_32 = ((x >> (sizeof (TYPE) * CHAR_BIT - 32)) \ + & 0xffffffffU), \ + count < CHAR_BIT * sizeof x - 32 && !leading_32); \ + count += 32) \ + x = x << 31 << 1; \ + return count + count_leading_zeros_32 (leading_32); \ + } \ + while (0) + +/* Compute and return the number of leading zeros in X, + where 0 < X < 2**32. */ +COUNT_LEADING_ZEROS_INLINE int +count_leading_zeros_32 (unsigned int x) +{ + /* http://graphics.stanford.edu/~seander/bithacks.html */ + static const char de_Bruijn_lookup[32] = { + 31, 22, 30, 21, 18, 10, 29, 2, 20, 17, 15, 13, 9, 6, 28, 1, + 23, 19, 11, 3, 16, 14, 7, 24, 12, 4, 8, 25, 5, 26, 27, 0 + }; + + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return de_Bruijn_lookup[((x * 0x07c4acddU) & 0xffffffffU) >> 27]; +} +#endif + +/* Compute and return the number of leading zeros in X. */ +COUNT_LEADING_ZEROS_INLINE int +count_leading_zeros (unsigned int x) +{ + COUNT_LEADING_ZEROS (__builtin_clz, _BitScanReverse, unsigned int); +} + +/* Compute and return the number of leading zeros in X. */ +COUNT_LEADING_ZEROS_INLINE int +count_leading_zeros_l (unsigned long int x) +{ + COUNT_LEADING_ZEROS (__builtin_clzl, _BitScanReverse, unsigned long int); +} + +#if HAVE_UNSIGNED_LONG_LONG_INT +/* Compute and return the number of leading zeros in X. */ +COUNT_LEADING_ZEROS_INLINE int +count_leading_zeros_ll (unsigned long long int x) +{ + COUNT_LEADING_ZEROS (__builtin_clzll, _BitScanReverse64, + unsigned long long int); +} +#endif + +_GL_INLINE_HEADER_END + +#endif /* COUNT_LEADING_ZEROS_H */ diff --git a/lib/diffseq.h b/lib/diffseq.h new file mode 100644 index 00000000000..a3cf140990b --- /dev/null +++ b/lib/diffseq.h @@ -0,0 +1,529 @@ +/* Analyze differences between two vectors. + + Copyright (C) 1988-1989, 1992-1995, 2001-2004, 2006-2017 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + + +/* The basic idea is to consider two vectors as similar if, when + transforming the first vector into the second vector through a + sequence of edits (inserts and deletes of one element each), + this sequence is short - or equivalently, if the ordered list + of elements that are untouched by these edits is long. For a + good introduction to the subject, read about the "Levenshtein + distance" in Wikipedia. + + The basic algorithm is described in: + "An O(ND) Difference Algorithm and its Variations", Eugene W. Myers, + Algorithmica Vol. 1, 1986, pp. 251-266, + <http://dx.doi.org/10.1007/BF01840446>. + See especially section 4.2, which describes the variation used below. + + The basic algorithm was independently discovered as described in: + "Algorithms for Approximate String Matching", Esko Ukkonen, + Information and Control Vol. 64, 1985, pp. 100-118, + <http://dx.doi.org/10.1016/S0019-9958(85)80046-2>. + + Unless the 'find_minimal' flag is set, this code uses the TOO_EXPENSIVE + heuristic, by Paul Eggert, to limit the cost to O(N**1.5 log N) + at the price of producing suboptimal output for large inputs with + many differences. */ + +/* Before including this file, you need to define: + ELEMENT The element type of the vectors being compared. + EQUAL A two-argument macro that tests two elements for + equality. + OFFSET A signed integer type sufficient to hold the + difference between two indices. Usually + something like ptrdiff_t. + EXTRA_CONTEXT_FIELDS Declarations of fields for 'struct context'. + NOTE_DELETE(ctxt, xoff) Record the removal of the object xvec[xoff]. + NOTE_INSERT(ctxt, yoff) Record the insertion of the object yvec[yoff]. + EARLY_ABORT(ctxt) (Optional) A boolean expression that triggers an + early abort of the computation. + USE_HEURISTIC (Optional) Define if you want to support the + heuristic for large vectors. + It is also possible to use this file with abstract arrays. In this case, + xvec and yvec are not represented in memory. They only exist conceptually. + In this case, the list of defines above is amended as follows: + ELEMENT Undefined. + EQUAL Undefined. + XVECREF_YVECREF_EQUAL(ctxt, xoff, yoff) + A three-argument macro: References xvec[xoff] and + yvec[yoff] and tests these elements for equality. + Before including this file, you also need to include: + #include <limits.h> + #include <stdbool.h> + #include "minmax.h" + */ + +/* Maximum value of type OFFSET. */ +#define OFFSET_MAX \ + ((((OFFSET)1 << (sizeof (OFFSET) * CHAR_BIT - 2)) - 1) * 2 + 1) + +/* Default to no early abort. */ +#ifndef EARLY_ABORT +# define EARLY_ABORT(ctxt) false +#endif + +/* Use this to suppress gcc's "...may be used before initialized" warnings. + Beware: The Code argument must not contain commas. */ +#ifndef IF_LINT +# if defined GCC_LINT || defined lint +# define IF_LINT(Code) Code +# else +# define IF_LINT(Code) /* empty */ +# endif +#endif + +/* As above, but when Code must contain one comma. */ +#ifndef IF_LINT2 +# if defined GCC_LINT || defined lint +# define IF_LINT2(Code1, Code2) Code1, Code2 +# else +# define IF_LINT2(Code1, Code2) /* empty */ +# endif +#endif + +/* + * Context of comparison operation. + */ +struct context +{ + #ifdef ELEMENT + /* Vectors being compared. */ + ELEMENT const *xvec; + ELEMENT const *yvec; + #endif + + /* Extra fields. */ + EXTRA_CONTEXT_FIELDS + + /* Vector, indexed by diagonal, containing 1 + the X coordinate of the point + furthest along the given diagonal in the forward search of the edit + matrix. */ + OFFSET *fdiag; + + /* Vector, indexed by diagonal, containing the X coordinate of the point + furthest along the given diagonal in the backward search of the edit + matrix. */ + OFFSET *bdiag; + + #ifdef USE_HEURISTIC + /* This corresponds to the diff --speed-large-files flag. With this + heuristic, for vectors with a constant small density of changes, + the algorithm is linear in the vector size. */ + bool heuristic; + #endif + + /* Edit scripts longer than this are too expensive to compute. */ + OFFSET too_expensive; + + /* Snakes bigger than this are considered "big". */ + #define SNAKE_LIMIT 20 +}; + +struct partition +{ + /* Midpoints of this partition. */ + OFFSET xmid; + OFFSET ymid; + + /* True if low half will be analyzed minimally. */ + bool lo_minimal; + + /* Likewise for high half. */ + bool hi_minimal; +}; + + +/* Find the midpoint of the shortest edit script for a specified portion + of the two vectors. + + Scan from the beginnings of the vectors, and simultaneously from the ends, + doing a breadth-first search through the space of edit-sequence. + When the two searches meet, we have found the midpoint of the shortest + edit sequence. + + If FIND_MINIMAL is true, find the minimal edit script regardless of + expense. Otherwise, if the search is too expensive, use heuristics to + stop the search and report a suboptimal answer. + + Set PART->(xmid,ymid) to the midpoint (XMID,YMID). The diagonal number + XMID - YMID equals the number of inserted elements minus the number + of deleted elements (counting only elements before the midpoint). + + Set PART->lo_minimal to true iff the minimal edit script for the + left half of the partition is known; similarly for PART->hi_minimal. + + This function assumes that the first elements of the specified portions + of the two vectors do not match, and likewise that the last elements do not + match. The caller must trim matching elements from the beginning and end + of the portions it is going to specify. + + If we return the "wrong" partitions, the worst this can do is cause + suboptimal diff output. It cannot cause incorrect diff output. */ + +static void +diag (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim, bool find_minimal, + struct partition *part, struct context *ctxt) +{ + OFFSET *const fd = ctxt->fdiag; /* Give the compiler a chance. */ + OFFSET *const bd = ctxt->bdiag; /* Additional help for the compiler. */ +#ifdef ELEMENT + ELEMENT const *const xv = ctxt->xvec; /* Still more help for the compiler. */ + ELEMENT const *const yv = ctxt->yvec; /* And more and more . . . */ + #define XREF_YREF_EQUAL(x,y) EQUAL (xv[x], yv[y]) +#else + #define XREF_YREF_EQUAL(x,y) XVECREF_YVECREF_EQUAL (ctxt, x, y) +#endif + const OFFSET dmin = xoff - ylim; /* Minimum valid diagonal. */ + const OFFSET dmax = xlim - yoff; /* Maximum valid diagonal. */ + const OFFSET fmid = xoff - yoff; /* Center diagonal of top-down search. */ + const OFFSET bmid = xlim - ylim; /* Center diagonal of bottom-up search. */ + OFFSET fmin = fmid; + OFFSET fmax = fmid; /* Limits of top-down search. */ + OFFSET bmin = bmid; + OFFSET bmax = bmid; /* Limits of bottom-up search. */ + OFFSET c; /* Cost. */ + bool odd = (fmid - bmid) & 1; /* True if southeast corner is on an odd + diagonal with respect to the northwest. */ + + fd[fmid] = xoff; + bd[bmid] = xlim; + + for (c = 1;; ++c) + { + OFFSET d; /* Active diagonal. */ + bool big_snake = false; + + /* Extend the top-down search by an edit step in each diagonal. */ + if (fmin > dmin) + fd[--fmin - 1] = -1; + else + ++fmin; + if (fmax < dmax) + fd[++fmax + 1] = -1; + else + --fmax; + for (d = fmax; d >= fmin; d -= 2) + { + OFFSET x; + OFFSET y; + OFFSET tlo = fd[d - 1]; + OFFSET thi = fd[d + 1]; + OFFSET x0 = tlo < thi ? thi : tlo + 1; + + for (x = x0, y = x0 - d; + x < xlim && y < ylim && XREF_YREF_EQUAL (x, y); + x++, y++) + continue; + if (x - x0 > SNAKE_LIMIT) + big_snake = true; + fd[d] = x; + if (odd && bmin <= d && d <= bmax && bd[d] <= x) + { + part->xmid = x; + part->ymid = y; + part->lo_minimal = part->hi_minimal = true; + return; + } + } + + /* Similarly extend the bottom-up search. */ + if (bmin > dmin) + bd[--bmin - 1] = OFFSET_MAX; + else + ++bmin; + if (bmax < dmax) + bd[++bmax + 1] = OFFSET_MAX; + else + --bmax; + for (d = bmax; d >= bmin; d -= 2) + { + OFFSET x; + OFFSET y; + OFFSET tlo = bd[d - 1]; + OFFSET thi = bd[d + 1]; + OFFSET x0 = tlo < thi ? tlo : thi - 1; + + for (x = x0, y = x0 - d; + xoff < x && yoff < y && XREF_YREF_EQUAL (x - 1, y - 1); + x--, y--) + continue; + if (x0 - x > SNAKE_LIMIT) + big_snake = true; + bd[d] = x; + if (!odd && fmin <= d && d <= fmax && x <= fd[d]) + { + part->xmid = x; + part->ymid = y; + part->lo_minimal = part->hi_minimal = true; + return; + } + } + + if (find_minimal) + continue; + +#ifdef USE_HEURISTIC + bool heuristic = ctxt->heuristic; +#else + bool heuristic = false; +#endif + + /* Heuristic: check occasionally for a diagonal that has made lots + of progress compared with the edit distance. If we have any + such, find the one that has made the most progress and return it + as if it had succeeded. + + With this heuristic, for vectors with a constant small density + of changes, the algorithm is linear in the vector size. */ + + if (200 < c && big_snake && heuristic) + { + { + OFFSET best = 0; + + for (d = fmax; d >= fmin; d -= 2) + { + OFFSET dd = d - fmid; + OFFSET x = fd[d]; + OFFSET y = x - d; + OFFSET v = (x - xoff) * 2 - dd; + + if (v > 12 * (c + (dd < 0 ? -dd : dd))) + { + if (v > best + && xoff + SNAKE_LIMIT <= x && x < xlim + && yoff + SNAKE_LIMIT <= y && y < ylim) + { + /* We have a good enough best diagonal; now insist + that it end with a significant snake. */ + int k; + + for (k = 1; XREF_YREF_EQUAL (x - k, y - k); k++) + if (k == SNAKE_LIMIT) + { + best = v; + part->xmid = x; + part->ymid = y; + break; + } + } + } + } + if (best > 0) + { + part->lo_minimal = true; + part->hi_minimal = false; + return; + } + } + + { + OFFSET best = 0; + + for (d = bmax; d >= bmin; d -= 2) + { + OFFSET dd = d - bmid; + OFFSET x = bd[d]; + OFFSET y = x - d; + OFFSET v = (xlim - x) * 2 + dd; + + if (v > 12 * (c + (dd < 0 ? -dd : dd))) + { + if (v > best + && xoff < x && x <= xlim - SNAKE_LIMIT + && yoff < y && y <= ylim - SNAKE_LIMIT) + { + /* We have a good enough best diagonal; now insist + that it end with a significant snake. */ + int k; + + for (k = 0; XREF_YREF_EQUAL (x + k, y + k); k++) + if (k == SNAKE_LIMIT - 1) + { + best = v; + part->xmid = x; + part->ymid = y; + break; + } + } + } + } + if (best > 0) + { + part->lo_minimal = false; + part->hi_minimal = true; + return; + } + } + } + + /* Heuristic: if we've gone well beyond the call of duty, give up + and report halfway between our best results so far. */ + if (c >= ctxt->too_expensive) + { + OFFSET fxybest; + OFFSET fxbest IF_LINT (= 0); + OFFSET bxybest; + OFFSET bxbest IF_LINT (= 0); + + /* Find forward diagonal that maximizes X + Y. */ + fxybest = -1; + for (d = fmax; d >= fmin; d -= 2) + { + OFFSET x = MIN (fd[d], xlim); + OFFSET y = x - d; + if (ylim < y) + { + x = ylim + d; + y = ylim; + } + if (fxybest < x + y) + { + fxybest = x + y; + fxbest = x; + } + } + + /* Find backward diagonal that minimizes X + Y. */ + bxybest = OFFSET_MAX; + for (d = bmax; d >= bmin; d -= 2) + { + OFFSET x = MAX (xoff, bd[d]); + OFFSET y = x - d; + if (y < yoff) + { + x = yoff + d; + y = yoff; + } + if (x + y < bxybest) + { + bxybest = x + y; + bxbest = x; + } + } + + /* Use the better of the two diagonals. */ + if ((xlim + ylim) - bxybest < fxybest - (xoff + yoff)) + { + part->xmid = fxbest; + part->ymid = fxybest - fxbest; + part->lo_minimal = true; + part->hi_minimal = false; + } + else + { + part->xmid = bxbest; + part->ymid = bxybest - bxbest; + part->lo_minimal = false; + part->hi_minimal = true; + } + return; + } + } + #undef XREF_YREF_EQUAL +} + + +/* Compare in detail contiguous subsequences of the two vectors + which are known, as a whole, to match each other. + + The subsequence of vector 0 is [XOFF, XLIM) and likewise for vector 1. + + Note that XLIM, YLIM are exclusive bounds. All indices into the vectors + are origin-0. + + If FIND_MINIMAL, find a minimal difference no matter how + expensive it is. + + The results are recorded by invoking NOTE_DELETE and NOTE_INSERT. + + Return false if terminated normally, or true if terminated through early + abort. */ + +static bool +compareseq (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim, + bool find_minimal, struct context *ctxt) +{ +#ifdef ELEMENT + ELEMENT const *xv = ctxt->xvec; /* Help the compiler. */ + ELEMENT const *yv = ctxt->yvec; + #define XREF_YREF_EQUAL(x,y) EQUAL (xv[x], yv[y]) +#else + #define XREF_YREF_EQUAL(x,y) XVECREF_YVECREF_EQUAL (ctxt, x, y) +#endif + + /* Slide down the bottom initial diagonal. */ + while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xoff, yoff)) + { + xoff++; + yoff++; + } + + /* Slide up the top initial diagonal. */ + while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xlim - 1, ylim - 1)) + { + xlim--; + ylim--; + } + + /* Handle simple cases. */ + if (xoff == xlim) + while (yoff < ylim) + { + NOTE_INSERT (ctxt, yoff); + if (EARLY_ABORT (ctxt)) + return true; + yoff++; + } + else if (yoff == ylim) + while (xoff < xlim) + { + NOTE_DELETE (ctxt, xoff); + if (EARLY_ABORT (ctxt)) + return true; + xoff++; + } + else + { + struct partition part IF_LINT2 (= { .xmid = 0, .ymid = 0 }); + + /* Find a point of correspondence in the middle of the vectors. */ + diag (xoff, xlim, yoff, ylim, find_minimal, &part, ctxt); + + /* Use the partitions to split this problem into subproblems. */ + if (compareseq (xoff, part.xmid, yoff, part.ymid, part.lo_minimal, ctxt)) + return true; + if (compareseq (part.xmid, xlim, part.ymid, ylim, part.hi_minimal, ctxt)) + return true; + } + + return false; + #undef XREF_YREF_EQUAL +} + +#undef ELEMENT +#undef EQUAL +#undef OFFSET +#undef EXTRA_CONTEXT_FIELDS +#undef NOTE_DELETE +#undef NOTE_INSERT +#undef EARLY_ABORT +#undef USE_HEURISTIC +#undef XVECREF_YVECREF_EQUAL +#undef OFFSET_MAX diff --git a/lib/dtotimespec.c b/lib/dtotimespec.c index 9d81b68d817..3ca5a9cfd35 100644 --- a/lib/dtotimespec.c +++ b/lib/dtotimespec.c @@ -29,15 +29,9 @@ struct timespec dtotimespec (double sec) { - double min_representable = TYPE_MINIMUM (time_t); - double max_representable = - ((TYPE_MAXIMUM (time_t) * (double) TIMESPEC_RESOLUTION - + (TIMESPEC_RESOLUTION - 1)) - / TIMESPEC_RESOLUTION); - - if (! (min_representable < sec)) + if (! (TYPE_MINIMUM (time_t) < sec)) return make_timespec (TYPE_MINIMUM (time_t), 0); - else if (! (sec < max_representable)) + else if (! (sec < 1.0 + TYPE_MAXIMUM (time_t))) return make_timespec (TYPE_MAXIMUM (time_t), TIMESPEC_RESOLUTION - 1); else { diff --git a/lib/dup2.c b/lib/dup2.c index c0c7cadf4a8..002dc8c76cb 100644 --- a/lib/dup2.c +++ b/lib/dup2.c @@ -35,10 +35,39 @@ # define WIN32_LEAN_AND_MEAN # include <windows.h> -# include "msvc-inval.h" +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +# include "msvc-inval.h" +# endif /* Get _get_osfhandle. */ -# include "msvc-nothrow.h" +# if GNULIB_MSVC_NOTHROW +# include "msvc-nothrow.h" +# else +# include <io.h> +# endif + +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static int +dup2_nothrow (int fd, int desired_fd) +{ + int result; + + TRY_MSVC_INVAL + { + result = dup2 (fd, desired_fd); + } + CATCH_MSVC_INVAL + { + errno = EBADF; + result = -1; + } + DONE_MSVC_INVAL; + + return result; +} +# else +# define dup2_nothrow dup2 +# endif static int ms_windows_dup2 (int fd, int desired_fd) @@ -66,16 +95,7 @@ ms_windows_dup2 (int fd, int desired_fd) return -1; } - TRY_MSVC_INVAL - { - result = dup2 (fd, desired_fd); - } - CATCH_MSVC_INVAL - { - errno = EBADF; - result = -1; - } - DONE_MSVC_INVAL; + result = dup2_nothrow (fd, desired_fd); if (result == 0) result = desired_fd; diff --git a/lib/fcntl.c b/lib/fcntl.c index afe15468ffa..d4dd144e05d 100644 --- a/lib/fcntl.c +++ b/lib/fcntl.c @@ -38,7 +38,11 @@ # include <windows.h> /* Get _get_osfhandle. */ -# include "msvc-nothrow.h" +# if GNULIB_MSVC_NOTHROW +# include "msvc-nothrow.h" +# else +# include <io.h> +# endif /* Upper bound on getdtablesize(). See lib/getdtablesize.c. */ # define OPEN_MAX_MAX 0x10000 diff --git a/lib/fpending.c b/lib/fpending.c index c9b77866858..02602a1c27f 100644 --- a/lib/fpending.c +++ b/lib/fpending.c @@ -41,7 +41,7 @@ __fpending (FILE *fp) return fp->_ptr - fp->_buffer; #elif defined __minix /* Minix */ return fp_->_ptr - fp_->_buf; -#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw, MSVC, NonStop Kernel */ +#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw, MSVC, NonStop Kernel, OpenVMS */ return (fp_->_ptr ? fp_->_ptr - fp_->_base : 0); #elif defined __UCLIBC__ /* uClibc */ return (fp->__modeflags & __FLAG_WRITING ? fp->__bufpos - fp->__bufstart : 0); @@ -51,8 +51,6 @@ __fpending (FILE *fp) return fp->__bufp - fp->__buffer; #elif defined EPLAN9 /* Plan9 */ return fp->wp - fp->buf; -#elif defined __VMS /* VMS */ - return (*fp)->_ptr - (*fp)->_base; #else # error "Please port gnulib fpending.c to your platform!" return 1; diff --git a/lib/fsync.c b/lib/fsync.c index 46dd59b3d2c..5a4945ef2bf 100644 --- a/lib/fsync.c +++ b/lib/fsync.c @@ -34,7 +34,11 @@ # include <errno.h> /* Get _get_osfhandle. */ -# include "msvc-nothrow.h" +# if GNULIB_MSVC_NOTHROW +# include "msvc-nothrow.h" +# else +# include <io.h> +# endif int fsync (int fd) diff --git a/lib/ftoastr.c b/lib/ftoastr.c index 826340c3f77..f2434161db8 100644 --- a/lib/ftoastr.c +++ b/lib/ftoastr.c @@ -39,6 +39,7 @@ # define FLOAT_MIN LDBL_MIN # define FLOAT_PREC_BOUND _GL_LDBL_PREC_BOUND # define FTOASTR ldtoastr +# define PROMOTED_FLOAT long double # if HAVE_C99_STRTOLD # define STRTOF strtold # endif @@ -48,6 +49,7 @@ # define FLOAT_MIN DBL_MIN # define FLOAT_PREC_BOUND _GL_DBL_PREC_BOUND # define FTOASTR dtoastr +# define PROMOTED_FLOAT double #else # define LENGTH 1 # define FLOAT float @@ -55,6 +57,7 @@ # define FLOAT_MIN FLT_MIN # define FLOAT_PREC_BOUND _GL_FLT_PREC_BOUND # define FTOASTR ftoastr +# define PROMOTED_FLOAT double # if HAVE_STRTOF # define STRTOF strtof # endif @@ -77,20 +80,21 @@ static int ftoastr_snprintf (char *buf, size_t bufsize, char const *format, int width, int prec, FLOAT x) { + PROMOTED_FLOAT promoted_x = x; char width_0_buffer[LENGTH == 1 ? FLT_BUFSIZE_BOUND : LENGTH == 2 ? DBL_BUFSIZE_BOUND : LDBL_BUFSIZE_BOUND]; int n = width; if (bufsize < sizeof width_0_buffer) { - n = sprintf (width_0_buffer, format, 0, prec, x); + n = sprintf (width_0_buffer, format, 0, prec, promoted_x); if (n < 0) return n; if (n < width) n = width; } if (n < bufsize) - n = sprintf (buf, format, width, prec, x); + n = sprintf (buf, format, width, prec, promoted_x); return n; } #endif @@ -101,11 +105,12 @@ FTOASTR (char *buf, size_t bufsize, int flags, int width, FLOAT x) /* The following method is simple but slow. For ideas about speeding things up, please see: - Florian Loitsch, Printing floating-point numbers quickly and accurately - with integers. ACM SIGPLAN notices 46, 6 (June 2010), 233-243 - <http://dx.doi.org/10.1145/1809028.1806623>; also see the - 2010-03-21 draft <http://florian.loitsch.com/tmp/article.pdf>. */ + Andrysco M, Jhala R, Lerner S. Printing floating-point numbers: + a faster, always correct method. ACM SIGPLAN notices - POPL '16. + 2016;51(1):555-67 <http://dx.doi.org/10.1145/2914770.2837654>; draft at + <http://cseweb.ucsd.edu/~lerner/papers/fp-printing-popl16.pdf>. */ + PROMOTED_FLOAT promoted_x = x; char format[sizeof "%-+ 0*.*Lg"]; FLOAT abs_x = x < 0 ? -x : x; int prec; @@ -128,7 +133,7 @@ FTOASTR (char *buf, size_t bufsize, int flags, int width, FLOAT x) for (prec = abs_x < FLOAT_MIN ? 1 : FLOAT_DIG; ; prec++) { - int n = snprintf (buf, bufsize, format, width, prec, x); + int n = snprintf (buf, bufsize, format, width, prec, promoted_x); if (n < 0 || FLOAT_PREC_BOUND <= prec || (n < bufsize && STRTOF (buf, NULL) == x)) diff --git a/lib/getdtablesize.c b/lib/getdtablesize.c index 7fabb51e2c6..c356cf4aa97 100644 --- a/lib/getdtablesize.c +++ b/lib/getdtablesize.c @@ -24,7 +24,9 @@ # include <stdio.h> -# include "msvc-inval.h" +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +# include "msvc-inval.h" +# endif # if HAVE_MSVC_INVALID_PARAMETER_HANDLER static int @@ -44,7 +46,8 @@ _setmaxstdio_nothrow (int newmax) return result; } -# define _setmaxstdio _setmaxstdio_nothrow +# else +# define _setmaxstdio_nothrow _setmaxstdio # endif /* Cache for the previous getdtablesize () result. Safe to cache because @@ -76,9 +79,9 @@ getdtablesize (void) freed when we call _setmaxstdio with the original value. */ int orig_max_stdio = _getmaxstdio (); unsigned int bound; - for (bound = 0x10000; _setmaxstdio (bound) < 0; bound = bound / 2) + for (bound = 0x10000; _setmaxstdio_nothrow (bound) < 0; bound = bound / 2) ; - _setmaxstdio (orig_max_stdio); + _setmaxstdio_nothrow (orig_max_stdio); dtablesize = bound; } return dtablesize; diff --git a/lib/getopt-cdefs.in.h b/lib/getopt-cdefs.in.h new file mode 100644 index 00000000000..c71a4f11f64 --- /dev/null +++ b/lib/getopt-cdefs.in.h @@ -0,0 +1,67 @@ +/* getopt-on-non-glibc compatibility macros. + Copyright (C) 1989-2017 Free Software Foundation, Inc. + This file is part of gnulib. + Unlike most of the getopt implementation, it is NOT shared + with the GNU C Library. + + gnulib is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + gnulib is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with gnulib; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _GETOPT_CDEFS_H +#define _GETOPT_CDEFS_H 1 + +/* This header should not be used directly; include getopt.h or + unistd.h instead. It does not have a protective #error, because + the guard macro for getopt.h in gnulib is not fixed. */ + +/* getopt-core.h and getopt-ext.h are shared with GNU libc, and expect + a number of the internal macros supplied to GNU libc's headers by + sys/cdefs.h. Provide fallback definitions for all of them. */ +#if @HAVE_SYS_CDEFS_H@ +# include <sys/cdefs.h> +#endif + +#ifndef __BEGIN_DECLS +# ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# else +# define __BEGIN_DECLS /* nothing */ +# endif +#endif +#ifndef __END_DECLS +# ifdef __cplusplus +# define __END_DECLS } +# else +# define __END_DECLS /* nothing */ +# endif +#endif + +#ifndef __GNUC_PREREQ +# if defined __GNUC__ && defined __GNUC_VERSION__ +# define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +# else +# define __GNUC_PREREQ(maj, min) 0 +# endif +#endif + +#ifndef __THROW +# if defined __cplusplus && __GNUC_PREREQ (2,8) +# define __THROW throw () +# else +# define __THROW +# endif +#endif + +#endif /* _GETOPT_CDEFS_H */ diff --git a/lib/getopt-core.h b/lib/getopt-core.h new file mode 100644 index 00000000000..d315891aefd --- /dev/null +++ b/lib/getopt-core.h @@ -0,0 +1,96 @@ +/* Declarations for getopt (basic, portable features only). + Copyright (C) 1989-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library and is also part of gnulib. + Patches to this file should be submitted to both projects. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _GETOPT_CORE_H +#define _GETOPT_CORE_H 1 + +/* This header should not be used directly; include getopt.h or + unistd.h instead. Unlike most bits headers, it does not have + a protective #error, because the guard macro for getopt.h in + gnulib is not fixed. */ + +__BEGIN_DECLS + +/* For communication from 'getopt' to the caller. + When 'getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when 'ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to 'getopt'. + + On entry to 'getopt', zero means this is the first call; initialize. + + When 'getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, 'optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message 'getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Get definitions and prototypes for functions to process the + arguments in ARGV (ARGC of them, minus the program name) for + options given in OPTS. + + Return the option character from OPTS just read. Return -1 when + there are no more options. For unrecognized options, or options + missing arguments, 'optopt' is set to the option letter, and '?' is + returned. + + The OPTS string is a list of characters which are recognized option + letters, optionally followed by colons, specifying that that letter + takes an argument, to be placed in 'optarg'. + + If a letter in OPTS is followed by two colons, its argument is + optional. This behavior is specific to the GNU 'getopt'. + + The argument '--' causes premature termination of argument + scanning, explicitly telling 'getopt' that there are no more + options. + + If OPTS begins with '-', then non-option arguments are treated as + arguments to the option '\1'. This behavior is specific to the GNU + 'getopt'. If OPTS begins with '+', or POSIXLY_CORRECT is set in + the environment, then do not permute arguments. + + For standards compliance, the 'argv' argument has the type + char *const *, but this is inaccurate; if argument permutation is + enabled, the argv array (not the strings it points to) must be + writable. */ + +extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) + __THROW _GL_ARG_NONNULL ((2, 3)); + +__END_DECLS + +#endif /* _GETOPT_CORE_H */ diff --git a/lib/getopt-ext.h b/lib/getopt-ext.h new file mode 100644 index 00000000000..e4da22f54f5 --- /dev/null +++ b/lib/getopt-ext.h @@ -0,0 +1,77 @@ +/* Declarations for getopt (GNU extensions). + Copyright (C) 1989-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library and is also part of gnulib. + Patches to this file should be submitted to both projects. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _GETOPT_EXT_H +#define _GETOPT_EXT_H 1 + +/* This header should not be used directly; include getopt.h instead. + Unlike most bits headers, it does not have a protective #error, + because the guard macro for getopt.h in gnulib is not fixed. */ + +__BEGIN_DECLS + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of 'struct option' terminated by an element containing a name which is + zero. + + The field 'has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field 'flag' is not NULL, it points to a variable that is set + to the value given in the field 'val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an 'int' to + a compiled-in constant, such as set a value from 'optarg', set the + option's 'flag' field to zero and its 'val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero 'flag' field, 'getopt' + returns the contents of the 'val' field. */ + +struct option +{ + const char *name; + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the 'has_arg' field of 'struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind) + __THROW _GL_ARG_NONNULL ((2, 3)); +extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind) + __THROW _GL_ARG_NONNULL ((2, 3)); + +__END_DECLS + +#endif /* _GETOPT_EXT_H */ diff --git a/lib/getopt-pfx-core.h b/lib/getopt-pfx-core.h new file mode 100644 index 00000000000..db5f15c22d7 --- /dev/null +++ b/lib/getopt-pfx-core.h @@ -0,0 +1,59 @@ +/* getopt (basic, portable features) gnulib wrapper header. + Copyright (C) 1989-2017 Free Software Foundation, Inc. + This file is part of gnulib. + Unlike most of the getopt implementation, it is NOT shared + with the GNU C Library. + + gnulib is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + gnulib is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with gnulib; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _GETOPT_PFX_CORE_H +#define _GETOPT_PFX_CORE_H 1 + +/* This header should not be used directly; include getopt.h or + unistd.h instead. It does not have a protective #error, because + the guard macro for getopt.h in gnulib is not fixed. */ + +/* Standalone applications should #define __GETOPT_PREFIX to an + identifier that prefixes the external functions and variables + defined in getopt-core.h and getopt-ext.h. Systematically + rename identifiers so that they do not collide with the system + functions and variables. Renaming avoids problems with some + compilers and linkers. */ +#ifdef __GETOPT_PREFIX +# ifndef __GETOPT_ID +# define __GETOPT_CONCAT(x, y) x ## y +# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y) +# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y) +# endif +# undef getopt +# undef optarg +# undef opterr +# undef optind +# undef optopt +# define getopt __GETOPT_ID (getopt) +# define optarg __GETOPT_ID (optarg) +# define opterr __GETOPT_ID (opterr) +# define optind __GETOPT_ID (optind) +# define optopt __GETOPT_ID (optopt) + +/* The system's getopt.h may have already included getopt-core.h to + declare the unprefixed identifiers. Undef _GETOPT_CORE_H so that + getopt-core.h declares them with prefixes. */ +# undef _GETOPT_CORE_H +#endif + +#include <getopt-core.h> + +#endif /* _GETOPT_PFX_CORE_H */ diff --git a/lib/getopt-pfx-ext.h b/lib/getopt-pfx-ext.h new file mode 100644 index 00000000000..91f4df1720f --- /dev/null +++ b/lib/getopt-pfx-ext.h @@ -0,0 +1,71 @@ +/* getopt (GNU extensions) gnulib wrapper header. + Copyright (C) 1989-2017 Free Software Foundation, Inc. + This file is part of gnulib. + Unlike most of the getopt implementation, it is NOT shared + with the GNU C Library. + + gnulib is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + gnulib is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with gnulib; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _GETOPT_PFX_EXT_H +#define _GETOPT_PFX_EXT_H 1 + +/* This header should not be used directly; include getopt.h instead. + It does not have a protective #error, because the guard macro for + getopt.h in gnulib is not fixed. */ + +/* Standalone applications should #define __GETOPT_PREFIX to an + identifier that prefixes the external functions and variables + defined in getopt-core.h and getopt-ext.h. Systematically + rename identifiers so that they do not collide with the system + functions and variables. Renaming avoids problems with some + compilers and linkers. */ +#ifdef __GETOPT_PREFIX +# ifndef __GETOPT_ID +# define __GETOPT_CONCAT(x, y) x ## y +# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y) +# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y) +# endif +# undef getopt_long +# undef getopt_long_only +# undef option +# undef _getopt_internal +# define getopt_long __GETOPT_ID (getopt_long) +# define getopt_long_only __GETOPT_ID (getopt_long_only) +# define option __GETOPT_ID (option) +# define _getopt_internal __GETOPT_ID (getopt_internal) + +/* The system's getopt.h may have already included getopt-ext.h to + declare the unprefixed identifiers. Undef _GETOPT_EXT_H so that + getopt-ext.h declares them with prefixes. */ +# undef _GETOPT_EXT_H +#endif + +/* Standalone applications get correct prototypes for getopt_long and + getopt_long_only; they declare "char **argv". For backward + compatibility with old applications, if __GETOPT_PREFIX is not + defined, we supply GNU-libc-compatible, but incorrect, prototypes + using "char *const *argv". (GNU libc is stuck with the incorrect + prototypes, as they are baked into older versions of LSB.) */ +#ifndef __getopt_argv_const +# if defined __GETOPT_PREFIX +# define __getopt_argv_const /* empty */ +# else +# define __getopt_argv_const const +# endif +#endif + +#include <getopt-ext.h> + +#endif /* _GETOPT_PFX_EXT_H */ diff --git a/lib/getopt.c b/lib/getopt.c index e40ea8d5eaa..9a2867db277 100644 --- a/lib/getopt.c +++ b/lib/getopt.c @@ -1,23 +1,21 @@ /* Getopt for GNU. - NOTE: getopt is part of the C library, so if you don't know what - "Keep this file name-space clean" means, talk to drepper@gnu.org - before changing it! - Copyright (C) 1987-1996, 1998-2004, 2006, 2008-2017 Free Software - Foundation, Inc. - This file is part of the GNU C Library. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, + Copyright (C) 1987-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library and is also part of gnulib. + Patches to this file should be submitted to both projects. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #ifndef _LIBC # include <config.h> @@ -31,30 +29,54 @@ #include <unistd.h> #ifdef _LIBC +/* When used as part of glibc, error printing must be done differently + for standards compliance. getopt is not a cancellation point, so + it must not call functions that are, and it is specified by an + older standard than stdio locking, so it must not refer to + functions in the "user namespace" related to stdio locking. + Finally, it must use glibc's internal message translation so that + the messages are looked up in the proper text domain. */ # include <libintl.h> +# define fprintf __fxprintf_nocancel +# define flockfile(fp) _IO_flockfile (fp) +# define funlockfile(fp) _IO_funlockfile (fp) #else # include "gettext.h" # define _(msgid) gettext (msgid) +/* When used standalone, flockfile and funlockfile might not be + available. */ +# if (!defined _POSIX_THREAD_SAFE_FUNCTIONS \ + || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)) +# define flockfile(fp) /* nop */ +# define funlockfile(fp) /* nop */ +# endif +/* When used standalone, do not attempt to use alloca. */ +# define __libc_use_alloca(size) 0 +# undef alloca +# define alloca(size) (abort (), (void *)0) #endif -#if defined _LIBC && defined USE_IN_LIBIO -# include <wchar.h> -#endif - -/* This version of 'getopt' appears to the caller like standard Unix 'getopt' - but it behaves differently for the user, since it allows the user - to intersperse the options with the other arguments. - - As 'getopt_long' works, it permutes the elements of ARGV so that, - when it is done, all the options precede everything else. Thus - all application programs are extended to handle flexible argument order. - - Using 'getopt' or setting the environment variable POSIXLY_CORRECT +/* This implementation of 'getopt' has three modes for handling + options interspersed with non-option arguments. It can stop + scanning for options at the first non-option argument encountered, + as POSIX specifies. It can continue scanning for options after the + first non-option argument, but permute 'argv' as it goes so that, + after 'getopt' is done, all the options precede all the non-option + arguments and 'optind' points to the first non-option argument. + Or, it can report non-option arguments as if they were arguments to + the option character '\x01'. + + The default behavior of 'getopt_long' is to permute the argument list. + When this implementation is used standalone, the default behavior of + 'getopt' is to stop at the first non-option argument, but when it is + used as part of GNU libc it also permutes the argument list. In both + cases, setting the environment variable POSIXLY_CORRECT to any value disables permutation. - Then the behavior is completely standard. - GNU application programs can use a third alternative mode in which - they can distinguish the relative order of options and other arguments. */ + If the first character of the OPTSTRING argument to 'getopt' or + 'getopt_long' is '+', both functions will stop at the first + non-option argument. If it is '-', both functions will report + non-option arguments as arguments to the option character '\x01'. */ #include "getopt_int.h" @@ -95,42 +117,7 @@ int optopt = '?'; /* Keep a global copy of all internal members of getopt_data. */ static struct _getopt_data getopt_data; - - -#if defined HAVE_DECL_GETENV && !HAVE_DECL_GETENV -extern char *getenv (); -#endif -#ifdef _LIBC -/* Stored original parameters. - XXX This is no good solution. We should rather copy the args so - that we can compare them later. But we must not use malloc(3). */ -extern int __libc_argc; -extern char **__libc_argv; - -/* Bash 2.0 gives us an environment variable containing flags - indicating ARGV elements that should not be considered arguments. */ - -# ifdef USE_NONOPTION_FLAGS -/* Defined in getopt_init.c */ -extern char *__getopt_nonoption_flags; -# endif - -# ifdef USE_NONOPTION_FLAGS -# define SWAP_FLAGS(ch1, ch2) \ - if (d->__nonoption_flags_len > 0) \ - { \ - char __tmp = __getopt_nonoption_flags[ch1]; \ - __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ - __getopt_nonoption_flags[ch2] = __tmp; \ - } -# else -# define SWAP_FLAGS(ch1, ch2) -# endif -#else /* !_LIBC */ -# define SWAP_FLAGS(ch1, ch2) -#endif /* _LIBC */ - /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. @@ -153,64 +140,40 @@ exchange (char **argv, struct _getopt_data *d) It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ -#if defined _LIBC && defined USE_NONOPTION_FLAGS - /* First make sure the handling of the '__getopt_nonoption_flags' - string can work normally. Our top argument must be in the range - of the string. */ - if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len) - { - /* We must extend the array. The user plays games with us and - presents new arguments. */ - char *new_str = malloc (top + 1); - if (new_str == NULL) - d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0; - else - { - memset (__mempcpy (new_str, __getopt_nonoption_flags, - d->__nonoption_flags_max_len), - '\0', top + 1 - d->__nonoption_flags_max_len); - d->__nonoption_flags_max_len = top + 1; - __getopt_nonoption_flags = new_str; - } - } -#endif - while (top > middle && middle > bottom) { if (top - middle > middle - bottom) - { - /* Bottom segment is the short one. */ - int len = middle - bottom; - register int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } else - { - /* Top segment is the short one. */ - int len = top - middle; - register int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - SWAP_FLAGS (bottom + i, middle + i); - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } + { + /* Top segment is the short one. */ + int len = top - middle; + int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } } /* Update records for the slots the non-options now occupy. */ @@ -219,25 +182,216 @@ exchange (char **argv, struct _getopt_data *d) d->__last_nonopt = d->optind; } -/* Initialize the internal data when the first call is made. */ +/* Process the argument starting with d->__nextchar as a long option. + d->optind should *not* have been advanced over this argument. + + If the value returned is -1, it was not actually a long option, the + state is unchanged, and the argument should be processed as a set + of short options (this can only happen when long_only is true). + Otherwise, the option (and its argument, if any) have been consumed + and the return value is the value to return from _getopt_internal_r. */ +static int +process_long_option (int argc, char **argv, const char *optstring, + const struct option *longopts, int *longind, + int long_only, struct _getopt_data *d, + int print_errors, const char *prefix) +{ + char *nameend; + size_t namelen; + const struct option *p; + const struct option *pfound = NULL; + int n_options; + int option_index; + + for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + namelen = nameend - d->__nextchar; + + /* First look for an exact match, counting the options as a side + effect. */ + for (p = longopts, n_options = 0; p->name; p++, n_options++) + if (!strncmp (p->name, d->__nextchar, namelen) + && namelen == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + option_index = n_options; + break; + } + + if (pfound == NULL) + { + /* Didn't find an exact match, so look for abbreviations. */ + unsigned char *ambig_set = NULL; + int ambig_malloced = 0; + int ambig_fallback = 0; + int indfound = -1; + + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, d->__nextchar, namelen)) + { + if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else if (long_only + || pfound->has_arg != p->has_arg + || pfound->flag != p->flag + || pfound->val != p->val) + { + /* Second or later nonexact match found. */ + if (!ambig_fallback) + { + if (!print_errors) + /* Don't waste effort tracking the ambig set if + we're not going to print it anyway. */ + ambig_fallback = 1; + else if (!ambig_set) + { + if (__libc_use_alloca (n_options)) + ambig_set = alloca (n_options); + else if ((ambig_set = malloc (n_options)) == NULL) + /* Fall back to simpler error message. */ + ambig_fallback = 1; + else + ambig_malloced = 1; + + if (ambig_set) + { + memset (ambig_set, 0, n_options); + ambig_set[indfound] = 1; + } + } + if (ambig_set) + ambig_set[option_index] = 1; + } + } + } + + if (ambig_set || ambig_fallback) + { + if (print_errors) + { + if (ambig_fallback) + fprintf (stderr, _("%s: option '%s%s' is ambiguous\n"), + argv[0], prefix, d->__nextchar); + else + { + flockfile (stderr); + fprintf (stderr, + _("%s: option '%s%s' is ambiguous; possibilities:"), + argv[0], prefix, d->__nextchar); + + for (option_index = 0; option_index < n_options; option_index++) + if (ambig_set[option_index]) + fprintf (stderr, " '%s%s'", + prefix, longopts[option_index].name); + + /* This must use 'fprintf' even though it's only + printing a single character, so that it goes through + __fxprintf_nocancel when compiled as part of glibc. */ + fprintf (stderr, "\n"); + funlockfile (stderr); + } + } + if (ambig_malloced) + free (ambig_set); + d->__nextchar += strlen (d->__nextchar); + d->optind++; + d->optopt = 0; + return '?'; + } + + option_index = indfound; + } + + if (pfound == NULL) + { + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short option, + then it's an error. */ + if (!long_only || argv[d->optind][1] == '-' + || strchr (optstring, *d->__nextchar) == NULL) + { + if (print_errors) + fprintf (stderr, _("%s: unrecognized option '%s%s'\n"), + argv[0], prefix, d->__nextchar); + + d->__nextchar = NULL; + d->optind++; + d->optopt = 0; + return '?'; + } + + /* Otherwise interpret it as a short option. */ + return -1; + } + + /* We have found a matching long option. Consume it. */ + d->optind++; + d->__nextchar = NULL; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + d->optarg = nameend + 1; + else + { + if (print_errors) + fprintf (stderr, + _("%s: option '%s%s' doesn't allow an argument\n"), + argv[0], prefix, pfound->name); + + d->optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (d->optind < argc) + d->optarg = argv[d->optind++]; + else + { + if (print_errors) + fprintf (stderr, + _("%s: option '%s%s' requires an argument\n"), + argv[0], prefix, pfound->name); + + d->optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; +} + +/* Initialize internal data upon the first call to getopt. */ static const char * _getopt_initialize (int argc _GL_UNUSED, - char **argv _GL_UNUSED, const char *optstring, - struct _getopt_data *d, int posixly_correct) + char **argv _GL_UNUSED, const char *optstring, + struct _getopt_data *d, int posixly_correct) { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ + if (d->optind == 0) + d->optind = 1; d->__first_nonopt = d->__last_nonopt = d->optind; - d->__nextchar = NULL; - d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT"); - /* Determine how to handle the ordering of options and nonoptions. */ - if (optstring[0] == '-') { d->__ordering = RETURN_IN_ORDER; @@ -248,41 +402,12 @@ _getopt_initialize (int argc _GL_UNUSED, d->__ordering = REQUIRE_ORDER; ++optstring; } - else if (d->__posixly_correct) + else if (posixly_correct || !!getenv ("POSIXLY_CORRECT")) d->__ordering = REQUIRE_ORDER; else d->__ordering = PERMUTE; -#if defined _LIBC && defined USE_NONOPTION_FLAGS - if (!d->__posixly_correct - && argc == __libc_argc && argv == __libc_argv) - { - if (d->__nonoption_flags_max_len == 0) - { - if (__getopt_nonoption_flags == NULL - || __getopt_nonoption_flags[0] == '\0') - d->__nonoption_flags_max_len = -1; - else - { - const char *orig_str = __getopt_nonoption_flags; - int len = d->__nonoption_flags_max_len = strlen (orig_str); - if (d->__nonoption_flags_max_len < argc) - d->__nonoption_flags_max_len = argc; - __getopt_nonoption_flags = - (char *) malloc (d->__nonoption_flags_max_len); - if (__getopt_nonoption_flags == NULL) - d->__nonoption_flags_max_len = -1; - else - memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), - '\0', d->__nonoption_flags_max_len - len); - } - } - d->__nonoption_flags_len = d->__nonoption_flags_max_len; - } - else - d->__nonoption_flags_len = 0; -#endif - + d->__initialized = 1; return optstring; } @@ -344,8 +469,8 @@ _getopt_initialize (int argc _GL_UNUSED, int _getopt_internal_r (int argc, char **argv, const char *optstring, - const struct option *longopts, int *longind, - int long_only, struct _getopt_data *d, int posixly_correct) + const struct option *longopts, int *longind, + int long_only, struct _getopt_data *d, int posixly_correct) { int print_errors = d->opterr; @@ -355,461 +480,129 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, d->optarg = NULL; if (d->optind == 0 || !d->__initialized) - { - if (d->optind == 0) - d->optind = 1; /* Don't scan ARGV[0], the program name. */ - optstring = _getopt_initialize (argc, argv, optstring, d, - posixly_correct); - d->__initialized = 1; - } + optstring = _getopt_initialize (argc, argv, optstring, d, posixly_correct); else if (optstring[0] == '-' || optstring[0] == '+') optstring++; + if (optstring[0] == ':') print_errors = 0; - /* Test whether ARGV[optind] points to a non-option argument. - Either it does not have option syntax, or there is an environment flag - from the shell indicating it is not an option. The later information - is only used when the used in the GNU libc. */ -#if defined _LIBC && defined USE_NONOPTION_FLAGS -# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \ - || (d->optind < d->__nonoption_flags_len \ - && __getopt_nonoption_flags[d->optind] == '1')) -#else -# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') -#endif + /* Test whether ARGV[optind] points to a non-option argument. */ +#define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') if (d->__nextchar == NULL || *d->__nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been - moved back by the user (who may also have changed the arguments). */ + moved back by the user (who may also have changed the arguments). */ if (d->__last_nonopt > d->optind) - d->__last_nonopt = d->optind; + d->__last_nonopt = d->optind; if (d->__first_nonopt > d->optind) - d->__first_nonopt = d->optind; + d->__first_nonopt = d->optind; if (d->__ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ - if (d->__first_nonopt != d->__last_nonopt - && d->__last_nonopt != d->optind) - exchange ((char **) argv, d); - else if (d->__last_nonopt != d->optind) - d->__first_nonopt = d->optind; + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange (argv, d); + else if (d->__last_nonopt != d->optind) + d->__first_nonopt = d->optind; - /* Skip any additional non-options - and extend the range of non-options previously skipped. */ + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ - while (d->optind < argc && NONOPTION_P) - d->optind++; - d->__last_nonopt = d->optind; - } + while (d->optind < argc && NONOPTION_P) + d->optind++; + d->__last_nonopt = d->optind; + } /* The special ARGV-element '--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ if (d->optind != argc && !strcmp (argv[d->optind], "--")) - { - d->optind++; + { + d->optind++; - if (d->__first_nonopt != d->__last_nonopt - && d->__last_nonopt != d->optind) - exchange ((char **) argv, d); - else if (d->__first_nonopt == d->__last_nonopt) - d->__first_nonopt = d->optind; - d->__last_nonopt = argc; + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange (argv, d); + else if (d->__first_nonopt == d->__last_nonopt) + d->__first_nonopt = d->optind; + d->__last_nonopt = argc; - d->optind = argc; - } + d->optind = argc; + } /* If we have done all the ARGV-elements, stop the scan - and back over any non-options that we skipped and permuted. */ + and back over any non-options that we skipped and permuted. */ if (d->optind == argc) - { - /* Set the next-arg-index to point at the non-options - that we previously skipped, so the caller will digest them. */ - if (d->__first_nonopt != d->__last_nonopt) - d->optind = d->__first_nonopt; - return -1; - } + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (d->__first_nonopt != d->__last_nonopt) + d->optind = d->__first_nonopt; + return -1; + } /* If we have come to a non-option and did not permute it, - either stop the scan or describe it to the caller and pass it by. */ + either stop the scan or describe it to the caller and pass it by. */ if (NONOPTION_P) - { - if (d->__ordering == REQUIRE_ORDER) - return -1; - d->optarg = argv[d->optind++]; - return 1; - } + { + if (d->__ordering == REQUIRE_ORDER) + return -1; + d->optarg = argv[d->optind++]; + return 1; + } /* We have found another option-ARGV-element. - Skip the initial punctuation. */ - - d->__nextchar = (argv[d->optind] + 1 - + (longopts != NULL && argv[d->optind][1] == '-')); - } - - /* Decode the current option-ARGV-element. */ - - /* Check whether the ARGV-element is a long option. - - If long_only and the ARGV-element has the form "-f", where f is - a valid short option, don't consider it an abbreviated form of - a long option that starts with f. Otherwise there would be no - way to give the -f short option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an abbreviation of - the long option, just like "--fu", and not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - - if (longopts != NULL - && (argv[d->optind][1] == '-' - || (long_only && (argv[d->optind][2] - || !strchr (optstring, argv[d->optind][1]))))) - { - char *nameend; - unsigned int namelen; - const struct option *p; - const struct option *pfound = NULL; - struct option_list - { - const struct option *p; - struct option_list *next; - } *ambig_list = NULL; -#ifdef _LIBC -/* malloc() not used for _LIBC to simplify failure messages. */ -# define free_option_list(l) -#else -# define free_option_list(l) \ - while (l != NULL) \ - { \ - struct option_list *pn = l->next; \ - free (l); \ - l = pn; \ - } -#endif - int exact = 0; - int ambig = 0; - int indfound = -1; - int option_index; - - for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - namelen = nameend - d->__nextchar; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, d->__nextchar, namelen)) - { - if (namelen == (unsigned int) strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else if (ambig) - ; /* Taking simpler path to handling ambiguities. */ - else if (long_only - || pfound->has_arg != p->has_arg - || pfound->flag != p->flag - || pfound->val != p->val) - { - /* Second or later nonexact match found. */ -#ifdef _LIBC - struct option_list *newp = alloca (sizeof (*newp)); -#else - struct option_list *newp = malloc (sizeof (*newp)); - if (newp == NULL) - { - free_option_list (ambig_list); - ambig_list = NULL; - ambig = 1; /* Use simpler fallback message. */ - } - else -#endif - { - newp->p = p; - newp->next = ambig_list; - ambig_list = newp; - } - } - } - - if ((ambig || ambig_list) && !exact) - { - if (print_errors && ambig_list) - { - struct option_list first; - first.p = pfound; - first.next = ambig_list; - ambig_list = &first; - -#if defined _LIBC && defined USE_IN_LIBIO - char *buf = NULL; - size_t buflen = 0; - - FILE *fp = open_memstream (&buf, &buflen); - if (fp != NULL) - { - fprintf (fp, - _("%s: option '%s' is ambiguous; possibilities:"), - argv[0], argv[d->optind]); - - do - { - fprintf (fp, " '--%s'", ambig_list->p->name); - ambig_list = ambig_list->next; - } - while (ambig_list != NULL); - - fputc_unlocked ('\n', fp); - - if (__builtin_expect (fclose (fp) != EOF, 1)) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } - } -#else - fprintf (stderr, - _("%s: option '%s' is ambiguous; possibilities:"), - argv[0], argv[d->optind]); - do - { - fprintf (stderr, " '--%s'", ambig_list->p->name); - ambig_list = ambig_list->next; - } - while (ambig_list != NULL); - - fputc ('\n', stderr); -#endif - } - else if (print_errors && ambig) - { - fprintf (stderr, - _("%s: option '%s' is ambiguous\n"), - argv[0], argv[d->optind]); - } - d->__nextchar += strlen (d->__nextchar); - d->optind++; - d->optopt = 0; - free_option_list (ambig_list); - return '?'; - } - - free_option_list (ambig_list); - - if (pfound != NULL) - { - option_index = indfound; - d->optind++; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - d->optarg = nameend + 1; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - int n; -#endif - - if (argv[d->optind - 1][1] == '-') - { - /* --option */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("\ -%s: option '--%s' doesn't allow an argument\n"), - argv[0], pfound->name); -#else - fprintf (stderr, _("\ -%s: option '--%s' doesn't allow an argument\n"), - argv[0], pfound->name); -#endif - } - else - { - /* +option or -option */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("\ -%s: option '%c%s' doesn't allow an argument\n"), - argv[0], argv[d->optind - 1][0], - pfound->name); -#else - fprintf (stderr, _("\ -%s: option '%c%s' doesn't allow an argument\n"), - argv[0], argv[d->optind - 1][0], - pfound->name); -#endif - } - -#if defined _LIBC && defined USE_IN_LIBIO - if (n >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 - |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#endif - } - - d->__nextchar += strlen (d->__nextchar); - - d->optopt = pfound->val; - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (d->optind < argc) - d->optarg = argv[d->optind++]; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option '--%s' requires an argument\n"), - argv[0], pfound->name) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 - |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, - _("%s: option '--%s' requires an argument\n"), - argv[0], pfound->name); -#endif - } - d->__nextchar += strlen (d->__nextchar); - d->optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; - } - } - d->__nextchar += strlen (d->__nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - - /* Can't find it as a long option. If this is not getopt_long_only, - or the option starts with '--' or is not a valid short - option, then it's an error. - Otherwise interpret it as a short option. */ - if (!long_only || argv[d->optind][1] == '-' - || strchr (optstring, *d->__nextchar) == NULL) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - int n; -#endif - - if (argv[d->optind][1] == '-') - { - /* --option */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: unrecognized option '--%s'\n"), - argv[0], d->__nextchar); -#else - fprintf (stderr, _("%s: unrecognized option '--%s'\n"), - argv[0], d->__nextchar); -#endif - } - else - { - /* +option or -option */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: unrecognized option '%c%s'\n"), - argv[0], argv[d->optind][0], d->__nextchar); -#else - fprintf (stderr, _("%s: unrecognized option '%c%s'\n"), - argv[0], argv[d->optind][0], d->__nextchar); -#endif - } - -#if defined _LIBC && defined USE_IN_LIBIO - if (n >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#endif - } - d->__nextchar = (char *) ""; - d->optind++; - d->optopt = 0; - return '?'; - } + Check whether it might be a long option. */ + if (longopts) + { + if (argv[d->optind][1] == '-') + { + /* "--foo" is always a long option. The special option + "--" was handled above. */ + d->__nextchar = argv[d->optind] + 2; + return process_long_option (argc, argv, optstring, longopts, + longind, long_only, d, + print_errors, "--"); + } + + /* If long_only and the ARGV-element has the form "-f", + where f is a valid short option, don't consider it an + abbreviated form of a long option that starts with f. + Otherwise there would be no way to give the -f short + option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an + abbreviation of the long option, just like "--fu", and + not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + if (long_only && (argv[d->optind][2] + || !strchr (optstring, argv[d->optind][1]))) + { + int code; + d->__nextchar = argv[d->optind] + 1; + code = process_long_option (argc, argv, optstring, longopts, + longind, long_only, d, + print_errors, "-"); + if (code != -1) + return code; + } + } + + /* It is not a long option. Skip the initial punctuation. */ + d->__nextchar = argv[d->optind] + 1; } /* Look at and handle the next short option-character. */ @@ -824,331 +617,83 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, if (temp == NULL || c == ':' || c == ';') { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - int n; -#endif - -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: invalid option -- '%c'\n"), - argv[0], c); -#else - fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c); -#endif - -#if defined _LIBC && defined USE_IN_LIBIO - if (n >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#endif - } - d->optopt = c; - return '?'; + if (print_errors) + fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c); + d->optopt = c; + return '?'; } + /* Convenience. Treat POSIX -W foo same as long option --foo */ - if (temp[0] == 'W' && temp[1] == ';') + if (temp[0] == 'W' && temp[1] == ';' && longopts != NULL) { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - - if (longopts == NULL) - goto no_longs; - - /* This is an option that requires an argument. */ - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - d->optind++; - } - else if (d->optind == argc) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, - _("%s: option requires an argument -- '%c'\n"), - argv[0], c) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, - _("%s: option requires an argument -- '%c'\n"), - argv[0], c); -#endif - } - d->optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - return c; - } - else - /* We already incremented 'd->optind' once; - increment it again when taking next ARGV-elt as argument. */ - d->optarg = argv[d->optind++]; - - /* optarg is now the argument, see if it's in the - table of longopts. */ - - for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; - nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) - { - if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else if (long_only - || pfound->has_arg != p->has_arg - || pfound->flag != p->flag - || pfound->val != p->val) - /* Second or later nonexact match found. */ - ambig = 1; - } - if (ambig && !exact) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("%s: option '-W %s' is ambiguous\n"), - argv[0], d->optarg) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, _("%s: option '-W %s' is ambiguous\n"), - argv[0], d->optarg); -#endif - } - d->__nextchar += strlen (d->__nextchar); - d->optind++; - return '?'; - } - if (pfound != NULL) - { - option_index = indfound; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - d->optarg = nameend + 1; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option '-W %s' doesn't allow an argument\n"), - argv[0], pfound->name) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 - |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, _("\ -%s: option '-W %s' doesn't allow an argument\n"), - argv[0], pfound->name); -#endif - } - - d->__nextchar += strlen (d->__nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (d->optind < argc) - d->optarg = argv[d->optind++]; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option '-W %s' requires an argument\n"), - argv[0], pfound->name) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 - |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, _("\ -%s: option '-W %s' requires an argument\n"), - argv[0], pfound->name); -#endif - } - d->__nextchar += strlen (d->__nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - else - d->optarg = NULL; - d->__nextchar += strlen (d->__nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - - no_longs: - d->__nextchar = NULL; - return 'W'; /* Let the application handle it. */ + /* This is an option that requires an argument. */ + if (*d->__nextchar != '\0') + d->optarg = d->__nextchar; + else if (d->optind == argc) + { + if (print_errors) + fprintf (stderr, + _("%s: option requires an argument -- '%c'\n"), + argv[0], c); + + d->optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + d->optarg = argv[d->optind]; + + d->__nextchar = d->optarg; + d->optarg = NULL; + return process_long_option (argc, argv, optstring, longopts, longind, + 0 /* long_only */, d, print_errors, "-W "); } if (temp[1] == ':') { - if (temp[2] == ':') - { - /* This is an option that accepts an argument optionally. */ - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - d->optind++; - } - else - d->optarg = NULL; - d->__nextchar = NULL; - } - else - { - /* This is an option that requires an argument. */ - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - d->optind++; - } - else if (d->optind == argc) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option requires an argument -- '%c'\n"), - argv[0], c) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, - _("%s: option requires an argument -- '%c'\n"), - argv[0], c); -#endif - } - d->optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - /* We already incremented 'optind' once; - increment it again when taking next ARGV-elt as argument. */ - d->optarg = argv[d->optind++]; - d->__nextchar = NULL; - } + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + d->optind++; + } + else + d->optarg = NULL; + d->__nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + d->optind++; + } + else if (d->optind == argc) + { + if (print_errors) + fprintf (stderr, + _("%s: option requires an argument -- '%c'\n"), + argv[0], c); + + d->optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented 'optind' once; + increment it again when taking next ARGV-elt as argument. */ + d->optarg = argv[d->optind++]; + d->__nextchar = NULL; + } } return c; } @@ -1156,8 +701,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, int _getopt_internal (int argc, char **argv, const char *optstring, - const struct option *longopts, int *longind, int long_only, - int posixly_correct) + const struct option *longopts, int *longind, int long_only, + int posixly_correct) { int result; @@ -1165,8 +710,8 @@ _getopt_internal (int argc, char **argv, const char *optstring, getopt_data.opterr = opterr; result = _getopt_internal_r (argc, argv, optstring, longopts, - longind, long_only, &getopt_data, - posixly_correct); + longind, long_only, &getopt_data, + posixly_correct); optind = getopt_data.optind; optarg = getopt_data.optarg; @@ -1175,32 +720,23 @@ _getopt_internal (int argc, char **argv, const char *optstring, return result; } -/* glibc gets a LSB-compliant getopt. - Standalone applications get a POSIX-compliant getopt. */ -#if _LIBC -enum { POSIXLY_CORRECT = 0 }; -#else -enum { POSIXLY_CORRECT = 1 }; -#endif - -int -getopt (int argc, char *const *argv, const char *optstring) -{ - return _getopt_internal (argc, (char **) argv, optstring, - (const struct option *) 0, - (int *) 0, - 0, POSIXLY_CORRECT); -} +/* glibc gets a LSB-compliant getopt and a POSIX-complaint __posix_getopt. + Standalone applications just get a POSIX-compliant getopt. + POSIX and LSB both require these functions to take 'char *const *argv' + even though this is incorrect (because of the permutation). */ +#define GETOPT_ENTRY(NAME, POSIXLY_CORRECT) \ + int \ + NAME (int argc, char *const *argv, const char *optstring) \ + { \ + return _getopt_internal (argc, (char **)argv, optstring, \ + 0, 0, 0, POSIXLY_CORRECT); \ + } #ifdef _LIBC -int -__posix_getopt (int argc, char *const *argv, const char *optstring) -{ - return _getopt_internal (argc, argv, optstring, - (const struct option *) 0, - (int *) 0, - 0, 1); -} +GETOPT_ENTRY(getopt, 0) +GETOPT_ENTRY(__posix_getopt, 1) +#else +GETOPT_ENTRY(getopt, 1) #endif @@ -1221,51 +757,51 @@ main (int argc, char **argv) c = getopt (argc, argv, "abc:d:0123456789"); if (c == -1) - break; + break; switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value '%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value '%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) - printf ("%s ", argv[optind++]); + printf ("%s ", argv[optind++]); printf ("\n"); } diff --git a/lib/getopt.in.h b/lib/getopt.in.h index 6cbad8e0339..4ce1eb485af 100644 --- a/lib/getopt.in.h +++ b/lib/getopt.in.h @@ -1,20 +1,22 @@ /* Declarations for getopt. - Copyright (C) 1989-1994, 1996-1999, 2001, 2003-2007, 2009-2017 Free Software - Foundation, Inc. - This file is part of the GNU C Library. + Copyright (C) 1989-2017 Free Software Foundation, Inc. + This file is part of gnulib. + Unlike most of the getopt implementation, it is NOT shared + with the GNU C Library, which supplies a different version of + this file. - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. + gnulib is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + gnulib is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + You should have received a copy of the GNU General Public + License along with gnulib; if not, see <http://www.gnu.org/licenses/>. */ #ifndef _@GUARD_PREFIX@_GETOPT_H @@ -32,230 +34,28 @@ # undef _GL_SYSTEM_GETOPT #endif -#ifndef _@GUARD_PREFIX@_GETOPT_H - -#ifndef __need_getopt -# define _@GUARD_PREFIX@_GETOPT_H 1 -#endif +#define _@GUARD_PREFIX@_GETOPT_H 1 /* Standalone applications should #define __GETOPT_PREFIX to an identifier that prefixes the external functions and variables - defined in this header. When this happens, include the - headers that might declare getopt so that they will not cause - confusion if included after this file (if the system had <getopt.h>, - we have already included it). Then systematically rename - identifiers so that they do not collide with the system functions - and variables. Renaming avoids problems with some compilers and - linkers. */ + defined in getopt-core.h and getopt-ext.h. When this happens, + include the headers that might declare getopt so that they will not + cause confusion if included after this file (if the system had + <getopt.h>, we have already included it). */ #if defined __GETOPT_PREFIX -# if !defined __need_getopt -# if !@HAVE_GETOPT_H@ -# define __need_system_stdlib_h -# include <stdlib.h> -# undef __need_system_stdlib_h -# include <stdio.h> -# include <unistd.h> -# endif -# undef __need_getopt -# endif -# undef __GETOPT_CONCAT -# undef __GETOPT_XCONCAT -# undef __GETOPT_ID -# undef getopt -# undef getopt_long -# undef getopt_long_only -# undef optarg -# undef opterr -# undef optind -# undef optopt -# undef option -# undef _getopt_internal -# define __GETOPT_CONCAT(x, y) x ## y -# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y) -# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y) -# define getopt __GETOPT_ID (getopt) -# define getopt_long __GETOPT_ID (getopt_long) -# define getopt_long_only __GETOPT_ID (getopt_long_only) -# define optarg __GETOPT_ID (optarg) -# define opterr __GETOPT_ID (opterr) -# define optind __GETOPT_ID (optind) -# define optopt __GETOPT_ID (optopt) -# define option __GETOPT_ID (option) -# define _getopt_internal __GETOPT_ID (getopt_internal) -#endif - -/* Standalone applications get correct prototypes for getopt_long and - getopt_long_only; they declare "char **argv". libc uses prototypes - with "char *const *argv" that are incorrect because getopt_long and - getopt_long_only can permute argv; this is required for backward - compatibility (e.g., for LSB 2.0.1). - - This used to be '#if defined __GETOPT_PREFIX && !defined __need_getopt', - but it caused redefinition warnings if both unistd.h and getopt.h were - included, since unistd.h includes getopt.h having previously defined - __need_getopt. - - The only place where __getopt_argv_const is used is in definitions - of getopt_long and getopt_long_only below, but these are visible - only if __need_getopt is not defined, so it is quite safe to rewrite - the conditional as follows: -*/ -#if !defined __need_getopt -# if defined __GETOPT_PREFIX -# define __getopt_argv_const /* empty */ -# else -# define __getopt_argv_const const -# endif -#endif - -/* If __GNU_LIBRARY__ is not already defined, either we are being used - standalone, or this is the first header included in the source file. - If we are being used with glibc, we need to include <features.h>, but - that does not exist if we are standalone. So: if __GNU_LIBRARY__ is - not defined, include <ctype.h>, which will pull in <features.h> for us - if it's from glibc. (Why ctype.h? It's guaranteed to exist and it - doesn't flood the namespace with stuff the way some other headers do.) */ -#if !defined __GNU_LIBRARY__ -# include <ctype.h> -#endif - -#ifndef __THROW -# ifndef __GNUC_PREREQ -# define __GNUC_PREREQ(maj, min) (0) -# endif -# if defined __cplusplus && __GNUC_PREREQ (2,8) -# define __THROW throw () -# else -# define __THROW +# if !@HAVE_GETOPT_H@ +# define __need_system_stdlib_h +# include <stdlib.h> +# undef __need_system_stdlib_h +# include <stdio.h> +# include <unistd.h> # endif #endif /* The definition of _GL_ARG_NONNULL is copied here. */ -#ifdef __cplusplus -extern "C" { -#endif - -/* For communication from 'getopt' to the caller. - When 'getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when 'ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -extern char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to 'getopt'. - - On entry to 'getopt', zero means this is the first call; initialize. - - When 'getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, 'optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -extern int optind; - -/* Callers store zero here to inhibit the error message 'getopt' prints - for unrecognized options. */ - -extern int opterr; - -/* Set to an option character which was unrecognized. */ +#include <getopt-cdefs.h> +#include <getopt-pfx-core.h> +#include <getopt-pfx-ext.h> -extern int optopt; - -#ifndef __need_getopt -/* Describe the long-named options requested by the application. - The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector - of 'struct option' terminated by an element containing a name which is - zero. - - The field 'has_arg' is: - no_argument (or 0) if the option does not take an argument, - required_argument (or 1) if the option requires an argument, - optional_argument (or 2) if the option takes an optional argument. - - If the field 'flag' is not NULL, it points to a variable that is set - to the value given in the field 'val' when the option is found, but - left unchanged if the option is not found. - - To have a long-named option do something other than set an 'int' to - a compiled-in constant, such as set a value from 'optarg', set the - option's 'flag' field to zero and its 'val' field to a nonzero - value (the equivalent single-letter option character, if there is - one). For long options that have a zero 'flag' field, 'getopt' - returns the contents of the 'val' field. */ - -# if !GNULIB_defined_struct_option -struct option -{ - const char *name; - /* has_arg can't be an enum because some compilers complain about - type mismatches in all the code that assumes it is an int. */ - int has_arg; - int *flag; - int val; -}; -# define GNULIB_defined_struct_option 1 -# endif - -/* Names for the values of the 'has_arg' field of 'struct option'. */ - -# define no_argument 0 -# define required_argument 1 -# define optional_argument 2 -#endif /* need getopt */ - - -/* Get definitions and prototypes for functions to process the - arguments in ARGV (ARGC of them, minus the program name) for - options given in OPTS. - - Return the option character from OPTS just read. Return -1 when - there are no more options. For unrecognized options, or options - missing arguments, 'optopt' is set to the option letter, and '?' is - returned. - - The OPTS string is a list of characters which are recognized option - letters, optionally followed by colons, specifying that that letter - takes an argument, to be placed in 'optarg'. - - If a letter in OPTS is followed by two colons, its argument is - optional. This behavior is specific to the GNU 'getopt'. - - The argument '--' causes premature termination of argument - scanning, explicitly telling 'getopt' that there are no more - options. - - If OPTS begins with '-', then non-option arguments are treated as - arguments to the option '\1'. This behavior is specific to the GNU - 'getopt'. If OPTS begins with '+', or POSIXLY_CORRECT is set in - the environment, then do not permute arguments. */ - -extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) - __THROW _GL_ARG_NONNULL ((2, 3)); - -#ifndef __need_getopt -extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind) - __THROW _GL_ARG_NONNULL ((2, 3)); -extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind) - __THROW _GL_ARG_NONNULL ((2, 3)); - -#endif - -#ifdef __cplusplus -} -#endif - -/* Make sure we later can get all the definitions and declarations. */ -#undef __need_getopt - -#endif /* _@GUARD_PREFIX@_GETOPT_H */ #endif /* _@GUARD_PREFIX@_GETOPT_H */ diff --git a/lib/getopt1.c b/lib/getopt1.c index 4d2e8cbac33..2bc5926016a 100644 --- a/lib/getopt1.c +++ b/lib/getopt1.c @@ -1,56 +1,44 @@ /* getopt_long and getopt_long_only entry points for GNU getopt. - Copyright (C) 1987-1994, 1996-1998, 2004, 2006, 2009-2017 Free Software - Foundation, Inc. - This file is part of the GNU C Library. + Copyright (C) 1987-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library and is also part of gnulib. + Patches to this file should be submitted to both projects. - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ -#ifdef _LIBC -# include <getopt.h> -#else +#ifndef _LIBC # include <config.h> -# include "getopt.h" #endif -#include "getopt_int.h" - -#include <stdio.h> -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -#include <stdlib.h> -#endif - -#ifndef NULL -#define NULL 0 -#endif +#include "getopt.h" +#include "getopt_int.h" int getopt_long (int argc, char *__getopt_argv_const *argv, const char *options, - const struct option *long_options, int *opt_index) + const struct option *long_options, int *opt_index) { return _getopt_internal (argc, (char **) argv, options, long_options, - opt_index, 0, 0); + opt_index, 0, 0); } int _getopt_long_r (int argc, char **argv, const char *options, - const struct option *long_options, int *opt_index, - struct _getopt_data *d) + const struct option *long_options, int *opt_index, + struct _getopt_data *d) { return _getopt_internal_r (argc, argv, options, long_options, opt_index, - 0, d, 0); + 0, d, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. @@ -60,26 +48,27 @@ _getopt_long_r (int argc, char **argv, const char *options, int getopt_long_only (int argc, char *__getopt_argv_const *argv, - const char *options, - const struct option *long_options, int *opt_index) + const char *options, + const struct option *long_options, int *opt_index) { return _getopt_internal (argc, (char **) argv, options, long_options, - opt_index, 1, 0); + opt_index, 1, 0); } int _getopt_long_only_r (int argc, char **argv, const char *options, - const struct option *long_options, int *opt_index, - struct _getopt_data *d) + const struct option *long_options, int *opt_index, + struct _getopt_data *d) { return _getopt_internal_r (argc, argv, options, long_options, opt_index, - 1, d, 0); + 1, d, 0); } #ifdef TEST #include <stdio.h> +#include <stdlib.h> int main (int argc, char **argv) @@ -93,74 +82,74 @@ main (int argc, char **argv) int option_index = 0; static const struct option long_options[] = { - {"add", 1, 0, 0}, - {"append", 0, 0, 0}, - {"delete", 1, 0, 0}, - {"verbose", 0, 0, 0}, - {"create", 0, 0, 0}, - {"file", 1, 0, 0}, - {0, 0, 0, 0} + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} }; c = getopt_long (argc, argv, "abc:d:0123456789", - long_options, &option_index); + long_options, &option_index); if (c == -1) - break; + break; switch (c) - { - case 0: - printf ("option %s", long_options[option_index].name); - if (optarg) - printf (" with arg %s", optarg); - printf ("\n"); - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value '%s'\n", optarg); - break; - - case 'd': - printf ("option d with value '%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value '%s'\n", optarg); + break; + + case 'd': + printf ("option d with value '%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) - printf ("%s ", argv[optind++]); + printf ("%s ", argv[optind++]); printf ("\n"); } diff --git a/lib/getopt_int.h b/lib/getopt_int.h index a7ce0e9cc14..a5562195123 100644 --- a/lib/getopt_int.h +++ b/lib/getopt_int.h @@ -1,30 +1,31 @@ /* Internal declarations for getopt. - Copyright (C) 1989-1994, 1996-1999, 2001, 2003-2004, 2009-2017 Free Software - Foundation, Inc. - This file is part of the GNU C Library. + Copyright (C) 1989-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library and is also part of gnulib. + Patches to this file should be submitted to both projects. - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #ifndef _GETOPT_INT_H -#define _GETOPT_INT_H 1 +#define _GETOPT_INT_H 1 #include <getopt.h> extern int _getopt_internal (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - int __long_only, int __posixly_correct); + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only, int __posixly_correct); /* Reentrant versions which can handle parsing multiple argument @@ -32,28 +33,20 @@ extern int _getopt_internal (int ___argc, char **___argv, /* Describe how to deal with options that follow non-option ARGV-elements. - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. + REQUIRE_ORDER means don't recognize them as options; stop option + processing when the first non-option is seen. This is what POSIX + specifies should happen. - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using '+' as the first character - of the list of option characters, or by calling getopt. - - PERMUTE is the default. We permute the contents of ARGV as we - scan, so that eventually all the non-options are at the end. - This allows options to be given in any order, even with programs - that were not written to expect this. + PERMUTE means permute the contents of ARGV as we scan, so that + eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written + to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option - with character code 1. Using '-' as the first character of the - list of option characters selects this mode of operation. + with character code 1. The special argument '--' forces an end of option-scanning regardless of the value of 'ordering'. In the case of RETURN_IN_ORDER, only @@ -91,11 +84,6 @@ struct _getopt_data /* See __ord above. */ enum __ord __ordering; - /* If the POSIXLY_CORRECT environment variable is set - or getopt was called. */ - int __posixly_correct; - - /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have @@ -104,32 +92,27 @@ struct _getopt_data int __first_nonopt; int __last_nonopt; - -#if defined _LIBC && defined USE_NONOPTION_FLAGS - int __nonoption_flags_max_len; - int __nonoption_flags_len; -#endif }; /* The initializer is necessary to set OPTIND and OPTERR to their default values and to clear the initialization flag. */ -#define _GETOPT_DATA_INITIALIZER { 1, 1 } +#define _GETOPT_DATA_INITIALIZER { 1, 1 } extern int _getopt_internal_r (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - int __long_only, struct _getopt_data *__data, - int __posixly_correct); + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only, struct _getopt_data *__data, + int __posixly_correct); extern int _getopt_long_r (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - struct _getopt_data *__data); + const char *__shortopts, + const struct option *__longopts, int *__longind, + struct _getopt_data *__data); extern int _getopt_long_only_r (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, - int *__longind, - struct _getopt_data *__data); + const char *__shortopts, + const struct option *__longopts, + int *__longind, + struct _getopt_data *__data); #endif /* getopt_int.h */ diff --git a/lib/gettext.h b/lib/gettext.h index 0465d7ad148..742ce37e6ce 100644 --- a/lib/gettext.h +++ b/lib/gettext.h @@ -18,8 +18,9 @@ #ifndef _LIBGETTEXT_H #define _LIBGETTEXT_H 1 -/* NLS can be disabled through the configure --disable-nls option. */ -#if ENABLE_NLS +/* NLS can be disabled through the configure --disable-nls option + or through "#define ENABLE NLS 0" before including this file. */ +#if defined ENABLE_NLS && ENABLE_NLS /* Get declarations of GNU message catalog functions. */ # include <libintl.h> @@ -184,7 +185,8 @@ npgettext_aux (const char *domain, #include <string.h> #if (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \ - /* || __STDC_VERSION__ >= 199901L */ ) + /* || __STDC_VERSION__ == 199901L + || (__STDC_VERSION__ >= 201112L && !defined __STDC_NO_VLA__) */ ) # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1 #else # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0 diff --git a/lib/gettimeofday.c b/lib/gettimeofday.c index 18dcbda4db5..8ae7622af31 100644 --- a/lib/gettimeofday.c +++ b/lib/gettimeofday.c @@ -24,93 +24,95 @@ #include <time.h> -#if HAVE_SYS_TIMEB_H -# include <sys/timeb.h> +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# define WINDOWS_NATIVE +# include <windows.h> #endif -#if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME +#include "localtime-buffer.h" -/* Work around the bug in some systems whereby gettimeofday clobbers - the static buffer that localtime uses for its return value. The - gettimeofday function from Mac OS X 10.0.4 (i.e., Darwin 1.3.7) has - this problem. The tzset replacement is necessary for at least - Solaris 2.5, 2.5.1, and 2.6. */ - -static struct tm tm_zero_buffer; -static struct tm *localtime_buffer_addr = &tm_zero_buffer; - -# undef localtime -extern struct tm *localtime (time_t const *); - -# undef gmtime -extern struct tm *gmtime (time_t const *); - -/* This is a wrapper for localtime. It is used only on systems for which - gettimeofday clobbers the static buffer used for localtime's result. +#ifdef WINDOWS_NATIVE - On the first call, record the address of the static buffer that - localtime uses for its result. */ - -struct tm * -rpl_localtime (time_t const *timep) -{ - struct tm *tm = localtime (timep); - - if (localtime_buffer_addr == &tm_zero_buffer) - localtime_buffer_addr = tm; - - return tm; -} +/* GetSystemTimePreciseAsFileTime was introduced only in Windows 8. */ +typedef void (WINAPI * GetSystemTimePreciseAsFileTimeFuncType) (FILETIME *lpTime); +static GetSystemTimePreciseAsFileTimeFuncType GetSystemTimePreciseAsFileTimeFunc = NULL; +static BOOL initialized = FALSE; -/* Same as above, since gmtime and localtime use the same buffer. */ -struct tm * -rpl_gmtime (time_t const *timep) +static void +initialize (void) { - struct tm *tm = gmtime (timep); - - if (localtime_buffer_addr == &tm_zero_buffer) - localtime_buffer_addr = tm; - - return tm; + HMODULE kernel32 = LoadLibrary ("kernel32.dll"); + if (kernel32 != NULL) + { + GetSystemTimePreciseAsFileTimeFunc = + (GetSystemTimePreciseAsFileTimeFuncType) GetProcAddress (kernel32, "GetSystemTimePreciseAsFileTime"); + } + initialized = TRUE; } -#endif /* GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME */ - -#if TZSET_CLOBBERS_LOCALTIME - -# undef tzset -extern void tzset (void); - -/* This is a wrapper for tzset, for systems on which tzset may clobber - the static buffer used for localtime's result. */ -void -rpl_tzset (void) -{ - /* Save and restore the contents of the buffer used for localtime's - result around the call to tzset. */ - struct tm save = *localtime_buffer_addr; - tzset (); - *localtime_buffer_addr = save; -} #endif /* This is a wrapper for gettimeofday. It is used only on systems that lack this function, or whose implementation of this function - causes problems. */ + causes problems. + Work around the bug in some systems whereby gettimeofday clobbers + the static buffer that localtime uses for its return value. The + gettimeofday function from Mac OS X 10.0.4 (i.e., Darwin 1.3.7) has + this problem. */ int gettimeofday (struct timeval *restrict tv, void *restrict tz) { #undef gettimeofday -#if HAVE_GETTIMEOFDAY -# if GETTIMEOFDAY_CLOBBERS_LOCALTIME +#ifdef WINDOWS_NATIVE + + /* On native Windows, there are two ways to get the current time: + GetSystemTimeAsFileTime + <https://msdn.microsoft.com/en-us/library/ms724397.aspx> + or + GetSystemTimePreciseAsFileTime + <https://msdn.microsoft.com/en-us/library/hh706895.aspx>. + GetSystemTimeAsFileTime produces values that jump by increments of + 15.627 milliseconds (!) on average. + Whereas GetSystemTimePreciseAsFileTime values usually jump by 1 or 2 + microseconds. + More discussion on this topic: + <http://www.windowstimestamp.com/description>. */ + FILETIME current_time; + + if (!initialized) + initialize (); + if (GetSystemTimePreciseAsFileTimeFunc != NULL) + GetSystemTimePreciseAsFileTimeFunc (¤t_time); + else + GetSystemTimeAsFileTime (¤t_time); + + /* Convert from FILETIME to 'struct timeval'. */ + /* FILETIME: <https://msdn.microsoft.com/en-us/library/ms724284.aspx> */ + ULONGLONG since_1601 = + ((ULONGLONG) current_time.dwHighDateTime << 32) + | (ULONGLONG) current_time.dwLowDateTime; + /* Between 1601-01-01 and 1970-01-01 there were 280 normal years and 89 leap + years, in total 134774 days. */ + ULONGLONG since_1970 = + since_1601 - (ULONGLONG) 134774 * (ULONGLONG) 86400 * (ULONGLONG) 10000000; + ULONGLONG microseconds_since_1970 = since_1970 / (ULONGLONG) 10; + tv->tv_sec = microseconds_since_1970 / (ULONGLONG) 1000000; + tv->tv_usec = microseconds_since_1970 % (ULONGLONG) 1000000; + + return 0; + +#else + +# if HAVE_GETTIMEOFDAY +# if GETTIMEOFDAY_CLOBBERS_LOCALTIME /* Save and restore the contents of the buffer used for localtime's result around the call to gettimeofday. */ struct tm save = *localtime_buffer_addr; -# endif +# endif -# if defined timeval /* 'struct timeval' overridden by gnulib? */ -# undef timeval +# if defined timeval /* 'struct timeval' overridden by gnulib? */ +# undef timeval struct timeval otv; int result = gettimeofday (&otv, (struct timezone *) tz); if (result == 0) @@ -118,25 +120,16 @@ gettimeofday (struct timeval *restrict tv, void *restrict tz) tv->tv_sec = otv.tv_sec; tv->tv_usec = otv.tv_usec; } -# else +# else int result = gettimeofday (tv, (struct timezone *) tz); -# endif +# endif -# if GETTIMEOFDAY_CLOBBERS_LOCALTIME +# if GETTIMEOFDAY_CLOBBERS_LOCALTIME *localtime_buffer_addr = save; -# endif +# endif return result; -#else - -# if HAVE__FTIME - - struct _timeb timebuf; - _ftime (&timebuf); - tv->tv_sec = timebuf.time; - tv->tv_usec = timebuf.millitm * 1000; - # else # if !defined OK_TO_USE_1S_CLOCK @@ -146,9 +139,8 @@ gettimeofday (struct timeval *restrict tv, void *restrict tz) tv->tv_sec = time (NULL); tv->tv_usec = 0; -# endif - return 0; +# endif #endif } diff --git a/lib/gnulib.mk b/lib/gnulib.mk.in similarity index 60% rename from lib/gnulib.mk rename to lib/gnulib.mk.in index 5fea3f26e25..918118684e9 100644 --- a/lib/gnulib.mk +++ b/lib/gnulib.mk.in @@ -21,10 +21,934 @@ # the same distribution terms as the rest of that program. # # Generated by gnulib-tool. -# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=unsetenv --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings +# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stat --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=tzset --avoid=unsetenv --avoid=utime --avoid=utime-h --gnu-make --makefile-name=gnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 diffseq dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr minmax mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strftime strtoimax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub unlocked-io update-copyright utimens vla warnings MOSTLYCLEANFILES += core *.stackdump +# Start of GNU Make output. +ALLOCA = @ALLOCA@ +ALLOCA_H = @ALLOCA_H@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +AM_DEFAULT_V = @AM_DEFAULT_V@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AM_V = @AM_V@ +APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@ +AR = @AR@ +ARFLAGS = @ARFLAGS@ +AUTO_DEPEND = @AUTO_DEPEND@ +AWK = @AWK@ +BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@ +BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@ +BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@ +BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@ +BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@ +BLESSMAIL_TARGET = @BLESSMAIL_TARGET@ +BUILD_DETAILS = @BUILD_DETAILS@ +BYTESWAP_H = @BYTESWAP_H@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CANNOT_DUMP = @CANNOT_DUMP@ +CC = @CC@ +CFLAGS = @CFLAGS@ +CFLAGS_SOUND = @CFLAGS_SOUND@ +CLIENTRES = @CLIENTRES@ +CLIENTW = @CLIENTW@ +CM_OBJ = @CM_OBJ@ +COM_ERRLIB = @COM_ERRLIB@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPTOLIB = @CRYPTOLIB@ +CYGWIN_OBJ = @CYGWIN_OBJ@ +C_SWITCH_MACHINE = @C_SWITCH_MACHINE@ +C_SWITCH_SYSTEM = @C_SWITCH_SYSTEM@ +C_SWITCH_X_SITE = @C_SWITCH_X_SITE@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_OBJ = @DBUS_OBJ@ +DEFS = @DEFS@ +DESLIB = @DESLIB@ +DOCMISC_W32 = @DOCMISC_W32@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EMACSRES = @EMACSRES@ +EMACS_MANIFEST = @EMACS_MANIFEST@ +EMULTIHOP_HIDDEN = @EMULTIHOP_HIDDEN@ +EMULTIHOP_VALUE = @EMULTIHOP_VALUE@ +ENOLINK_HIDDEN = @ENOLINK_HIDDEN@ +ENOLINK_VALUE = @ENOLINK_VALUE@ +EOVERFLOW_HIDDEN = @EOVERFLOW_HIDDEN@ +EOVERFLOW_VALUE = @EOVERFLOW_VALUE@ +ERRNO_H = @ERRNO_H@ +EXECINFO_H = @EXECINFO_H@ +EXEEXT = @EXEEXT@ +FIND_DELETE = @FIND_DELETE@ +FIRSTFILE_OBJ = @FIRSTFILE_OBJ@ +FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ +FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ +FONT_OBJ = @FONT_OBJ@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +GCONF_CFLAGS = @GCONF_CFLAGS@ +GCONF_LIBS = @GCONF_LIBS@ +GETADDRINFO_A_LIBS = @GETADDRINFO_A_LIBS@ +GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ +GETOPT_CDEFS_H = @GETOPT_CDEFS_H@ +GETOPT_H = @GETOPT_H@ +GFILENOTIFY_CFLAGS = @GFILENOTIFY_CFLAGS@ +GFILENOTIFY_LIBS = @GFILENOTIFY_LIBS@ +GL_COND_LIBTOOL = @GL_COND_LIBTOOL@ +GL_GENERATE_ALLOCA_H = @GL_GENERATE_ALLOCA_H@ +GL_GENERATE_BYTESWAP_H = @GL_GENERATE_BYTESWAP_H@ +GL_GENERATE_ERRNO_H = @GL_GENERATE_ERRNO_H@ +GL_GENERATE_EXECINFO_H = @GL_GENERATE_EXECINFO_H@ +GL_GENERATE_LIMITS_H = @GL_GENERATE_LIMITS_H@ +GL_GENERATE_STDALIGN_H = @GL_GENERATE_STDALIGN_H@ +GL_GENERATE_STDDEF_H = @GL_GENERATE_STDDEF_H@ +GL_GENERATE_STDINT_H = @GL_GENERATE_STDINT_H@ +GMALLOC_OBJ = @GMALLOC_OBJ@ +GNULIB_ALPHASORT = @GNULIB_ALPHASORT@ +GNULIB_ATOLL = @GNULIB_ATOLL@ +GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@ +GNULIB_CANONICALIZE_FILE_NAME = @GNULIB_CANONICALIZE_FILE_NAME@ +GNULIB_CHDIR = @GNULIB_CHDIR@ +GNULIB_CHOWN = @GNULIB_CHOWN@ +GNULIB_CLOSE = @GNULIB_CLOSE@ +GNULIB_CLOSEDIR = @GNULIB_CLOSEDIR@ +GNULIB_CTIME = @GNULIB_CTIME@ +GNULIB_DIRFD = @GNULIB_DIRFD@ +GNULIB_DPRINTF = @GNULIB_DPRINTF@ +GNULIB_DUP = @GNULIB_DUP@ +GNULIB_DUP2 = @GNULIB_DUP2@ +GNULIB_DUP3 = @GNULIB_DUP3@ +GNULIB_ENVIRON = @GNULIB_ENVIRON@ +GNULIB_EUIDACCESS = @GNULIB_EUIDACCESS@ +GNULIB_FACCESSAT = @GNULIB_FACCESSAT@ +GNULIB_FCHDIR = @GNULIB_FCHDIR@ +GNULIB_FCHMODAT = @GNULIB_FCHMODAT@ +GNULIB_FCHOWNAT = @GNULIB_FCHOWNAT@ +GNULIB_FCLOSE = @GNULIB_FCLOSE@ +GNULIB_FCNTL = @GNULIB_FCNTL@ +GNULIB_FDATASYNC = @GNULIB_FDATASYNC@ +GNULIB_FDOPEN = @GNULIB_FDOPEN@ +GNULIB_FDOPENDIR = @GNULIB_FDOPENDIR@ +GNULIB_FFLUSH = @GNULIB_FFLUSH@ +GNULIB_FFSL = @GNULIB_FFSL@ +GNULIB_FFSLL = @GNULIB_FFSLL@ +GNULIB_FGETC = @GNULIB_FGETC@ +GNULIB_FGETS = @GNULIB_FGETS@ +GNULIB_FOPEN = @GNULIB_FOPEN@ +GNULIB_FPRINTF = @GNULIB_FPRINTF@ +GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@ +GNULIB_FPURGE = @GNULIB_FPURGE@ +GNULIB_FPUTC = @GNULIB_FPUTC@ +GNULIB_FPUTS = @GNULIB_FPUTS@ +GNULIB_FREAD = @GNULIB_FREAD@ +GNULIB_FREOPEN = @GNULIB_FREOPEN@ +GNULIB_FSCANF = @GNULIB_FSCANF@ +GNULIB_FSEEK = @GNULIB_FSEEK@ +GNULIB_FSEEKO = @GNULIB_FSEEKO@ +GNULIB_FSTAT = @GNULIB_FSTAT@ +GNULIB_FSTATAT = @GNULIB_FSTATAT@ +GNULIB_FSYNC = @GNULIB_FSYNC@ +GNULIB_FTELL = @GNULIB_FTELL@ +GNULIB_FTELLO = @GNULIB_FTELLO@ +GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@ +GNULIB_FUTIMENS = @GNULIB_FUTIMENS@ +GNULIB_FWRITE = @GNULIB_FWRITE@ +GNULIB_GETC = @GNULIB_GETC@ +GNULIB_GETCHAR = @GNULIB_GETCHAR@ +GNULIB_GETCWD = @GNULIB_GETCWD@ +GNULIB_GETDELIM = @GNULIB_GETDELIM@ +GNULIB_GETDOMAINNAME = @GNULIB_GETDOMAINNAME@ +GNULIB_GETDTABLESIZE = @GNULIB_GETDTABLESIZE@ +GNULIB_GETGROUPS = @GNULIB_GETGROUPS@ +GNULIB_GETHOSTNAME = @GNULIB_GETHOSTNAME@ +GNULIB_GETLINE = @GNULIB_GETLINE@ +GNULIB_GETLOADAVG = @GNULIB_GETLOADAVG@ +GNULIB_GETLOGIN = @GNULIB_GETLOGIN@ +GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@ +GNULIB_GETPAGESIZE = @GNULIB_GETPAGESIZE@ +GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@ +GNULIB_GETTIMEOFDAY = @GNULIB_GETTIMEOFDAY@ +GNULIB_GETUSERSHELL = @GNULIB_GETUSERSHELL@ +GNULIB_GL_UNISTD_H_GETOPT = @GNULIB_GL_UNISTD_H_GETOPT@ +GNULIB_GRANTPT = @GNULIB_GRANTPT@ +GNULIB_GROUP_MEMBER = @GNULIB_GROUP_MEMBER@ +GNULIB_IMAXABS = @GNULIB_IMAXABS@ +GNULIB_IMAXDIV = @GNULIB_IMAXDIV@ +GNULIB_ISATTY = @GNULIB_ISATTY@ +GNULIB_LCHMOD = @GNULIB_LCHMOD@ +GNULIB_LCHOWN = @GNULIB_LCHOWN@ +GNULIB_LINK = @GNULIB_LINK@ +GNULIB_LINKAT = @GNULIB_LINKAT@ +GNULIB_LOCALTIME = @GNULIB_LOCALTIME@ +GNULIB_LSEEK = @GNULIB_LSEEK@ +GNULIB_LSTAT = @GNULIB_LSTAT@ +GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@ +GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@ +GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@ +GNULIB_MBSCHR = @GNULIB_MBSCHR@ +GNULIB_MBSCSPN = @GNULIB_MBSCSPN@ +GNULIB_MBSLEN = @GNULIB_MBSLEN@ +GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@ +GNULIB_MBSNLEN = @GNULIB_MBSNLEN@ +GNULIB_MBSPBRK = @GNULIB_MBSPBRK@ +GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@ +GNULIB_MBSRCHR = @GNULIB_MBSRCHR@ +GNULIB_MBSSEP = @GNULIB_MBSSEP@ +GNULIB_MBSSPN = @GNULIB_MBSSPN@ +GNULIB_MBSSTR = @GNULIB_MBSSTR@ +GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@ +GNULIB_MBTOWC = @GNULIB_MBTOWC@ +GNULIB_MEMCHR = @GNULIB_MEMCHR@ +GNULIB_MEMMEM = @GNULIB_MEMMEM@ +GNULIB_MEMPCPY = @GNULIB_MEMPCPY@ +GNULIB_MEMRCHR = @GNULIB_MEMRCHR@ +GNULIB_MKDIRAT = @GNULIB_MKDIRAT@ +GNULIB_MKDTEMP = @GNULIB_MKDTEMP@ +GNULIB_MKFIFO = @GNULIB_MKFIFO@ +GNULIB_MKFIFOAT = @GNULIB_MKFIFOAT@ +GNULIB_MKNOD = @GNULIB_MKNOD@ +GNULIB_MKNODAT = @GNULIB_MKNODAT@ +GNULIB_MKOSTEMP = @GNULIB_MKOSTEMP@ +GNULIB_MKOSTEMPS = @GNULIB_MKOSTEMPS@ +GNULIB_MKSTEMP = @GNULIB_MKSTEMP@ +GNULIB_MKSTEMPS = @GNULIB_MKSTEMPS@ +GNULIB_MKTIME = @GNULIB_MKTIME@ +GNULIB_NANOSLEEP = @GNULIB_NANOSLEEP@ +GNULIB_NONBLOCKING = @GNULIB_NONBLOCKING@ +GNULIB_OBSTACK_PRINTF = @GNULIB_OBSTACK_PRINTF@ +GNULIB_OBSTACK_PRINTF_POSIX = @GNULIB_OBSTACK_PRINTF_POSIX@ +GNULIB_OPEN = @GNULIB_OPEN@ +GNULIB_OPENAT = @GNULIB_OPENAT@ +GNULIB_OPENDIR = @GNULIB_OPENDIR@ +GNULIB_OVERRIDES_STRUCT_STAT = @GNULIB_OVERRIDES_STRUCT_STAT@ +GNULIB_OVERRIDES_WINT_T = @GNULIB_OVERRIDES_WINT_T@ +GNULIB_PCLOSE = @GNULIB_PCLOSE@ +GNULIB_PERROR = @GNULIB_PERROR@ +GNULIB_PIPE = @GNULIB_PIPE@ +GNULIB_PIPE2 = @GNULIB_PIPE2@ +GNULIB_POPEN = @GNULIB_POPEN@ +GNULIB_POSIX_OPENPT = @GNULIB_POSIX_OPENPT@ +GNULIB_PREAD = @GNULIB_PREAD@ +GNULIB_PRINTF = @GNULIB_PRINTF@ +GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@ +GNULIB_PSELECT = @GNULIB_PSELECT@ +GNULIB_PTHREAD_SIGMASK = @GNULIB_PTHREAD_SIGMASK@ +GNULIB_PTSNAME = @GNULIB_PTSNAME@ +GNULIB_PTSNAME_R = @GNULIB_PTSNAME_R@ +GNULIB_PUTC = @GNULIB_PUTC@ +GNULIB_PUTCHAR = @GNULIB_PUTCHAR@ +GNULIB_PUTENV = @GNULIB_PUTENV@ +GNULIB_PUTS = @GNULIB_PUTS@ +GNULIB_PWRITE = @GNULIB_PWRITE@ +GNULIB_QSORT_R = @GNULIB_QSORT_R@ +GNULIB_RAISE = @GNULIB_RAISE@ +GNULIB_RANDOM = @GNULIB_RANDOM@ +GNULIB_RANDOM_R = @GNULIB_RANDOM_R@ +GNULIB_RAWMEMCHR = @GNULIB_RAWMEMCHR@ +GNULIB_READ = @GNULIB_READ@ +GNULIB_READDIR = @GNULIB_READDIR@ +GNULIB_READLINK = @GNULIB_READLINK@ +GNULIB_READLINKAT = @GNULIB_READLINKAT@ +GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@ +GNULIB_REALPATH = @GNULIB_REALPATH@ +GNULIB_REMOVE = @GNULIB_REMOVE@ +GNULIB_RENAME = @GNULIB_RENAME@ +GNULIB_RENAMEAT = @GNULIB_RENAMEAT@ +GNULIB_REWINDDIR = @GNULIB_REWINDDIR@ +GNULIB_RMDIR = @GNULIB_RMDIR@ +GNULIB_RPMATCH = @GNULIB_RPMATCH@ +GNULIB_SCANDIR = @GNULIB_SCANDIR@ +GNULIB_SCANF = @GNULIB_SCANF@ +GNULIB_SECURE_GETENV = @GNULIB_SECURE_GETENV@ +GNULIB_SELECT = @GNULIB_SELECT@ +GNULIB_SETENV = @GNULIB_SETENV@ +GNULIB_SETHOSTNAME = @GNULIB_SETHOSTNAME@ +GNULIB_SIGACTION = @GNULIB_SIGACTION@ +GNULIB_SIGNAL_H_SIGPIPE = @GNULIB_SIGNAL_H_SIGPIPE@ +GNULIB_SIGPROCMASK = @GNULIB_SIGPROCMASK@ +GNULIB_SLEEP = @GNULIB_SLEEP@ +GNULIB_SNPRINTF = @GNULIB_SNPRINTF@ +GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@ +GNULIB_STAT = @GNULIB_STAT@ +GNULIB_STDIO_H_NONBLOCKING = @GNULIB_STDIO_H_NONBLOCKING@ +GNULIB_STDIO_H_SIGPIPE = @GNULIB_STDIO_H_SIGPIPE@ +GNULIB_STPCPY = @GNULIB_STPCPY@ +GNULIB_STPNCPY = @GNULIB_STPNCPY@ +GNULIB_STRCASESTR = @GNULIB_STRCASESTR@ +GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@ +GNULIB_STRDUP = @GNULIB_STRDUP@ +GNULIB_STRERROR = @GNULIB_STRERROR@ +GNULIB_STRERROR_R = @GNULIB_STRERROR_R@ +GNULIB_STRFTIME = @GNULIB_STRFTIME@ +GNULIB_STRNCAT = @GNULIB_STRNCAT@ +GNULIB_STRNDUP = @GNULIB_STRNDUP@ +GNULIB_STRNLEN = @GNULIB_STRNLEN@ +GNULIB_STRPBRK = @GNULIB_STRPBRK@ +GNULIB_STRPTIME = @GNULIB_STRPTIME@ +GNULIB_STRSEP = @GNULIB_STRSEP@ +GNULIB_STRSIGNAL = @GNULIB_STRSIGNAL@ +GNULIB_STRSTR = @GNULIB_STRSTR@ +GNULIB_STRTOD = @GNULIB_STRTOD@ +GNULIB_STRTOIMAX = @GNULIB_STRTOIMAX@ +GNULIB_STRTOK_R = @GNULIB_STRTOK_R@ +GNULIB_STRTOLL = @GNULIB_STRTOLL@ +GNULIB_STRTOULL = @GNULIB_STRTOULL@ +GNULIB_STRTOUMAX = @GNULIB_STRTOUMAX@ +GNULIB_STRVERSCMP = @GNULIB_STRVERSCMP@ +GNULIB_SYMLINK = @GNULIB_SYMLINK@ +GNULIB_SYMLINKAT = @GNULIB_SYMLINKAT@ +GNULIB_SYSTEM_POSIX = @GNULIB_SYSTEM_POSIX@ +GNULIB_TIMEGM = @GNULIB_TIMEGM@ +GNULIB_TIME_R = @GNULIB_TIME_R@ +GNULIB_TIME_RZ = @GNULIB_TIME_RZ@ +GNULIB_TMPFILE = @GNULIB_TMPFILE@ +GNULIB_TRUNCATE = @GNULIB_TRUNCATE@ +GNULIB_TTYNAME_R = @GNULIB_TTYNAME_R@ +GNULIB_TZSET = @GNULIB_TZSET@ +GNULIB_UNISTD_H_NONBLOCKING = @GNULIB_UNISTD_H_NONBLOCKING@ +GNULIB_UNISTD_H_SIGPIPE = @GNULIB_UNISTD_H_SIGPIPE@ +GNULIB_UNLINK = @GNULIB_UNLINK@ +GNULIB_UNLINKAT = @GNULIB_UNLINKAT@ +GNULIB_UNLOCKPT = @GNULIB_UNLOCKPT@ +GNULIB_UNSETENV = @GNULIB_UNSETENV@ +GNULIB_USLEEP = @GNULIB_USLEEP@ +GNULIB_UTIMENSAT = @GNULIB_UTIMENSAT@ +GNULIB_VASPRINTF = @GNULIB_VASPRINTF@ +GNULIB_VDPRINTF = @GNULIB_VDPRINTF@ +GNULIB_VFPRINTF = @GNULIB_VFPRINTF@ +GNULIB_VFPRINTF_POSIX = @GNULIB_VFPRINTF_POSIX@ +GNULIB_VFSCANF = @GNULIB_VFSCANF@ +GNULIB_VPRINTF = @GNULIB_VPRINTF@ +GNULIB_VPRINTF_POSIX = @GNULIB_VPRINTF_POSIX@ +GNULIB_VSCANF = @GNULIB_VSCANF@ +GNULIB_VSNPRINTF = @GNULIB_VSNPRINTF@ +GNULIB_VSPRINTF_POSIX = @GNULIB_VSPRINTF_POSIX@ +GNULIB_WARN_CFLAGS = @GNULIB_WARN_CFLAGS@ +GNULIB_WCTOMB = @GNULIB_WCTOMB@ +GNULIB_WRITE = @GNULIB_WRITE@ +GNULIB__EXIT = @GNULIB__EXIT@ +GNUSTEP_CFLAGS = @GNUSTEP_CFLAGS@ +GNU_OBJC_CFLAGS = @GNU_OBJC_CFLAGS@ +GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ +GOBJECT_LIBS = @GOBJECT_LIBS@ +GREP = @GREP@ +GSETTINGS_CFLAGS = @GSETTINGS_CFLAGS@ +GSETTINGS_LIBS = @GSETTINGS_LIBS@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_OBJ = @GTK_OBJ@ +GZIP_PROG = @GZIP_PROG@ +HAVE_ALPHASORT = @HAVE_ALPHASORT@ +HAVE_ATOLL = @HAVE_ATOLL@ +HAVE_C99_STDINT_H = @HAVE_C99_STDINT_H@ +HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@ +HAVE_CHOWN = @HAVE_CHOWN@ +HAVE_CLOSEDIR = @HAVE_CLOSEDIR@ +HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@ +HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@ +HAVE_DECL_FCHDIR = @HAVE_DECL_FCHDIR@ +HAVE_DECL_FDATASYNC = @HAVE_DECL_FDATASYNC@ +HAVE_DECL_FDOPENDIR = @HAVE_DECL_FDOPENDIR@ +HAVE_DECL_FPURGE = @HAVE_DECL_FPURGE@ +HAVE_DECL_FSEEKO = @HAVE_DECL_FSEEKO@ +HAVE_DECL_FTELLO = @HAVE_DECL_FTELLO@ +HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@ +HAVE_DECL_GETDOMAINNAME = @HAVE_DECL_GETDOMAINNAME@ +HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@ +HAVE_DECL_GETLOADAVG = @HAVE_DECL_GETLOADAVG@ +HAVE_DECL_GETLOGIN = @HAVE_DECL_GETLOGIN@ +HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@ +HAVE_DECL_GETPAGESIZE = @HAVE_DECL_GETPAGESIZE@ +HAVE_DECL_GETUSERSHELL = @HAVE_DECL_GETUSERSHELL@ +HAVE_DECL_IMAXABS = @HAVE_DECL_IMAXABS@ +HAVE_DECL_IMAXDIV = @HAVE_DECL_IMAXDIV@ +HAVE_DECL_LOCALTIME_R = @HAVE_DECL_LOCALTIME_R@ +HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@ +HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@ +HAVE_DECL_OBSTACK_PRINTF = @HAVE_DECL_OBSTACK_PRINTF@ +HAVE_DECL_SETENV = @HAVE_DECL_SETENV@ +HAVE_DECL_SETHOSTNAME = @HAVE_DECL_SETHOSTNAME@ +HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@ +HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@ +HAVE_DECL_STRERROR_R = @HAVE_DECL_STRERROR_R@ +HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@ +HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@ +HAVE_DECL_STRSIGNAL = @HAVE_DECL_STRSIGNAL@ +HAVE_DECL_STRTOIMAX = @HAVE_DECL_STRTOIMAX@ +HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@ +HAVE_DECL_STRTOUMAX = @HAVE_DECL_STRTOUMAX@ +HAVE_DECL_TTYNAME_R = @HAVE_DECL_TTYNAME_R@ +HAVE_DECL_UNSETENV = @HAVE_DECL_UNSETENV@ +HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@ +HAVE_DIRENT_H = @HAVE_DIRENT_H@ +HAVE_DPRINTF = @HAVE_DPRINTF@ +HAVE_DUP2 = @HAVE_DUP2@ +HAVE_DUP3 = @HAVE_DUP3@ +HAVE_EUIDACCESS = @HAVE_EUIDACCESS@ +HAVE_FACCESSAT = @HAVE_FACCESSAT@ +HAVE_FCHDIR = @HAVE_FCHDIR@ +HAVE_FCHMODAT = @HAVE_FCHMODAT@ +HAVE_FCHOWNAT = @HAVE_FCHOWNAT@ +HAVE_FCNTL = @HAVE_FCNTL@ +HAVE_FDATASYNC = @HAVE_FDATASYNC@ +HAVE_FDOPENDIR = @HAVE_FDOPENDIR@ +HAVE_FFSL = @HAVE_FFSL@ +HAVE_FFSLL = @HAVE_FFSLL@ +HAVE_FSEEKO = @HAVE_FSEEKO@ +HAVE_FSTATAT = @HAVE_FSTATAT@ +HAVE_FSYNC = @HAVE_FSYNC@ +HAVE_FTELLO = @HAVE_FTELLO@ +HAVE_FTRUNCATE = @HAVE_FTRUNCATE@ +HAVE_FUTIMENS = @HAVE_FUTIMENS@ +HAVE_GETDTABLESIZE = @HAVE_GETDTABLESIZE@ +HAVE_GETGROUPS = @HAVE_GETGROUPS@ +HAVE_GETHOSTNAME = @HAVE_GETHOSTNAME@ +HAVE_GETLOGIN = @HAVE_GETLOGIN@ +HAVE_GETOPT_H = @HAVE_GETOPT_H@ +HAVE_GETPAGESIZE = @HAVE_GETPAGESIZE@ +HAVE_GETSUBOPT = @HAVE_GETSUBOPT@ +HAVE_GETTIMEOFDAY = @HAVE_GETTIMEOFDAY@ +HAVE_GRANTPT = @HAVE_GRANTPT@ +HAVE_GROUP_MEMBER = @HAVE_GROUP_MEMBER@ +HAVE_INTTYPES_H = @HAVE_INTTYPES_H@ +HAVE_LCHMOD = @HAVE_LCHMOD@ +HAVE_LCHOWN = @HAVE_LCHOWN@ +HAVE_LINK = @HAVE_LINK@ +HAVE_LINKAT = @HAVE_LINKAT@ +HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@ +HAVE_LSTAT = @HAVE_LSTAT@ +HAVE_MAKEINFO = @HAVE_MAKEINFO@ +HAVE_MAX_ALIGN_T = @HAVE_MAX_ALIGN_T@ +HAVE_MBSLEN = @HAVE_MBSLEN@ +HAVE_MEMCHR = @HAVE_MEMCHR@ +HAVE_MEMPCPY = @HAVE_MEMPCPY@ +HAVE_MKDIRAT = @HAVE_MKDIRAT@ +HAVE_MKDTEMP = @HAVE_MKDTEMP@ +HAVE_MKFIFO = @HAVE_MKFIFO@ +HAVE_MKFIFOAT = @HAVE_MKFIFOAT@ +HAVE_MKNOD = @HAVE_MKNOD@ +HAVE_MKNODAT = @HAVE_MKNODAT@ +HAVE_MKOSTEMP = @HAVE_MKOSTEMP@ +HAVE_MKOSTEMPS = @HAVE_MKOSTEMPS@ +HAVE_MKSTEMP = @HAVE_MKSTEMP@ +HAVE_MKSTEMPS = @HAVE_MKSTEMPS@ +HAVE_MODULES = @HAVE_MODULES@ +HAVE_NANOSLEEP = @HAVE_NANOSLEEP@ +HAVE_OPENAT = @HAVE_OPENAT@ +HAVE_OPENDIR = @HAVE_OPENDIR@ +HAVE_OS_H = @HAVE_OS_H@ +HAVE_PCLOSE = @HAVE_PCLOSE@ +HAVE_PIPE = @HAVE_PIPE@ +HAVE_PIPE2 = @HAVE_PIPE2@ +HAVE_POPEN = @HAVE_POPEN@ +HAVE_POSIX_OPENPT = @HAVE_POSIX_OPENPT@ +HAVE_POSIX_SIGNALBLOCKING = @HAVE_POSIX_SIGNALBLOCKING@ +HAVE_PREAD = @HAVE_PREAD@ +HAVE_PSELECT = @HAVE_PSELECT@ +HAVE_PTHREAD_SIGMASK = @HAVE_PTHREAD_SIGMASK@ +HAVE_PTSNAME = @HAVE_PTSNAME@ +HAVE_PTSNAME_R = @HAVE_PTSNAME_R@ +HAVE_PWRITE = @HAVE_PWRITE@ +HAVE_QSORT_R = @HAVE_QSORT_R@ +HAVE_RAISE = @HAVE_RAISE@ +HAVE_RANDOM = @HAVE_RANDOM@ +HAVE_RANDOM_H = @HAVE_RANDOM_H@ +HAVE_RANDOM_R = @HAVE_RANDOM_R@ +HAVE_RAWMEMCHR = @HAVE_RAWMEMCHR@ +HAVE_READDIR = @HAVE_READDIR@ +HAVE_READLINK = @HAVE_READLINK@ +HAVE_READLINKAT = @HAVE_READLINKAT@ +HAVE_REALPATH = @HAVE_REALPATH@ +HAVE_RENAMEAT = @HAVE_RENAMEAT@ +HAVE_REWINDDIR = @HAVE_REWINDDIR@ +HAVE_RPMATCH = @HAVE_RPMATCH@ +HAVE_SCANDIR = @HAVE_SCANDIR@ +HAVE_SECURE_GETENV = @HAVE_SECURE_GETENV@ +HAVE_SETENV = @HAVE_SETENV@ +HAVE_SETHOSTNAME = @HAVE_SETHOSTNAME@ +HAVE_SIGACTION = @HAVE_SIGACTION@ +HAVE_SIGHANDLER_T = @HAVE_SIGHANDLER_T@ +HAVE_SIGINFO_T = @HAVE_SIGINFO_T@ +HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@ +HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@ +HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ +HAVE_SIGSET_T = @HAVE_SIGSET_T@ +HAVE_SLEEP = @HAVE_SLEEP@ +HAVE_STDINT_H = @HAVE_STDINT_H@ +HAVE_STPCPY = @HAVE_STPCPY@ +HAVE_STPNCPY = @HAVE_STPNCPY@ +HAVE_STRCASESTR = @HAVE_STRCASESTR@ +HAVE_STRCHRNUL = @HAVE_STRCHRNUL@ +HAVE_STRPBRK = @HAVE_STRPBRK@ +HAVE_STRPTIME = @HAVE_STRPTIME@ +HAVE_STRSEP = @HAVE_STRSEP@ +HAVE_STRTOD = @HAVE_STRTOD@ +HAVE_STRTOLL = @HAVE_STRTOLL@ +HAVE_STRTOULL = @HAVE_STRTOULL@ +HAVE_STRUCT_RANDOM_DATA = @HAVE_STRUCT_RANDOM_DATA@ +HAVE_STRUCT_SIGACTION_SA_SIGACTION = @HAVE_STRUCT_SIGACTION_SA_SIGACTION@ +HAVE_STRUCT_TIMEVAL = @HAVE_STRUCT_TIMEVAL@ +HAVE_STRVERSCMP = @HAVE_STRVERSCMP@ +HAVE_SYMLINK = @HAVE_SYMLINK@ +HAVE_SYMLINKAT = @HAVE_SYMLINKAT@ +HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@ +HAVE_SYS_CDEFS_H = @HAVE_SYS_CDEFS_H@ +HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@ +HAVE_SYS_LOADAVG_H = @HAVE_SYS_LOADAVG_H@ +HAVE_SYS_PARAM_H = @HAVE_SYS_PARAM_H@ +HAVE_SYS_SELECT_H = @HAVE_SYS_SELECT_H@ +HAVE_SYS_TIME_H = @HAVE_SYS_TIME_H@ +HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@ +HAVE_TIMEGM = @HAVE_TIMEGM@ +HAVE_TIMEZONE_T = @HAVE_TIMEZONE_T@ +HAVE_TRUNCATE = @HAVE_TRUNCATE@ +HAVE_TYPE_VOLATILE_SIG_ATOMIC_T = @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@ +HAVE_TZSET = @HAVE_TZSET@ +HAVE_UNISTD_H = @HAVE_UNISTD_H@ +HAVE_UNLINKAT = @HAVE_UNLINKAT@ +HAVE_UNLOCKPT = @HAVE_UNLOCKPT@ +HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@ +HAVE_USLEEP = @HAVE_USLEEP@ +HAVE_UTIMENSAT = @HAVE_UTIMENSAT@ +HAVE_VASPRINTF = @HAVE_VASPRINTF@ +HAVE_VDPRINTF = @HAVE_VDPRINTF@ +HAVE_WCHAR_H = @HAVE_WCHAR_H@ +HAVE_WCHAR_T = @HAVE_WCHAR_T@ +HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@ +HAVE_XSERVER = @HAVE_XSERVER@ +HAVE__EXIT = @HAVE__EXIT@ +HYBRID_MALLOC = @HYBRID_MALLOC@ +IMAGEMAGICK_CFLAGS = @IMAGEMAGICK_CFLAGS@ +IMAGEMAGICK_LIBS = @IMAGEMAGICK_LIBS@ +INCLUDE_NEXT = @INCLUDE_NEXT@ +INCLUDE_NEXT_AS_FIRST_DIRECTIVE = @INCLUDE_NEXT_AS_FIRST_DIRECTIVE@ +INSTALL_ARCH_INDEP_EXTRA = @INSTALL_ARCH_INDEP_EXTRA@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_INFO = @INSTALL_INFO@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INT32_MAX_LT_INTMAX_MAX = @INT32_MAX_LT_INTMAX_MAX@ +INT64_MAX_EQ_LONG_MAX = @INT64_MAX_EQ_LONG_MAX@ +KQUEUE_CFLAGS = @KQUEUE_CFLAGS@ +KQUEUE_LIBS = @KQUEUE_LIBS@ +KRB4LIB = @KRB4LIB@ +KRB5LIB = @KRB5LIB@ +LDFLAGS = @LDFLAGS@ +LD_SWITCH_SYSTEM = @LD_SWITCH_SYSTEM@ +LD_SWITCH_SYSTEM_TEMACS = @LD_SWITCH_SYSTEM_TEMACS@ +LD_SWITCH_X_SITE = @LD_SWITCH_X_SITE@ +LD_SWITCH_X_SITE_RPATH = @LD_SWITCH_X_SITE_RPATH@ +LIBGIF = @LIBGIF@ +LIBGNUTLS3_CFLAGS = @LIBGNUTLS3_CFLAGS@ +LIBGNUTLS3_LIBS = @LIBGNUTLS3_LIBS@ +LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@ +LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@ +LIBGNU_LIBDEPS = @LIBGNU_LIBDEPS@ +LIBGNU_LTLIBDEPS = @LIBGNU_LTLIBDEPS@ +LIBGPM = @LIBGPM@ +LIBHESIOD = @LIBHESIOD@ +LIBINTL = @LIBINTL@ +LIBJPEG = @LIBJPEG@ +LIBMODULES = @LIBMODULES@ +LIBOBJS = @LIBOBJS@ +LIBOTF_CFLAGS = @LIBOTF_CFLAGS@ +LIBOTF_LIBS = @LIBOTF_LIBS@ +LIBPNG = @LIBPNG@ +LIBRESOLV = @LIBRESOLV@ +LIBS = @LIBS@ +LIBSELINUX_LIBS = @LIBSELINUX_LIBS@ +LIBSOUND = @LIBSOUND@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBS_ECLIENT = @LIBS_ECLIENT@ +LIBS_GNUSTEP = @LIBS_GNUSTEP@ +LIBS_MAIL = @LIBS_MAIL@ +LIBS_SYSTEM = @LIBS_SYSTEM@ +LIBS_TERMCAP = @LIBS_TERMCAP@ +LIBTIFF = @LIBTIFF@ +LIBXMENU = @LIBXMENU@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIBXMU = @LIBXMU@ +LIBXPM = @LIBXPM@ +LIBXSM = @LIBXSM@ +LIBXTR6 = @LIBXTR6@ +LIBXT_OTHER = @LIBXT_OTHER@ +LIBX_OTHER = @LIBX_OTHER@ +LIBZ = @LIBZ@ +LIB_ACL = @LIB_ACL@ +LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@ +LIB_EACCESS = @LIB_EACCESS@ +LIB_EXECINFO = @LIB_EXECINFO@ +LIB_FDATASYNC = @LIB_FDATASYNC@ +LIB_MATH = @LIB_MATH@ +LIB_PTHREAD = @LIB_PTHREAD@ +LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@ +LIB_TIMER_TIME = @LIB_TIMER_TIME@ +LIB_WSOCK32 = @LIB_WSOCK32@ +LIMITS_H = @LIMITS_H@ +LN_S_FILEONLY = @LN_S_FILEONLY@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +M17N_FLT_CFLAGS = @M17N_FLT_CFLAGS@ +M17N_FLT_LIBS = @M17N_FLT_LIBS@ +MAKEINFO = @MAKEINFO@ +MAKE_PROG = @MAKE_PROG@ +MKDIR_P = @MKDIR_P@ +MODULES_OBJ = @MODULES_OBJ@ +MODULES_SUFFIX = @MODULES_SUFFIX@ +NEXT_AS_FIRST_DIRECTIVE_DIRENT_H = @NEXT_AS_FIRST_DIRECTIVE_DIRENT_H@ +NEXT_AS_FIRST_DIRECTIVE_ERRNO_H = @NEXT_AS_FIRST_DIRECTIVE_ERRNO_H@ +NEXT_AS_FIRST_DIRECTIVE_FCNTL_H = @NEXT_AS_FIRST_DIRECTIVE_FCNTL_H@ +NEXT_AS_FIRST_DIRECTIVE_GETOPT_H = @NEXT_AS_FIRST_DIRECTIVE_GETOPT_H@ +NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H = @NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H@ +NEXT_AS_FIRST_DIRECTIVE_LIMITS_H = @NEXT_AS_FIRST_DIRECTIVE_LIMITS_H@ +NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H = @NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H@ +NEXT_AS_FIRST_DIRECTIVE_STDDEF_H = @NEXT_AS_FIRST_DIRECTIVE_STDDEF_H@ +NEXT_AS_FIRST_DIRECTIVE_STDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDINT_H@ +NEXT_AS_FIRST_DIRECTIVE_STDIO_H = @NEXT_AS_FIRST_DIRECTIVE_STDIO_H@ +NEXT_AS_FIRST_DIRECTIVE_STDLIB_H = @NEXT_AS_FIRST_DIRECTIVE_STDLIB_H@ +NEXT_AS_FIRST_DIRECTIVE_STRING_H = @NEXT_AS_FIRST_DIRECTIVE_STRING_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_SELECT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_SELECT_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H@ +NEXT_AS_FIRST_DIRECTIVE_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_TIME_H@ +NEXT_AS_FIRST_DIRECTIVE_UNISTD_H = @NEXT_AS_FIRST_DIRECTIVE_UNISTD_H@ +NEXT_DIRENT_H = @NEXT_DIRENT_H@ +NEXT_ERRNO_H = @NEXT_ERRNO_H@ +NEXT_FCNTL_H = @NEXT_FCNTL_H@ +NEXT_GETOPT_H = @NEXT_GETOPT_H@ +NEXT_INTTYPES_H = @NEXT_INTTYPES_H@ +NEXT_LIMITS_H = @NEXT_LIMITS_H@ +NEXT_SIGNAL_H = @NEXT_SIGNAL_H@ +NEXT_STDDEF_H = @NEXT_STDDEF_H@ +NEXT_STDINT_H = @NEXT_STDINT_H@ +NEXT_STDIO_H = @NEXT_STDIO_H@ +NEXT_STDLIB_H = @NEXT_STDLIB_H@ +NEXT_STRING_H = @NEXT_STRING_H@ +NEXT_SYS_SELECT_H = @NEXT_SYS_SELECT_H@ +NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@ +NEXT_SYS_TIME_H = @NEXT_SYS_TIME_H@ +NEXT_SYS_TYPES_H = @NEXT_SYS_TYPES_H@ +NEXT_TIME_H = @NEXT_TIME_H@ +NEXT_UNISTD_H = @NEXT_UNISTD_H@ +NOTIFY_CFLAGS = @NOTIFY_CFLAGS@ +NOTIFY_LIBS = @NOTIFY_LIBS@ +NOTIFY_OBJ = @NOTIFY_OBJ@ +NS_OBJ = @NS_OBJ@ +NS_OBJC_OBJ = @NS_OBJC_OBJ@ +NTDIR = @NTDIR@ +NTLIB = @NTLIB@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJEXT = @OBJEXT@ +OTHER_FILES = @OTHER_FILES@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PAXCTL = @PAXCTL@ +PAXCTL_dumped = @PAXCTL_dumped@ +PAXCTL_notdumped = @PAXCTL_notdumped@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_CFLAGS = @PNG_CFLAGS@ +POST_ALLOC_OBJ = @POST_ALLOC_OBJ@ +PRAGMA_COLUMNS = @PRAGMA_COLUMNS@ +PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@ +PRE_ALLOC_OBJ = @PRE_ALLOC_OBJ@ +PRIPTR_PREFIX = @PRIPTR_PREFIX@ +PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@ +PROFILING_CFLAGS = @PROFILING_CFLAGS@ +PTHREAD_H_DEFINES_STRUCT_TIMESPEC = @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@ +PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@ +RALLOC_OBJ = @RALLOC_OBJ@ +RANLIB = @RANLIB@ +REPLACE_CALLOC = @REPLACE_CALLOC@ +REPLACE_CANONICALIZE_FILE_NAME = @REPLACE_CANONICALIZE_FILE_NAME@ +REPLACE_CHOWN = @REPLACE_CHOWN@ +REPLACE_CLOSE = @REPLACE_CLOSE@ +REPLACE_CLOSEDIR = @REPLACE_CLOSEDIR@ +REPLACE_CTIME = @REPLACE_CTIME@ +REPLACE_DIRFD = @REPLACE_DIRFD@ +REPLACE_DPRINTF = @REPLACE_DPRINTF@ +REPLACE_DUP = @REPLACE_DUP@ +REPLACE_DUP2 = @REPLACE_DUP2@ +REPLACE_FCHOWNAT = @REPLACE_FCHOWNAT@ +REPLACE_FCLOSE = @REPLACE_FCLOSE@ +REPLACE_FCNTL = @REPLACE_FCNTL@ +REPLACE_FDOPEN = @REPLACE_FDOPEN@ +REPLACE_FDOPENDIR = @REPLACE_FDOPENDIR@ +REPLACE_FFLUSH = @REPLACE_FFLUSH@ +REPLACE_FOPEN = @REPLACE_FOPEN@ +REPLACE_FPRINTF = @REPLACE_FPRINTF@ +REPLACE_FPURGE = @REPLACE_FPURGE@ +REPLACE_FREOPEN = @REPLACE_FREOPEN@ +REPLACE_FSEEK = @REPLACE_FSEEK@ +REPLACE_FSEEKO = @REPLACE_FSEEKO@ +REPLACE_FSTAT = @REPLACE_FSTAT@ +REPLACE_FSTATAT = @REPLACE_FSTATAT@ +REPLACE_FTELL = @REPLACE_FTELL@ +REPLACE_FTELLO = @REPLACE_FTELLO@ +REPLACE_FTRUNCATE = @REPLACE_FTRUNCATE@ +REPLACE_FUTIMENS = @REPLACE_FUTIMENS@ +REPLACE_GETCWD = @REPLACE_GETCWD@ +REPLACE_GETDELIM = @REPLACE_GETDELIM@ +REPLACE_GETDOMAINNAME = @REPLACE_GETDOMAINNAME@ +REPLACE_GETDTABLESIZE = @REPLACE_GETDTABLESIZE@ +REPLACE_GETGROUPS = @REPLACE_GETGROUPS@ +REPLACE_GETLINE = @REPLACE_GETLINE@ +REPLACE_GETLOGIN_R = @REPLACE_GETLOGIN_R@ +REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@ +REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@ +REPLACE_GMTIME = @REPLACE_GMTIME@ +REPLACE_ISATTY = @REPLACE_ISATTY@ +REPLACE_LCHOWN = @REPLACE_LCHOWN@ +REPLACE_LINK = @REPLACE_LINK@ +REPLACE_LINKAT = @REPLACE_LINKAT@ +REPLACE_LOCALTIME = @REPLACE_LOCALTIME@ +REPLACE_LOCALTIME_R = @REPLACE_LOCALTIME_R@ +REPLACE_LSEEK = @REPLACE_LSEEK@ +REPLACE_LSTAT = @REPLACE_LSTAT@ +REPLACE_MALLOC = @REPLACE_MALLOC@ +REPLACE_MBTOWC = @REPLACE_MBTOWC@ +REPLACE_MEMCHR = @REPLACE_MEMCHR@ +REPLACE_MEMMEM = @REPLACE_MEMMEM@ +REPLACE_MKDIR = @REPLACE_MKDIR@ +REPLACE_MKFIFO = @REPLACE_MKFIFO@ +REPLACE_MKNOD = @REPLACE_MKNOD@ +REPLACE_MKSTEMP = @REPLACE_MKSTEMP@ +REPLACE_MKTIME = @REPLACE_MKTIME@ +REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@ +REPLACE_NULL = @REPLACE_NULL@ +REPLACE_OBSTACK_PRINTF = @REPLACE_OBSTACK_PRINTF@ +REPLACE_OPEN = @REPLACE_OPEN@ +REPLACE_OPENAT = @REPLACE_OPENAT@ +REPLACE_OPENDIR = @REPLACE_OPENDIR@ +REPLACE_PERROR = @REPLACE_PERROR@ +REPLACE_POPEN = @REPLACE_POPEN@ +REPLACE_PREAD = @REPLACE_PREAD@ +REPLACE_PRINTF = @REPLACE_PRINTF@ +REPLACE_PSELECT = @REPLACE_PSELECT@ +REPLACE_PTHREAD_SIGMASK = @REPLACE_PTHREAD_SIGMASK@ +REPLACE_PTSNAME = @REPLACE_PTSNAME@ +REPLACE_PTSNAME_R = @REPLACE_PTSNAME_R@ +REPLACE_PUTENV = @REPLACE_PUTENV@ +REPLACE_PWRITE = @REPLACE_PWRITE@ +REPLACE_QSORT_R = @REPLACE_QSORT_R@ +REPLACE_RAISE = @REPLACE_RAISE@ +REPLACE_RANDOM_R = @REPLACE_RANDOM_R@ +REPLACE_READ = @REPLACE_READ@ +REPLACE_READLINK = @REPLACE_READLINK@ +REPLACE_READLINKAT = @REPLACE_READLINKAT@ +REPLACE_REALLOC = @REPLACE_REALLOC@ +REPLACE_REALPATH = @REPLACE_REALPATH@ +REPLACE_REMOVE = @REPLACE_REMOVE@ +REPLACE_RENAME = @REPLACE_RENAME@ +REPLACE_RENAMEAT = @REPLACE_RENAMEAT@ +REPLACE_RMDIR = @REPLACE_RMDIR@ +REPLACE_SELECT = @REPLACE_SELECT@ +REPLACE_SETENV = @REPLACE_SETENV@ +REPLACE_SLEEP = @REPLACE_SLEEP@ +REPLACE_SNPRINTF = @REPLACE_SNPRINTF@ +REPLACE_SPRINTF = @REPLACE_SPRINTF@ +REPLACE_STAT = @REPLACE_STAT@ +REPLACE_STDIO_READ_FUNCS = @REPLACE_STDIO_READ_FUNCS@ +REPLACE_STDIO_WRITE_FUNCS = @REPLACE_STDIO_WRITE_FUNCS@ +REPLACE_STPNCPY = @REPLACE_STPNCPY@ +REPLACE_STRCASESTR = @REPLACE_STRCASESTR@ +REPLACE_STRCHRNUL = @REPLACE_STRCHRNUL@ +REPLACE_STRDUP = @REPLACE_STRDUP@ +REPLACE_STRERROR = @REPLACE_STRERROR@ +REPLACE_STRERROR_R = @REPLACE_STRERROR_R@ +REPLACE_STRFTIME = @REPLACE_STRFTIME@ +REPLACE_STRNCAT = @REPLACE_STRNCAT@ +REPLACE_STRNDUP = @REPLACE_STRNDUP@ +REPLACE_STRNLEN = @REPLACE_STRNLEN@ +REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@ +REPLACE_STRSTR = @REPLACE_STRSTR@ +REPLACE_STRTOD = @REPLACE_STRTOD@ +REPLACE_STRTOIMAX = @REPLACE_STRTOIMAX@ +REPLACE_STRTOK_R = @REPLACE_STRTOK_R@ +REPLACE_STRTOUMAX = @REPLACE_STRTOUMAX@ +REPLACE_STRUCT_TIMEVAL = @REPLACE_STRUCT_TIMEVAL@ +REPLACE_SYMLINK = @REPLACE_SYMLINK@ +REPLACE_SYMLINKAT = @REPLACE_SYMLINKAT@ +REPLACE_TIMEGM = @REPLACE_TIMEGM@ +REPLACE_TMPFILE = @REPLACE_TMPFILE@ +REPLACE_TRUNCATE = @REPLACE_TRUNCATE@ +REPLACE_TTYNAME_R = @REPLACE_TTYNAME_R@ +REPLACE_TZSET = @REPLACE_TZSET@ +REPLACE_UNLINK = @REPLACE_UNLINK@ +REPLACE_UNLINKAT = @REPLACE_UNLINKAT@ +REPLACE_UNSETENV = @REPLACE_UNSETENV@ +REPLACE_USLEEP = @REPLACE_USLEEP@ +REPLACE_UTIMENSAT = @REPLACE_UTIMENSAT@ +REPLACE_VASPRINTF = @REPLACE_VASPRINTF@ +REPLACE_VDPRINTF = @REPLACE_VDPRINTF@ +REPLACE_VFPRINTF = @REPLACE_VFPRINTF@ +REPLACE_VPRINTF = @REPLACE_VPRINTF@ +REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@ +REPLACE_VSPRINTF = @REPLACE_VSPRINTF@ +REPLACE_WCTOMB = @REPLACE_WCTOMB@ +REPLACE_WRITE = @REPLACE_WRITE@ +RSVG_CFLAGS = @RSVG_CFLAGS@ +RSVG_LIBS = @RSVG_LIBS@ +SEPCHAR = @SEPCHAR@ +SETFATTR = @SETFATTR@ +SETTINGS_CFLAGS = @SETTINGS_CFLAGS@ +SETTINGS_LIBS = @SETTINGS_LIBS@ +SHELL = @SHELL@ +SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ +SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ +STDALIGN_H = @STDALIGN_H@ +STDDEF_H = @STDDEF_H@ +STDINT_H = @STDINT_H@ +SUBDIR_MAKEFILES_IN = @SUBDIR_MAKEFILES_IN@ +SYSTEM_TYPE = @SYSTEM_TYPE@ +SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@ +TERMCAP_OBJ = @TERMCAP_OBJ@ +TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@ +TOOLKIT_LIBW = @TOOLKIT_LIBW@ +UINT32_MAX_LT_UINTMAX_MAX = @UINT32_MAX_LT_UINTMAX_MAX@ +UINT64_MAX_EQ_ULONG_MAX = @UINT64_MAX_EQ_ULONG_MAX@ +UNDEFINE_STRTOK_R = @UNDEFINE_STRTOK_R@ +UNEXEC_OBJ = @UNEXEC_OBJ@ +UNISTD_H_DEFINES_STRUCT_TIMESPEC = @UNISTD_H_DEFINES_STRUCT_TIMESPEC@ +UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@ +UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@ +USE_ACL = @USE_ACL@ +VMLIMIT_OBJ = @VMLIMIT_OBJ@ +W32_LIBS = @W32_LIBS@ +W32_OBJ = @W32_OBJ@ +W32_RES_LINK = @W32_RES_LINK@ +WARN_CFLAGS = @WARN_CFLAGS@ +WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@ +WEBKIT_CFLAGS = @WEBKIT_CFLAGS@ +WEBKIT_LIBS = @WEBKIT_LIBS@ +WERROR_CFLAGS = @WERROR_CFLAGS@ +WIDGET_OBJ = @WIDGET_OBJ@ +WINDOWS_64_BIT_OFF_T = @WINDOWS_64_BIT_OFF_T@ +WINDOWS_64_BIT_ST_SIZE = @WINDOWS_64_BIT_ST_SIZE@ +WINDOWS_STAT_INODES = @WINDOWS_STAT_INODES@ +WINDOWS_STAT_TIMESPEC = @WINDOWS_STAT_TIMESPEC@ +WINDOW_SYSTEM_OBJ = @WINDOW_SYSTEM_OBJ@ +WINDRES = @WINDRES@ +WINT_T_SUFFIX = @WINT_T_SUFFIX@ +XARGS_LIMIT = @XARGS_LIMIT@ +XCB_LIBS = @XCB_LIBS@ +XCRUN = @XCRUN@ +XDBE_CFLAGS = @XDBE_CFLAGS@ +XDBE_LIBS = @XDBE_LIBS@ +XFIXES_CFLAGS = @XFIXES_CFLAGS@ +XFIXES_LIBS = @XFIXES_LIBS@ +XFT_CFLAGS = @XFT_CFLAGS@ +XFT_LIBS = @XFT_LIBS@ +XGSELOBJ = @XGSELOBJ@ +XINERAMA_CFLAGS = @XINERAMA_CFLAGS@ +XINERAMA_LIBS = @XINERAMA_LIBS@ +XMENU_OBJ = @XMENU_OBJ@ +XMKMF = @XMKMF@ +XOBJ = @XOBJ@ +XRANDR_CFLAGS = @XRANDR_CFLAGS@ +XRANDR_LIBS = @XRANDR_LIBS@ +XWIDGETS_OBJ = @XWIDGETS_OBJ@ +X_TOOLKIT_TYPE = @X_TOOLKIT_TYPE@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_OBJC = @ac_ct_OBJC@ +archlibdir = @archlibdir@ +bindir = @bindir@ +bitmapdir = @bitmapdir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +cache_file = @cache_file@ +canonical = @canonical@ +comma_space_version = @comma_space_version@ +comma_version = @comma_version@ +configuration = @configuration@ +copyright = @copyright@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +etcdir = @etcdir@ +etcdocdir = @etcdocdir@ +exec_prefix = @exec_prefix@ +gamedir = @gamedir@ +gamegroup = @gamegroup@ +gameuser = @gameuser@ +gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7 = @gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7@ +gl_GNULIB_ENABLED_2049e887c7e5308faad27b3f894bb8c9 = @gl_GNULIB_ENABLED_2049e887c7e5308faad27b3f894bb8c9@ +gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b = @gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b@ +gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31 = @gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31@ +gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c = @gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c@ +gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec = @gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec@ +gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1 = @gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1@ +gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36 = @gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36@ +gl_GNULIB_ENABLED_dirfd = @gl_GNULIB_ENABLED_dirfd@ +gl_GNULIB_ENABLED_dosname = @gl_GNULIB_ENABLED_dosname@ +gl_GNULIB_ENABLED_euidaccess = @gl_GNULIB_ENABLED_euidaccess@ +gl_GNULIB_ENABLED_getdtablesize = @gl_GNULIB_ENABLED_getdtablesize@ +gl_GNULIB_ENABLED_getgroups = @gl_GNULIB_ENABLED_getgroups@ +gl_GNULIB_ENABLED_secure_getenv = @gl_GNULIB_ENABLED_secure_getenv@ +gl_GNULIB_ENABLED_strtoll = @gl_GNULIB_ENABLED_strtoll@ +gl_GNULIB_ENABLED_tempname = @gl_GNULIB_ENABLED_tempname@ +gl_LIBOBJS = @gl_LIBOBJS@ +gl_LTLIBOBJS = @gl_LTLIBOBJS@ +gltests_LIBOBJS = @gltests_LIBOBJS@ +gltests_LTLIBOBJS = @gltests_LTLIBOBJS@ +gltests_WITNESS = @gltests_WITNESS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +liblockfile = @liblockfile@ +lispdir = @lispdir@ +lisppath = @lisppath@ +localedir = @localedir@ +locallisppath = @locallisppath@ +localstatedir = @localstatedir@ +mandir = @mandir@ +ns_appbindir = @ns_appbindir@ +ns_appdir = @ns_appdir@ +ns_appresdir = @ns_appresdir@ +ns_appsrc = @ns_appsrc@ +ns_check_file = @ns_check_file@ +ns_self_contained = @ns_self_contained@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +standardlisppath = @standardlisppath@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +version = @version@ +with_mailutils = @with_mailutils@ +x_default_search_path = @x_default_search_path@ +# End of GNU Make output. noinst_LIBRARIES += libgnu.a @@ -34,15 +958,18 @@ libgnu_a_DEPENDENCIES = $(gl_LIBOBJS) EXTRA_libgnu_a_SOURCES = ## begin gnulib module absolute-header +ifeq (,$(OMIT_GNULIB_MODULE_absolute-header)) # Use this preprocessor expression to decide whether #include_next works. # Do not rely on a 'configure'-time test for this, since the expression # might appear in an installed header, which is used by some other compiler. HAVE_INCLUDE_NEXT = (__GNUC__ || 60000000 <= __DECC_VER) +endif ## end gnulib module absolute-header ## begin gnulib module acl-permissions +ifeq (,$(OMIT_GNULIB_MODULE_acl-permissions)) libgnu_a_SOURCES += acl-errno-valid.c acl-internal.c get-permissions.c set-permissions.c @@ -50,15 +977,17 @@ EXTRA_DIST += acl-internal.h acl.h acl_entries.c EXTRA_libgnu_a_SOURCES += acl_entries.c +endif ## end gnulib module acl-permissions ## begin gnulib module alloca-opt +ifeq (,$(OMIT_GNULIB_MODULE_alloca-opt)) BUILT_SOURCES += $(ALLOCA_H) # We need the following in order to create <alloca.h> when the system # doesn't have one that works with the given compiler. -if GL_GENERATE_ALLOCA_H +ifneq (,$(GL_GENERATE_ALLOCA_H)) alloca.h: alloca.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ @@ -73,40 +1002,48 @@ MOSTLYCLEANFILES += alloca.h alloca.h-t EXTRA_DIST += alloca.in.h +endif ## end gnulib module alloca-opt ## begin gnulib module allocator +ifeq (,$(OMIT_GNULIB_MODULE_allocator)) libgnu_a_SOURCES += allocator.c EXTRA_DIST += allocator.h +endif ## end gnulib module allocator ## begin gnulib module at-internal +ifeq (,$(OMIT_GNULIB_MODULE_at-internal)) -if gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b +ifneq (,$(gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b)) endif EXTRA_DIST += openat-priv.h openat-proc.c EXTRA_libgnu_a_SOURCES += openat-proc.c +endif ## end gnulib module at-internal ## begin gnulib module binary-io +ifeq (,$(OMIT_GNULIB_MODULE_binary-io)) libgnu_a_SOURCES += binary-io.h binary-io.c +endif ## end gnulib module binary-io ## begin gnulib module byteswap +ifeq (,$(OMIT_GNULIB_MODULE_byteswap)) BUILT_SOURCES += $(BYTESWAP_H) # We need the following in order to create <byteswap.h> when the system # doesn't have one. -if GL_GENERATE_BYTESWAP_H +ifneq (,$(GL_GENERATE_BYTESWAP_H)) byteswap.h: byteswap.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ @@ -121,58 +1058,83 @@ MOSTLYCLEANFILES += byteswap.h byteswap.h-t EXTRA_DIST += byteswap.in.h +endif ## end gnulib module byteswap ## begin gnulib module c-ctype +ifeq (,$(OMIT_GNULIB_MODULE_c-ctype)) libgnu_a_SOURCES += c-ctype.h c-ctype.c +endif ## end gnulib module c-ctype ## begin gnulib module c-strcase +ifeq (,$(OMIT_GNULIB_MODULE_c-strcase)) libgnu_a_SOURCES += c-strcase.h c-strcasecmp.c c-strncasecmp.c +endif ## end gnulib module c-strcase ## begin gnulib module careadlinkat +ifeq (,$(OMIT_GNULIB_MODULE_careadlinkat)) libgnu_a_SOURCES += careadlinkat.c EXTRA_DIST += careadlinkat.h +endif ## end gnulib module careadlinkat ## begin gnulib module close-stream +ifeq (,$(OMIT_GNULIB_MODULE_close-stream)) libgnu_a_SOURCES += close-stream.c EXTRA_DIST += close-stream.h +endif ## end gnulib module close-stream +## begin gnulib module count-leading-zeros +ifeq (,$(OMIT_GNULIB_MODULE_count-leading-zeros)) + +libgnu_a_SOURCES += count-leading-zeros.c + +EXTRA_DIST += count-leading-zeros.h + +endif +## end gnulib module count-leading-zeros + ## begin gnulib module count-one-bits +ifeq (,$(OMIT_GNULIB_MODULE_count-one-bits)) libgnu_a_SOURCES += count-one-bits.c EXTRA_DIST += count-one-bits.h +endif ## end gnulib module count-one-bits ## begin gnulib module count-trailing-zeros +ifeq (,$(OMIT_GNULIB_MODULE_count-trailing-zeros)) libgnu_a_SOURCES += count-trailing-zeros.c EXTRA_DIST += count-trailing-zeros.h +endif ## end gnulib module count-trailing-zeros ## begin gnulib module crypto/md5 +ifeq (,$(OMIT_GNULIB_MODULE_crypto/md5)) libgnu_a_SOURCES += md5.c EXTRA_DIST += gl_openssl.h md5.h +endif ## end gnulib module crypto/md5 ## begin crypto in rust @@ -181,7 +1143,16 @@ EXTRA_DIST += sha1.h gl_openssl.h sha256.h ## end crypto in rust +## begin gnulib module diffseq +ifeq (,$(OMIT_GNULIB_MODULE_diffseq)) + +libgnu_a_SOURCES += diffseq.h + +endif +## end gnulib module diffseq + ## begin gnulib module dirent +ifeq (,$(OMIT_GNULIB_MODULE_dirent)) BUILT_SOURCES += dirent.h @@ -227,29 +1198,35 @@ MOSTLYCLEANFILES += dirent.h dirent.h-t EXTRA_DIST += dirent.in.h +endif ## end gnulib module dirent ## begin gnulib module dirfd +ifeq (,$(OMIT_GNULIB_MODULE_dirfd)) -if gl_GNULIB_ENABLED_dirfd +ifneq (,$(gl_GNULIB_ENABLED_dirfd)) endif EXTRA_DIST += dirfd.c EXTRA_libgnu_a_SOURCES += dirfd.c +endif ## end gnulib module dirfd ## begin gnulib module dosname +ifeq (,$(OMIT_GNULIB_MODULE_dosname)) -if gl_GNULIB_ENABLED_dosname +ifneq (,$(gl_GNULIB_ENABLED_dosname)) endif EXTRA_DIST += dosname.h +endif ## end gnulib module dosname ## begin gnulib module dtoastr +ifeq (,$(OMIT_GNULIB_MODULE_dtoastr)) libgnu_a_SOURCES += dtoastr.c @@ -257,30 +1234,36 @@ EXTRA_DIST += ftoastr.c ftoastr.h EXTRA_libgnu_a_SOURCES += ftoastr.c +endif ## end gnulib module dtoastr ## begin gnulib module dtotimespec +ifeq (,$(OMIT_GNULIB_MODULE_dtotimespec)) libgnu_a_SOURCES += dtotimespec.c +endif ## end gnulib module dtotimespec ## begin gnulib module dup2 +ifeq (,$(OMIT_GNULIB_MODULE_dup2)) EXTRA_DIST += dup2.c EXTRA_libgnu_a_SOURCES += dup2.c +endif ## end gnulib module dup2 ## begin gnulib module errno +ifeq (,$(OMIT_GNULIB_MODULE_errno)) BUILT_SOURCES += $(ERRNO_H) # We need the following in order to create <errno.h> when the system # doesn't have one that is POSIX compliant. -if GL_GENERATE_ERRNO_H +ifneq (,$(GL_GENERATE_ERRNO_H)) errno.h: errno.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ @@ -306,26 +1289,30 @@ MOSTLYCLEANFILES += errno.h errno.h-t EXTRA_DIST += errno.in.h +endif ## end gnulib module errno ## begin gnulib module euidaccess +ifeq (,$(OMIT_GNULIB_MODULE_euidaccess)) -if gl_GNULIB_ENABLED_euidaccess +ifneq (,$(gl_GNULIB_ENABLED_euidaccess)) endif EXTRA_DIST += euidaccess.c EXTRA_libgnu_a_SOURCES += euidaccess.c +endif ## end gnulib module euidaccess ## begin gnulib module execinfo +ifeq (,$(OMIT_GNULIB_MODULE_execinfo)) BUILT_SOURCES += $(EXECINFO_H) # We need the following in order to create <execinfo.h> when the system # doesn't have one that works. -if GL_GENERATE_EXECINFO_H +ifneq (,$(GL_GENERATE_EXECINFO_H)) execinfo.h: execinfo.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ @@ -342,27 +1329,33 @@ EXTRA_DIST += execinfo.c execinfo.in.h EXTRA_libgnu_a_SOURCES += execinfo.c +endif ## end gnulib module execinfo ## begin gnulib module faccessat +ifeq (,$(OMIT_GNULIB_MODULE_faccessat)) EXTRA_DIST += at-func.c faccessat.c EXTRA_libgnu_a_SOURCES += at-func.c faccessat.c +endif ## end gnulib module faccessat ## begin gnulib module fcntl +ifeq (,$(OMIT_GNULIB_MODULE_fcntl)) EXTRA_DIST += fcntl.c EXTRA_libgnu_a_SOURCES += fcntl.c +endif ## end gnulib module fcntl ## begin gnulib module fcntl-h +ifeq (,$(OMIT_GNULIB_MODULE_fcntl-h)) BUILT_SOURCES += fcntl.h @@ -395,114 +1388,138 @@ MOSTLYCLEANFILES += fcntl.h fcntl.h-t EXTRA_DIST += fcntl.in.h +endif ## end gnulib module fcntl-h ## begin gnulib module fdatasync +ifeq (,$(OMIT_GNULIB_MODULE_fdatasync)) EXTRA_DIST += fdatasync.c EXTRA_libgnu_a_SOURCES += fdatasync.c +endif ## end gnulib module fdatasync ## begin gnulib module fdopendir +ifeq (,$(OMIT_GNULIB_MODULE_fdopendir)) EXTRA_DIST += fdopendir.c EXTRA_libgnu_a_SOURCES += fdopendir.c +endif ## end gnulib module fdopendir ## begin gnulib module filemode +ifeq (,$(OMIT_GNULIB_MODULE_filemode)) libgnu_a_SOURCES += filemode.c EXTRA_DIST += filemode.h +endif ## end gnulib module filemode ## begin gnulib module filevercmp +ifeq (,$(OMIT_GNULIB_MODULE_filevercmp)) libgnu_a_SOURCES += filevercmp.c EXTRA_DIST += filevercmp.h +endif ## end gnulib module filevercmp ## begin gnulib module flexmember +ifeq (,$(OMIT_GNULIB_MODULE_flexmember)) EXTRA_DIST += flexmember.h +endif ## end gnulib module flexmember ## begin gnulib module fpending +ifeq (,$(OMIT_GNULIB_MODULE_fpending)) EXTRA_DIST += fpending.c fpending.h stdio-impl.h EXTRA_libgnu_a_SOURCES += fpending.c +endif ## end gnulib module fpending ## begin gnulib module fstatat +ifeq (,$(OMIT_GNULIB_MODULE_fstatat)) EXTRA_DIST += at-func.c fstatat.c EXTRA_libgnu_a_SOURCES += at-func.c fstatat.c +endif ## end gnulib module fstatat ## begin gnulib module fsync +ifeq (,$(OMIT_GNULIB_MODULE_fsync)) EXTRA_DIST += fsync.c EXTRA_libgnu_a_SOURCES += fsync.c +endif ## end gnulib module fsync ## begin gnulib module getdtablesize +ifeq (,$(OMIT_GNULIB_MODULE_getdtablesize)) -if gl_GNULIB_ENABLED_getdtablesize +ifneq (,$(gl_GNULIB_ENABLED_getdtablesize)) endif EXTRA_DIST += getdtablesize.c EXTRA_libgnu_a_SOURCES += getdtablesize.c +endif ## end gnulib module getdtablesize ## begin gnulib module getgroups +ifeq (,$(OMIT_GNULIB_MODULE_getgroups)) -if gl_GNULIB_ENABLED_getgroups +ifneq (,$(gl_GNULIB_ENABLED_getgroups)) endif EXTRA_DIST += getgroups.c EXTRA_libgnu_a_SOURCES += getgroups.c +endif ## end gnulib module getgroups ## begin gnulib module getloadavg +ifeq (,$(OMIT_GNULIB_MODULE_getloadavg)) EXTRA_DIST += getloadavg.c EXTRA_libgnu_a_SOURCES += getloadavg.c +endif ## end gnulib module getloadavg ## begin gnulib module getopt-posix +ifeq (,$(OMIT_GNULIB_MODULE_getopt-posix)) -BUILT_SOURCES += $(GETOPT_H) +BUILT_SOURCES += $(GETOPT_H) $(GETOPT_CDEFS_H) # We need the following in order to create <getopt.h> when the system # doesn't have one that works with the given compiler. -getopt.h: getopt.in.h $(top_builddir)/config.status $(ARG_NONNULL_H) +getopt.h: getopt.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ @@ -515,70 +1532,95 @@ getopt.h: getopt.in.h $(top_builddir)/config.status $(ARG_NONNULL_H) < $(srcdir)/getopt.in.h; \ } > $@-t && \ mv -f $@-t $@ -MOSTLYCLEANFILES += getopt.h getopt.h-t -EXTRA_DIST += getopt.c getopt.in.h getopt1.c getopt_int.h +getopt-cdefs.h: getopt-cdefs.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''HAVE_SYS_CDEFS_H''@|$(HAVE_SYS_CDEFS_H)|g' \ + < $(srcdir)/getopt-cdefs.in.h; \ + } > $@-t && \ + mv -f $@-t $@ + +MOSTLYCLEANFILES += getopt.h getopt.h-t getopt-cdefs.h getopt-cdefs.h-t + +EXTRA_DIST += getopt-cdefs.in.h getopt-core.h getopt-ext.h getopt-pfx-core.h getopt-pfx-ext.h getopt.c getopt.in.h getopt1.c getopt_int.h EXTRA_libgnu_a_SOURCES += getopt.c getopt1.c +endif ## end gnulib module getopt-posix ## begin gnulib module gettext-h +ifeq (,$(OMIT_GNULIB_MODULE_gettext-h)) -if gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36 +ifneq (,$(gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36)) libgnu_a_SOURCES += gettext.h +endif endif ## end gnulib module gettext-h ## begin gnulib module gettime +ifeq (,$(OMIT_GNULIB_MODULE_gettime)) libgnu_a_SOURCES += gettime.c +endif ## end gnulib module gettime ## begin gnulib module gettimeofday +ifeq (,$(OMIT_GNULIB_MODULE_gettimeofday)) EXTRA_DIST += gettimeofday.c EXTRA_libgnu_a_SOURCES += gettimeofday.c +endif ## end gnulib module gettimeofday ## begin gnulib module gitlog-to-changelog +ifeq (,$(OMIT_GNULIB_MODULE_gitlog-to-changelog)) EXTRA_DIST += $(top_srcdir)/build-aux/gitlog-to-changelog +endif ## end gnulib module gitlog-to-changelog ## begin gnulib module group-member +ifeq (,$(OMIT_GNULIB_MODULE_group-member)) -if gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1 +ifneq (,$(gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1)) endif EXTRA_DIST += group-member.c EXTRA_libgnu_a_SOURCES += group-member.c +endif ## end gnulib module group-member ## begin gnulib module ignore-value +ifeq (,$(OMIT_GNULIB_MODULE_ignore-value)) EXTRA_DIST += ignore-value.h +endif ## end gnulib module ignore-value ## begin gnulib module intprops +ifeq (,$(OMIT_GNULIB_MODULE_intprops)) EXTRA_DIST += intprops.h +endif ## end gnulib module intprops ## begin gnulib module inttypes-incomplete +ifeq (,$(OMIT_GNULIB_MODULE_inttypes-incomplete)) BUILT_SOURCES += inttypes.h @@ -621,15 +1663,17 @@ MOSTLYCLEANFILES += inttypes.h inttypes.h-t EXTRA_DIST += inttypes.in.h +endif ## end gnulib module inttypes-incomplete ## begin gnulib module limits-h +ifeq (,$(OMIT_GNULIB_MODULE_limits-h)) BUILT_SOURCES += $(LIMITS_H) # We need the following in order to create <limits.h> when the system # doesn't have one that is compatible with GNU. -if GL_GENERATE_LIMITS_H +ifneq (,$(GL_GENERATE_LIMITS_H)) limits.h: limits.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ @@ -649,151 +1693,195 @@ MOSTLYCLEANFILES += limits.h limits.h-t EXTRA_DIST += limits.in.h +endif ## end gnulib module limits-h +## begin gnulib module localtime-buffer +ifeq (,$(OMIT_GNULIB_MODULE_localtime-buffer)) + +ifneq (,$(gl_GNULIB_ENABLED_2049e887c7e5308faad27b3f894bb8c9)) + +endif +EXTRA_DIST += localtime-buffer.c localtime-buffer.h + +EXTRA_libgnu_a_SOURCES += localtime-buffer.c + +endif +## end gnulib module localtime-buffer + ## begin gnulib module lstat +ifeq (,$(OMIT_GNULIB_MODULE_lstat)) EXTRA_DIST += lstat.c EXTRA_libgnu_a_SOURCES += lstat.c +endif ## end gnulib module lstat ## begin gnulib module memrchr +ifeq (,$(OMIT_GNULIB_MODULE_memrchr)) EXTRA_DIST += memrchr.c EXTRA_libgnu_a_SOURCES += memrchr.c +endif ## end gnulib module memrchr +## begin gnulib module minmax +ifeq (,$(OMIT_GNULIB_MODULE_minmax)) + +libgnu_a_SOURCES += minmax.h + +endif +## end gnulib module minmax + ## begin gnulib module mkostemp +ifeq (,$(OMIT_GNULIB_MODULE_mkostemp)) EXTRA_DIST += mkostemp.c EXTRA_libgnu_a_SOURCES += mkostemp.c +endif ## end gnulib module mkostemp ## begin gnulib module mktime +ifeq (,$(OMIT_GNULIB_MODULE_mktime)) EXTRA_DIST += mktime-internal.h mktime.c EXTRA_libgnu_a_SOURCES += mktime.c +endif ## end gnulib module mktime ## begin gnulib module mktime-internal +ifeq (,$(OMIT_GNULIB_MODULE_mktime-internal)) -if gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31 +ifneq (,$(gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31)) endif EXTRA_DIST += mktime-internal.h mktime.c EXTRA_libgnu_a_SOURCES += mktime.c +endif ## end gnulib module mktime-internal ## begin gnulib module openat-h +ifeq (,$(OMIT_GNULIB_MODULE_openat-h)) -if gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7 +ifneq (,$(gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7)) endif EXTRA_DIST += openat.h -## end gnulib module openat-h - -## begin gnulib module pathmax - -if gl_GNULIB_ENABLED_pathmax - endif -EXTRA_DIST += pathmax.h - -## end gnulib module pathmax +## end gnulib module openat-h ## begin gnulib module pipe2 +ifeq (,$(OMIT_GNULIB_MODULE_pipe2)) libgnu_a_SOURCES += pipe2.c +endif ## end gnulib module pipe2 ## begin gnulib module pselect +ifeq (,$(OMIT_GNULIB_MODULE_pselect)) EXTRA_DIST += pselect.c EXTRA_libgnu_a_SOURCES += pselect.c +endif ## end gnulib module pselect ## begin gnulib module pthread_sigmask +ifeq (,$(OMIT_GNULIB_MODULE_pthread_sigmask)) EXTRA_DIST += pthread_sigmask.c EXTRA_libgnu_a_SOURCES += pthread_sigmask.c +endif ## end gnulib module pthread_sigmask ## begin gnulib module putenv +ifeq (,$(OMIT_GNULIB_MODULE_putenv)) EXTRA_DIST += putenv.c EXTRA_libgnu_a_SOURCES += putenv.c +endif ## end gnulib module putenv ## begin gnulib module qcopy-acl +ifeq (,$(OMIT_GNULIB_MODULE_qcopy-acl)) libgnu_a_SOURCES += qcopy-acl.c +endif ## end gnulib module qcopy-acl ## begin gnulib module readlink +ifeq (,$(OMIT_GNULIB_MODULE_readlink)) EXTRA_DIST += readlink.c EXTRA_libgnu_a_SOURCES += readlink.c +endif ## end gnulib module readlink ## begin gnulib module readlinkat +ifeq (,$(OMIT_GNULIB_MODULE_readlinkat)) EXTRA_DIST += at-func.c readlinkat.c EXTRA_libgnu_a_SOURCES += at-func.c readlinkat.c +endif ## end gnulib module readlinkat ## begin gnulib module root-uid +ifeq (,$(OMIT_GNULIB_MODULE_root-uid)) -if gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c +ifneq (,$(gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c)) endif EXTRA_DIST += root-uid.h +endif ## end gnulib module root-uid ## begin gnulib module secure_getenv +ifeq (,$(OMIT_GNULIB_MODULE_secure_getenv)) -if gl_GNULIB_ENABLED_secure_getenv +ifneq (,$(gl_GNULIB_ENABLED_secure_getenv)) endif EXTRA_DIST += secure_getenv.c EXTRA_libgnu_a_SOURCES += secure_getenv.c +endif ## end gnulib module secure_getenv ## begin gnulib module signal-h +ifeq (,$(OMIT_GNULIB_MODULE_signal-h)) BUILT_SOURCES += signal.h @@ -833,115 +1921,83 @@ MOSTLYCLEANFILES += signal.h signal.h-t EXTRA_DIST += signal.in.h +endif ## end gnulib module signal-h ## begin gnulib module snippet/_Noreturn +ifeq (,$(OMIT_GNULIB_MODULE_snippet/_Noreturn)) # Because this Makefile snippet defines a variable used by other -# gnulib Makefile snippets, it must be present in all Makefile.am that +# gnulib Makefile snippets, it must be present in all makefiles that # need it. This is ensured by the applicability 'all' defined above. -_NORETURN_H=$(top_srcdir)/build-aux/snippet/_Noreturn.h +_NORETURN_H=$(srcdir)/_Noreturn.h -EXTRA_DIST += $(top_srcdir)/build-aux/snippet/_Noreturn.h +EXTRA_DIST += _Noreturn.h +endif ## end gnulib module snippet/_Noreturn ## begin gnulib module snippet/arg-nonnull +ifeq (,$(OMIT_GNULIB_MODULE_snippet/arg-nonnull)) -# The BUILT_SOURCES created by this Makefile snippet are not used via #include -# statements but through direct file reference. Therefore this snippet must be -# present in all Makefile.am that need it. This is ensured by the applicability -# 'all' defined above. - -BUILT_SOURCES += arg-nonnull.h -# The arg-nonnull.h that gets inserted into generated .h files is the same as -# build-aux/snippet/arg-nonnull.h, except that it has the copyright header cut -# off. -arg-nonnull.h: $(top_srcdir)/build-aux/snippet/arg-nonnull.h - $(AM_V_GEN)rm -f $@-t $@ && \ - sed -n -e '/GL_ARG_NONNULL/,$$p' \ - < $(top_srcdir)/build-aux/snippet/arg-nonnull.h \ - > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += arg-nonnull.h arg-nonnull.h-t +# Because this Makefile snippet defines a variable used by other +# gnulib Makefile snippets, it must be present in all makefiles that +# need it. This is ensured by the applicability 'all' defined above. -ARG_NONNULL_H=arg-nonnull.h +ARG_NONNULL_H=$(srcdir)/arg-nonnull.h -EXTRA_DIST += $(top_srcdir)/build-aux/snippet/arg-nonnull.h +EXTRA_DIST += arg-nonnull.h +endif ## end gnulib module snippet/arg-nonnull ## begin gnulib module snippet/c++defs +ifeq (,$(OMIT_GNULIB_MODULE_snippet/c++defs)) -# The BUILT_SOURCES created by this Makefile snippet are not used via #include -# statements but through direct file reference. Therefore this snippet must be -# present in all Makefile.am that need it. This is ensured by the applicability -# 'all' defined above. - -BUILT_SOURCES += c++defs.h -# The c++defs.h that gets inserted into generated .h files is the same as -# build-aux/snippet/c++defs.h, except that it has the copyright header cut off. -c++defs.h: $(top_srcdir)/build-aux/snippet/c++defs.h - $(AM_V_GEN)rm -f $@-t $@ && \ - sed -n -e '/_GL_CXXDEFS/,$$p' \ - < $(top_srcdir)/build-aux/snippet/c++defs.h \ - > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += c++defs.h c++defs.h-t +# Because this Makefile snippet defines a variable used by other +# gnulib Makefile snippets, it must be present in all makefiles that +# need it. This is ensured by the applicability 'all' defined above. -CXXDEFS_H=c++defs.h +CXXDEFS_H=$(srcdir)/c++defs.h -EXTRA_DIST += $(top_srcdir)/build-aux/snippet/c++defs.h +EXTRA_DIST += c++defs.h +endif ## end gnulib module snippet/c++defs ## begin gnulib module snippet/warn-on-use +ifeq (,$(OMIT_GNULIB_MODULE_snippet/warn-on-use)) -BUILT_SOURCES += warn-on-use.h -# The warn-on-use.h that gets inserted into generated .h files is the same as -# build-aux/snippet/warn-on-use.h, except that it has the copyright header cut -# off. -warn-on-use.h: $(top_srcdir)/build-aux/snippet/warn-on-use.h - $(AM_V_GEN)rm -f $@-t $@ && \ - sed -n -e '/^.ifndef/,$$p' \ - < $(top_srcdir)/build-aux/snippet/warn-on-use.h \ - > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += warn-on-use.h warn-on-use.h-t - -WARN_ON_USE_H=warn-on-use.h - -EXTRA_DIST += $(top_srcdir)/build-aux/snippet/warn-on-use.h - -## end gnulib module snippet/warn-on-use +# Because this Makefile snippet defines a variable used by other +# gnulib Makefile snippets, it must be present in all makefiles that +# need it. This is ensured by the applicability 'all' defined above. -## begin gnulib module stat +WARN_ON_USE_H=$(srcdir)/warn-on-use.h -if gl_GNULIB_ENABLED_stat +EXTRA_DIST += warn-on-use.h endif -EXTRA_DIST += stat.c - -EXTRA_libgnu_a_SOURCES += stat.c - -## end gnulib module stat +## end gnulib module snippet/warn-on-use ## begin gnulib module stat-time +ifeq (,$(OMIT_GNULIB_MODULE_stat-time)) libgnu_a_SOURCES += stat-time.c EXTRA_DIST += stat-time.h +endif ## end gnulib module stat-time ## begin gnulib module stdalign +ifeq (,$(OMIT_GNULIB_MODULE_stdalign)) BUILT_SOURCES += $(STDALIGN_H) # We need the following in order to create <stdalign.h> when the system # doesn't have one that works. -if GL_GENERATE_STDALIGN_H +ifneq (,$(GL_GENERATE_STDALIGN_H)) stdalign.h: stdalign.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ @@ -956,15 +2012,17 @@ MOSTLYCLEANFILES += stdalign.h stdalign.h-t EXTRA_DIST += stdalign.in.h +endif ## end gnulib module stdalign ## begin gnulib module stddef +ifeq (,$(OMIT_GNULIB_MODULE_stddef)) BUILT_SOURCES += $(STDDEF_H) # We need the following in order to create <stddef.h> when the system # doesn't have one that works with the given compiler. -if GL_GENERATE_STDDEF_H +ifneq (,$(GL_GENERATE_STDDEF_H)) stddef.h: stddef.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ @@ -987,15 +2045,17 @@ MOSTLYCLEANFILES += stddef.h stddef.h-t EXTRA_DIST += stddef.in.h +endif ## end gnulib module stddef ## begin gnulib module stdint +ifeq (,$(OMIT_GNULIB_MODULE_stdint)) BUILT_SOURCES += $(STDINT_H) # We need the following in order to create <stdint.h> when the system # doesn't have one that works with the given compiler. -if GL_GENERATE_STDINT_H +ifneq (,$(GL_GENERATE_STDINT_H)) stdint.h: stdint.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ @@ -1039,9 +2099,11 @@ MOSTLYCLEANFILES += stdint.h stdint.h-t EXTRA_DIST += stdint.in.h +endif ## end gnulib module stdint ## begin gnulib module stdio +ifeq (,$(OMIT_GNULIB_MODULE_stdio)) BUILT_SOURCES += stdio.h @@ -1167,9 +2229,11 @@ MOSTLYCLEANFILES += stdio.h stdio.h-t EXTRA_DIST += stdio.in.h +endif ## end gnulib module stdio ## begin gnulib module stdlib +ifeq (,$(OMIT_GNULIB_MODULE_stdlib)) BUILT_SOURCES += stdlib.h @@ -1273,26 +2337,32 @@ MOSTLYCLEANFILES += stdlib.h stdlib.h-t EXTRA_DIST += stdlib.in.h +endif ## end gnulib module stdlib ## begin gnulib module stpcpy +ifeq (,$(OMIT_GNULIB_MODULE_stpcpy)) EXTRA_DIST += stpcpy.c EXTRA_libgnu_a_SOURCES += stpcpy.c +endif ## end gnulib module stpcpy ## begin gnulib module strftime +ifeq (,$(OMIT_GNULIB_MODULE_strftime)) libgnu_a_SOURCES += strftime.c EXTRA_DIST += strftime.h +endif ## end gnulib module strftime ## begin gnulib module string +ifeq (,$(OMIT_GNULIB_MODULE_string)) BUILT_SOURCES += string.h @@ -1390,58 +2460,46 @@ MOSTLYCLEANFILES += string.h string.h-t EXTRA_DIST += string.in.h +endif ## end gnulib module string ## begin gnulib module strtoimax +ifeq (,$(OMIT_GNULIB_MODULE_strtoimax)) EXTRA_DIST += strtoimax.c EXTRA_libgnu_a_SOURCES += strtoimax.c +endif ## end gnulib module strtoimax ## begin gnulib module strtoll +ifeq (,$(OMIT_GNULIB_MODULE_strtoll)) -if gl_GNULIB_ENABLED_strtoll +ifneq (,$(gl_GNULIB_ENABLED_strtoll)) endif EXTRA_DIST += strtol.c strtoll.c EXTRA_libgnu_a_SOURCES += strtol.c strtoll.c -## end gnulib module strtoll - -## begin gnulib module strtoull - -if gl_GNULIB_ENABLED_strtoull - endif -EXTRA_DIST += strtol.c strtoul.c strtoull.c - -EXTRA_libgnu_a_SOURCES += strtol.c strtoul.c strtoull.c - -## end gnulib module strtoull - -## begin gnulib module strtoumax - - -EXTRA_DIST += strtoimax.c strtoumax.c - -EXTRA_libgnu_a_SOURCES += strtoimax.c strtoumax.c - -## end gnulib module strtoumax +## end gnulib module strtoll ## begin gnulib module symlink +ifeq (,$(OMIT_GNULIB_MODULE_symlink)) EXTRA_DIST += symlink.c EXTRA_libgnu_a_SOURCES += symlink.c +endif ## end gnulib module symlink ## begin gnulib module sys_select +ifeq (,$(OMIT_GNULIB_MODULE_sys_select)) BUILT_SOURCES += sys/select.h @@ -1473,9 +2531,11 @@ MOSTLYCLEANDIRS += sys EXTRA_DIST += sys_select.in.h +endif ## end gnulib module sys_select ## begin gnulib module sys_stat +ifeq (,$(OMIT_GNULIB_MODULE_sys_stat)) BUILT_SOURCES += sys/stat.h @@ -1491,6 +2551,7 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_SYS_STAT_H''@|$(NEXT_SYS_STAT_H)|g' \ -e 's|@''WINDOWS_64_BIT_ST_SIZE''@|$(WINDOWS_64_BIT_ST_SIZE)|g' \ + -e 's|@''WINDOWS_STAT_TIMESPEC''@|$(WINDOWS_STAT_TIMESPEC)|g' \ -e 's/@''GNULIB_FCHMODAT''@/$(GNULIB_FCHMODAT)/g' \ -e 's/@''GNULIB_FSTAT''@/$(GNULIB_FSTAT)/g' \ -e 's/@''GNULIB_FSTATAT''@/$(GNULIB_FSTATAT)/g' \ @@ -1504,6 +2565,7 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU -e 's/@''GNULIB_MKNODAT''@/$(GNULIB_MKNODAT)/g' \ -e 's/@''GNULIB_STAT''@/$(GNULIB_STAT)/g' \ -e 's/@''GNULIB_UTIMENSAT''@/$(GNULIB_UTIMENSAT)/g' \ + -e 's/@''GNULIB_OVERRIDES_STRUCT_STAT''@/$(GNULIB_OVERRIDES_STRUCT_STAT)/g' \ -e 's|@''HAVE_FCHMODAT''@|$(HAVE_FCHMODAT)|g' \ -e 's|@''HAVE_FSTATAT''@|$(HAVE_FSTATAT)|g' \ -e 's|@''HAVE_FUTIMENS''@|$(HAVE_FUTIMENS)|g' \ @@ -1535,9 +2597,11 @@ MOSTLYCLEANDIRS += sys EXTRA_DIST += sys_stat.in.h +endif ## end gnulib module sys_stat ## begin gnulib module sys_time +ifeq (,$(OMIT_GNULIB_MODULE_sys_time)) BUILT_SOURCES += sys/time.h @@ -1569,9 +2633,11 @@ MOSTLYCLEANFILES += sys/time.h sys/time.h-t EXTRA_DIST += sys_time.in.h +endif ## end gnulib module sys_time ## begin gnulib module sys_types +ifeq (,$(OMIT_GNULIB_MODULE_sys_types)) BUILT_SOURCES += sys/types.h @@ -1587,6 +2653,7 @@ sys/types.h: sys_types.in.h $(top_builddir)/config.status -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_SYS_TYPES_H''@|$(NEXT_SYS_TYPES_H)|g' \ -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \ + -e 's|@''WINDOWS_STAT_INODES''@|$(WINDOWS_STAT_INODES)|g' \ < $(srcdir)/sys_types.in.h; \ } > $@-t && \ mv $@-t $@ @@ -1594,19 +2661,23 @@ MOSTLYCLEANFILES += sys/types.h sys/types.h-t EXTRA_DIST += sys_types.in.h +endif ## end gnulib module sys_types ## begin gnulib module tempname +ifeq (,$(OMIT_GNULIB_MODULE_tempname)) -if gl_GNULIB_ENABLED_tempname +ifneq (,$(gl_GNULIB_ENABLED_tempname)) libgnu_a_SOURCES += tempname.c endif EXTRA_DIST += tempname.h +endif ## end gnulib module tempname ## begin gnulib module time +ifeq (,$(OMIT_GNULIB_MODULE_time)) BUILT_SOURCES += time.h @@ -1620,24 +2691,31 @@ time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $( -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_TIME_H''@|$(NEXT_TIME_H)|g' \ - -e 's/@''GNULIB_GETTIMEOFDAY''@/$(GNULIB_GETTIMEOFDAY)/g' \ + -e 's/@''GNULIB_CTIME''@/$(GNULIB_CTIME)/g' \ + -e 's/@''GNULIB_LOCALTIME''@/$(GNULIB_LOCALTIME)/g' \ -e 's/@''GNULIB_MKTIME''@/$(GNULIB_MKTIME)/g' \ -e 's/@''GNULIB_NANOSLEEP''@/$(GNULIB_NANOSLEEP)/g' \ + -e 's/@''GNULIB_STRFTIME''@/$(GNULIB_STRFTIME)/g' \ -e 's/@''GNULIB_STRPTIME''@/$(GNULIB_STRPTIME)/g' \ -e 's/@''GNULIB_TIMEGM''@/$(GNULIB_TIMEGM)/g' \ -e 's/@''GNULIB_TIME_R''@/$(GNULIB_TIME_R)/g' \ -e 's/@''GNULIB_TIME_RZ''@/$(GNULIB_TIME_RZ)/g' \ + -e 's/@''GNULIB_TZSET''@/$(GNULIB_TZSET)/g' \ -e 's|@''HAVE_DECL_LOCALTIME_R''@|$(HAVE_DECL_LOCALTIME_R)|g' \ -e 's|@''HAVE_NANOSLEEP''@|$(HAVE_NANOSLEEP)|g' \ -e 's|@''HAVE_STRPTIME''@|$(HAVE_STRPTIME)|g' \ -e 's|@''HAVE_TIMEGM''@|$(HAVE_TIMEGM)|g' \ -e 's|@''HAVE_TIMEZONE_T''@|$(HAVE_TIMEZONE_T)|g' \ + -e 's|@''HAVE_TZSET''@|$(HAVE_TZSET)|g' \ + -e 's|@''REPLACE_CTIME''@|$(REPLACE_CTIME)|g' \ -e 's|@''REPLACE_GMTIME''@|$(REPLACE_GMTIME)|g' \ -e 's|@''REPLACE_LOCALTIME''@|$(REPLACE_LOCALTIME)|g' \ -e 's|@''REPLACE_LOCALTIME_R''@|$(REPLACE_LOCALTIME_R)|g' \ -e 's|@''REPLACE_MKTIME''@|$(REPLACE_MKTIME)|g' \ -e 's|@''REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \ + -e 's|@''REPLACE_STRFTIME''@|$(REPLACE_STRFTIME)|g' \ -e 's|@''REPLACE_TIMEGM''@|$(REPLACE_TIMEGM)|g' \ + -e 's|@''REPLACE_TZSET''@|$(REPLACE_TZSET)|g' \ -e 's|@''PTHREAD_H_DEFINES_STRUCT_TIMESPEC''@|$(PTHREAD_H_DEFINES_STRUCT_TIMESPEC)|g' \ -e 's|@''SYS_TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(SYS_TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \ -e 's|@''TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \ @@ -1652,64 +2730,80 @@ MOSTLYCLEANFILES += time.h time.h-t EXTRA_DIST += time.in.h +endif ## end gnulib module time ## begin gnulib module time_r +ifeq (,$(OMIT_GNULIB_MODULE_time_r)) EXTRA_DIST += time_r.c EXTRA_libgnu_a_SOURCES += time_r.c +endif ## end gnulib module time_r ## begin gnulib module time_rz +ifeq (,$(OMIT_GNULIB_MODULE_time_rz)) EXTRA_DIST += time-internal.h time_rz.c EXTRA_libgnu_a_SOURCES += time_rz.c +endif ## end gnulib module time_rz ## begin gnulib module timegm +ifeq (,$(OMIT_GNULIB_MODULE_timegm)) EXTRA_DIST += mktime-internal.h timegm.c EXTRA_libgnu_a_SOURCES += timegm.c +endif ## end gnulib module timegm ## begin gnulib module timespec +ifeq (,$(OMIT_GNULIB_MODULE_timespec)) libgnu_a_SOURCES += timespec.c EXTRA_DIST += timespec.h +endif ## end gnulib module timespec ## begin gnulib module timespec-add +ifeq (,$(OMIT_GNULIB_MODULE_timespec-add)) libgnu_a_SOURCES += timespec-add.c +endif ## end gnulib module timespec-add ## begin gnulib module timespec-sub +ifeq (,$(OMIT_GNULIB_MODULE_timespec-sub)) libgnu_a_SOURCES += timespec-sub.c +endif ## end gnulib module timespec-sub ## begin gnulib module u64 +ifeq (,$(OMIT_GNULIB_MODULE_u64)) libgnu_a_SOURCES += u64.c EXTRA_DIST += u64.h +endif ## end gnulib module u64 ## begin gnulib module unistd +ifeq (,$(OMIT_GNULIB_MODULE_unistd)) BUILT_SOURCES += unistd.h libgnu_a_SOURCES += unistd.c @@ -1767,6 +2861,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's/@''GNULIB_SLEEP''@/$(GNULIB_SLEEP)/g' \ -e 's/@''GNULIB_SYMLINK''@/$(GNULIB_SYMLINK)/g' \ -e 's/@''GNULIB_SYMLINKAT''@/$(GNULIB_SYMLINKAT)/g' \ + -e 's/@''GNULIB_TRUNCATE''@/$(GNULIB_TRUNCATE)/g' \ -e 's/@''GNULIB_TTYNAME_R''@/$(GNULIB_TTYNAME_R)/g' \ -e 's/@''GNULIB_UNISTD_H_GETOPT''@/0$(GNULIB_GL_UNISTD_H_GETOPT)/g' \ -e 's/@''GNULIB_UNISTD_H_NONBLOCKING''@/$(GNULIB_UNISTD_H_NONBLOCKING)/g' \ @@ -1804,6 +2899,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's|@''HAVE_SLEEP''@|$(HAVE_SLEEP)|g' \ -e 's|@''HAVE_SYMLINK''@|$(HAVE_SYMLINK)|g' \ -e 's|@''HAVE_SYMLINKAT''@|$(HAVE_SYMLINKAT)|g' \ + -e 's|@''HAVE_TRUNCATE''@|$(HAVE_TRUNCATE)|g' \ -e 's|@''HAVE_UNLINKAT''@|$(HAVE_UNLINKAT)|g' \ -e 's|@''HAVE_USLEEP''@|$(HAVE_USLEEP)|g' \ -e 's|@''HAVE_DECL_ENVIRON''@|$(HAVE_DECL_ENVIRON)|g' \ @@ -1845,6 +2941,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's|@''REPLACE_SLEEP''@|$(REPLACE_SLEEP)|g' \ -e 's|@''REPLACE_SYMLINK''@|$(REPLACE_SYMLINK)|g' \ -e 's|@''REPLACE_SYMLINKAT''@|$(REPLACE_SYMLINKAT)|g' \ + -e 's|@''REPLACE_TRUNCATE''@|$(REPLACE_TRUNCATE)|g' \ -e 's|@''REPLACE_TTYNAME_R''@|$(REPLACE_TTYNAME_R)|g' \ -e 's|@''REPLACE_UNLINK''@|$(REPLACE_UNLINK)|g' \ -e 's|@''REPLACE_UNLINKAT''@|$(REPLACE_UNLINKAT)|g' \ @@ -1861,44 +2958,64 @@ MOSTLYCLEANFILES += unistd.h unistd.h-t EXTRA_DIST += unistd.in.h +endif ## end gnulib module unistd +## begin gnulib module unlocked-io +ifeq (,$(OMIT_GNULIB_MODULE_unlocked-io)) + + +EXTRA_DIST += unlocked-io.h + +endif +## end gnulib module unlocked-io + ## begin gnulib module update-copyright +ifeq (,$(OMIT_GNULIB_MODULE_update-copyright)) EXTRA_DIST += $(top_srcdir)/build-aux/update-copyright +endif ## end gnulib module update-copyright ## begin gnulib module utimens +ifeq (,$(OMIT_GNULIB_MODULE_utimens)) libgnu_a_SOURCES += utimens.c EXTRA_DIST += utimens.h +endif ## end gnulib module utimens ## begin gnulib module verify +ifeq (,$(OMIT_GNULIB_MODULE_verify)) EXTRA_DIST += verify.h +endif ## end gnulib module verify ## begin gnulib module vla +ifeq (,$(OMIT_GNULIB_MODULE_vla)) EXTRA_DIST += vla.h +endif ## end gnulib module vla ## begin gnulib module xalloc-oversized +ifeq (,$(OMIT_GNULIB_MODULE_xalloc-oversized)) -if gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec +ifneq (,$(gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec)) endif EXTRA_DIST += xalloc-oversized.h +endif ## end gnulib module xalloc-oversized diff --git a/lib/intprops.h b/lib/intprops.h index 85ed61f8d8c..28f43613fe2 100644 --- a/lib/intprops.h +++ b/lib/intprops.h @@ -21,7 +21,6 @@ #define _GL_INTPROPS_H #include <limits.h> -#include <verify.h> /* Return a value with the common real type of E and V and the value of V. */ #define _GL_INT_CONVERT(e, v) (0 * (e) + (v)) @@ -80,24 +79,7 @@ /* This include file assumes that signed types are two's complement without padding bits; the above macros have undefined behavior otherwise. If this is a problem for you, please let us know how to fix it for your host. - As a sanity check, test the assumption for some signed types that - <limits.h> bounds. */ -verify (TYPE_MINIMUM (signed char) == SCHAR_MIN); -verify (TYPE_MAXIMUM (signed char) == SCHAR_MAX); -verify (TYPE_MINIMUM (short int) == SHRT_MIN); -verify (TYPE_MAXIMUM (short int) == SHRT_MAX); -verify (TYPE_MINIMUM (int) == INT_MIN); -verify (TYPE_MAXIMUM (int) == INT_MAX); -verify (TYPE_MINIMUM (long int) == LONG_MIN); -verify (TYPE_MAXIMUM (long int) == LONG_MAX); -#ifdef LLONG_MAX -verify (TYPE_MINIMUM (long long int) == LLONG_MIN); -verify (TYPE_MAXIMUM (long long int) == LLONG_MAX); -#endif -/* Similarly, sanity-check one ISO/IEC TS 18661-1:2014 macro if defined. */ -#ifdef UINT_WIDTH -verify (TYPE_WIDTH (unsigned int) == UINT_WIDTH); -#endif + This assumption is tested by the intprops-tests module. */ /* Does the __typeof__ keyword work? This could be done by 'configure', but for now it's easier to do it by hand. */ @@ -237,7 +219,11 @@ verify (TYPE_WIDTH (unsigned int) == UINT_WIDTH); : (max) >> (b) < (a)) /* True if __builtin_add_overflow (A, B, P) works when P is non-null. */ -#define _GL_HAS_BUILTIN_OVERFLOW (5 <= __GNUC__) +#if 5 <= __GNUC__ && !defined __ICC +# define _GL_HAS_BUILTIN_OVERFLOW 1 +#else +# define _GL_HAS_BUILTIN_OVERFLOW 0 +#endif /* True if __builtin_add_overflow_p (A, B, C) works. */ #define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__) @@ -389,10 +375,10 @@ verify (TYPE_WIDTH (unsigned int) == UINT_WIDTH); (_Generic \ (*(r), \ signed char: \ - _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned char, \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ signed char, SCHAR_MIN, SCHAR_MAX), \ short int: \ - _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned short int, \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ short int, SHRT_MIN, SHRT_MAX), \ int: \ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ @@ -406,10 +392,10 @@ verify (TYPE_WIDTH (unsigned int) == UINT_WIDTH); #else # define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \ (sizeof *(r) == sizeof (signed char) \ - ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned char, \ + ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ signed char, SCHAR_MIN, SCHAR_MAX) \ : sizeof *(r) == sizeof (short int) \ - ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned short int, \ + ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ short int, SHRT_MIN, SHRT_MAX) \ : sizeof *(r) == sizeof (int) \ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ @@ -431,9 +417,8 @@ verify (TYPE_WIDTH (unsigned int) == UINT_WIDTH); /* Store the low-order bits of A <op> B into *R, where the operation is given by OP. Use the unsigned type UT for calculation to avoid - overflow problems. *R's type is T, with extremal values TMIN and - TMAX. T must be a signed integer type. Return 1 if the result - overflows. */ + overflow problems. *R's type is T, with extrema TMIN and TMAX. + T must be a signed integer type. Return 1 if the result overflows. */ #define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \ (sizeof ((a) op (b)) < sizeof (t) \ ? _GL_INT_OP_CALC1 ((t) (a), (t) (b), r, op, overflow, ut, t, tmin, tmax) \ @@ -442,17 +427,27 @@ verify (TYPE_WIDTH (unsigned int) == UINT_WIDTH); ((overflow (a, b) \ || (EXPR_SIGNED ((a) op (b)) && ((a) op (b)) < (tmin)) \ || (tmax) < ((a) op (b))) \ - ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t, tmin, tmax), 1) \ - : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t, tmin, tmax), 0)) - -/* Return A <op> B, where the operation is given by OP. Use the - unsigned type UT for calculation to avoid overflow problems. - Convert the result to type T without overflow by subtracting TMIN - from large values before converting, and adding it afterwards. - Compilers can optimize all the operations except OP. */ -#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t, tmin, tmax) \ - (((ut) (a) op (ut) (b)) <= (tmax) \ - ? (t) ((ut) (a) op (ut) (b)) \ - : ((t) (((ut) (a) op (ut) (b)) - (tmin)) + (tmin))) + ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 1) \ + : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 0)) + +/* Return the low-order bits of A <op> B, where the operation is given + by OP. Use the unsigned type UT for calculation to avoid undefined + behavior on signed integer overflow, and convert the result to type T. + UT is at least as wide as T and is no narrower than unsigned int, + T is two's complement, and there is no padding or trap representations. + Assume that converting UT to T yields the low-order bits, as is + done in all known two's-complement C compilers. E.g., see: + https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html + + According to the C standard, converting UT to T yields an + implementation-defined result or signal for values outside T's + range. However, code that works around this theoretical problem + runs afoul of a compiler bug in Oracle Studio 12.3 x86. See: + http://lists.gnu.org/archive/html/bug-gnulib/2017-04/msg00049.html + As the compiler bug is real, don't try to work around the + theoretical problem. */ + +#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \ + ((t) ((ut) (a) op (ut) (b))) #endif /* _GL_INTPROPS_H */ diff --git a/lib/limits.in.h b/lib/limits.in.h index a7e307f5c66..08d3c328c4a 100644 --- a/lib/limits.in.h +++ b/lib/limits.in.h @@ -28,6 +28,17 @@ #ifndef _@GUARD_PREFIX@_LIMITS_H #define _@GUARD_PREFIX@_LIMITS_H +/* For HP-UX 11.31. */ +#if defined LONG_LONG_MIN && !defined LLONG_MIN +# define LLONG_MIN LONG_LONG_MIN +#endif +#if defined LONG_LONG_MAX && !defined LLONG_MAX +# define LLONG_MAX LONG_LONG_MAX +#endif +#if defined ULONG_LONG_MAX && !defined ULLONG_MAX +# define ULLONG_MAX ULONG_LONG_MAX +#endif + /* The number of usable bits in an unsigned or signed integer type with minimum value MIN and maximum value MAX, as an int expression suitable in #if. Cover all known practical hosts. This diff --git a/lib/localtime-buffer.c b/lib/localtime-buffer.c new file mode 100644 index 00000000000..f84ad3e8238 --- /dev/null +++ b/lib/localtime-buffer.c @@ -0,0 +1,58 @@ +/* Provide access to the last buffer returned by localtime() or gmtime(). + + Copyright (C) 2001-2003, 2005-2007, 2009-2017 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. */ + +/* written by Jim Meyering */ + +#include <config.h> + +/* Specification. */ +#include "localtime-buffer.h" + +#if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME + +static struct tm tm_zero_buffer; +struct tm *localtime_buffer_addr = &tm_zero_buffer; + +/* This is a wrapper for localtime. + + On the first call, record the address of the static buffer that + localtime uses for its result. */ + +struct tm * +rpl_localtime (time_t const *timep) +{ + struct tm *tm = localtime (timep); + + if (localtime_buffer_addr == &tm_zero_buffer) + localtime_buffer_addr = tm; + + return tm; +} + +/* Same as above, since gmtime and localtime use the same buffer. */ +struct tm * +rpl_gmtime (time_t const *timep) +{ + struct tm *tm = gmtime (timep); + + if (localtime_buffer_addr == &tm_zero_buffer) + localtime_buffer_addr = tm; + + return tm; +} + +#endif diff --git a/lib/localtime-buffer.h b/lib/localtime-buffer.h new file mode 100644 index 00000000000..483a579bda4 --- /dev/null +++ b/lib/localtime-buffer.h @@ -0,0 +1,27 @@ +/* Provide access to the last buffer returned by localtime() or gmtime(). + + Copyright (C) 2001-2003, 2005-2007, 2009-2017 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. */ + +/* written by Jim Meyering */ + +#include <time.h> + +#if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME + +/* The address of the last buffer returned by localtime() or gmtime(). */ +extern struct tm *localtime_buffer_addr; + +#endif diff --git a/lib/md5.c b/lib/md5.c index e82b0514a0a..dcbba45ddff 100644 --- a/lib/md5.c +++ b/lib/md5.c @@ -246,7 +246,8 @@ md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); ctx->buflen &= 63; - /* The regions in the following copy operation cannot overlap. */ + /* The regions in the following copy operation cannot overlap, + because ctx->buflen < 64 ≤ (left_over + add) & ~63. */ memcpy (ctx->buffer, &((char *) ctx->buffer)[(left_over + add) & ~63], ctx->buflen); @@ -288,6 +289,8 @@ md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) { md5_process_block (ctx->buffer, 64, ctx); left_over -= 64; + /* The regions in the following copy operation cannot overlap, + because left_over ≤ 64. */ memcpy (ctx->buffer, &ctx->buffer[16], left_over); } ctx->buflen = left_over; diff --git a/lib/md5.h b/lib/md5.h index fb20b7b1bc2..e38a6198708 100644 --- a/lib/md5.h +++ b/lib/md5.h @@ -74,8 +74,8 @@ struct md5_ctx uint32_t D; uint32_t total[2]; - uint32_t buflen; - uint32_t buffer[32]; + uint32_t buflen; /* ≥ 0, ≤ 128 */ + uint32_t buffer[32]; /* 128 bytes; the first buflen bytes are in use */ }; /* diff --git a/lib/minmax.h b/lib/minmax.h new file mode 100644 index 00000000000..6b602a94fdb --- /dev/null +++ b/lib/minmax.h @@ -0,0 +1,60 @@ +/* MIN, MAX macros. + Copyright (C) 1995, 1998, 2001, 2003, 2005, 2009-2017 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. */ + +#ifndef _MINMAX_H +#define _MINMAX_H + +/* Note: MIN, MAX are also defined in <sys/param.h> on some systems + (glibc, IRIX, HP-UX, OSF/1). Therefore you might get warnings about + MIN, MAX macro redefinitions on some systems; the workaround is to + #include this file as the last one among the #include list. */ + +/* Before we define the following symbols we get the <limits.h> file + since otherwise we get redefinitions on some systems if <limits.h> is + included after this file. Likewise for <sys/param.h>. + If more than one of these system headers define MIN and MAX, pick just + one of the headers (because the definitions most likely are the same). */ +#if HAVE_MINMAX_IN_LIMITS_H +# include <limits.h> +#elif HAVE_MINMAX_IN_SYS_PARAM_H +# include <sys/param.h> +#endif + +/* Note: MIN and MAX should be used with two arguments of the + same type. They might not return the minimum and maximum of their two + arguments, if the arguments have different types or have unusual + floating-point values. For example, on a typical host with 32-bit 'int', + 64-bit 'long long', and 64-bit IEEE 754 'double' types: + + MAX (-1, 2147483648) returns 4294967295. + MAX (9007199254740992.0, 9007199254740993) returns 9007199254740992.0. + MAX (NaN, 0.0) returns 0.0. + MAX (+0.0, -0.0) returns -0.0. + + and in each case the answer is in some sense bogus. */ + +/* MAX(a,b) returns the maximum of A and B. */ +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +/* MIN(a,b) returns the minimum of A and B. */ +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#endif /* _MINMAX_H */ diff --git a/lib/mktime.c b/lib/mktime.c index 998882f5860..058ab65c03e 100644 --- a/lib/mktime.c +++ b/lib/mktime.c @@ -23,6 +23,19 @@ # define DEBUG_MKTIME 0 #endif +/* The following macros influence what gets defined when this file is compiled: + + Macro/expression Which gnulib module This compilation unit + should define + + NEED_MKTIME_WORKING mktime rpl_mktime + || NEED_MKTIME_WINDOWS + + NEED_MKTIME_INTERNAL mktime-internal mktime_internal + + DEBUG_MKTIME (defined manually) my_mktime, main + */ + #if !defined _LIBC && !DEBUG_MKTIME # include <config.h> #endif @@ -51,6 +64,13 @@ # define mktime my_mktime #endif +#if NEED_MKTIME_WINDOWS /* on native Windows */ +# include <stdlib.h> +# include <string.h> +#endif + +#if NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL || DEBUG_MKTIME + /* A signed type that can represent an integer number of years multiplied by three times the number of seconds in a year. It is needed when converting a tm_year value times the number of seconds @@ -458,25 +478,65 @@ __mktime_internal (struct tm *tp, return t; } +#endif /* NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL || DEBUG_MKTIME */ + +#if NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS || DEBUG_MKTIME +# if NEED_MKTIME_WORKING || DEBUG_MKTIME static mktime_offset_t localtime_offset; +# endif /* Convert *TP to a time_t value. */ time_t mktime (struct tm *tp) { -#ifdef _LIBC +# if NEED_MKTIME_WINDOWS + /* Rectify the value of the environment variable TZ. + There are four possible kinds of such values: + - Traditional US time zone names, e.g. "PST8PDT". Syntax: see + <https://msdn.microsoft.com/en-us/library/90s5c885.aspx> + - Time zone names based on geography, that contain one or more + slashes, e.g. "Europe/Moscow". + - Time zone names based on geography, without slashes, e.g. + "Singapore". + - Time zone names that contain explicit DST rules. Syntax: see + <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03> + The Microsoft CRT understands only the first kind. It produces incorrect + results if the value of TZ is of the other kinds. + But in a Cygwin environment, /etc/profile.d/tzset.sh sets TZ to a value + of the second kind for most geographies, or of the first kind in a few + other geographies. If it is of the second kind, neutralize it. For the + Microsoft CRT, an absent or empty TZ means the time zone that the user + has set in the Windows Control Panel. + If the value of TZ is of the third or fourth kind -- Cygwin programs + understand these syntaxes as well --, it does not matter whether we + neutralize it or not, since these values occur only when a Cygwin user + has set TZ explicitly; this case is 1. rare and 2. under the user's + responsibility. */ + const char *tz = getenv ("TZ"); + if (tz != NULL && strchr (tz, '/') != NULL) + _putenv ("TZ="); +# endif + +# if NEED_MKTIME_WORKING || DEBUG_MKTIME +# ifdef _LIBC /* POSIX.1 8.1.1 requires that whenever mktime() is called, the time zone names contained in the external variable 'tzname' shall be set as if the tzset() function had been called. */ __tzset (); -#elif HAVE_TZSET +# elif HAVE_TZSET tzset (); -#endif +# endif return __mktime_internal (tp, __localtime_r, &localtime_offset); +# else +# undef mktime + return mktime (tp); +# endif } +#endif /* NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS || DEBUG_MKTIME */ + #ifdef weak_alias weak_alias (mktime, timelocal) #endif diff --git a/lib/pathmax.h b/lib/pathmax.h deleted file mode 100644 index aa0730e27a8..00000000000 --- a/lib/pathmax.h +++ /dev/null @@ -1,83 +0,0 @@ -/* Define PATH_MAX somehow. Requires sys/types.h. - Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2017 Free Software - Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _PATHMAX_H -# define _PATHMAX_H - -/* POSIX:2008 defines PATH_MAX to be the maximum number of bytes in a filename, - including the terminating NUL byte. - <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html> - PATH_MAX is not defined on systems which have no limit on filename length, - such as GNU/Hurd. - - This file does *not* define PATH_MAX always. Programs that use this file - can handle the GNU/Hurd case in several ways: - - Either with a package-wide handling, or with a per-file handling, - - Either through a - #ifdef PATH_MAX - or through a fallback like - #ifndef PATH_MAX - # define PATH_MAX 8192 - #endif - or through a fallback like - #ifndef PATH_MAX - # define PATH_MAX pathconf ("/", _PC_PATH_MAX) - #endif - */ - -# include <unistd.h> - -# include <limits.h> - -# ifndef _POSIX_PATH_MAX -# define _POSIX_PATH_MAX 256 -# endif - -/* Don't include sys/param.h if it already has been. */ -# if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN -# include <sys/param.h> -# endif - -# if !defined PATH_MAX && defined MAXPATHLEN -# define PATH_MAX MAXPATHLEN -# endif - -# ifdef __hpux -/* On HP-UX, PATH_MAX designates the maximum number of bytes in a filename, - *not* including the terminating NUL byte, and is set to 1023. - Additionally, when _XOPEN_SOURCE is defined to 500 or more, PATH_MAX is - not defined at all any more. */ -# undef PATH_MAX -# define PATH_MAX 1024 -# endif - -# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -/* The page "Naming Files, Paths, and Namespaces" on msdn.microsoft.com, - section "Maximum Path Length Limitation", - <http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85).aspx#maxpath> - explains that the maximum size of a filename, including the terminating - NUL byte, is 260 = 3 + 256 + 1. - This is the same value as - - FILENAME_MAX in <stdio.h>, - - _MAX_PATH in <stdlib.h>, - - MAX_PATH in <windef.h>. - Undefine the original value, because mingw's <limits.h> gets it wrong. */ -# undef PATH_MAX -# define PATH_MAX 260 -# endif - -#endif /* _PATHMAX_H */ diff --git a/lib/stat-time.h b/lib/stat-time.h index 9402b3fc1c0..9e45e855655 100644 --- a/lib/stat-time.h +++ b/lib/stat-time.h @@ -31,6 +31,10 @@ _GL_INLINE_HEADER_BEGIN # define _GL_STAT_TIME_INLINE _GL_INLINE #endif +#ifdef __cplusplus +extern "C" { +#endif + /* STAT_TIMESPEC (ST, ST_XTIM) is the ST_XTIM member for *ST of type struct timespec, if available. If not, then STAT_TIMESPEC_NS (ST, ST_XTIM) is the nanosecond component of the ST_XTIM member for *ST, @@ -39,8 +43,8 @@ _GL_INLINE_HEADER_BEGIN time respectively. These macros are private to stat-time.h. */ -#if defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC -# ifdef TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC +#if _GL_WINDOWS_STAT_TIMESPEC || defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC +# if _GL_WINDOWS_STAT_TIMESPEC || defined TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC # define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim) # else # define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec) @@ -165,9 +169,13 @@ get_stat_birthtime (struct stat const *st) #elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ /* Native Windows platforms (but not Cygwin) put the "file creation time" in st_ctime (!). See - <http://msdn2.microsoft.com/de-de/library/14h5k7ff(VS.80).aspx>. */ + <https://msdn.microsoft.com/en-us/library/14h5k7ff(VS.80).aspx>. */ +# if _GL_WINDOWS_STAT_TIMESPEC + t = st->st_ctim; +# else t.tv_sec = st->st_ctime; t.tv_nsec = 0; +# endif #else /* Birth time is not supported. */ t.tv_sec = -1; @@ -194,6 +202,10 @@ get_stat_birthtime (struct stat const *st) return t; } +#ifdef __cplusplus +} +#endif + _GL_INLINE_HEADER_END #endif diff --git a/lib/stat.c b/lib/stat.c deleted file mode 100644 index 7e7c2f6f887..00000000000 --- a/lib/stat.c +++ /dev/null @@ -1,138 +0,0 @@ -/* Work around platform bugs in stat. - Copyright (C) 2009-2017 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -/* written by Eric Blake */ - -/* If the user's config.h happens to include <sys/stat.h>, let it include only - the system's <sys/stat.h> here, so that orig_stat doesn't recurse to - rpl_stat. */ -#define __need_system_sys_stat_h -#include <config.h> - -/* Get the original definition of stat. It might be defined as a macro. */ -#include <sys/types.h> -#include <sys/stat.h> -#undef __need_system_sys_stat_h - -#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -# if _GL_WINDOWS_64_BIT_ST_SIZE -# undef stat /* avoid warning on mingw64 with _FILE_OFFSET_BITS=64 */ -# define stat _stati64 -# define REPLACE_FUNC_STAT_DIR 1 -# undef REPLACE_FUNC_STAT_FILE -# elif REPLACE_FUNC_STAT_FILE -/* mingw64 has a broken stat() function, based on _stat(), in libmingwex.a. - Bypass it. */ -# define stat _stat -# define REPLACE_FUNC_STAT_DIR 1 -# undef REPLACE_FUNC_STAT_FILE -# endif -#endif - -static int -orig_stat (const char *filename, struct stat *buf) -{ - return stat (filename, buf); -} - -/* Specification. */ -/* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc - eliminates this include because of the preliminary #include <sys/stat.h> - above. */ -#include "sys/stat.h" - -#include <errno.h> -#include <limits.h> -#include <stdbool.h> -#include <string.h> -#include "dosname.h" -#include "verify.h" - -#if REPLACE_FUNC_STAT_DIR -# include "pathmax.h" - /* The only known systems where REPLACE_FUNC_STAT_DIR is needed also - have a constant PATH_MAX. */ -# ifndef PATH_MAX -# error "Please port this replacement to your platform" -# endif -#endif - -/* Store information about NAME into ST. Work around bugs with - trailing slashes. Mingw has other bugs (such as st_ino always - being 0 on success) which this wrapper does not work around. But - at least this implementation provides the ability to emulate fchdir - correctly. */ - -int -rpl_stat (char const *name, struct stat *st) -{ - int result = orig_stat (name, st); -#if REPLACE_FUNC_STAT_FILE - /* Solaris 9 mistakenly succeeds when given a non-directory with a - trailing slash. */ - if (result == 0 && !S_ISDIR (st->st_mode)) - { - size_t len = strlen (name); - if (ISSLASH (name[len - 1])) - { - errno = ENOTDIR; - return -1; - } - } -#endif /* REPLACE_FUNC_STAT_FILE */ -#if REPLACE_FUNC_STAT_DIR - - if (result == -1 && errno == ENOENT) - { - /* Due to mingw's oddities, there are some directories (like - c:\) where stat() only succeeds with a trailing slash, and - other directories (like c:\windows) where stat() only - succeeds without a trailing slash. But we want the two to be - synonymous, since chdir() manages either style. Likewise, Mingw also - reports ENOENT for names longer than PATH_MAX, when we want - ENAMETOOLONG, and for stat("file/"), when we want ENOTDIR. - Fortunately, mingw PATH_MAX is small enough for stack - allocation. */ - char fixed_name[PATH_MAX + 1] = {0}; - size_t len = strlen (name); - bool check_dir = false; - verify (PATH_MAX <= 4096); - if (PATH_MAX <= len) - errno = ENAMETOOLONG; - else if (len) - { - strcpy (fixed_name, name); - if (ISSLASH (fixed_name[len - 1])) - { - check_dir = true; - while (len && ISSLASH (fixed_name[len - 1])) - fixed_name[--len] = '\0'; - if (!len) - fixed_name[0] = '/'; - } - else - fixed_name[len++] = '/'; - result = orig_stat (fixed_name, st); - if (result == 0 && check_dir && !S_ISDIR (st->st_mode)) - { - result = -1; - errno = ENOTDIR; - } - } - } -#endif /* REPLACE_FUNC_STAT_DIR */ - return result; -} diff --git a/lib/stdalign.in.h b/lib/stdalign.in.h index 5f56eeefd3f..ea248231701 100644 --- a/lib/stdalign.in.h +++ b/lib/stdalign.in.h @@ -103,7 +103,7 @@ # elif ((defined __APPLE__ && defined __MACH__ \ ? 4 < __GNUC__ + (1 <= __GNUC_MINOR__) \ : __GNUC__) \ - || 061200 <= __HP_cc || 061200 <= __HP_aCC \ + || (__ia64 && (61200 <= __HP_cc || 61200 <= __HP_aCC)) \ || __ICC || 0x590 <= __SUNPRO_C || 0x0600 <= __xlC__) # define _Alignas(a) __attribute__ ((__aligned__ (a))) # elif 1300 <= _MSC_VER diff --git a/lib/stdint.in.h b/lib/stdint.in.h index d899c1e034e..5fbec34310f 100644 --- a/lib/stdint.in.h +++ b/lib/stdint.in.h @@ -128,8 +128,13 @@ Return an unspecified value if BITS == 0, adding a check to pacify picky compilers. */ -# define _STDINT_MIN(signed, bits, zero) \ - ((signed) ? ~ _STDINT_MAX (signed, bits, zero) : (zero)) +/* These are separate macros, because if you try to merge these macros into + a single one, HP-UX cc rejects the resulting expression in constant + expressions. */ +# define _STDINT_UNSIGNED_MIN(bits, zero) \ + (zero) +# define _STDINT_SIGNED_MIN(bits, zero) \ + (~ _STDINT_MAX (1, bits, zero)) # define _STDINT_MAX(signed, bits, zero) \ (((((zero) + 1) << ((bits) ? (bits) - 1 - (signed) : 0)) - 1) * 2 + 1) @@ -512,15 +517,15 @@ typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t) # undef PTRDIFF_MAX # if @APPLE_UNIVERSAL_BUILD@ # ifdef _LP64 -# define PTRDIFF_MIN _STDINT_MIN (1, 64, 0l) +# define PTRDIFF_MIN _STDINT_SIGNED_MIN (64, 0l) # define PTRDIFF_MAX _STDINT_MAX (1, 64, 0l) # else -# define PTRDIFF_MIN _STDINT_MIN (1, 32, 0) +# define PTRDIFF_MIN _STDINT_SIGNED_MIN (32, 0) # define PTRDIFF_MAX _STDINT_MAX (1, 32, 0) # endif # else # define PTRDIFF_MIN \ - _STDINT_MIN (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) + _STDINT_SIGNED_MIN (@BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) # define PTRDIFF_MAX \ _STDINT_MAX (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) # endif @@ -528,9 +533,13 @@ typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t) /* sig_atomic_t limits */ # undef SIG_ATOMIC_MIN # undef SIG_ATOMIC_MAX -# define SIG_ATOMIC_MIN \ - _STDINT_MIN (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \ - 0@SIG_ATOMIC_T_SUFFIX@) +# if @HAVE_SIGNED_SIG_ATOMIC_T@ +# define SIG_ATOMIC_MIN \ + _STDINT_SIGNED_MIN (@BITSIZEOF_SIG_ATOMIC_T@, 0@SIG_ATOMIC_T_SUFFIX@) +# else +# define SIG_ATOMIC_MIN \ + _STDINT_UNSIGNED_MIN (@BITSIZEOF_SIG_ATOMIC_T@, 0@SIG_ATOMIC_T_SUFFIX@) +# endif # define SIG_ATOMIC_MAX \ _STDINT_MAX (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \ 0@SIG_ATOMIC_T_SUFFIX@) @@ -566,16 +575,26 @@ typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t) # endif # undef WCHAR_MIN # undef WCHAR_MAX -# define WCHAR_MIN \ - _STDINT_MIN (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) +# if @HAVE_SIGNED_WCHAR_T@ +# define WCHAR_MIN \ + _STDINT_SIGNED_MIN (@BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) +# else +# define WCHAR_MIN \ + _STDINT_UNSIGNED_MIN (@BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) +# endif # define WCHAR_MAX \ _STDINT_MAX (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) /* wint_t limits */ # undef WINT_MIN # undef WINT_MAX -# define WINT_MIN \ - _STDINT_MIN (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) +# if @HAVE_SIGNED_WINT_T@ +# define WINT_MIN \ + _STDINT_SIGNED_MIN (@BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) +# else +# define WINT_MIN \ + _STDINT_UNSIGNED_MIN (@BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) +# endif # define WINT_MAX \ _STDINT_MAX (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) diff --git a/lib/stdio-impl.h b/lib/stdio-impl.h index 75a945eb724..d5b5943fd7c 100644 --- a/lib/stdio-impl.h +++ b/lib/stdio-impl.h @@ -99,6 +99,8 @@ int _file; \ unsigned int _flag; \ } *) fp) +# elif defined __VMS /* OpenVMS */ +# define fp_ ((struct _iobuf *) fp) # else # define fp_ fp # endif diff --git a/lib/strftime.c b/lib/strftime.c index e4d78ef7011..99bee4ef978 100644 --- a/lib/strftime.c +++ b/lib/strftime.c @@ -68,6 +68,14 @@ extern char *tzname[]; #include <string.h> #include <stdbool.h> +#ifndef FALLTHROUGH +# if __GNUC__ < 7 +# define FALLTHROUGH ((void) 0) +# else +# define FALLTHROUGH __attribute__ ((__fallthrough__)) +# endif +#endif + #ifdef COMPILE_WIDE # include <endian.h> # define CHAR_T wchar_t @@ -1138,8 +1146,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) #ifndef _NL_CURRENT format_char = L_('p'); #endif - /* FALLTHROUGH */ - + FALLTHROUGH; case L_('p'): if (change_case) { @@ -1474,7 +1481,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) case L_('\0'): /* GNU extension: % at end of format. */ --f; - /* Fall through. */ + FALLTHROUGH; default: /* Unknown format; output the format, including the '%', since this is most likely the right thing to do if a diff --git a/lib/strtoul.c b/lib/strtoul.c deleted file mode 100644 index c4974e069e5..00000000000 --- a/lib/strtoul.c +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (C) 1991, 1997, 2009-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -#define UNSIGNED 1 - -#include "strtol.c" diff --git a/lib/strtoull.c b/lib/strtoull.c deleted file mode 100644 index 51ae3acb03c..00000000000 --- a/lib/strtoull.c +++ /dev/null @@ -1,26 +0,0 @@ -/* Function to parse an 'unsigned long long int' from text. - Copyright (C) 1995-1997, 1999, 2009-2017 Free Software Foundation, Inc. - NOTE: The canonical source of this file is maintained with the GNU C - Library. Bugs can be reported to bug-glibc@gnu.org. - - This program is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 3 of the License, or any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -#define QUAD 1 - -#include "strtoul.c" - -#ifdef _LIBC -strong_alias (__strtoull_internal, __strtouq_internal) -weak_alias (strtoull, strtouq) -#endif diff --git a/lib/strtoumax.c b/lib/strtoumax.c deleted file mode 100644 index dc395d626ab..00000000000 --- a/lib/strtoumax.c +++ /dev/null @@ -1,2 +0,0 @@ -#define UNSIGNED 1 -#include "strtoimax.c" diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h index d5ca343437f..1831740900b 100644 --- a/lib/sys_stat.in.h +++ b/lib/sys_stat.in.h @@ -1,4 +1,4 @@ -/* Provide a more complete sys/stat header file. +/* Provide a more complete sys/stat.h header file. Copyright (C) 2005-2017 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -72,6 +72,75 @@ # define stat _stati64 #endif +/* Optionally, override 'struct stat' on native Windows. */ +#if @GNULIB_OVERRIDES_STRUCT_STAT@ + +# undef stat +# if @GNULIB_STAT@ +# define stat rpl_stat +# else + /* Provoke a clear link error if stat() is used as a function and + module 'stat' is not in use. */ +# define stat stat_used_without_requesting_gnulib_module_stat +# endif + +# if !GNULIB_defined_struct_stat +struct stat +{ + dev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; +# if 0 + uid_t st_uid; +# else /* uid_t is not defined by default on native Windows. */ + short st_uid; +# endif +# if 0 + gid_t st_gid; +# else /* gid_t is not defined by default on native Windows. */ + short st_gid; +# endif + dev_t st_rdev; + off_t st_size; +# if 0 + blksize_t st_blksize; + blkcnt_t st_blocks; +# endif + +# if @WINDOWS_STAT_TIMESPEC@ + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; +# else + time_t st_atime; + time_t st_mtime; + time_t st_ctime; +# endif +}; +# if @WINDOWS_STAT_TIMESPEC@ +# define st_atime st_atim.tv_sec +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec + /* Indicator, for gnulib internal purposes. */ +# define _GL_WINDOWS_STAT_TIMESPEC 1 +# endif +# define GNULIB_defined_struct_stat 1 +# endif + +/* Other possible values of st_mode. */ +# if 0 +# define _S_IFBLK 0x6000 +# endif +# if 0 +# define _S_IFLNK 0xA000 +# endif +# if 0 +# define _S_IFSOCK 0xC000 +# endif + +#endif + #ifndef S_IFIFO # ifdef _S_IFIFO # define S_IFIFO _S_IFIFO @@ -345,6 +414,9 @@ _GL_CXXALIAS_RPL (fstat, int, (int fd, struct stat *buf)); _GL_CXXALIAS_SYS (fstat, int, (int fd, struct stat *buf)); # endif _GL_CXXALIASWARN (fstat); +#elif @GNULIB_OVERRIDES_STRUCT_STAT@ +# undef fstat +# define fstat fstat_used_without_requesting_gnulib_module_fstat #elif @WINDOWS_64_BIT_ST_SIZE@ /* Above, we define stat to _stati64. */ # define fstat _fstati64 @@ -378,6 +450,9 @@ _GL_CXXALIAS_SYS (fstatat, int, (int fd, char const *name, struct stat *st, int flags)); # endif _GL_CXXALIASWARN (fstatat); +#elif @GNULIB_OVERRIDES_STRUCT_STAT@ +# undef fstatat +# define fstatat fstatat_used_without_requesting_gnulib_module_fstatat #elif defined GNULIB_POSIXCHECK # undef fstatat # if HAVE_RAW_DECL_FSTATAT @@ -476,6 +551,9 @@ _GL_CXXALIAS_SYS (lstat, int, (const char *name, struct stat *buf)); # if @HAVE_LSTAT@ _GL_CXXALIASWARN (lstat); # endif +#elif @GNULIB_OVERRIDES_STRUCT_STAT@ +# undef lstat +# define lstat lstat_used_without_requesting_gnulib_module_lstat #elif defined GNULIB_POSIXCHECK # undef lstat # if HAVE_RAW_DECL_LSTAT @@ -625,63 +703,69 @@ _GL_WARN_ON_USE (mknodat, "mknodat is not portable - " #if @GNULIB_STAT@ # if @REPLACE_STAT@ -/* We can't use the object-like #define stat rpl_stat, because of - struct stat. This means that rpl_stat will not be used if the user - does (stat)(a,b). Oh well. */ -# if defined _AIX && defined stat && defined _LARGE_FILES - /* With _LARGE_FILES defined, AIX (only) defines stat to stat64, - so we have to replace stat64() instead of stat(). */ -# undef stat64 -# define stat64(name, st) rpl_stat (name, st) -# elif @WINDOWS_64_BIT_ST_SIZE@ - /* Above, we define stat to _stati64. */ -# if defined __MINGW32__ && defined _stati64 -# ifndef _USE_32BIT_TIME_T - /* The system headers define _stati64 to _stat64. */ -# undef _stat64 -# define _stat64(name, st) rpl_stat (name, st) +# if !@GNULIB_OVERRIDES_STRUCT_STAT@ + /* We can't use the object-like #define stat rpl_stat, because of + struct stat. This means that rpl_stat will not be used if the user + does (stat)(a,b). Oh well. */ +# if defined _AIX && defined stat && defined _LARGE_FILES + /* With _LARGE_FILES defined, AIX (only) defines stat to stat64, + so we have to replace stat64() instead of stat(). */ +# undef stat64 +# define stat64(name, st) rpl_stat (name, st) +# elif @WINDOWS_64_BIT_ST_SIZE@ + /* Above, we define stat to _stati64. */ +# if defined __MINGW32__ && defined _stati64 +# ifndef _USE_32BIT_TIME_T + /* The system headers define _stati64 to _stat64. */ +# undef _stat64 +# define _stat64(name, st) rpl_stat (name, st) +# endif +# elif defined _MSC_VER && defined _stati64 +# ifdef _USE_32BIT_TIME_T + /* The system headers define _stati64 to _stat32i64. */ +# undef _stat32i64 +# define _stat32i64(name, st) rpl_stat (name, st) +# else + /* The system headers define _stati64 to _stat64. */ +# undef _stat64 +# define _stat64(name, st) rpl_stat (name, st) +# endif +# else +# undef _stati64 +# define _stati64(name, st) rpl_stat (name, st) # endif -# elif defined _MSC_VER && defined _stati64 +# elif defined __MINGW32__ && defined stat # ifdef _USE_32BIT_TIME_T - /* The system headers define _stati64 to _stat32i64. */ + /* The system headers define stat to _stat32i64. */ # undef _stat32i64 # define _stat32i64(name, st) rpl_stat (name, st) # else - /* The system headers define _stati64 to _stat64. */ + /* The system headers define stat to _stat64. */ # undef _stat64 # define _stat64(name, st) rpl_stat (name, st) # endif -# else -# undef _stati64 -# define _stati64(name, st) rpl_stat (name, st) -# endif -# elif defined __MINGW32__ && defined stat -# ifdef _USE_32BIT_TIME_T - /* The system headers define stat to _stat32i64. */ -# undef _stat32i64 -# define _stat32i64(name, st) rpl_stat (name, st) -# else - /* The system headers define stat to _stat64. */ -# undef _stat64 -# define _stat64(name, st) rpl_stat (name, st) -# endif -# elif defined _MSC_VER && defined stat -# ifdef _USE_32BIT_TIME_T - /* The system headers define stat to _stat32. */ -# undef _stat32 -# define _stat32(name, st) rpl_stat (name, st) -# else - /* The system headers define stat to _stat64i32. */ -# undef _stat64i32 -# define _stat64i32(name, st) rpl_stat (name, st) -# endif -# else /* !(_AIX ||__MINGW32__ || _MSC_VER) */ -# undef stat -# define stat(name, st) rpl_stat (name, st) -# endif /* !_LARGE_FILES */ +# elif defined _MSC_VER && defined stat +# ifdef _USE_32BIT_TIME_T + /* The system headers define stat to _stat32. */ +# undef _stat32 +# define _stat32(name, st) rpl_stat (name, st) +# else + /* The system headers define stat to _stat64i32. */ +# undef _stat64i32 +# define _stat64i32(name, st) rpl_stat (name, st) +# endif +# else /* !(_AIX || __MINGW32__ || _MSC_VER) */ +# undef stat +# define stat(name, st) rpl_stat (name, st) +# endif /* !_LARGE_FILES */ +# endif /* !@GNULIB_OVERRIDES_STRUCT_STAT@ */ _GL_EXTERN_C int stat (const char *name, struct stat *buf) _GL_ARG_NONNULL ((1, 2)); # endif +#elif @GNULIB_OVERRIDES_STRUCT_STAT@ +/* see above: + #define stat stat_used_without_requesting_gnulib_module_stat + */ #elif defined GNULIB_POSIXCHECK # undef stat # if HAVE_RAW_DECL_STAT diff --git a/lib/sys_types.in.h b/lib/sys_types.in.h index 30ebfbdd294..3cea44884e3 100644 --- a/lib/sys_types.in.h +++ b/lib/sys_types.in.h @@ -42,6 +42,48 @@ # define _GL_WINDOWS_64_BIT_OFF_T 1 #endif +/* Override dev_t and ino_t if distinguishable inodes support is requested + on native Windows. */ +#if @WINDOWS_STAT_INODES@ + +# if @WINDOWS_STAT_INODES@ == 2 +/* Experimental, not useful in Windows 10. */ + +/* Define dev_t to a 64-bit type. */ +# if !defined GNULIB_defined_dev_t +typedef unsigned long long int rpl_dev_t; +# undef dev_t +# define dev_t rpl_dev_t +# define GNULIB_defined_dev_t 1 +# endif + +/* Define ino_t to a 128-bit type. */ +# if !defined GNULIB_defined_ino_t +/* MSVC does not have a 128-bit integer type. + GCC has a 128-bit integer type __int128, but only on 64-bit targets. */ +typedef struct { unsigned long long int _gl_ino[2]; } rpl_ino_t; +# undef ino_t +# define ino_t rpl_ino_t +# define GNULIB_defined_ino_t 1 +# endif + +# else /* @WINDOWS_STAT_INODES@ == 1 */ + +/* Define ino_t to a 64-bit type. */ +# if !defined GNULIB_defined_ino_t +typedef unsigned long long int rpl_ino_t; +# undef ino_t +# define ino_t rpl_ino_t +# define GNULIB_defined_ino_t 1 +# endif + +# endif + +/* Indicator, for gnulib internal purposes. */ +# define _GL_WINDOWS_STAT_INODES @WINDOWS_STAT_INODES@ + +#endif + /* MSVC 9 defines size_t in <stddef.h>, not in <sys/types.h>. */ /* But avoid namespace pollution on glibc systems. */ #if ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) \ diff --git a/lib/time.in.h b/lib/time.in.h index fef89807f8a..f0c7ef86667 100644 --- a/lib/time.in.h +++ b/lib/time.in.h @@ -120,6 +120,24 @@ _GL_CXXALIAS_SYS (nanosleep, int, _GL_CXXALIASWARN (nanosleep); # endif +/* Initialize time conversion information. */ +# if @GNULIB_TZSET@ +# if @REPLACE_TZSET@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef tzset +# define tzset rpl_tzset +# endif +_GL_FUNCDECL_RPL (tzset, void, (void)); +_GL_CXXALIAS_RPL (tzset, void, (void)); +# else +# if ! @HAVE_TZSET@ +_GL_FUNCDECL_SYS (tzset, void, (void)); +# endif +_GL_CXXALIAS_SYS (tzset, void, (void)); +# endif +_GL_CXXALIASWARN (tzset); +# endif + /* Return the 'time_t' representation of TP and normalize TP. */ # if @GNULIB_MKTIME@ # if @REPLACE_MKTIME@ @@ -187,7 +205,7 @@ _GL_CXXALIASWARN (gmtime_r); /* Convert TIMER to RESULT, assuming local time and UTC respectively. See <http://www.opengroup.org/susv3xsh/localtime.html> and <http://www.opengroup.org/susv3xsh/gmtime.html>. */ -# if @GNULIB_GETTIMEOFDAY@ +# if @GNULIB_LOCALTIME@ || @REPLACE_LOCALTIME@ # if @REPLACE_LOCALTIME@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef localtime @@ -202,7 +220,7 @@ _GL_CXXALIAS_SYS (localtime, struct tm *, (time_t const *__timer)); _GL_CXXALIASWARN (localtime); # endif -# if @GNULIB_GETTIMEOFDAY@ +# if 0 || @REPLACE_GMTIME@ # if @REPLACE_GMTIME@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef gmtime @@ -233,6 +251,41 @@ _GL_CXXALIAS_SYS (strptime, char *, (char const *restrict __buf, _GL_CXXALIASWARN (strptime); # endif +/* Convert *TP to a date and time string. See + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/ctime.html>. */ +# if @GNULIB_CTIME@ +# if @REPLACE_CTIME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define ctime rpl_ctime +# endif +_GL_FUNCDECL_RPL (ctime, char *, (time_t const *__tp) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (ctime, char *, (time_t const *__tp)); +# else +_GL_CXXALIAS_SYS (ctime, char *, (time_t const *__tp)); +# endif +_GL_CXXALIASWARN (ctime); +# endif + +/* Convert *TP to a date and time string. See + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/strftime.html>. */ +# if @GNULIB_STRFTIME@ +# if @REPLACE_STRFTIME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strftime rpl_strftime +# endif +_GL_FUNCDECL_RPL (strftime, size_t, (char *__buf, size_t __bufsize, + const char *__fmt, const struct tm *__tp) + _GL_ARG_NONNULL ((1, 3, 4))); +_GL_CXXALIAS_RPL (strftime, size_t, (char *__buf, size_t __bufsize, + const char *__fmt, const struct tm *__tp)); +# else +_GL_CXXALIAS_SYS (strftime, size_t, (char *__buf, size_t __bufsize, + const char *__fmt, const struct tm *__tp)); +# endif +_GL_CXXALIASWARN (strftime); +# endif + # if defined _GNU_SOURCE && @GNULIB_TIME_RZ@ && ! @HAVE_TIMEZONE_T@ typedef struct tm_zone *timezone_t; _GL_FUNCDECL_SYS (tzalloc, timezone_t, (char const *__name)); diff --git a/lib/time_rz.c b/lib/time_rz.c index adb9c1c2361..17bc11c20e9 100644 --- a/lib/time_rz.c +++ b/lib/time_rz.c @@ -27,6 +27,7 @@ #include <time.h> #include <errno.h> +#include <limits.h> #include <stdbool.h> #include <stddef.h> #include <stdlib.h> @@ -35,15 +36,15 @@ #include "flexmember.h" #include "time-internal.h" -#if !HAVE_TZSET -static void tzset (void) { } +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) #endif /* The approximate size to use for small allocation requests. This is the largest "small" request for the GNU C library malloc. */ enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 }; -/* Minimum size of the ABBRS member of struct abbr. ABBRS is larger +/* Minimum size of the ABBRS member of struct tm_zone. ABBRS is larger only in the unlikely case where an abbreviation longer than this is used. */ enum { ABBR_SIZE_MIN = DEFAULT_MXFAST - offsetof (struct tm_zone, abbrs) }; @@ -150,7 +151,13 @@ save_abbr (timezone_t tz, struct tm *tm) if (! (*zone_copy || (zone_copy == tz->abbrs && tz->tz_is_set))) { size_t zone_size = strlen (zone) + 1; - if (zone_size < tz->abbrs + ABBR_SIZE_MIN - zone_copy) + size_t zone_used = zone_copy - tz->abbrs; + if (SIZE_MAX - zone_used < zone_size) + { + errno = ENOMEM; + return false; + } + if (zone_used + zone_size < ABBR_SIZE_MIN) extend_abbrs (zone_copy, zone, zone_size); else { diff --git a/lib/timespec.h b/lib/timespec.h index a5eca797ce3..f5d823aefe9 100644 --- a/lib/timespec.h +++ b/lib/timespec.h @@ -29,6 +29,10 @@ _GL_INLINE_HEADER_BEGIN # define _GL_TIMESPEC_INLINE _GL_INLINE #endif +#ifdef __cplusplus +extern "C" { +#endif + /* Resolution of timespec timestamps (in units per second), and log base 10 of the resolution. */ @@ -107,6 +111,10 @@ timespectod (struct timespec a) void gettime (struct timespec *); int settime (struct timespec const *); +#ifdef __cplusplus +} +#endif + _GL_INLINE_HEADER_END #endif diff --git a/lib/unistd.in.h b/lib/unistd.in.h index d5fa34dbe56..f366caffa55 100644 --- a/lib/unistd.in.h +++ b/lib/unistd.in.h @@ -127,11 +127,18 @@ # include <sys/types.h> #endif +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + /* Get getopt(), optarg, optind, opterr, optopt. But avoid namespace pollution on glibc systems. */ #if @GNULIB_UNISTD_H_GETOPT@ && !defined __GLIBC__ && !defined _GL_SYSTEM_GETOPT -# define __need_getopt -# include <getopt.h> +# include <getopt-cdefs.h> +# include <getopt-pfx-core.h> #endif #ifndef _GL_INLINE_HEADER_BEGIN @@ -142,13 +149,6 @@ _GL_INLINE_HEADER_BEGIN # define _GL_UNISTD_INLINE _GL_INLINE #endif -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - - /* Hide some function declarations from <winsock2.h>. */ #if @GNULIB_GETHOSTNAME@ && @UNISTD_H_HAVE_WINSOCK2_H@ @@ -1457,6 +1457,36 @@ _GL_WARN_ON_USE (symlinkat, "symlinkat is not portable - " #endif +#if @GNULIB_TRUNCATE@ +/* Change the size of the file designated by FILENAME to become equal to LENGTH. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html>. */ +# if @REPLACE_TRUNCATE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef truncate +# define truncate rpl_truncate +# endif +_GL_FUNCDECL_RPL (truncate, int, (const char *filename, off_t length) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (truncate, int, (const char *filename, off_t length)); +# else +# if !@HAVE_TRUNCATE@ +_GL_FUNCDECL_SYS (truncate, int, (const char *filename, off_t length) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (truncate, int, (const char *filename, off_t length)); +# endif +_GL_CXXALIASWARN (truncate); +#elif defined GNULIB_POSIXCHECK +# undef truncate +# if HAVE_RAW_DECL_TRUNCATE +_GL_WARN_ON_USE (truncate, "truncate is unportable - " + "use gnulib module truncate for portability"); +# endif +#endif + + #if @GNULIB_TTYNAME_R@ /* Store at most BUFLEN characters of the pathname of the terminal FD is open on in BUF. Return 0 on success, otherwise an error number. */ diff --git a/lib/unlocked-io.h b/lib/unlocked-io.h new file mode 100644 index 00000000000..aaf60a0fb4e --- /dev/null +++ b/lib/unlocked-io.h @@ -0,0 +1,136 @@ +/* Prefer faster, non-thread-safe stdio functions if available. + + Copyright (C) 2001-2004, 2009-2017 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Jim Meyering. */ + +#ifndef UNLOCKED_IO_H +# define UNLOCKED_IO_H 1 + +/* These are wrappers for functions/macros from the GNU C library, and + from other C libraries supporting POSIX's optional thread-safe functions. + + The standard I/O functions are thread-safe. These *_unlocked ones are + more efficient but not thread-safe. That they're not thread-safe is + fine since all of the applications in this package are single threaded. + + Also, some code that is shared with the GNU C library may invoke + the *_unlocked functions directly. On hosts that lack those + functions, invoke the non-thread-safe versions instead. */ + +# include <stdio.h> + +# if HAVE_DECL_CLEARERR_UNLOCKED +# undef clearerr +# define clearerr(x) clearerr_unlocked (x) +# else +# define clearerr_unlocked(x) clearerr (x) +# endif + +# if HAVE_DECL_FEOF_UNLOCKED +# undef feof +# define feof(x) feof_unlocked (x) +# else +# define feof_unlocked(x) feof (x) +# endif + +# if HAVE_DECL_FERROR_UNLOCKED +# undef ferror +# define ferror(x) ferror_unlocked (x) +# else +# define ferror_unlocked(x) ferror (x) +# endif + +# if HAVE_DECL_FFLUSH_UNLOCKED +# undef fflush +# define fflush(x) fflush_unlocked (x) +# else +# define fflush_unlocked(x) fflush (x) +# endif + +# if HAVE_DECL_FGETS_UNLOCKED +# undef fgets +# define fgets(x,y,z) fgets_unlocked (x,y,z) +# else +# define fgets_unlocked(x,y,z) fgets (x,y,z) +# endif + +# if HAVE_DECL_FPUTC_UNLOCKED +# undef fputc +# define fputc(x,y) fputc_unlocked (x,y) +# else +# define fputc_unlocked(x,y) fputc (x,y) +# endif + +# if HAVE_DECL_FPUTS_UNLOCKED +# undef fputs +# define fputs(x,y) fputs_unlocked (x,y) +# else +# define fputs_unlocked(x,y) fputs (x,y) +# endif + +# if HAVE_DECL_FREAD_UNLOCKED +# undef fread +# define fread(w,x,y,z) fread_unlocked (w,x,y,z) +# else +# define fread_unlocked(w,x,y,z) fread (w,x,y,z) +# endif + +# if HAVE_DECL_FWRITE_UNLOCKED +# undef fwrite +# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z) +# else +# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z) +# endif + +# if HAVE_DECL_GETC_UNLOCKED +# undef getc +# define getc(x) getc_unlocked (x) +# else +# define getc_unlocked(x) getc (x) +# endif + +# if HAVE_DECL_GETCHAR_UNLOCKED +# undef getchar +# define getchar() getchar_unlocked () +# else +# define getchar_unlocked() getchar () +# endif + +# if HAVE_DECL_PUTC_UNLOCKED +# undef putc +# define putc(x,y) putc_unlocked (x,y) +# else +# define putc_unlocked(x,y) putc (x,y) +# endif + +# if HAVE_DECL_PUTCHAR_UNLOCKED +# undef putchar +# define putchar(x) putchar_unlocked (x) +# else +# define putchar_unlocked(x) putchar (x) +# endif + +# undef flockfile +# define flockfile(x) ((void) 0) + +# undef ftrylockfile +# define ftrylockfile(x) 0 + +# undef funlockfile +# define funlockfile(x) ((void) 0) + +#endif /* UNLOCKED_IO_H */ diff --git a/lib/unsetenv.c b/lib/unsetenv.c deleted file mode 100644 index 6d742c15964..00000000000 --- a/lib/unsetenv.c +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright (C) 1992, 1995-2002, 2005-2017 Free Software Foundation, - Inc. - This file is part of the GNU C Library. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc - optimizes away the name == NULL test below. */ -#define _GL_ARG_NONNULL(params) - -#include <config.h> - -/* Specification. */ -#include <stdlib.h> - -#include <errno.h> -#if !_LIBC -# define __set_errno(ev) ((errno) = (ev)) -#endif - -#include <string.h> -#include <unistd.h> - -#if !_LIBC -# define __environ environ -#endif - -#if _LIBC -/* This lock protects against simultaneous modifications of 'environ'. */ -# include <bits/libc-lock.h> -__libc_lock_define_initialized (static, envlock) -# define LOCK __libc_lock_lock (envlock) -# define UNLOCK __libc_lock_unlock (envlock) -#else -# define LOCK -# define UNLOCK -#endif - -/* In the GNU C library we must keep the namespace clean. */ -#ifdef _LIBC -# define unsetenv __unsetenv -#endif - -#if _LIBC || !HAVE_UNSETENV - -int -unsetenv (const char *name) -{ - size_t len; - char **ep; - - if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) - { - __set_errno (EINVAL); - return -1; - } - - len = strlen (name); - - LOCK; - - ep = __environ; - while (*ep != NULL) - if (!strncmp (*ep, name, len) && (*ep)[len] == '=') - { - /* Found it. Remove this pointer by moving later ones back. */ - char **dp = ep; - - do - dp[0] = dp[1]; - while (*dp++); - /* Continue the loop in case NAME appears again. */ - } - else - ++ep; - - UNLOCK; - - return 0; -} - -#ifdef _LIBC -# undef unsetenv -weak_alias (__unsetenv, unsetenv) -#endif - -#else /* HAVE_UNSETENV */ - -# undef unsetenv -# if !HAVE_DECL_UNSETENV -# if VOID_UNSETENV -extern void unsetenv (const char *); -# else -extern int unsetenv (const char *); -# endif -# endif - -/* Call the underlying unsetenv, in case there is hidden bookkeeping - that needs updating beyond just modifying environ. */ -int -rpl_unsetenv (const char *name) -{ - int result = 0; - if (!name || !*name || strchr (name, '=')) - { - errno = EINVAL; - return -1; - } - while (getenv (name)) -# if !VOID_UNSETENV - result = -# endif - unsetenv (name); - return result; -} - -#endif /* HAVE_UNSETENV */ diff --git a/lib/utimens.c b/lib/utimens.c index 3643668c3a5..ff4eab073c1 100644 --- a/lib/utimens.c +++ b/lib/utimens.c @@ -30,22 +30,25 @@ #include <sys/stat.h> #include <sys/time.h> #include <unistd.h> +#include <utime.h> #include "stat-time.h" #include "timespec.h" -#if HAVE_UTIME_H -# include <utime.h> -#endif - -/* Some systems (even some that do have <utime.h>) don't declare this - structure anywhere. */ -#ifndef HAVE_STRUCT_UTIMBUF -struct utimbuf -{ - long actime; - long modtime; -}; +/* On native Windows, use SetFileTime; but avoid this when compiling + GNU Emacs, which arranges for this in some other way and which + defines WIN32_LEAN_AND_MEAN itself. */ + +#if ((defined _WIN32 || defined __WIN32__) \ + && ! defined __CYGWIN__ && ! defined EMACS_CONFIGURATION) +# define USE_SETFILETIME +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# if GNULIB_MSVC_NOTHROW +# include "msvc-nothrow.h" +# else +# include <io.h> +# endif #endif /* Avoid recursion with rpl_futimens or rpl_utimensat. */ @@ -284,6 +287,90 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2]) lutimensat_works_really = -1; #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */ +#ifdef USE_SETFILETIME + /* On native Windows, use SetFileTime(). See + <https://msdn.microsoft.com/en-us/library/ms724933.aspx> + <https://msdn.microsoft.com/en-us/library/ms724284.aspx> */ + if (0 <= fd) + { + HANDLE handle; + FILETIME current_time; + FILETIME last_access_time; + FILETIME last_write_time; + + handle = (HANDLE) _get_osfhandle (fd); + if (handle == INVALID_HANDLE_VALUE) + { + errno = EBADF; + return -1; + } + + if (ts == NULL || ts[0].tv_nsec == UTIME_NOW || ts[1].tv_nsec == UTIME_NOW) + { + /* GetSystemTimeAsFileTime + <https://msdn.microsoft.com/en-us/library/ms724397.aspx>. + It would be overkill to use + GetSystemTimePreciseAsFileTime + <https://msdn.microsoft.com/en-us/library/hh706895.aspx>. */ + GetSystemTimeAsFileTime (¤t_time); + } + + if (ts == NULL || ts[0].tv_nsec == UTIME_NOW) + { + last_access_time = current_time; + } + else if (ts[0].tv_nsec == UTIME_OMIT) + { + last_access_time.dwLowDateTime = 0; + last_access_time.dwHighDateTime = 0; + } + else + { + ULONGLONG time_since_16010101 = + (ULONGLONG) ts[0].tv_sec * 10000000 + ts[0].tv_nsec / 100 + 116444736000000000LL; + last_access_time.dwLowDateTime = (DWORD) time_since_16010101; + last_access_time.dwHighDateTime = time_since_16010101 >> 32; + } + + if (ts == NULL || ts[1].tv_nsec == UTIME_NOW) + { + last_write_time = current_time; + } + else if (ts[1].tv_nsec == UTIME_OMIT) + { + last_write_time.dwLowDateTime = 0; + last_write_time.dwHighDateTime = 0; + } + else + { + ULONGLONG time_since_16010101 = + (ULONGLONG) ts[1].tv_sec * 10000000 + ts[1].tv_nsec / 100 + 116444736000000000LL; + last_write_time.dwLowDateTime = (DWORD) time_since_16010101; + last_write_time.dwHighDateTime = time_since_16010101 >> 32; + } + + if (SetFileTime (handle, NULL, &last_access_time, &last_write_time)) + return 0; + else + { + DWORD sft_error = GetLastError (); + #if 0 + fprintf (stderr, "fdutimens SetFileTime error 0x%x\n", (unsigned int) sft_error); + #endif + switch (sft_error) + { + case ERROR_ACCESS_DENIED: /* fd was opened without O_RDWR */ + errno = EACCES; /* not specified by POSIX */ + break; + default: + errno = EINVAL; + break; + } + return -1; + } + } +#endif + /* The platform lacks an interface to set file timestamps with nanosecond resolution, so do the best we can, discarding any fractional part of the timestamp. */ @@ -390,7 +477,9 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2]) return -1; } -#if HAVE_WORKING_UTIMES +#ifdef USE_SETFILETIME + return _gl_utimens_windows (file, ts); +#elif HAVE_WORKING_UTIMES return utimes (file, t); #else { diff --git a/build-aux/snippet/warn-on-use.h b/lib/warn-on-use.h similarity index 100% rename from build-aux/snippet/warn-on-use.h rename to lib/warn-on-use.h diff --git a/lib/xalloc-oversized.h b/lib/xalloc-oversized.h index ff0efc6ba40..2e09bab0be2 100644 --- a/lib/xalloc-oversized.h +++ b/lib/xalloc-oversized.h @@ -44,7 +44,7 @@ typedef size_t __xalloc_count_type; #if 7 <= __GNUC__ # define xalloc_oversized(n, s) \ __builtin_mul_overflow_p (n, s, (__xalloc_count_type) 1) -#elif 5 <= __GNUC__ && !__STRICT_ANSI__ +#elif 5 <= __GNUC__ && !defined __ICC && !__STRICT_ANSI__ # define xalloc_oversized(n, s) \ (__builtin_constant_p (n) && __builtin_constant_p (s) \ ? __xalloc_oversized (n, s) \ diff --git a/lisp/Makefile.in b/lisp/Makefile.in index 226ecc988d9..492b643b285 100644 --- a/lisp/Makefile.in +++ b/lisp/Makefile.in @@ -47,6 +47,9 @@ am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = + +FIND_DELETE = @FIND_DELETE@ + # You can specify a different executable on the make command line, # e.g. "make EMACS=../src/emacs ...". @@ -65,36 +68,20 @@ BYTE_COMPILE_EXTRA_FLAGS = # BYTE_COMPILE_EXTRA_FLAGS = --eval '(setq byte-compile-warnings (quote (not unresolved)))' # The example above is just for developers, it should not be used by default. -# Automatically generated autoload files, apart from lisp/loaddefs.el. -# Note this includes only those files that need special rules to -# build; ie it does not need to include things created via -# generated-autoload-file (eg calc/calc-loaddefs.el). +# Those automatically generated autoload files that need special rules +# to build; ie not including things created via generated-autoload-file +# (eg calc/calc-loaddefs.el). LOADDEFS = $(lisp)/calendar/cal-loaddefs.el \ $(lisp)/calendar/diary-loaddefs.el \ $(lisp)/calendar/hol-loaddefs.el \ $(lisp)/mh-e/mh-loaddefs.el \ $(lisp)/net/tramp-loaddefs.el +# All generated autoload files. +loaddefs = $(shell find ${srcdir} -name '*loaddefs.el' ! -name '.*') # Elisp files auto-generated. -AUTOGENEL = loaddefs.el \ - $(LOADDEFS) \ - cus-load.el \ - finder-inf.el \ - subdirs.el \ - ps-print-loaddefs.el \ - emacs-lisp/cl-loaddefs.el \ - calc/calc-loaddefs.el \ - eshell/esh-groups.el \ - cedet/semantic/loaddefs.el \ - cedet/ede/loaddefs.el \ - cedet/srecode/loaddefs.el \ - org/org-loaddefs.el \ - textmodes/reftex-loaddefs.el \ - mail/rmail-loaddefs.el \ - ibuffer-loaddefs.el \ - htmlfontify-loaddefs \ - emacs-lisp/eieio-loaddefs.el \ - dired-loaddefs.el +AUTOGENEL = ${loaddefs} ${srcdir}/cus-load.el ${srcdir}/finder-inf.el \ + ${srcdir}/subdirs.el ${srcdir}/eshell/esh-groups.el # Set load-prefer-newer for the benefit of the non-bootstrappers. BYTE_COMPILE_FLAGS = \ @@ -175,14 +162,41 @@ $(lisp)/finder-inf.el: --eval '(setq generated-finder-keywords-file (unmsys--file-name "$(srcdir)/finder-inf.el"))' \ -f finder-compile-keywords-make-dist ${SUBDIRS_FINDER} +## Comments on loaddefs generation: + +# loaddefs depends on gen-lisp for two reasons: +# 1) In ../src, the emacs target depends on loaddefs but not on eg leim-list. +# So having leim as a dependency of loaddefs (via gen-lisp) ensures leim-list +# gets created before the final emacs is dumped. Having leim +# dependencies in ../src as well would create a parallel race condition. +# +# 2) Files that are marked no-update-autoloads still get recorded in loaddefs. +# So those files should be generated before we make autoloads, if we +# don't want a successive make autoloads to change the output file. +# Said changes are trivial (only comments in the "files without autoloads" +# section), but still can be annoying. Of course, if generated lisp files +# do contain autoloads, it is essential they be built before make autoloads. +# (Also, if a generated file is not written atomically, it is possible that +# in a parallel build, make autoloads could read a partial version of it.) +# +# We'd really like to add "make -C ../admin/unidata all" to gen-lisp +# because of 2) above, but it causes a race condition in parallel +# builds because ../src also runs that rule. Given the limitations of +# recursive make, the only way to fix that would be to remove unidata +# from ../src rules, but that doesn't seem possible due to the various +# non-trivial dependencies. + +# We make $(lisp)/loaddefs.el a dependency of .PHONY to cause Make to +# ignore its time stamp. That's because the real dependencies of +# loaddefs.el aren't known to Make, they are implemented in +# batch-update-autoloads, which only updates the autoloads whose +# sources have changed. + # Use expand-file-name rather than $abs_scrdir so that Emacs does not # get confused when it compares file-names for equality. -# -# Note that we set no-update-autoloads in _generated_ leim files. -# If you want to allow autoloads in such files, remove that, -# and make this depend on leim. + autoloads .PHONY: $(lisp)/loaddefs.el -$(lisp)/loaddefs.el: $(LOADDEFS) +$(lisp)/loaddefs.el: gen-lisp $(LOADDEFS) @echo Directories for loaddefs: ${SUBDIRS_ALMOST} $(AM_V_GEN)$(emacs) -l autoload \ --eval '(setq autoload-ensure-writable t)' \ @@ -193,7 +207,8 @@ $(lisp)/loaddefs.el: $(LOADDEFS) # autoloads only runs when loaddefs.el is nonexistent, although it # generates a number of different files. Provide a force option to enable # regeneration of all these files. -autoloads-force .PHONY: +.PHONY: autoloads-force +autoloads-force: rm loaddefs.el $(MAKE) autoloads @@ -233,9 +248,9 @@ update-gnus-news: FORCE: .PHONY: FORCE -tagsfiles = $(shell find ${srcdir} -name '*.el') -tagsfiles := $(filter-out ${srcdir}/%loaddefs.el,${tagsfiles}) -tagsfiles := $(filter-out ${srcdir}/ldefs-boot%.el,${tagsfiles}) +tagsfiles = $(shell find ${srcdir} -name '*.el' \ + ! -name '.*' ! -name '*loaddefs.el') +tagsfiles := $(filter-out ${srcdir}/ldefs-boot.el,${tagsfiles}) tagsfiles := $(filter-out ${srcdir}/eshell/esh-groups.el,${tagsfiles}) ETAGS = ../lib-src/etags${EXEEXT} @@ -288,7 +303,7 @@ $(THEFILE)c: .PHONY: compile-first compile-main compile compile-always -compile-first: loaddefs.el $(COMPILE_FIRST) +compile-first: $(COMPILE_FIRST) # In 'compile-main' we could directly do # ... | xargs $(MAKE) @@ -306,7 +321,7 @@ compile-targets: $(TARGETS) # Compile all the Elisp files that need it. Beware: it approximates # 'no-byte-compile', so watch out for false-positives! -compile-main: leim semantic compile-clean +compile-main: gen-lisp compile-clean @(cd $(lisp) && \ els=`echo "${SUBDIRS_REL} " | sed -e 's|/\./|/|g' -e 's|/\. | |g' -e 's| |/*.el |g'`; \ for el in $$els; do \ @@ -330,7 +345,12 @@ compile-clean: fi \ done -.PHONY: leim semantic +.PHONY: gen-lisp leim semantic + +## make -C ../admin/unidata all should be here, but that would race +## with ../src. See comments above for loaddefs. +gen-lisp: leim semantic + leim: $(MAKE) -C ../leim all EMACS="$(EMACS)" @@ -348,7 +368,7 @@ compile: $(LOADDEFS) autoloads compile-first # unconditionally. Some files don't actually get compiled because they # set the local variable no-byte-compile. compile-always: - cd $(lisp) && rm -f *.elc */*.elc */*/*.elc */*/*/*.elc + find $(lisp) -name '*.elc' $(FIND_DELETE) $(MAKE) compile .PHONY: backup-compiled-files compile-after-backup @@ -438,7 +458,8 @@ $(CAL_DIR)/hol-loaddefs.el: $(CAL_SRC) $(CAL_DIR)/diary-loaddefs.el .PHONY: bootstrap-clean distclean maintainer-clean bootstrap-clean: - -cd $(lisp) && rm -f *.elc */*.elc */*/*.elc */*/*/*.elc $(AUTOGENEL) + find $(lisp) -name '*.elc' $(FIND_DELETE) + rm -f $(AUTOGENEL) distclean: -rm -f ./Makefile $(lisp)/loaddefs.el~ @@ -454,8 +475,8 @@ check-declare: ## This finds a lot of duplicates between foo.el and obsolete/foo.el. check-defun-dups: sed -n -e '/^(defun /s/\(.\)(.*/\1/p' \ - $$(find . -name '*.el' -print | \ - grep -Ev '(loaddefs|ldefs-boot*)\.el') | sort | uniq -d + $$(find . -name '*.el' ! -name '.*' -print | \ + grep -Ev '(loaddefs|ldefs-boot)\.el|obsolete') | sort | uniq -d # Dependencies diff --git a/lisp/abbrev.el b/lisp/abbrev.el index cbc604c23d6..01ad3d478fc 100644 --- a/lisp/abbrev.el +++ b/lisp/abbrev.el @@ -720,9 +720,10 @@ then ABBREV is looked up in that table only." (setq start abbrev-start-location) (setq abbrev-start-location nil) ;; Remove the hyphen inserted by `abbrev-prefix-mark'. - (if (and (< start (point-max)) - (eq (char-after start) ?-)) - (delete-region start (1+ start))) + (when (and (< start (point-max)) + (eq (char-after start) ?-)) + (delete-region start (1+ start)) + (setq pos (1- pos))) (skip-syntax-backward " ") (setq end (point)) (when (> end start) diff --git a/lisp/align.el b/lisp/align.el index b6a855b4954..081f587d4b2 100644 --- a/lisp/align.el +++ b/lisp/align.el @@ -1322,8 +1322,7 @@ aligner would have dealt with are." (modes (assq 'modes rule))) ;; unless the `run-if' form tells us not to, look for the ;; rule.. - (unless (or (and modes (not (memq major-mode - (eval (cdr modes))))) + (unless (or (and modes (not (apply #'derived-mode-p (eval (cdr modes))))) (and run-if (not (funcall (cdr run-if))))) (let* ((case-fold-search case-fold-search) (case-fold (assq 'case-fold rule)) diff --git a/lisp/allout.el b/lisp/allout.el index e837f83ed38..529de85cd42 100644 --- a/lisp/allout.el +++ b/lisp/allout.el @@ -6503,7 +6503,7 @@ not its value." (let ((inhibit-field-text-motion t)) (beginning-of-line)) (allout-goto-prefix-doublechecked) - (push-mark (point)) + (push-mark) (allout-end-of-current-subtree) (exchange-point-and-mark)) ;;;_ : UI: diff --git a/lisp/ansi-color.el b/lisp/ansi-color.el index 47437bb7c87..72d70c2102e 100644 --- a/lisp/ansi-color.el +++ b/lisp/ansi-color.el @@ -150,17 +150,14 @@ foreground and background colors, respectively." :version "24.4" ; default colors copied from `xterm-standard-colors' :group 'ansi-colors) -(defconst ansi-color-regexp "\033\\[\\([0-9;]*m\\)" - "Regexp that matches SGR control sequences.") - -(defconst ansi-color-drop-regexp - "\033\\[\\([ABCDsuK]\\|[12][JK]\\|=[0-9]+[hI]\\|[0-9;]*[Hf]\\|\\?[0-9]+[hl]\\)" - "Regexp that matches ANSI control sequences to silently drop.") +(defconst ansi-color-control-seq-regexp + ;; See ECMA 48, section 5.4 "Control Sequences". + "\e\\[[\x30-\x3F]*[\x20-\x2F]*[\x40-\x7E]" + "Regexp matching an ANSI control sequence.") (defconst ansi-color-parameter-regexp "\\([0-9]*\\)[m;]" "Regexp that matches SGR control sequence parameters.") - ;; Convenience functions for comint modes (eg. shell-mode) @@ -259,22 +256,20 @@ This function can be added to `comint-preoutput-filter-functions'." (setq string (concat (cadr ansi-color-context) string) ansi-color-context nil)) ;; find the next escape sequence - (while (setq end (string-match ansi-color-regexp string start)) - (setq result (concat result (substring string start end)) - start (match-end 0))) - ;; eliminate unrecognized escape sequences - (while (string-match ansi-color-drop-regexp string) - (setq string - (replace-match "" nil nil string))) + (while (setq end (string-match ansi-color-control-seq-regexp string start)) + (push (substring string start end) result) + (setq start (match-end 0))) ;; save context, add the remainder of the string to the result (let (fragment) - (if (string-match "\033" string start) - (let ((pos (match-beginning 0))) - (setq fragment (substring string pos) - result (concat result (substring string start pos)))) - (setq result (concat result (substring string start)))) + (push (substring string start + (if (string-match "\033" string start) + (let ((pos (match-beginning 0))) + (setq fragment (substring string pos)) + pos) + nil)) + result) (setq ansi-color-context (if fragment (list nil fragment)))) - result)) + (apply #'concat (nreverse result)))) (defun ansi-color--find-face (codes) "Return the face corresponding to CODES." @@ -306,35 +301,29 @@ Set `ansi-color-context' to nil if you don't want this. This function can be added to `comint-preoutput-filter-functions'." (let ((codes (car ansi-color-context)) - (start 0) end escape-sequence result - colorized-substring) + (start 0) end result) ;; If context was saved and is a string, prepend it. (if (cadr ansi-color-context) (setq string (concat (cadr ansi-color-context) string) ansi-color-context nil)) ;; Find the next escape sequence. - (while (setq end (string-match ansi-color-regexp string start)) - (setq escape-sequence (match-string 1 string)) - ;; Colorize the old block from start to end using old face. - (when codes - (put-text-property start end 'font-lock-face (ansi-color--find-face codes) string)) - (setq colorized-substring (substring string start end) - start (match-end 0)) - ;; Eliminate unrecognized ANSI sequences. - (while (string-match ansi-color-drop-regexp colorized-substring) - (setq colorized-substring - (replace-match "" nil nil colorized-substring))) - (push colorized-substring result) - ;; Create new face, by applying escape sequence parameters. - (setq codes (ansi-color-apply-sequence escape-sequence codes))) + (while (setq end (string-match ansi-color-control-seq-regexp string start)) + (let ((esc-end (match-end 0))) + ;; Colorize the old block from start to end using old face. + (when codes + (put-text-property start end 'font-lock-face + (ansi-color--find-face codes) string)) + (push (substring string start end) result) + (setq start (match-end 0)) + ;; If this is a color escape sequence, + (when (eq (aref string (1- esc-end)) ?m) + ;; create a new face from it. + (setq codes (ansi-color-apply-sequence + (substring string end esc-end) codes))))) ;; if the rest of the string should have a face, put it there (when codes (put-text-property start (length string) 'font-lock-face (ansi-color--find-face codes) string)) - ;; eliminate unrecognized escape sequences - (while (string-match ansi-color-drop-regexp string) - (setq string - (replace-match "" nil nil string))) ;; save context, add the remainder of the string to the result (let (fragment) (if (string-match "\033" string start) @@ -367,13 +356,9 @@ it will override BEGIN, the start of the region. Set (start (or (cadr ansi-color-context-region) begin))) (save-excursion (goto-char start) - ;; Delete unrecognized escape sequences. - (while (re-search-forward ansi-color-drop-regexp end-marker t) - (replace-match "")) - (goto-char start) - ;; Delete SGR escape sequences. - (while (re-search-forward ansi-color-regexp end-marker t) - (replace-match "")) + ;; Delete escape sequences. + (while (re-search-forward ansi-color-control-seq-regexp end-marker t) + (delete-region (match-beginning 0) (match-end 0))) ;; save context, add the remainder of the string to the result (if (re-search-forward "\033" end-marker t) (setq ansi-color-context-region (list nil (match-beginning 0))) @@ -400,28 +385,24 @@ this." (let ((codes (car ansi-color-context-region)) (start-marker (or (cadr ansi-color-context-region) (copy-marker begin))) - (end-marker (copy-marker end)) - escape-sequence) - ;; First, eliminate unrecognized ANSI control sequences. - (save-excursion - (goto-char start-marker) - (while (re-search-forward ansi-color-drop-regexp end-marker t) - (replace-match ""))) + (end-marker (copy-marker end))) (save-excursion (goto-char start-marker) - ;; Find the next SGR sequence. - (while (re-search-forward ansi-color-regexp end-marker t) - ;; Colorize the old block from start to end using old face. - (funcall ansi-color-apply-face-function - start-marker (match-beginning 0) - (ansi-color--find-face codes)) - ;; store escape sequence and new start position - (setq escape-sequence (match-string 1) - start-marker (copy-marker (match-end 0))) - ;; delete the escape sequence - (replace-match "") - ;; Update the list of ansi codes. - (setq codes (ansi-color-apply-sequence escape-sequence codes))) + ;; Find the next escape sequence. + (while (re-search-forward ansi-color-control-seq-regexp end-marker t) + ;; Remove escape sequence. + (let ((esc-seq (delete-and-extract-region + (match-beginning 0) (point)))) + ;; Colorize the old block from start to end using old face. + (funcall ansi-color-apply-face-function + (prog1 (marker-position start-marker) + ;; Store new start position. + (set-marker start-marker (point))) + (match-beginning 0) (ansi-color--find-face codes)) + ;; If this is a color sequence, + (when (eq (aref esc-seq (1- (length esc-seq))) ?m) + ;; update the list of ansi codes. + (setq codes (ansi-color-apply-sequence esc-seq codes))))) ;; search for the possible start of a new escape sequence (if (re-search-forward "\033" end-marker t) (progn @@ -500,6 +481,7 @@ Emacs requires OBJECT to be a buffer." ;; property to make sure it works. (let ((overlay (make-overlay from to object))) (overlay-put overlay 'modification-hooks '(ansi-color-freeze-overlay)) + (overlay-put overlay 'insert-behind-hooks '(ansi-color-freeze-overlay)) overlay))) (defun ansi-color-freeze-overlay (overlay is-after begin end &optional len) diff --git a/lisp/auth-source-pass.el b/lisp/auth-source-pass.el new file mode 100644 index 00000000000..529e3024a62 --- /dev/null +++ b/lisp/auth-source-pass.el @@ -0,0 +1,253 @@ +;;; auth-source-pass.el --- Integrate auth-source with password-store -*- lexical-binding: t -*- + +;; Copyright (C) 2015, 2017 Free Software Foundation, Inc. + +;; Author: Damien Cassou <damien@cassou.me>, +;; Nicolas Petton <nicolas@petton.fr> +;; Version: 2.0.0 +;; Package-Requires: ((emacs "24.4") +;; Created: 07 Jun 2015 +;; Keywords: pass password-store auth-source username password login + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. + +;;; Commentary: + +;; Integrates password-store (http://passwordstore.org/) within +;; auth-source. + +;;; Code: + +(require 'seq) +(eval-when-compile (require 'subr-x)) +(eval-when-compile + (require 'cl-lib)) +(require 'auth-source) +(require 'url-parse) + +(cl-defun auth-source-pass-search (&rest spec + &key backend type host user port + &allow-other-keys) + "Given a property list SPEC, return search matches from the :backend. +See `auth-source-search' for details on SPEC." + (cl-assert (or (null type) (eq type (oref backend type))) + t "Invalid password-store search: %s %s") + (when (listp host) + ;; Take the first non-nil item of the list of hosts + (setq host (seq-find #'identity host))) + (list (auth-source-pass--build-result host port user))) + +(defun auth-source-pass--build-result (host port user) + "Build auth-source-pass entry matching HOST, PORT and USER." + (let ((entry (auth-source-pass--find-match host user))) + (when entry + (let ((retval (list + :host host + :port (or (auth-source-pass-get "port" entry) port) + :user (or (auth-source-pass-get "user" entry) user) + :secret (lambda () (auth-source-pass-get 'secret entry))))) + (auth-source-pass--do-debug "return %s as final result (plus hidden password)" + (seq-subseq retval 0 -2)) ;; remove password + retval)))) + +;;;###autoload +(defun auth-source-pass-enable () + "Enable auth-source-password-store." + ;; To add password-store to the list of sources, evaluate the following: + (add-to-list 'auth-sources 'password-store) + ;; clear the cache (required after each change to #'auth-source-pass-search) + (auth-source-forget-all-cached)) + +(defvar auth-source-pass-backend + (auth-source-backend + (format "Password store") + :source "." ;; not used + :type 'password-store + :search-function #'auth-source-pass-search) + "Auth-source backend for password-store.") + +(defun auth-source-pass-backend-parse (entry) + "Create a password-store auth-source backend from ENTRY." + (when (eq entry 'password-store) + (auth-source-backend-parse-parameters entry auth-source-pass-backend))) + +(add-hook 'auth-source-backend-parser-functions #'auth-source-pass-backend-parse) + + +(defun auth-source-pass-get (key entry) + "Return the value associated to KEY in the password-store entry ENTRY. + +ENTRY is the name of a password-store entry. +The key used to retrieve the password is the symbol `secret'. + +The convention used as the format for a password-store file is +the following (see http://www.passwordstore.org/#organization): + +secret +key1: value1 +key2: value2" + (let ((data (auth-source-pass-parse-entry entry))) + (or (cdr (assoc key data)) + (and (string= key "user") + (cdr (assoc "username" data)))))) + +(defun auth-source-pass--read-entry (entry) + "Return a string with the file content of ENTRY." + (with-temp-buffer + (insert-file-contents (expand-file-name + (format "%s.gpg" entry) + "~/.password-store")) + (buffer-substring-no-properties (point-min) (point-max)))) + +(defun auth-source-pass-parse-entry (entry) + "Return an alist of the data associated with ENTRY. + +ENTRY is the name of a password-store entry." + (let ((file-contents (ignore-errors (auth-source-pass--read-entry entry)))) + (and file-contents + (cons `(secret . ,(auth-source-pass--parse-secret file-contents)) + (auth-source-pass--parse-data file-contents))))) + +(defun auth-source-pass--parse-secret (contents) + "Parse the password-store data in the string CONTENTS and return its secret. +The secret is the first line of CONTENTS." + (car (split-string contents "\\\n" t))) + +(defun auth-source-pass--parse-data (contents) + "Parse the password-store data in the string CONTENTS and return an alist. +CONTENTS is the contents of a password-store formatted file." + (let ((lines (split-string contents "\\\n" t "\\\s"))) + (seq-remove #'null + (mapcar (lambda (line) + (let ((pair (mapcar (lambda (s) (string-trim s)) + (split-string line ":")))) + (when (> (length pair) 1) + (cons (car pair) + (mapconcat #'identity (cdr pair) ":"))))) + (cdr lines))))) + +(defun auth-source-pass--user-match-p (entry user) + "Return true iff ENTRY match USER." + (or (null user) + (string= user (auth-source-pass-get "user" entry)))) + +(defun auth-source-pass--hostname (host) + "Extract hostname from HOST." + (let ((url (url-generic-parse-url host))) + (or (url-host url) host))) + +(defun auth-source-pass--hostname-with-user (host) + "Extract hostname and user from HOST." + (let* ((url (url-generic-parse-url host)) + (user (url-user url)) + (hostname (url-host url))) + (cond + ((and user hostname) (format "%s@%s" user hostname)) + (hostname hostname) + (t host)))) + +(defun auth-source-pass--do-debug (&rest msg) + "Call `auth-source-do-debug` with MSG and a prefix." + (apply #'auth-source-do-debug + (cons (concat "auth-source-password-store: " (car msg)) + (cdr msg)))) + +(defun auth-source-pass--select-one-entry (entries user) + "Select one entry from ENTRIES by searching for a field matching USER." + (let ((number (length entries)) + (entry-with-user + (and user + (seq-find (lambda (entry) + (string-equal (auth-source-pass-get "user" entry) user)) + entries)))) + (auth-source-pass--do-debug "found %s matches: %s" number + (mapconcat #'identity entries ", ")) + (if entry-with-user + (progn + (auth-source-pass--do-debug "return %s as it contains matching user field" + entry-with-user) + entry-with-user) + (auth-source-pass--do-debug "return %s as it is the first one" (car entries)) + (car entries)))) + +(defun auth-source-pass--entry-valid-p (entry) + "Return t iff ENTRY can be opened. +Also displays a warning if not. This function is slow, don't call it too +often." + (if (auth-source-pass-parse-entry entry) + t + (auth-source-pass--do-debug "entry '%s' is not valid" entry) + nil)) + +;; TODO: add tests for that when `assess-with-filesystem' is included +;; in Emacs +(defun auth-source-pass-entries () + "Return a list of all password store entries." + (let ((store-dir (expand-file-name "~/.password-store/"))) + (mapcar + (lambda (file) (file-name-sans-extension (file-relative-name file store-dir))) + (directory-files-recursively store-dir "\.gpg$")))) + +(defun auth-source-pass--find-all-by-entry-name (entryname user) + "Search the store for all entries either matching ENTRYNAME/USER or ENTRYNAME. +Only return valid entries as of `auth-source-pass--entry-valid-p'." + (seq-filter (lambda (entry) + (and + (or + (let ((components-host-user + (member entryname (split-string entry "/")))) + (and (= (length components-host-user) 2) + (string-equal user (cadr components-host-user)))) + (string-equal entryname (file-name-nondirectory entry))) + (auth-source-pass--entry-valid-p entry))) + (auth-source-pass-entries))) + +(defun auth-source-pass--find-one-by-entry-name (entryname user) + "Search the store for an entry matching ENTRYNAME. +If USER is non nil, give precedence to entries containing a user field +matching USER." + (auth-source-pass--do-debug "searching for '%s' in entry names (user: %s)" + entryname + user) + (let ((matching-entries (auth-source-pass--find-all-by-entry-name entryname user))) + (pcase (length matching-entries) + (0 (auth-source-pass--do-debug "no match found") + nil) + (1 (auth-source-pass--do-debug "found 1 match: %s" (car matching-entries)) + (car matching-entries)) + (_ (auth-source-pass--select-one-entry matching-entries user))))) + +(defun auth-source-pass--find-match (host user) + "Return a password-store entry name matching HOST and USER. +If many matches are found, return the first one. If no match is +found, return nil." + (or + (if (url-user (url-generic-parse-url host)) + ;; if HOST contains a user (e.g., "user@host.com"), <HOST> + (auth-source-pass--find-one-by-entry-name (auth-source-pass--hostname-with-user host) user) + ;; otherwise, if USER is provided, search for <USER>@<HOST> + (when (stringp user) + (auth-source-pass--find-one-by-entry-name (concat user "@" (auth-source-pass--hostname host)) user))) + ;; if that didn't work, search for HOST without it's user component if any + (auth-source-pass--find-one-by-entry-name (auth-source-pass--hostname host) user) + ;; if that didn't work, remove subdomain: foo.bar.com -> bar.com + (let ((components (split-string host "\\."))) + (when (= (length components) 3) + ;; start from scratch + (auth-source-pass--find-match (mapconcat 'identity (cdr components) ".") user))))) + +(provide 'auth-source-pass) +;;; auth-source-pass.el ends here diff --git a/lisp/auth-source.el b/lisp/auth-source.el index 7402ab21d74..d1747bda3da 100644 --- a/lisp/auth-source.el +++ b/lisp/auth-source.el @@ -317,25 +317,6 @@ If the value is not a list, symmetric encryption will be used." (repeat :tag "Recipient public keys" (string :tag "Recipient public key")))) -;; temp for debugging -;; (unintern 'auth-source-protocols) -;; (unintern 'auth-sources) -;; (customize-variable 'auth-sources) -;; (setq auth-sources nil) -;; (format "%S" auth-sources) -;; (customize-variable 'auth-source-protocols) -;; (setq auth-source-protocols nil) -;; (format "%S" auth-source-protocols) -;; (auth-source-pick nil :host "a" :port 'imap) -;; (auth-source-user-or-password "login" "imap.myhost.com" 'imap) -;; (auth-source-user-or-password "password" "imap.myhost.com" 'imap) -;; (auth-source-user-or-password-imap "login" "imap.myhost.com") -;; (auth-source-user-or-password-imap "password" "imap.myhost.com") -;; (auth-source-protocol-defaults 'imap) - -;; (let ((auth-source-debug 'debug)) (auth-source-do-debug "hello")) -;; (let ((auth-source-debug t)) (auth-source-do-debug "hello")) -;; (let ((auth-source-debug nil)) (auth-source-do-debug "hello")) (defun auth-source-do-debug (&rest msg) (when auth-source-debug (apply #'auth-source-do-warn msg))) @@ -354,8 +335,6 @@ If the value is not a list, symmetric encryption will be used." 'message) msg)) - -;; (auth-source-read-char-choice "enter choice? " '(?a ?b ?q)) (defun auth-source-read-char-choice (prompt choices) "Read one of CHOICES by `read-char-choice', or `read-char'. `dropdown-list' support is disabled because it doesn't work reliably. @@ -373,152 +352,150 @@ with \"[a/b/c] \" if CHOICES is \(?a ?b ?c)." (setq k (read-char-choice full-prompt choices))) k))) -;; (auth-source-pick nil :host "any" :port 'imap :user "joe") -;; (auth-source-pick t :host "any" :port 'imap :user "joe") -;; (setq auth-sources '((:source (:secrets default) :host t :port t :user "joe") -;; (:source (:secrets "session") :host t :port t :user "joe") -;; (:source (:secrets "Login") :host t :port t) -;; (:source "~/.authinfo.gpg" :host t :port t))) - -;; (setq auth-sources '((:source (:secrets default) :host t :port t :user "joe") -;; (:source (:secrets "session") :host t :port t :user "joe") -;; (:source (:secrets "Login") :host t :port t) -;; )) - -;; (setq auth-sources '((:source "~/.authinfo.gpg" :host t :port t))) - -;; (auth-source-backend-parse "myfile.gpg") -;; (auth-source-backend-parse 'default) -;; (auth-source-backend-parse "secrets:Login") -;; (auth-source-backend-parse 'macos-keychain-internet) -;; (auth-source-backend-parse 'macos-keychain-generic) -;; (auth-source-backend-parse "macos-keychain-internet:/path/here.keychain") -;; (auth-source-backend-parse "macos-keychain-generic:/path/here.keychain") +(defvar auth-source-backend-parser-functions nil + "List of auth-source parser functions. +Each function takes an entry from `auth-sources' as parameter and +returns a backend or nil if the entry is not supported. Add a +parser function to this list with `add-hook'. Searching for a +backend starts with the first element on the list and stops as +soon as a function returns non-nil.") (defun auth-source-backend-parse (entry) - "Creates an auth-source-backend from an ENTRY in `auth-sources'." - (auth-source-backend-parse-parameters - entry - (cond - ;; take 'default and recurse to get it as a Secrets API default collection - ;; matching any user, host, and protocol - ((eq entry 'default) - (auth-source-backend-parse '(:source (:secrets default)))) - ;; take secrets:XYZ and recurse to get it as Secrets API collection "XYZ" - ;; matching any user, host, and protocol - ((and (stringp entry) (string-match "^secrets:\\(.+\\)" entry)) - (auth-source-backend-parse `(:source (:secrets ,(match-string 1 entry))))) - - ;; take 'macos-keychain-internet and recurse to get it as a Mac OS - ;; Keychain collection matching any user, host, and protocol - ((eq entry 'macos-keychain-internet) - (auth-source-backend-parse '(:source (:macos-keychain-internet default)))) - ;; take 'macos-keychain-generic and recurse to get it as a Mac OS - ;; Keychain collection matching any user, host, and protocol - ((eq entry 'macos-keychain-generic) - (auth-source-backend-parse '(:source (:macos-keychain-generic default)))) - ;; take macos-keychain-internet:XYZ and recurse to get it as macOS - ;; Keychain "XYZ" matching any user, host, and protocol - ((and (stringp entry) (string-match "^macos-keychain-internet:\\(.+\\)" - entry)) - (auth-source-backend-parse `(:source (:macos-keychain-internet - ,(match-string 1 entry))))) - ;; take macos-keychain-generic:XYZ and recurse to get it as macOS - ;; Keychain "XYZ" matching any user, host, and protocol - ((and (stringp entry) (string-match "^macos-keychain-generic:\\(.+\\)" - entry)) - (auth-source-backend-parse `(:source (:macos-keychain-generic - ,(match-string 1 entry))))) - - ;; take just a file name and recurse to get it as a netrc file - ;; matching any user, host, and protocol - ((stringp entry) - (auth-source-backend-parse `(:source ,entry))) - - ;; a file name with parameters - ((stringp (plist-get entry :source)) - (if (equal (file-name-extension (plist-get entry :source)) "plist") - (auth-source-backend - (plist-get entry :source) - :source (plist-get entry :source) - :type 'plstore - :search-function #'auth-source-plstore-search - :create-function #'auth-source-plstore-create - :data (plstore-open (plist-get entry :source))) - (auth-source-backend - (plist-get entry :source) - :source (plist-get entry :source) - :type 'netrc - :search-function #'auth-source-netrc-search - :create-function #'auth-source-netrc-create))) - - ;; the macOS Keychain - ((and - (not (null (plist-get entry :source))) ; the source must not be nil - (listp (plist-get entry :source)) ; and it must be a list - (or - (plist-get (plist-get entry :source) :macos-keychain-generic) - (plist-get (plist-get entry :source) :macos-keychain-internet))) - - (let* ((source-spec (plist-get entry :source)) - (keychain-generic (plist-get source-spec :macos-keychain-generic)) - (keychain-type (if keychain-generic - 'macos-keychain-generic - 'macos-keychain-internet)) - (source (plist-get source-spec (if keychain-generic - :macos-keychain-generic - :macos-keychain-internet)))) - - (when (symbolp source) - (setq source (symbol-name source))) - - (auth-source-backend - (format "Mac OS Keychain (%s)" source) - :source source - :type keychain-type - :search-function #'auth-source-macos-keychain-search - :create-function #'auth-source-macos-keychain-create))) - - ;; the Secrets API. We require the package, in order to have a - ;; defined value for `secrets-enabled'. - ((and - (not (null (plist-get entry :source))) ; the source must not be nil - (listp (plist-get entry :source)) ; and it must be a list - (require 'secrets nil t) ; and we must load the Secrets API - secrets-enabled) ; and that API must be enabled - - ;; the source is either the :secrets key in ENTRY or - ;; if that's missing or nil, it's "session" - (let ((source (or (plist-get (plist-get entry :source) :secrets) - "session"))) - - ;; if the source is a symbol, we look for the alias named so, - ;; and if that alias is missing, we use "Login" - (when (symbolp source) - (setq source (or (secrets-get-alias (symbol-name source)) - "Login"))) - - (if (featurep 'secrets) - (auth-source-backend - (format "Secrets API (%s)" source) - :source source - :type 'secrets - :search-function #'auth-source-secrets-search - :create-function #'auth-source-secrets-create) - (auth-source-do-warn - "auth-source-backend-parse: no Secrets API, ignoring spec: %S" entry) - (auth-source-backend - (format "Ignored Secrets API (%s)" source) - :source "" - :type 'ignore)))) - - ;; none of them - (t - (auth-source-do-warn - "auth-source-backend-parse: invalid backend spec: %S" entry) - (make-instance 'auth-source-backend - :source "" - :type 'ignore))))) + "Create an auth-source-backend from an ENTRY in `auth-sources'." + + (let (backend) + (cl-dolist (f auth-source-backend-parser-functions) + (when (setq backend (funcall f entry)) + (cl-return))) + + (unless backend + ;; none of the parsers worked + (auth-source-do-warn + "auth-source-backend-parse: invalid backend spec: %S" entry) + (setq backend (make-instance 'auth-source-backend + :source "" + :type 'ignore))) + (auth-source-backend-parse-parameters entry backend))) + +(defun auth-source-backends-parser-file (entry) + ;; take just a file name use it as a netrc/plist file + ;; matching any user, host, and protocol + (when (stringp entry) + (setq entry `(:source ,entry))) + (cond + ;; a file name with parameters + ((stringp (plist-get entry :source)) + (if (equal (file-name-extension (plist-get entry :source)) "plist") + (auth-source-backend + (plist-get entry :source) + :source (plist-get entry :source) + :type 'plstore + :search-function #'auth-source-plstore-search + :create-function #'auth-source-plstore-create + :data (plstore-open (plist-get entry :source))) + (auth-source-backend + (plist-get entry :source) + :source (plist-get entry :source) + :type 'netrc + :search-function #'auth-source-netrc-search + :create-function #'auth-source-netrc-create))))) + +;; Note this function should be last in the parser functions, so we add it first +(add-hook 'auth-source-backend-parser-functions 'auth-source-backends-parser-file) + +(defun auth-source-backends-parser-macos-keychain (entry) + ;; take macos-keychain-{internet,generic}:XYZ and use it as macOS + ;; Keychain "XYZ" matching any user, host, and protocol + (when (and (stringp entry) (string-match "^macos-keychain-internet:\\(.+\\)" + entry)) + (setq entry `(:source (:macos-keychain-internet + ,(match-string 1 entry))))) + (when (and (stringp entry) (string-match "^macos-keychain-generic:\\(.+\\)" + entry)) + (setq entry `(:source (:macos-keychain-generic + ,(match-string 1 entry))))) + ;; take 'macos-keychain-internet or generic and use it as a Mac OS + ;; Keychain collection matching any user, host, and protocol + (when (eq entry 'macos-keychain-internet) + (setq entry '(:source (:macos-keychain-internet default)))) + (when (eq entry 'macos-keychain-generic) + (setq entry '(:source (:macos-keychain-generic default)))) + (cond + ;; the macOS Keychain + ((and + (not (null (plist-get entry :source))) ; the source must not be nil + (listp (plist-get entry :source)) ; and it must be a list + (or + (plist-get (plist-get entry :source) :macos-keychain-generic) + (plist-get (plist-get entry :source) :macos-keychain-internet))) + + (let* ((source-spec (plist-get entry :source)) + (keychain-generic (plist-get source-spec :macos-keychain-generic)) + (keychain-type (if keychain-generic + 'macos-keychain-generic + 'macos-keychain-internet)) + (source (plist-get source-spec (if keychain-generic + :macos-keychain-generic + :macos-keychain-internet)))) + + (when (symbolp source) + (setq source (symbol-name source))) + + (auth-source-backend + (format "Mac OS Keychain (%s)" source) + :source source + :type keychain-type + :search-function #'auth-source-macos-keychain-search + :create-function #'auth-source-macos-keychain-create))))) + +(add-hook 'auth-source-backend-parser-functions 'auth-source-backends-parser-macos-keychain) + +(defun auth-source-backends-parser-secrets (entry) + ;; take secrets:XYZ and use it as Secrets API collection "XYZ" + ;; matching any user, host, and protocol + (when (and (stringp entry) (string-match "^secrets:\\(.+\\)" entry)) + (setq entry `(:source (:secrets ,(match-string 1 entry))))) + ;; take 'default and use it as a Secrets API default collection + ;; matching any user, host, and protocol + (when (eq entry 'default) + (setq entry '(:source (:secrets default)))) + (cond + ;; the Secrets API. We require the package, in order to have a + ;; defined value for `secrets-enabled'. + ((and + (not (null (plist-get entry :source))) ; the source must not be nil + (listp (plist-get entry :source)) ; and it must be a list + (not (null (plist-get + (plist-get entry :source) + :secrets))) ; the source must have :secrets + (require 'secrets nil t) ; and we must load the Secrets API + secrets-enabled) ; and that API must be enabled + + ;; the source is either the :secrets key in ENTRY or + ;; if that's missing or nil, it's "session" + (let ((source (plist-get (plist-get entry :source) :secrets))) + + ;; if the source is a symbol, we look for the alias named so, + ;; and if that alias is missing, we use "Login" + (when (symbolp source) + (setq source (or (secrets-get-alias (symbol-name source)) + "Login"))) + + (if (featurep 'secrets) + (auth-source-backend + (format "Secrets API (%s)" source) + :source source + :type 'secrets + :search-function #'auth-source-secrets-search + :create-function #'auth-source-secrets-create) + (auth-source-do-warn + "auth-source-backend-parse: no Secrets API, ignoring spec: %S" entry) + (auth-source-backend + (format "Ignored Secrets API (%s)" source) + :source "" + :type 'ignore)))))) + +(add-hook 'auth-source-backend-parser-functions 'auth-source-backends-parser-secrets) (defun auth-source-backend-parse-parameters (entry backend) "Fills in the extra auth-source-backend parameters of ENTRY. @@ -781,12 +758,6 @@ must call it to obtain the actual value." (setq matches (append matches bmatches)))))) matches)) -;; (auth-source-search :max 0) -;; (auth-source-search :max 1) -;; (funcall (plist-get (nth 0 (auth-source-search :max 1)) :secret)) -;; (auth-source-search :host "nonesuch" :type 'netrc :K 1) -;; (auth-source-search :host "nonesuch" :type 'secrets) - (defun auth-source-delete (&rest spec) "Delete entries from the authentication backends according to SPEC. Calls `auth-source-search' with the :delete property in SPEC set to t. @@ -844,17 +815,6 @@ This is the same SPEC you passed to `auth-source-search'. Returns t or nil for forgotten or not found." (password-cache-remove (auth-source-format-cache-entry spec))) -;; (loop for sym being the symbols of password-data when (string-match (concat "^" auth-source-magic) (symbol-name sym)) collect (symbol-name sym)) - -;; (auth-source-remember '(:host "wedd") '(4 5 6)) -;; (auth-source-remembered-p '(:host "wedd")) -;; (auth-source-remember '(:host "xedd") '(1 2 3)) -;; (auth-source-remembered-p '(:host "xedd")) -;; (auth-source-remembered-p '(:host "zedd")) -;; (auth-source-recall '(:host "xedd")) -;; (auth-source-recall '(:host t)) -;; (auth-source-forget+ :host t) - (defun auth-source-forget+ (&rest spec) "Forget any cached data matching SPEC. Returns forgotten count. @@ -886,8 +846,6 @@ while \(:host t) would find all host entries." (cl-return 'no))) 'no)))) -;; (auth-source-pick-first-password :host "z.lifelogs.com") -;; (auth-source-pick-first-password :port "imap") (defun auth-source-pick-first-password (&rest spec) "Pick the first secret found from applying SPEC to `auth-source-search'." (let* ((result (nth 0 (apply #'auth-source-search (plist-put spec :max 1)))) @@ -897,7 +855,6 @@ while \(:host t) would find all host entries." (funcall secret) secret))) -;; (auth-source-format-prompt "test %u %h %p" '((?u "user") (?h "host"))) (defun auth-source-format-prompt (prompt alist) "Format PROMPT using %x (for any character x) specifiers in ALIST." (dolist (cell alist) @@ -977,7 +934,7 @@ Note that the MAX parameter is used so we can exit the parse early." (or ;; the required list of keys is nil, or (null require) - ;; every element of require is in n(ormalized) + ;; every element of require is in n (normalized) (let ((n (nth 0 (auth-source-netrc-normalize (list alist) file)))) (cl-loop for req in require @@ -1119,7 +1076,6 @@ Note that the MAX parameter is used so we can exit the parse early." (lambda () p))) passphrase)))) -;; (auth-source-epa-extract-gpg-token "gpg:LS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tClZlcnNpb246IEdudVBHIHYxLjQuMTEgKEdOVS9MaW51eCkKCmpBMEVBd01DT25qMjB1ak9rZnRneVI3K21iNm9aZWhuLzRad3cySkdlbnVaKzRpeEswWDY5di9icDI1U1dsQT0KPS9yc2wKLS0tLS1FTkQgUEdQIE1FU1NBR0UtLS0tLQo=" "~/.netrc") (defun auth-source-epa-extract-gpg-token (secret file) "Pass either the decoded SECRET or the gpg:BASE64DATA version. FILE is the file from which we obtained this token." @@ -1134,7 +1090,6 @@ FILE is the file from which we obtained this token." (defvar pp-escape-newlines) -;; (insert (auth-source-epa-make-gpg-token "mysecret" "~/.netrc")) (defun auth-source-epa-make-gpg-token (secret file) (let ((context (epg-make-context 'OpenPGP)) (pp-escape-newlines nil) @@ -1193,9 +1148,6 @@ FILE is the file from which we obtained this token." ret)) alist)) -;; (setq secret (plist-get (nth 0 (auth-source-search :host t :type 'netrc :K 1 :max 1)) :secret)) -;; (funcall secret) - (cl-defun auth-source-netrc-search (&rest spec &key backend require create type max host user port @@ -1415,7 +1367,6 @@ See `auth-source-search' for details on SPEC." (list artificial))) -;;(funcall (plist-get (nth 0 (auth-source-search :host '("nonesuch2") :user "tzz" :port "imap" :create t :max 1)) :save-function)) (defun auth-source-netrc-saver (file add) "Save a line ADD in FILE, prompting along the way. Respects `auth-source-save-behavior'. Uses @@ -1496,13 +1447,6 @@ Respects `auth-source-save-behavior'. Uses ;;; Backend specific parsing: Secrets API backend -;; (let ((auth-sources '(default))) (auth-source-search :max 1 :create t)) -;; (let ((auth-sources '(default))) (auth-source-search :max 1 :delete t)) -;; (let ((auth-sources '(default))) (auth-source-search :max 1)) -;; (let ((auth-sources '(default))) (auth-source-search)) -;; (let ((auth-sources '("secrets:Login"))) (auth-source-search :max 1)) -;; (let ((auth-sources '("secrets:Login"))) (auth-source-search :max 1 :signon_realm "https://git.gnus.org/Git")) - (defun auth-source-secrets-listify-pattern (pattern) "Convert a pattern with lists to a list of string patterns. @@ -1630,20 +1574,6 @@ authentication tokens: ;;; Backend specific parsing: Mac OS Keychain (using /usr/bin/security) backend -;; (let ((auth-sources '(macos-keychain-internet))) (auth-source-search :max 1 :create t)) -;; (let ((auth-sources '(macos-keychain-internet))) (auth-source-search :max 1 :delete t)) -;; (let ((auth-sources '(macos-keychain-internet))) (auth-source-search :max 1)) -;; (let ((auth-sources '(macos-keychain-internet))) (auth-source-search)) - -;; (let ((auth-sources '(macos-keychain-generic))) (auth-source-search :max 1 :create t)) -;; (let ((auth-sources '(macos-keychain-generic))) (auth-source-search :max 1 :delete t)) -;; (let ((auth-sources '(macos-keychain-generic))) (auth-source-search :max 1)) -;; (let ((auth-sources '(macos-keychain-generic))) (auth-source-search)) - -;; (let ((auth-sources '("macos-keychain-internet:/Users/tzz/Library/Keychains/login.keychain"))) (auth-source-search :max 1)) -;; (let ((auth-sources '("macos-keychain-generic:Login"))) (auth-source-search :max 1 :host "git.gnus.org")) -;; (let ((auth-sources '("macos-keychain-generic:Login"))) (auth-source-search :max 1)) - (cl-defun auth-source-macos-keychain-search (&rest spec &key backend create delete type max &allow-other-keys) diff --git a/lisp/autoinsert.el b/lisp/autoinsert.el index 2ca557c52b7..fef42161bf3 100644 --- a/lisp/autoinsert.el +++ b/lisp/autoinsert.el @@ -348,7 +348,7 @@ Matches the visited file name against the elements of `auto-insert-alist'." (setq desc (cdr cond) cond (car cond))) (if (if (symbolp cond) - (eq cond major-mode) + (derived-mode-p cond) (and buffer-file-name (string-match cond buffer-file-name))) (setq action (cdr (car alist)) diff --git a/lisp/autorevert.el b/lisp/autorevert.el index 79291624523..a15386aa1af 100644 --- a/lisp/autorevert.el +++ b/lisp/autorevert.el @@ -319,10 +319,12 @@ the list of old buffers.") (defvar auto-revert-tail-pos 0 "Position of last known end of file.") +(defun auto-revert-find-file-function () + (setq-local auto-revert-tail-pos + (nth 7 (file-attributes buffer-file-name)))) + (add-hook 'find-file-hook - (lambda () - (setq-local auto-revert-tail-pos - (nth 7 (file-attributes buffer-file-name))))) + #'auto-revert-find-file-function) (defvar auto-revert-notify-watch-descriptor-hash-list (make-hash-table :test 'equal) @@ -341,6 +343,11 @@ This has been reported by a file notification event.") ;; Functions: +(defun auto-revert-remove-current-buffer () + "Remove dead buffer from `auto-revert-buffer-list'." + (setq auto-revert-buffer-list + (delq (current-buffer) auto-revert-buffer-list))) + ;;;###autoload (define-minor-mode auto-revert-mode "Toggle reverting buffer when the file changes (Auto-Revert Mode). @@ -364,13 +371,10 @@ without being changed in the part that is already in the buffer." (push (current-buffer) auto-revert-buffer-list) (add-hook 'kill-buffer-hook - (lambda () - (setq auto-revert-buffer-list - (delq (current-buffer) auto-revert-buffer-list))) + #'auto-revert-remove-current-buffer nil t)) (when auto-revert-use-notify (auto-revert-notify-rm-watch)) - (setq auto-revert-buffer-list - (delq (current-buffer) auto-revert-buffer-list))) + (auto-revert-remove-current-buffer)) (auto-revert-set-timer) (when auto-revert-mode (auto-revert-buffers) @@ -786,24 +790,24 @@ the timer when no buffers need to be checked." (not (and auto-revert-stop-on-user-input (input-pending-p)))) (let ((buf (car bufs))) - (if (buffer-live-p buf) - (with-current-buffer buf - ;; Test if someone has turned off Auto-Revert Mode in a - ;; non-standard way, for example by changing major mode. - (if (and (not auto-revert-mode) - (not auto-revert-tail-mode) - (memq buf auto-revert-buffer-list)) - (setq auto-revert-buffer-list - (delq buf auto-revert-buffer-list))) - (when (auto-revert-active-p) - ;; Enable file notification. - (when (and auto-revert-use-notify - (not auto-revert-notify-watch-descriptor)) - (auto-revert-notify-add-watch)) - (auto-revert-handler))) - ;; Remove dead buffer from `auto-revert-buffer-list'. - (setq auto-revert-buffer-list - (delq buf auto-revert-buffer-list)))) + (with-current-buffer buf + (if (buffer-live-p buf) + (progn + ;; Test if someone has turned off Auto-Revert Mode + ;; in a non-standard way, for example by changing + ;; major mode. + (if (and (not auto-revert-mode) + (not auto-revert-tail-mode) + (memq buf auto-revert-buffer-list)) + (auto-revert-remove-current-buffer)) + (when (auto-revert-active-p) + ;; Enable file notification. + (when (and auto-revert-use-notify + (not auto-revert-notify-watch-descriptor)) + (auto-revert-notify-add-watch)) + (auto-revert-handler))) + ;; Remove dead buffer from `auto-revert-buffer-list'. + (auto-revert-remove-current-buffer)))) (setq bufs (cdr bufs))) (setq auto-revert-remaining-buffers bufs) ;; Check if we should cancel the timer. diff --git a/lisp/bindings.el b/lisp/bindings.el index a77fd4d599a..be44b45136e 100644 --- a/lisp/bindings.el +++ b/lisp/bindings.el @@ -354,14 +354,44 @@ mouse-3: Toggle minor modes" map) "\ Keymap to display on column and line numbers.") +(defcustom column-number-indicator-zero-based t + "When non-nil, mode line displays column numbers zero-based. + +This variable has effect only when Column Number mode is turned on, +which displays column numbers in the mode line. +If the value is non-nil, the displayed column numbers start from +zero, otherwise they start from one." + :type 'boolean + :group 'mode-line + :version "26.1") + +(defcustom mode-line-percent-position '(-3 "%p") + "Specification of \"percentage offset\" of window through buffer. +This option specifies both the field width and the type of offset +displayed in `mode-line-position', a component of the default +`mode-line-format'." + :type `(radio + (const :tag "nil: No offset is displayed" nil) + (const :tag "\"%o\": Proportion of \"travel\" of the window through the buffer" + (-3 "%o")) + (const :tag "\"%p\": Percentage offset of top of window" + (-3 "%p")) + (const :tag "\"%P\": Percentage offset of bottom of window" + (-3 "%P")) + (const :tag "\"%q\": Offsets of both top and bottom of window" + (6 "%q"))) + :version "26.1" + :group 'mode-line) +(put 'mode-line-percent-position 'risky-local-variable t) + (defvar mode-line-position - `((-3 ,(propertize - "%p" - 'local-map mode-line-column-line-number-mode-map - 'mouse-face 'mode-line-highlight - ;; XXX needs better description - 'help-echo "Size indication mode\n\ -mouse-1: Display Line and Column Mode Menu")) + `((:propertize + mode-line-percent-position + local-map ,mode-line-column-line-number-mode-map + mouse-face mode-line-highlight + ;; XXX needs better description + help-echo "Size indication mode\n\ +mouse-1: Display Line and Column Mode Menu") (size-indication-mode (8 ,(propertize " of %I" @@ -372,12 +402,19 @@ mouse-1: Display Line and Column Mode Menu")) mouse-1: Display Line and Column Mode Menu"))) (line-number-mode ((column-number-mode - (10 ,(propertize - " (%l,%c)" - 'local-map mode-line-column-line-number-mode-map - 'mouse-face 'mode-line-highlight - 'help-echo "Line number and Column number\n\ + (column-number-indicator-zero-based + (10 ,(propertize + " (%l,%c)" + 'local-map mode-line-column-line-number-mode-map + 'mouse-face 'mode-line-highlight + 'help-echo "Line number and Column number\n\ mouse-1: Display Line and Column Mode Menu")) + (10 ,(propertize + " (%l,%C)" + 'local-map mode-line-column-line-number-mode-map + 'mouse-face 'mode-line-highlight + 'help-echo "Line number and Column number\n\ +mouse-1: Display Line and Column Mode Menu"))) (6 ,(propertize " L%l" 'local-map mode-line-column-line-number-mode-map @@ -385,12 +422,19 @@ mouse-1: Display Line and Column Mode Menu")) 'help-echo "Line Number\n\ mouse-1: Display Line and Column Mode Menu")))) ((column-number-mode - (5 ,(propertize - " C%c" - 'local-map mode-line-column-line-number-mode-map - 'mouse-face 'mode-line-highlight - 'help-echo "Column number\n\ -mouse-1: Display Line and Column Mode Menu")))))) + (column-number-indicator-zero-based + (5 ,(propertize + " C%c" + 'local-map mode-line-column-line-number-mode-map + 'mouse-face 'mode-line-highlight + 'help-echo "Column number\n\ +mouse-1: Display Line and Column Mode Menu")) + (5 ,(propertize + " C%C" + 'local-map mode-line-column-line-number-mode-map + 'mouse-face 'mode-line-highlight + 'help-echo "Column number\n\ +mouse-1: Display Line and Column Mode Menu"))))))) "Mode line construct for displaying the position in the buffer. Normally displays the buffer percentage and, optionally, the buffer size, the line number and the column number.") diff --git a/lisp/bs.el b/lisp/bs.el index 838e72d68c6..c626698faf9 100644 --- a/lisp/bs.el +++ b/lisp/bs.el @@ -2,7 +2,7 @@ ;; Copyright (C) 1998-2017 Free Software Foundation, Inc. ;; Author: Olaf Sylvester <Olaf.Sylvester@netsurf.de> -;; Maintainer: Olaf Sylvester <Olaf.Sylvester@netsurf.de> +;; Maintainer: emacs-devel@gnu.org ;; Keywords: convenience ;; This file is part of GNU Emacs. diff --git a/lisp/button.el b/lisp/button.el index c39e4f97c13..99c03d9d687 100644 --- a/lisp/button.el +++ b/lisp/button.el @@ -194,6 +194,8 @@ changes to a supertype are not reflected in its subtypes)." ((button--area-button-p button) (get-text-property (cdr button) prop (button--area-button-string button))) + ((markerp button) + (get-text-property button prop (marker-buffer button))) (t ; Must be a text-property button. (get-text-property button prop)))) @@ -493,7 +495,7 @@ Returns the button found." (unless (button-get button 'skip) (setq n (1- n))))))) (if (null button) - (error (if wrap "No buttons!" "No more buttons")) + (user-error (if wrap "No buttons!" "No more buttons")) (let ((msg (and display-message (button-get button 'help-echo)))) (when msg (message "%s" msg))) diff --git a/lisp/calc/calc-alg.el b/lisp/calc/calc-alg.el index 4e63d238c78..9db901a9753 100644 --- a/lisp/calc/calc-alg.el +++ b/lisp/calc/calc-alg.el @@ -355,10 +355,19 @@ ;; math-simplify-step, which is called by math-simplify. (defvar math-top-only) +(defun calc-input-angle-units (input) + (cond ((math-expr-contains input '(var deg var-deg)) 'deg) + ((math-expr-contains input '(var rad var-rad)) 'rad) + ((math-expr-contains input '(var hms var-hms)) 'hms) + (t nil))) + ;; math-normalize-error is declared in calc.el. (defvar math-normalize-error) (defun math-simplify (top-expr) (let ((math-simplifying t) + (calc-angle-mode (if (calc-input-angle-units top-expr) + 'rad + calc-angle-mode)) (math-top-only (consp calc-simplify-mode)) (simp-rules (append (and (calc-has-rules 'var-AlgSimpRules) '((var AlgSimpRules var-AlgSimpRules))) diff --git a/lisp/calc/calc-comb.el b/lisp/calc/calc-comb.el index c84ff236851..91fbb7b2b8a 100644 --- a/lisp/calc/calc-comb.el +++ b/lisp/calc/calc-comb.el @@ -362,11 +362,13 @@ (math-gammap1-raw '(float -25 -2)))) (defun math-factorial-iter (count n f) - (if (= (% n 5) 1) - (math-working (format "factorial(%d)" (1- n)) f)) - (if (> count 0) - (math-factorial-iter (1- count) (1+ n) (math-mul n f)) - f)) + (while (> count 0) + (if (= (% n 5) 1) + (math-working (format "factorial(%d)" (1- n)) f)) + (setq count (1- count) + f (math-mul n f) + n (1+ n))) + f) (defun calcFunc-dfact (n) ; [I I] [F F] [Public] (cond ((Math-integer-negp n) diff --git a/lisp/calc/calc-embed.el b/lisp/calc/calc-embed.el index bb37d7f9c98..14ab97fbed8 100644 --- a/lisp/calc/calc-embed.el +++ b/lisp/calc/calc-embed.el @@ -27,6 +27,7 @@ (require 'calc-ext) (require 'calc-macs) +(require 'cl-lib) ;; Declare functions which are defined elsewhere. (declare-function thing-at-point-looking-at "thingatpt" @@ -804,7 +805,7 @@ The command \\[yank] can retrieve it from there." (backward-char 6)) (goto-char save-pt) (unless (assq 'the-language modes) - (let ((lang (assoc major-mode calc-language-alist))) + (let ((lang (cl-assoc-if #'derived-mode-p calc-language-alist))) (if lang (setq modes (cons (cons 'the-language (cdr lang)) modes))))) @@ -829,13 +830,19 @@ The command \\[yank] can retrieve it from there." (setq found (list (current-buffer)) calc-embedded-active (cons found calc-embedded-active) calc-embedded-firsttime-buf t) - (let ((newann (assoc major-mode calc-embedded-announce-formula-alist)) - (newform (assoc major-mode calc-embedded-open-close-formula-alist)) - (newword (assoc major-mode calc-embedded-word-regexp-alist)) - (newplain (assoc major-mode calc-embedded-open-close-plain-alist)) + (let ((newann (cl-assoc-if #'derived-mode-p + calc-embedded-announce-formula-alist)) + (newform (cl-assoc-if #'derived-mode-p + calc-embedded-open-close-formula-alist)) + (newword (cl-assoc-if #'derived-mode-p + calc-embedded-word-regexp-alist)) + (newplain (cl-assoc-if #'derived-mode-p + calc-embedded-open-close-plain-alist)) (newnewform - (assoc major-mode calc-embedded-open-close-new-formula-alist)) - (newmode (assoc major-mode calc-embedded-open-close-mode-alist))) + (cl-assoc-if #'derived-mode-p + calc-embedded-open-close-new-formula-alist)) + (newmode (cl-assoc-if #'derived-mode-p + calc-embedded-open-close-mode-alist))) (when newann (make-local-variable 'calc-embedded-announce-formula) (setq calc-embedded-announce-formula (cdr newann))) diff --git a/lisp/calc/calc-units.el b/lisp/calc/calc-units.el index 0e3715eb4cf..a8074eaeb20 100644 --- a/lisp/calc/calc-units.el +++ b/lisp/calc/calc-units.el @@ -825,21 +825,18 @@ If COMP or STD is non-nil, put that in the units table instead." (forward-char -1)) (insert ";;; Custom units stored by Calc on " (current-time-string) "\n") (if math-additional-units - (progn + (let (expr) (insert "(setq math-additional-units '(\n") - (let ((list math-additional-units)) - (while list - (insert " (" (symbol-name (car (car list))) " " - (if (nth 1 (car list)) - (if (stringp (nth 1 (car list))) - (prin1-to-string (nth 1 (car list))) - (prin1-to-string (math-format-flat-expr - (nth 1 (car list)) 0))) - "nil") - " " - (prin1-to-string (nth 2 (car list))) - ")\n") - (setq list (cdr list)))) + (dolist (u math-additional-units) + (insert " (" (symbol-name (car u)) " " + (if (setq expr (nth 1 u)) + (if (stringp expr) + (prin1-to-string expr) + (prin1-to-string (math-format-flat-expr expr 0))) + "nil") + " " + (prin1-to-string (nth 2 u)) + ")\n")) (insert "))\n")) (insert ";;; (no custom units defined)\n")) (insert ";;; End of custom units\n") @@ -916,15 +913,13 @@ If COMP or STD is non-nil, put that in the units table instead." (defun math-find-base-units-rec (expr pow) (let ((u (math-check-unit-name expr))) (cond (u - (let ((ulist (math-find-base-units u))) - (while ulist - (let ((p (* (cdr (car ulist)) pow)) - (old (assq (car (car ulist)) math-fbu-base))) - (if old - (setcdr old (+ (cdr old) p)) - (setq math-fbu-base - (cons (cons (car (car ulist)) p) math-fbu-base)))) - (setq ulist (cdr ulist))))) + (dolist (x (math-find-base-units u)) + (let ((p (* (cdr x) pow)) + (old (assq (car x) math-fbu-base))) + (if old + (setcdr old (+ (cdr old) p)) + (setq math-fbu-base + (cons (cons (car x) p) math-fbu-base)))))) ((math-scalarp expr)) ((and (eq (car expr) '^) (integerp (nth 2 expr))) @@ -1377,20 +1372,15 @@ If COMP or STD is non-nil, put that in the units table instead." (if (eq pow1 1) (math-to-standard-units (list '/ n d) nil) (list '^ (math-to-standard-units (list '/ n d) nil) pow1)) - (let (ud1) - (setq un (nth 4 un) - ud (nth 4 ud)) - (while un - (setq ud1 ud) - (while ud1 - (and (eq (car (car un)) (car (car ud1))) - (setq math-try-cancel-units - (+ math-try-cancel-units - (- (* (cdr (car un)) pow1) - (* (cdr (car ud)) pow2))))) - (setq ud1 (cdr ud1))) - (setq un (cdr un))) - nil)))))) + (setq un (nth 4 un) + ud (nth 4 ud)) + (dolist (x un) + (dolist (y ud) + (when (eq (car x) (car y)) + (setq math-try-cancel-units + (+ math-try-cancel-units + (- (* (cdr x) pow1) + (* (cdr (car ud)) pow2)))))))))))) (math-defsimplify ^ (and math-simplifying-units @@ -1578,9 +1568,8 @@ If COMP or STD is non-nil, put that in the units table instead." (insert "Calculator Units Table:\n\n") (insert "(All definitions are exact unless marked with an asterisk (*).)\n\n") (insert "Unit Type Definition Description\n\n") - (while uptr - (setq u (car uptr) - name (nth 2 u)) + (dolist (u uptr) + (setq name (nth 2 u)) (when (eq (car u) 'm) (setq std t)) (setq shadowed (and std (assq (car u) math-additional-units))) @@ -1618,8 +1607,7 @@ If COMP or STD is non-nil, put that in the units table instead." (insert " (redefined above)") (unless (nth 1 u) (insert " (base unit)"))) - (insert "\n") - (setq uptr (cdr uptr))) + (insert "\n")) (insert "\n\nUnit Prefix Table:\n\n") (setq uptr math-unit-prefixes) (while uptr diff --git a/lisp/calendar/timeclock.el b/lisp/calendar/timeclock.el index f8de084f776..a4709c3b4b5 100644 --- a/lisp/calendar/timeclock.el +++ b/lisp/calendar/timeclock.el @@ -656,9 +656,9 @@ that variable's documentation." (setq timeclock-mode-string (propertize (format " %c%s%c " - (if last-in ?< ?[) + (if last-in ?< ?\[) (timeclock-seconds-to-string remainder nil t) - (if last-in ?> ?])) + (if last-in ?> ?\])) 'help-echo "timeclock: time remaining")))) (put 'timeclock-mode-string 'risky-local-variable t) diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el index 5d4fcf8fcbf..235eb83e85b 100644 --- a/lisp/calendar/todo-mode.el +++ b/lisp/calendar/todo-mode.el @@ -820,14 +820,10 @@ buries it and restores state as needed." (message "There is no todo file for this archive"))) ;; When todo-check-file runs in todo-show, it kills the ;; buffer if the archive file was deleted externally. - (when (buffer-live-p buf) (bury-buffer buf))) + (when (buffer-live-p buf) (kill-buffer buf))) ((eq major-mode 'todo-mode) (todo-save) - ;; If we just quit archive mode, just burying the buffer - ;; in todo-mode would return to archive. - (set-window-buffer (selected-window) - (set-buffer (other-buffer))) - (bury-buffer buf))))) + (bury-buffer))))) ;; ----------------------------------------------------------------------------- ;;; Navigation between and within categories @@ -1038,29 +1034,41 @@ empty line above the done items separator." (hl-line-mode -1) (hl-line-mode 1)))) +(defvar todo--item-headers-hidden nil + "Non-nil if item date-time headers in current buffer are hidden.") + (defun todo-toggle-item-header () "Hide or show item date-time headers in the current file. With done items, this hides only the done date-time string, not the the original date-time string." (interactive) - (save-excursion - (save-restriction - (goto-char (point-min)) - (let ((ov (todo-get-overlay 'header))) - (if ov - (remove-overlays 1 (1+ (buffer-size)) 'todo 'header) - (widen) - (goto-char (point-min)) - (while (not (eobp)) - (when (re-search-forward - (concat todo-item-start - "\\( " diary-time-regexp "\\)?" - (regexp-quote todo-nondiary-end) "? ") - nil t) - (setq ov (make-overlay (match-beginning 0) (match-end 0) nil t)) - (overlay-put ov 'todo 'header) - (overlay-put ov 'display "")) - (todo-forward-item))))))) + (unless (catch 'nonempty + (dolist (type '(todo done)) + (dolist (c todo-categories) + (let ((count (todo-get-count type (car c)))) + (unless (zerop count) + (throw 'nonempty t)))))) + (user-error "This file has no items")) + (if todo--item-headers-hidden + (progn + (remove-overlays 1 (1+ (buffer-size)) 'todo 'header) + (setq todo--item-headers-hidden nil)) + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (let (ov) + (while (not (eobp)) + (when (re-search-forward + (concat todo-item-start + "\\( " diary-time-regexp "\\)?" + (regexp-quote todo-nondiary-end) "? ") + nil t) + (setq ov (make-overlay (match-beginning 0) (match-end 0) nil t)) + (overlay-put ov 'todo 'header) + (overlay-put ov 'display "")) + (forward-line))) + (setq todo--item-headers-hidden t))))) ;; ----------------------------------------------------------------------------- ;;; File and category editing @@ -1735,46 +1743,49 @@ done items sections are visible, the sequence of N items can consist of the the last todo items and the first done items." (interactive "p") (when (todo-item-string) - (unless (> n 1) (setq n 1)) - (catch 'end - (dotimes (i n) - (let* ((cat (todo-current-category)) - (marks (assoc cat todo-categories-with-marks)) - (ov (progn - (unless (looking-at todo-item-start) - (todo-item-start)) - (todo-get-overlay 'prefix))) - (pref (overlay-get ov 'before-string))) - (if (todo-marked-item-p) - (progn - (overlay-put ov 'before-string (substring pref 1)) - (if (= (cdr marks) 1) ; Deleted last mark in this category. - (setq todo-categories-with-marks - (assq-delete-all cat todo-categories-with-marks)) - (setcdr marks (1- (cdr marks))))) - (overlay-put ov 'before-string (concat todo-item-mark pref)) - (if marks - (setcdr marks (1+ (cdr marks))) - (push (cons cat 1) todo-categories-with-marks)))) - (todo-forward-item) - ;; Don't try to mark the empty lines at the end of the todo - ;; and done items sections. - (when (looking-at "^$") - (if (eobp) - (throw 'end nil) - (todo-forward-item))))))) + (let ((cat (todo-current-category))) + (unless (> n 1) (setq n 1)) + (catch 'end + (dotimes (i n) + (let* ((marks (assoc cat todo-categories-with-marks)) + (ov (progn + (unless (looking-at todo-item-start) + (todo-item-start)) + (todo-get-overlay 'prefix))) + (pref (overlay-get ov 'before-string))) + (if (todo-marked-item-p) + (progn + (overlay-put ov 'before-string (substring pref 1)) + (if (= (cdr marks) 1) ; Deleted last mark in this category. + (setq todo-categories-with-marks + (assq-delete-all cat todo-categories-with-marks)) + (setcdr marks (1- (cdr marks))))) + (overlay-put ov 'before-string (concat todo-item-mark pref)) + (if marks + (setcdr marks (1+ (cdr marks))) + (push (cons cat 1) todo-categories-with-marks)))) + (todo-forward-item) + ;; Don't try to mark the empty lines at the end of the todo + ;; and done items sections. + (when (looking-at "^$") + (if (eobp) + (throw 'end nil) + (todo-forward-item)))))))) (defun todo-mark-category () "Mark all visible items in this category with `todo-item-mark'." (interactive) - (let* ((cat (todo-current-category)) - (marks (assoc cat todo-categories-with-marks))) + (let ((cat (todo-current-category))) (save-excursion (goto-char (point-min)) (while (not (eobp)) - (let* ((ov (todo-get-overlay 'prefix)) - (pref (overlay-get ov 'before-string))) - (unless (todo-marked-item-p) + (let* ((marks (assoc cat todo-categories-with-marks)) + (ov (todo-get-overlay 'prefix)) + ;; When done items are shown and there are no todo items, the + ;; loop starts on the empty line in the todo items sections, + ;; which has no overlay, so don't try to get it. + (pref (when ov (overlay-get ov 'before-string)))) + (unless (or (todo-marked-item-p) (not ov)) (overlay-put ov 'before-string (concat todo-item-mark pref)) (if marks (setcdr marks (1+ (cdr marks))) @@ -1795,7 +1806,7 @@ consist of the the last todo items and the first done items." (goto-char (point-min)) (while (not (eobp)) (let* ((ov (todo-get-overlay 'prefix)) - ;; No overlay on empty line between todo and done items. + ;; See comment above in `todo-mark-category'. (pref (when ov (overlay-get ov 'before-string)))) (when (todo-marked-item-p) (overlay-put ov 'before-string (substring pref 1))) @@ -2517,7 +2528,7 @@ numerical prefix argument, or noninteractively by argument ARG, whose value can be either of the symbols `raise' or `lower', meaning to raise or lower the item's priority by one." (interactive) - (unless (and (called-interactively-p 'any) + (unless (and (or (called-interactively-p 'any) (memq arg '(raise lower))) (or (todo-done-item-p) (looking-at "^$"))) (let* ((item (or item (todo-item-string))) (marked (todo-marked-item-p)) @@ -2534,7 +2545,7 @@ meaning to raise or lower the item's priority by one." (re-search-forward regexp1 nil t) (match-string-no-properties 1))))))) curnum - (todo (cond ((or (eq arg 'raise) (eq arg 'lower) + (todo (cond ((or (memq arg '(raise lower)) (eq major-mode 'todo-filtered-items-mode)) (save-excursion (let ((curstart (todo-item-start)) @@ -2674,7 +2685,7 @@ section in the category moved to." (num todo-category-number) (item (todo-item-string)) (diary-item (todo-diary-item-p)) - (done-item (and (todo-done-item-p) (concat item "\n"))) + (done-item (and (todo-done-item-p) item)) (omark (save-excursion (todo-item-start) (point-marker))) (todo 0) (diary 0) @@ -2704,43 +2715,51 @@ section in the category moved to." (while (not (eobp)) (when (todo-marked-item-p) (if (todo-done-item-p) - (setq done-items (concat done-items - (todo-item-string) "\n") - done (1+ done)) - (setq todo-items (concat todo-items - (todo-item-string) "\n") - todo (1+ todo)) + (progn + (push (todo-item-string) done-items) + (setq done (1+ done))) + (push (todo-item-string) todo-items) + (setq todo (1+ todo)) (when (todo-diary-item-p) (setq diary (1+ diary))))) (todo-forward-item)) - ;; Chop off last newline of multiple todo item string, - ;; since it will be reinserted when setting priority - ;; (but with done items priority is not set, so keep - ;; last newline). - (and todo-items - (setq todo-items (substring todo-items 0 -1)))) + (setq todo-items (nreverse todo-items)) + (setq done-items (nreverse done-items))) (if (todo-done-item-p) - (setq done 1) - (setq todo 1) + (progn + (push done-item done-items) + (setq done 1)) + (push item todo-items) + (setq todo 1) (when (todo-diary-item-p) (setq diary 1)))) (set-window-buffer (selected-window) (set-buffer (find-file-noselect file2 'nowarn))) (unwind-protect - (progn - (when (or todo-items (and item (not done-item))) - (todo-set-item-priority (or todo-items item) cat2 t)) + (let (here) + (when todo-items + (todo-set-item-priority (pop todo-items) cat2 t) + (setq here (point)) + (while todo-items + (todo-forward-item) + (todo-insert-with-overlays (pop todo-items)))) ;; Move done items en bloc to top of done items section. - (when (or done-items done-item) + (when done-items (todo-category-number cat2) (widen) (goto-char (point-min)) (re-search-forward - (concat "^" (regexp-quote (concat todo-category-beg cat2)) - "$") nil t) + (concat "^" (regexp-quote (concat todo-category-beg cat2)) "$") + nil t) (re-search-forward (concat "^" (regexp-quote todo-category-done)) nil t) (forward-line) - (insert (or done-items done-item))) + (unless here (setq here (point))) + (while done-items + (todo-insert-with-overlays (pop done-items)) + (todo-forward-item))) + ;; If only done items were moved, move point to the top + ;; one, otherwise, move point to the top moved todo item. + (goto-char here) (setq moved t)) (cond ;; Move succeeded, so remove item from starting category, @@ -2765,10 +2784,13 @@ section in the category moved to." (forward-line) (setq beg (point)) (setq end (if (re-search-forward - (concat "^" (regexp-quote - todo-category-beg)) nil t) - (match-beginning 0) - (point-max))) + (concat "^" + (regexp-quote todo-category-beg)) + nil t) + (progn + (goto-char (match-beginning 0)) + (point-marker)) + (point-max-marker))) (goto-char beg) (while (< (point) end) (if (todo-marked-item-p) @@ -2785,7 +2807,7 @@ section in the category moved to." (set-window-buffer (selected-window) (set-buffer (find-file-noselect file2 'nowarn))) (setq todo-category-number (todo-category-number cat2)) - (let ((todo-show-with-done (or done-items done-item))) + (let ((todo-show-with-done (> done 0))) (todo-category-select)) (goto-char nmark) ;; If item is moved to end of (just first?) category, make @@ -2834,12 +2856,13 @@ visible." (goto-char (point-min)) (re-search-forward todo-done-string-start nil t))) (buffer-read-only nil) - item done-item + header item done-items (opoint (point))) ;; Don't add empty comment to done item. (setq comment (unless (zerop (length comment)) (concat " [" todo-comment-string ": " comment "]"))) (and marked (goto-char (point-min))) + (setq header (todo-get-overlay 'header)) (catch 'done ;; Stop looping when we hit the empty line below the last ;; todo item (this is eobp if only done items are hidden). @@ -2847,17 +2870,15 @@ visible." (if (or (not marked) (and marked (todo-marked-item-p))) (progn (setq item (todo-item-string)) - (setq done-item (concat done-item done-prefix item - comment (and marked "\n"))) + (push (concat done-prefix item comment) done-items) (setq item-count (1+ item-count)) (when (todo-diary-item-p) (setq diary-count (1+ diary-count))) (todo-remove-item) (unless marked (throw 'done nil))) (todo-forward-item)))) + (setq done-items (nreverse done-items)) (when marked - ;; Chop off last newline of done item string. - (setq done-item (substring done-item 0 -1)) (setq todo-categories-with-marks (assq-delete-all cat todo-categories-with-marks))) (save-excursion @@ -2866,7 +2887,17 @@ visible." (concat "^" (regexp-quote todo-category-done)) nil t) (forward-char) (when show-done (setq opoint (point))) - (insert done-item "\n")) + (while done-items + (insert (pop done-items) "\n") + (when header (let ((copy (copy-overlay header))) + (re-search-backward + (concat todo-item-start + "\\( " diary-time-regexp "\\)?" + (regexp-quote todo-nondiary-end) "? ") + nil t) + (move-overlay copy (match-beginning 0) (match-end 0))) + (todo-item-end) + (forward-char)))) (todo-update-count 'todo (- item-count)) (todo-update-count 'done item-count) (todo-update-count 'diary (- diary-count)) @@ -3093,7 +3124,9 @@ this category does not exist in the archive, it is created." (throw 'end (message "Only done items can be archived")) (with-current-buffer archive (unless (derived-mode-p 'todo-archive-mode) (todo-archive-mode)) - (let (buffer-read-only) + (let ((headers-hidden todo--item-headers-hidden) + buffer-read-only) + (if headers-hidden (todo-toggle-item-header)) (widen) (goto-char (point-min)) (if (and (re-search-forward @@ -3119,7 +3152,8 @@ this category does not exist in the archive, it is created." (unless (nth 7 (file-attributes afile)) (write-region nil nil afile t t) (setq todo-archives (funcall todo-files-function t)) - (todo-archive-mode)))) + (todo-archive-mode)) + (if headers-hidden (todo-toggle-item-header)))) (with-current-buffer tbuf (cond (all @@ -3198,7 +3232,9 @@ the only category in the archive, the archive file is deleted." (todo-forward-item)))) ;; Restore items to top of category's done section and update counts. (with-current-buffer tbuf - (let (buffer-read-only newcat) + (let ((headers-hidden todo--item-headers-hidden) + buffer-read-only newcat) + (if headers-hidden (todo-toggle-item-header)) (widen) (goto-char (point-min)) ;; Find the corresponding todo category, or if there isn't @@ -3222,6 +3258,7 @@ the only category in the archive, the archive file is deleted." (todo-update-count 'done 1 cat) (unless newcat ; Newly added category has no archive. (todo-update-count 'archived -1 cat)))) + (if headers-hidden (todo-toggle-item-header)) (todo-update-categories-sexp))) ;; Delete restored items from archive. (when marked @@ -3267,6 +3304,10 @@ the only category in the archive, the archive file is deleted." (set-buffer (find-file-noselect tfile))) (todo-category-number cat) (todo-category-select) + ;; Selecting the category leaves point at the end of the done + ;; items separator string, so move it to the (first) restored + ;; done item. + (forward-line) (message "Items unarchived."))))) (defun todo-jump-to-archive-category (&optional file) @@ -5150,7 +5191,17 @@ empty line above the done items separator." (let* ((done (todo-done-item-p))) (todo-item-start) (unless (bobp) - (re-search-backward todo-item-start nil t (or count 1))) + (re-search-backward (concat todo-item-start + "\\( " diary-time-regexp "\\)?" + (regexp-quote todo-nondiary-end) "? ") + nil t (or count 1)) + ;; If the item date-time header is hidden, the display engine + ;; moves point to the next earlier displayable position, which + ;; is the end of the next item above, so we move it to the start + ;; of the current item's text (that's what the display engine + ;; does with todo-forward-item in this case.) + ;; FIXME: would it be better to use cursor-sensor-functions? + (when todo--item-headers-hidden (goto-char (match-end 0)))) ;; Unless this is a regexp filtered items buffer (which can contain ;; intermixed todo and done items), if points advances by one from a ;; done to a todo item, go back to the space above @@ -5166,10 +5217,12 @@ empty line above the done items separator." (defun todo-remove-item () "Internal function called in editing, deleting or moving items." - (let* ((end (progn (todo-item-end) (1+ (point)))) - (beg (todo-item-start)) - (ov (todo-get-overlay 'prefix))) - (when ov (delete-overlay ov)) + (let ((end (progn (todo-item-end) (1+ (point)))) + (beg (todo-item-start)) + ovs) + (push (todo-get-overlay 'prefix) ovs) + (push (todo-get-overlay 'header) ovs) + (dolist (ov ovs) (when ov (delete-overlay ov))) (delete-region beg end))) (defun todo-diary-item-p () @@ -5225,7 +5278,10 @@ Also preserve category display, if applicable." (let ((revert-buffer-function nil)) (revert-buffer ignore-auto noconfirm 'preserve-modes) (when (memq major-mode '(todo-mode todo-archive-mode)) - (todo-category-select)))) + (save-excursion (todo-category-select)) + ;; revert-buffer--default calls after-find-file, which makes + ;; buffer writable. + (setq buffer-read-only t)))) (defun todo-desktop-save-buffer (_dir) `((catnum . ,(todo-category-number (todo-current-category))))) @@ -5300,6 +5356,11 @@ marked) not done todo items." (defun todo-get-overlay (val) "Return the overlay at point whose `todo' property has value VAL." + ;; When headers are hidden, the display engine makes item's start + ;; inaccessible to commands, so go there here, if necessary, in + ;; order to check for prefix and header overlays. + (when (memq val '(prefix header)) + (unless (looking-at todo-item-start) (todo-item-start))) ;; Use overlays-in to find prefix overlays and check over two ;; positions to find done separator overlay. (let ((ovs (overlays-in (point) (1+ (point)))) @@ -5324,16 +5385,26 @@ In that case, return the item's prefix overlay." (when marked ov))) (defun todo-insert-with-overlays (item) - "Insert ITEM at point and update prefix/priority number overlays." + "Insert ITEM at point and update prefix and header overlays." (todo-item-start) - ;; Insertion pushes item down but not its prefix overlay. When the - ;; overlay includes a mark, this would now mark the inserted ITEM, - ;; so move it to the pushed down item. (let ((ov (todo-get-overlay 'prefix)) (marked (todo-marked-item-p))) (insert item "\n") - (when marked (move-overlay ov (point) (point)))) - (todo-backward-item) + ;; Insertion pushes item down but not its prefix overlay. When + ;; the overlay includes a mark, this would now mark the inserted + ;; ITEM, so move it to the pushed down item. + (when marked (move-overlay ov (point) (point))) + (todo-backward-item) + ;; With hidden headers, todo-backward-item puts point on first + ;; visible character after header, so we have to search backward. + (when todo--item-headers-hidden + (re-search-backward (concat todo-item-start + "\\( " diary-time-regexp "\\)?" + (regexp-quote todo-nondiary-end) "? ") + nil t) + (setq ov (make-overlay (match-beginning 0) (match-end 0) nil t)) + (overlay-put ov 'todo 'header) + (overlay-put ov 'display ""))) (todo-prefix-overlays)) (defun todo-prefix-overlays () @@ -6587,17 +6658,20 @@ Added to `window-configuration-change-hook' in Todo mode." (visual-line-mode) (setq wrap-prefix (make-string todo-indent-to-here 32)))) +(defun todo-hl-line-range () + "Make `todo-toggle-item-highlighting' highlight entire item." + (save-excursion + (when (todo-item-end) + (cons (todo-item-start) + (todo-item-end))))) + (defun todo-modes-set-2 () "Make some settings that apply to multiple Todo modes." (add-to-invisibility-spec 'todo) (setq buffer-read-only t) + (setq-local todo--item-headers-hidden nil) (setq-local desktop-save-buffer 'todo-desktop-save-buffer) - (when (boundp 'hl-line-range-function) - (setq-local hl-line-range-function - (lambda() (save-excursion - (when (todo-item-end) - (cons (todo-item-start) - (todo-item-end)))))))) + (setq-local hl-line-range-function 'todo-hl-line-range)) (defun todo-modes-set-3 () "Make some settings that apply to multiple Todo modes." diff --git a/lisp/cdl.el b/lisp/cdl.el index 2fc74decaf2..16ba7e7d527 100644 --- a/lisp/cdl.el +++ b/lisp/cdl.el @@ -2,7 +2,7 @@ ;; Copyright (C) 1993, 2001-2017 Free Software Foundation, Inc. -;; Author: ATAE@spva.physics.imperial.ac.uk (Ata Etemadi) +;; Author: Ata Etemadi <ATAE@spva.physics.imperial.ac.uk> ;; Maintainer: emacs-devel@gnu.org ;; Keywords: data diff --git a/lisp/cedet/semantic.el b/lisp/cedet/semantic.el index bf5bfa89caf..c38afed3964 100644 --- a/lisp/cedet/semantic.el +++ b/lisp/cedet/semantic.el @@ -37,6 +37,7 @@ (require 'cedet) (require 'semantic/tag) (require 'semantic/lex) +(require 'cl-lib) (defvar semantic-version "2.2" "Current version of Semantic.") @@ -329,7 +330,7 @@ If the major mode is ready for Semantic, and no to use Semantic, and `semantic-init-hook' is run." ;; In upstream Semantic, the parser setup functions are called from ;; mode hooks. In the version bundled with Emacs, we do it here. - (let ((entry (assq major-mode semantic-new-buffer-setup-functions))) + (let ((entry (cl-assoc-if #'derived-mode-p semantic-new-buffer-setup-functions))) (when entry (funcall (cdr entry)))) ;; Do stuff if semantic was activated by a mode hook in this buffer, @@ -1115,8 +1116,9 @@ Semantic mode. ;; Enable all the global auxiliary minor modes in ;; `semantic-submode-list'. (dolist (mode semantic-submode-list) - (if (memq mode semantic-default-submodes) - (funcall mode 1))) + (and (memq mode semantic-default-submodes) + (fboundp mode) + (funcall mode 1))) (unless semantic-load-system-cache-loaded (setq semantic-load-system-cache-loaded t) (when (and (boundp 'semanticdb-default-system-save-directory) @@ -1138,7 +1140,7 @@ Semantic mode. (add-hook 'completion-at-point-functions 'semantic-analyze-completion-at-point-function) - (if global-ede-mode + (if (bound-and-true-p global-ede-mode) (define-key cedet-menu-map [cedet-menu-separator] '("--"))) (dolist (b (buffer-list)) (with-current-buffer b diff --git a/lisp/cedet/semantic/bovine/c.el b/lisp/cedet/semantic/bovine/c.el index bef4b179b23..3200a5c1435 100644 --- a/lisp/cedet/semantic/bovine/c.el +++ b/lisp/cedet/semantic/bovine/c.el @@ -2253,7 +2253,7 @@ actually in their parent which is not accessible.") (princ " Your project symbol map is also derived from the EDE object:\n ") (princ (object-print ede-object))) (princ "\n\n") - (if (arrayp semantic-lex-spp-project-macro-symbol-obarray) + (if (obarrayp semantic-lex-spp-project-macro-symbol-obarray) (let ((macros nil)) (mapatoms #'(lambda (symbol) diff --git a/lisp/cedet/semantic/db-global.el b/lisp/cedet/semantic/db-global.el index 61af619b292..0afa6619d25 100644 --- a/lisp/cedet/semantic/db-global.el +++ b/lisp/cedet/semantic/db-global.el @@ -39,6 +39,8 @@ ;;; Code: +(defvar semanticdb--ih) + ;;;###autoload (defun semanticdb-enable-gnu-global-databases (mode &optional noerror) "Enable the use of the GNU Global SemanticDB back end for all files of MODE. @@ -64,10 +66,10 @@ values." (when (stringp mode) (setq mode (intern mode))) - (let ((ih (mode-local-value mode 'semantic-init-mode-hook))) + (let ((semanticdb--ih (mode-local-value mode 'semantic-init-mode-hook))) (eval `(setq-mode-local ,mode semantic-init-mode-hook - (cons 'semanticdb-enable-gnu-global-hook ih)))) + (cons 'semanticdb-enable-gnu-global-hook semanticdb--ih)))) t ) ) @@ -94,7 +96,7 @@ if optional DONT-ERR-IF-NOT-AVAILABLE is non-nil; else throw an error." (setq ;; Add to the system database list. semanticdb-project-system-databases - (cons (semanticdb-project-database-global "global") + (cons (make-instance 'semanticdb-project-database-global) semanticdb-project-system-databases) ;; Apply the throttle. semanticdb-find-default-throttle @@ -132,7 +134,7 @@ For each file hit, get the traditional semantic table from that file." ;; We need to return something since there is always the "master table" ;; The table can then answer file name type questions. (when (not (slot-boundp obj 'tables)) - (let ((newtable (semanticdb-table-global "GNU Global Search Table"))) + (let ((newtable (make-instance 'semanticdb-table-global))) (oset obj tables (list newtable)) (oset newtable parent-db obj) (oset newtable tags nil) @@ -191,7 +193,7 @@ Returns a table of all matching tags." (faketags nil) ) (when result - (dolist (T (oref result :hit-text)) + (dolist (T (oref result hit-text)) ;; We should look up each tag one at a time, but I'm lazy! ;; Doing this may be good enough. (setq faketags (cons diff --git a/lisp/cedet/semantic/fw.el b/lisp/cedet/semantic/fw.el index 3884cd09ccc..3527f3e6af8 100644 --- a/lisp/cedet/semantic/fw.el +++ b/lisp/cedet/semantic/fw.el @@ -30,7 +30,7 @@ ;; (require 'mode-local) (require 'eieio) -(load "semantic/loaddefs" nil 'nomessage) +(load "semantic/loaddefs" 'noerror 'nomessage) ;;; Compatibility ;; diff --git a/lisp/cedet/semantic/lex-spp.el b/lisp/cedet/semantic/lex-spp.el index 8d6467e5ed0..cb33e483a6b 100644 --- a/lisp/cedet/semantic/lex-spp.el +++ b/lisp/cedet/semantic/lex-spp.el @@ -147,13 +147,13 @@ The search priority is: ;; Do the check of the various tables. (or ;; DYNAMIC - (and (arrayp semantic-lex-spp-dynamic-macro-symbol-obarray) + (and (obarrayp semantic-lex-spp-dynamic-macro-symbol-obarray) (intern-soft name semantic-lex-spp-dynamic-macro-symbol-obarray)) ;; PROJECT - (and (arrayp semantic-lex-spp-project-macro-symbol-obarray) + (and (obarrayp semantic-lex-spp-project-macro-symbol-obarray) (intern-soft name semantic-lex-spp-project-macro-symbol-obarray)) ;; SYSTEM - (and (arrayp semantic-lex-spp-macro-symbol-obarray) + (and (obarrayp semantic-lex-spp-macro-symbol-obarray) (intern-soft name semantic-lex-spp-macro-symbol-obarray)) ;; ... ))) @@ -291,7 +291,7 @@ REPLACEMENT a string that would be substituted in for NAME." "Return a list of spp macros and values. The return list is meant to be saved in a semanticdb table." (let (macros) - (when (arrayp semantic-lex-spp-dynamic-macro-symbol-obarray) + (when (obarrayp semantic-lex-spp-dynamic-macro-symbol-obarray) (mapatoms #'(lambda (symbol) (setq macros (cons (cons (symbol-name symbol) @@ -304,17 +304,17 @@ The return list is meant to be saved in a semanticdb table." "Return a list of spp macros as Lisp symbols. The value of each symbol is the replacement stream." (let (macros) - (when (arrayp semantic-lex-spp-macro-symbol-obarray) + (when (obarrayp semantic-lex-spp-macro-symbol-obarray) (mapatoms #'(lambda (symbol) (setq macros (cons symbol macros))) semantic-lex-spp-macro-symbol-obarray)) - (when (arrayp semantic-lex-spp-project-macro-symbol-obarray) + (when (obarrayp semantic-lex-spp-project-macro-symbol-obarray) (mapatoms #'(lambda (symbol) (setq macros (cons symbol macros))) semantic-lex-spp-project-macro-symbol-obarray)) - (when (arrayp semantic-lex-spp-dynamic-macro-symbol-obarray) + (when (obarrayp semantic-lex-spp-dynamic-macro-symbol-obarray) (mapatoms #'(lambda (symbol) (setq macros (cons symbol macros))) diff --git a/lisp/cedet/semantic/lex.el b/lisp/cedet/semantic/lex.el index 2e8817e13a1..b2a63cdcc3c 100644 --- a/lisp/cedet/semantic/lex.el +++ b/lisp/cedet/semantic/lex.el @@ -1,4 +1,4 @@ -;;; semantic/lex.el --- Lexical Analyzer builder +;;; semantic/lex.el --- Lexical Analyzer builder -*- lexical-binding:t -*- ;; Copyright (C) 1999-2017 Free Software Foundation, Inc. @@ -190,7 +190,7 @@ "Call function FUN on every symbol in TABLE. If optional PROPERTY is non-nil, call FUN only on every symbol which as a PROPERTY value. FUN receives a symbol as argument." - (if (arrayp table) + (if (obarrayp table) (mapatoms #'(lambda (symbol) (if (or (null property) (get symbol property)) @@ -213,7 +213,7 @@ These keywords are matched explicitly, and converted into special symbols.") (defsubst semantic-lex-keyword-symbol (name) "Return keyword symbol with NAME or nil if not found." - (and (arrayp semantic-flex-keywords-obarray) + (and (obarrayp semantic-flex-keywords-obarray) (stringp name) (intern-soft name semantic-flex-keywords-obarray))) @@ -337,13 +337,13 @@ so that analysis can continue, if possible." "Buffer local types obarray for the lexical analyzer.") (make-variable-buffer-local 'semantic-lex-types-obarray) -(defmacro semantic-lex-type-invalid (type) +(defun semantic-lex-type-invalid (type) "Signal that TYPE is an invalid lexical type name." - `(signal 'wrong-type-argument '(semantic-lex-type-p ,type))) + (signal 'wrong-type-argument `(semantic-lex-type-p ,type))) (defsubst semantic-lex-type-symbol (type) "Return symbol with TYPE or nil if not found." - (and (arrayp semantic-lex-types-obarray) + (and (obarrayp semantic-lex-types-obarray) (stringp type) (intern-soft type semantic-lex-types-obarray))) @@ -635,7 +635,7 @@ This specifies how many lists to create tokens in.") (make-variable-buffer-local 'semantic-lex-depth) (defvar semantic-lex-unterminated-syntax-end-function - (lambda (syntax syntax-start lex-end) lex-end) + (lambda (_syntax _syntax-start lex-end) lex-end) "Function called when unterminated syntax is encountered. This should be set to one function. That function should take three parameters. The SYNTAX, or type of syntax which is unterminated. @@ -1779,7 +1779,7 @@ If there is no error, then the last value of FORMS is returned." See variable `semantic-lex-tokens'.") (defvar semantic-flex-unterminated-syntax-end-function - (lambda (syntax syntax-start flex-end) flex-end) + (lambda (_syntax _syntax-start flex-end) flex-end) "Function called when unterminated syntax is encountered. This should be set to one function. That function should take three parameters. The SYNTAX, or type of syntax which is unterminated. diff --git a/lisp/cedet/semantic/senator.el b/lisp/cedet/semantic/senator.el index 407bb05addc..f1918c40918 100644 --- a/lisp/cedet/semantic/senator.el +++ b/lisp/cedet/semantic/senator.el @@ -659,7 +659,7 @@ Use semantic tags to navigate." (end (progn (senator-end-of-defun) (point))) (start (progn (senator-beginning-of-defun) (point)))) (goto-char origin) - (push-mark (point)) + (push-mark) (goto-char end) ;; end-of-defun (push-mark (point) nil t) (goto-char start) ;; beginning-of-defun diff --git a/lisp/cedet/semantic/util.el b/lisp/cedet/semantic/util.el index f8f12ec56a5..31562bc16ab 100644 --- a/lisp/cedet/semantic/util.el +++ b/lisp/cedet/semantic/util.el @@ -110,12 +110,14 @@ buffer, or a filename. If SOMETHING is nil return nil." (semantic-file-tag-table something)) ;; A Semanticdb table ((and (featurep 'semantic/db) + (require 'semantic/db-mode) (semanticdb-minor-mode-p) (semanticdb-abstract-table-child-p something)) (semanticdb-refresh-table something) (semanticdb-get-tags something)) ;; Semanticdb find-results ((and (featurep 'semantic/db) + (require 'semantic/db-mode) (semanticdb-minor-mode-p) (require 'semantic/db-find) (semanticdb-find-results-p something)) diff --git a/lisp/cedet/semantic/wisent/wisent.el b/lisp/cedet/semantic/wisent/wisent.el index 36dff019792..08cad524aed 100644 --- a/lisp/cedet/semantic/wisent/wisent.el +++ b/lisp/cedet/semantic/wisent/wisent.el @@ -114,7 +114,7 @@ If OBJ is a symbol check its value." (and (vectorp obj) (= 4 (length obj)) (vectorp (aref obj 0)) (vectorp (aref obj 1)) (= (length (aref obj 0)) (length (aref obj 1))) - (listp (aref obj 2)) (vectorp (aref obj 3)))) + (listp (aref obj 2)) (obarrayp (aref obj 3)))) (defsubst wisent-region (&rest positions) "Return the start/end positions of the region including POSITIONS. diff --git a/lisp/color.el b/lisp/color.el index 32c8127e316..6dbf3d55cbc 100644 --- a/lisp/color.el +++ b/lisp/color.el @@ -52,14 +52,18 @@ displayed. If FRAME is omitted or nil, use the selected frame. If FRAME cannot display COLOR, return nil." ;; `colors-values' maximum value is either 65535 or 65280 depending on the ;; display system. So we use a white conversion to get the max value. - (let ((valmax (float (car (color-values "#ffffff"))))) + (let ((valmax (float (car (color-values "#ffffffffffff"))))) (mapcar (lambda (x) (/ x valmax)) (color-values color frame)))) -(defun color-rgb-to-hex (red green blue) - "Return hexadecimal notation for the color RED GREEN BLUE. -RED, GREEN, and BLUE should be numbers between 0.0 and 1.0, inclusive." - (format "#%02x%02x%02x" - (* red 255) (* green 255) (* blue 255))) +(defun color-rgb-to-hex (red green blue &optional digits-per-component) + "Return hexadecimal #RGB notation for the color specified by RED GREEN BLUE. +RED, GREEN, and BLUE should be numbers between 0.0 and 1.0, inclusive. +Optional argument DIGITS-PER-COMPONENT can be either 4 (the default) +or 2; use the latter if you need a 24-bit specification of a color." + (or digits-per-component (setq digits-per-component 4)) + (let* ((maxval (if (= digits-per-component 2) 255 65535)) + (fmt (if (= digits-per-component 2) "#%02x%02x%02x" "#%04x%04x%04x"))) + (format fmt (* red maxval) (* green maxval) (* blue maxval)))) (defun color-complement (color-name) "Return the color that is the complement of COLOR-NAME. diff --git a/lisp/comint.el b/lisp/comint.el index 7bac30598f4..51b659167d5 100644 --- a/lisp/comint.el +++ b/lisp/comint.el @@ -362,7 +362,8 @@ This variable is buffer-local." " +\\)" "\\(?:" (regexp-opt password-word-equivalents) "\\|Response\\)" "\\(?:\\(?:, try\\)? *again\\| (empty for no passphrase)\\| (again)\\)?" - "\\(?: for .+\\)?[::៖]\\s *\\'") + ;; "[[:alpha:]]" used to be "for", which fails to match non-English. + "\\(?: [[:alpha:]]+ .+\\)?[::៖]\\s *\\'") "Regexp matching prompts for passwords in the inferior process. This is used by `comint-watch-for-password-prompt'." :version "26.1" @@ -387,8 +388,7 @@ See also `completion-at-point'. This is a good thing to set in mode hooks.") -(defvar comint-input-filter - (function (lambda (str) (not (string-match "\\`\\s *\\'" str)))) +(defvar comint-input-filter #'comint-nonblank-p "Predicate for filtering additions to input history. Takes one argument, the input. If non-nil, the input may be saved on the input history list. Default is to save anything that isn't all whitespace.") @@ -857,6 +857,10 @@ series of processes in the same Comint buffer. The hook (set-process-coding-system proc decoding encoding)) proc)) +(defun comint-nonblank-p (str) + "Return non-nil if STR contains non-whitespace syntax." + (not (string-match "\\`\\s *\\'" str))) + (defun comint-insert-input (event) "In a Comint buffer, set the current input to the previous input at point. If there is no previous input at point, run the command specified diff --git a/lisp/cus-dep.el b/lisp/cus-dep.el index 641bf4f856b..ecdda4e7023 100644 --- a/lisp/cus-dep.el +++ b/lisp/cus-dep.el @@ -33,7 +33,7 @@ ;; See finder-no-scan-regexp in finder.el. (defvar custom-dependencies-no-scan-regexp "\\(^\\.#\\|\\(loaddefs\\|\ -ldefs-boot.*\\|cus-load\\|finder-inf\\|esh-groups\\|subdirs\\)\\.el$\\)" +ldefs-boot\\|cus-load\\|finder-inf\\|esh-groups\\|subdirs\\)\\.el$\\)" "Regexp matching file names not to scan for `custom-make-dependencies'.") (require 'autoload) diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index fac9c77e12a..6dbb45ec6b9 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -1334,7 +1334,7 @@ suggest to customize that face, if it's customizable." (if (get face 'face-alias) (setq face (get face 'face-alias))) (unless (facep face) - (error "Invalid face %S" face)) + (user-error "Invalid face %S" face)) (funcall display-fun (list (list face 'custom-face)) (format "*Customize Face: %s*" @@ -2518,7 +2518,10 @@ try matching its doc string against `custom-guess-doc-alist'." (copy-sequence type) (list type)))) (when options - (widget-put tmp :options options)) + ;; This used to use widget-put, but with strict plists that + ;; fails when type is an even-length list, eg (repeat character). + ;; Passing our result through widget-convert makes it a valid widget. + (setcdr tmp (append (list :options options) (cdr tmp)))) tmp)) (defun custom-variable-value-create (widget) @@ -3246,10 +3249,6 @@ Only match the specified window systems.") :sibling-args (:help-echo "\ The X11 Window System.") x) - (const :format "PM " - :sibling-args (:help-echo "\ -OS/2 Presentation Manager.") - pm) (const :format "W32 " :sibling-args (:help-echo "\ MS Windows.") @@ -4850,8 +4849,6 @@ if that value is non-nil." (define-obsolete-function-alias 'custom-mode 'Custom-mode "23.1") -(add-to-list 'debug-ignored-errors "^Invalid face:? ") - ;;; The End. (provide 'cus-edit) diff --git a/lisp/cus-start.el b/lisp/cus-start.el index 42391c4072b..fbaaf16ec27 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -286,7 +286,11 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of ;; fns.c (use-dialog-box menu boolean "21.1") (use-file-dialog menu boolean "22.1") - (focus-follows-mouse frames boolean "20.3") + (focus-follows-mouse + frames (choice + (const :tag "Off (nil)" :value nil) + (const :tag "On (t)" :value t) + (const :tag "Auto-raise" :value auto-raise)) "26.1") ;; fontset.c ;; FIXME nil is the initial value, fontset.el setqs it. (vertical-centering-font-regexp display @@ -492,14 +496,16 @@ since it could result in memory overflow and make Emacs crash." (window-combination-limit windows (choice (const :tag "Never (nil)" :value nil) - (const :tag "For Temp Buffer Resize mode (temp-buffer-resize)" + (const :tag "If requested via buffer display alist (window-size)" + :value window-size) + (const :tag "With Temp Buffer Resize mode (temp-buffer-resize)" :value temp-buffer-resize) (const :tag "For temporary buffers (temp-buffer)" :value temp-buffer) (const :tag "For buffer display (display-buffer)" :value display-buffer) (other :tag "Always (t)" :value t)) - "24.3") + "26.1") (fast-but-imprecise-scrolling scrolling boolean "25.1") (window-resize-pixelwise windows boolean "24.4") ;; xdisp.c @@ -548,7 +554,15 @@ since it could result in memory overflow and make Emacs crash." (const :tag "Text-image-horiz" :value text-image-horiz) (const :tag "System default" :value nil)) "24.1") (tool-bar-max-label-size frames integer "24.1") - (auto-hscroll-mode scrolling boolean "21.1") + (auto-hscroll-mode scrolling + (choice + (const :tag "Don't scroll automatically" + :value nil) + (const :tag "Scroll the entire window" + :value t) + (const :tag "Scroll only the current line" + :value current-line)) + "26.1") (void-text-area-pointer cursor (choice (const :tag "Standard (text pointer)" :value nil) @@ -567,6 +581,39 @@ since it could result in memory overflow and make Emacs crash." (const :tag "Fit (t)" :value t) (const :tag "Grow only" :value grow-only)) "25.1") + (display-raw-bytes-as-hex display boolean "26.1") + (display-line-numbers display + (choice + (const :tag "Off (nil)" :value nil) + (const :tag "Absolute line numbers" + :value t) + (const :tag "Relative line numbers" + :value relative) + (const :tag "Visually relative line numbers" + :value visual)) + "26.1") + (display-line-numbers-width display + (choice + (const :tag "Dynamically computed" + :value nil) + (integer :menu-tag "Fixed number of columns" + :value 2 + :format "%v")) + "26.1") + (display-line-numbers-current-absolute display + (choice + (const :tag "Display actual number of current line" + :value t) + (const :tag "Display zero as number of current line" + :value nil)) + "26.1") + (display-line-numbers-widen display + (choice + (const :tag "Disregard narrowing when calculating line numbers" + :value t) + (const :tag "Count lines from beginning of narrowed region" + :value nil)) + "26.1") ;; xfaces.c (scalable-fonts-allowed display boolean "22.1") ;; xfns.c diff --git a/lisp/dabbrev.el b/lisp/dabbrev.el index 3550d75c46a..86eb4e737df 100644 --- a/lisp/dabbrev.el +++ b/lisp/dabbrev.el @@ -6,7 +6,7 @@ ;; Author: Don Morrison ;; Lars Lindberg ;; (according to ack.texi) -;; Maintainer: Lars Lindberg <Lars.Lindberg@sypro.cap.se> +;; Maintainer: emacs-devel@gnu.org ;; Created: 16 Mars 1992 ;; Lindberg's last update version: 5.7 ;; Keywords: abbrev expand completion convenience @@ -191,23 +191,21 @@ This variable has an effect only when the value of This regexp will be surrounded with \\\\( ... \\\\) when actually used. Set this variable to \"\\\\sw\" if you want ordinary words or -\"\\\\sw\\\\|\\\\s_\" if you want symbols (including characters whose -syntax is \"symbol\" as well as those whose syntax is \"word\". - -The value nil has a special meaning: the abbreviation is from point to -previous word-start, but the search is for symbols. - -For instance, if you are programming in Lisp, `yes-or-no-p' is a symbol, -while `yes', `or', `no' and `p' are considered words. If this -variable is nil, then expanding `yes-or-no-' looks for a symbol -starting with or containing `no-'. If you set this variable to -\"\\\\sw\\\\|\\\\s_\", that expansion looks for a symbol starting with -`yes-or-no-'. Finally, if you set this variable to \"\\\\sw\", then -expanding `yes-or-no-' signals an error because `-' is not part of a word; -but expanding `yes-or-no' looks for a word starting with `no'. - -The recommended value is nil, which will make dabbrev default to -using \"\\\\sw\\\\|\\\\s_\"." +\"\\\\sw\\\\|\\\\s_\" if you want symbols (including characters +whose syntax is \"symbol\" as well as those whose syntax is +\"word\"). The abbreviation is from point to the start of the +previous sequence of characters matching this variable. + +The default value of nil is equivalent to \"\\\\sw\\\\|\\\\s_\". + +For instance, suppose the current buffer is in `c-mode'. If this +variable is nil or \"\\\\sw\\\\|\\\\s_\", then expanding +`debug_print_in_' looks for a symbol starting with +`debug_print_in_'. If you set this variable to \"\\\\sw\", that +expansion looks for a word prefixed with `in_' (e.g., it would +match `in_range', but not `in_close_range'). If expanding +`debug_print_in' it would look for a word starting with +`in' (e.g. `integer')." :type '(choice (const nil) regexp) :group 'dabbrev) diff --git a/lisp/descr-text.el b/lisp/descr-text.el index 6a6a8ea4479..6f36bbed680 100644 --- a/lisp/descr-text.el +++ b/lisp/descr-text.el @@ -413,12 +413,11 @@ relevant to POS." (multibyte-p enable-multibyte-characters) (overlays (mapcar (lambda (o) (overlay-properties o)) (overlays-at pos))) - (char-description (if (not multibyte-p) + (char-description (if (< char 128) (single-key-description char) - (if (< char 128) - (single-key-description char) - (string-to-multibyte - (char-to-string char))))) + (string (if (not multibyte-p) + (decode-char 'eight-bit char) + char)))) (text-props-desc (let ((tmp-buf (generate-new-buffer " *text-props*"))) (unwind-protect @@ -635,7 +634,9 @@ relevant to POS." ("buffer code" ,(if multibyte-p (encoded-string-description - (string-as-unibyte (char-to-string char)) nil) + (encode-coding-string (char-to-string char) + 'emacs-internal) + nil) (format "#x%02X" char))) ("file code" ,@(if multibyte-p @@ -704,7 +705,6 @@ relevant to POS." (called-interactively-p 'interactive)) (with-help-window (help-buffer) (with-current-buffer standard-output - (set-buffer-multibyte multibyte-p) (let ((formatter (format "%%%ds:" max-width))) (dolist (elt item-list) (when (cadr elt) diff --git a/lisp/desktop.el b/lisp/desktop.el index 39dc92fabe2..540d0e3b11d 100644 --- a/lisp/desktop.el +++ b/lisp/desktop.el @@ -733,6 +733,10 @@ if different)." (condition-case err (unless (or (eq frame this) (eq frame mini) + ;; Don't delete daemon's initial frame, or + ;; we'll never be able to close the last + ;; client's frame (Bug#26912). + (if (daemonp) (not (frame-parameter frame 'client))) (frame-parameter frame 'desktop-dont-clear)) (delete-frame frame)) (error diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index d7ca0527879..095ce8ba89c 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -51,6 +51,33 @@ into this list; they also should call `dired-log' to log the errors.") (defconst dired-star-subst-regexp "\\(^\\|[ \t]\\)\\*\\([ \t]\\|$\\)") (defconst dired-quark-subst-regexp "\\(^\\|[ \t]\\)\\?\\([ \t]\\|$\\)") +(make-obsolete-variable 'dired-star-subst-regexp nil "26.1") +(make-obsolete-variable 'dired-quark-subst-regexp nil "26.1") + +(defun dired-isolated-string-re (string) + "Return a regexp to match STRING isolated. +Isolated means that STRING is surrounded by spaces or at the beginning/end +of a string followed/prefixed with an space. +The regexp capture the preceding blank, STRING and the following blank as +the groups 1, 2 and 3 respectively." + (format "\\(\\`\\|[ \t]\\)\\(%s\\)\\([ \t]\\|\\'\\)" string)) + +(defun dired--star-or-qmark-p (string match &optional keep) + "Return non-nil if STRING contains isolated MATCH or `\\=`?\\=`'. +MATCH should be the strings \"?\", `\\=`?\\=`', \"*\" or nil. The latter +means STRING contains either \"?\" or `\\=`?\\=`' or \"*\". +If optional arg KEEP is non-nil, then preserve the match data. Otherwise, +this function changes it and saves MATCH as the second match group. + +Isolated means that MATCH is surrounded by spaces or at the beginning/end +of STRING followed/prefixed with an space. A match to `\\=`?\\=`', +isolated or not, is also valid." + (let ((regexps (list (dired-isolated-string-re (if match (regexp-quote match) "[*?]"))))) + (when (or (null match) (equal match "?")) + (setq regexps (append (list "\\(\\)\\(`\\?`\\)\\(\\)") regexps))) + (cl-some (lambda (x) + (funcall (if keep #'string-match-p #'string-match) x string)) + regexps))) ;;;###autoload (defun dired-diff (file &optional switches) @@ -308,7 +335,7 @@ List has a form of (file-name full-file-name (attribute-list))." failures) (setq failures (dired-bunch-files 10000 - (function dired-check-process) + #'dired-check-process (append (list operation program) (unless (or (string-equal new-attribute "") @@ -512,7 +539,7 @@ with a prefix argument." ;; If the file has numeric backup versions, ;; put on dired-file-version-alist an element of the form ;; (FILENAME . VERSION-NUMBER-LIST) - (dired-map-dired-file-lines (function dired-collect-file-versions)) + (dired-map-dired-file-lines #'dired-collect-file-versions) ;; Sort each VERSION-NUMBER-LIST, ;; and remove the versions not to be deleted. (let ((fval dired-file-version-alist)) @@ -528,7 +555,7 @@ with a prefix argument." (setq fval (cdr fval)))) ;; Look at each file. If it is a numeric backup file, ;; find it in a VERSION-NUMBER-LIST and maybe flag it for deletion. - (dired-map-dired-file-lines (function dired-trample-file-versions)) + (dired-map-dired-file-lines #'dired-trample-file-versions) (message "Cleaning numerical backups...done"))) ;;; Subroutines of dired-clean-directory. @@ -658,13 +685,13 @@ If there is a `*' in COMMAND, surrounded by whitespace, this runs COMMAND just once with the entire file list substituted there. If there is no `*', but there is a `?' in COMMAND, surrounded by -whitespace, this runs COMMAND on each file individually with the -file name substituted for `?'. +whitespace, or a `\\=`?\\=`' this runs COMMAND on each file +individually with the file name substituted for `?' or `\\=`?\\=`'. Otherwise, this runs COMMAND on each file individually with the file name added at the end of COMMAND (separated by a space). -`*' and `?' when not surrounded by whitespace have no special +`*' and `?' when not surrounded by whitespace nor `\\=`' have no special significance for `dired-do-shell-command', and are passed through normally to the shell, but you must confirm first. @@ -704,32 +731,40 @@ can be produced by `dired-get-marked-files', for example." (dired-read-shell-command "! on %s: " current-prefix-arg files) current-prefix-arg files))) - (let* ((on-each (not (string-match-p dired-star-subst-regexp command))) - (no-subst (not (string-match-p dired-quark-subst-regexp command))) - (star (string-match-p "\\*" command)) - (qmark (string-match-p "\\?" command))) - ;; Get confirmation for wildcards that may have been meant - ;; to control substitution of a file name or the file name list. - (if (cond ((not (or on-each no-subst)) - (error "You can not combine `*' and `?' substitution marks")) - ((and star on-each) - (y-or-n-p (format-message - "Confirm--do you mean to use `*' as a wildcard? "))) - ((and qmark no-subst) - (y-or-n-p (format-message - "Confirm--do you mean to use `?' as a wildcard? "))) - (t)) - (if on-each - (dired-bunch-files - (- 10000 (length command)) - (function (lambda (&rest files) - (dired-run-shell-command - (dired-shell-stuff-it command files t arg)))) - nil - file-list) - ;; execute the shell command - (dired-run-shell-command - (dired-shell-stuff-it command file-list nil arg)))))) + (cl-flet ((need-confirm-p + (cmd str) + (let ((res cmd) + (regexp (regexp-quote str))) + ;; Drop all ? and * surrounded by spaces and `?`. + (while (and (string-match regexp res) + (dired--star-or-qmark-p res str)) + (setq res (replace-match "" t t res 2))) + (string-match regexp res)))) + (let* ((on-each (not (dired--star-or-qmark-p command "*" 'keep))) + (no-subst (not (dired--star-or-qmark-p command "?" 'keep))) + (star (string-match "\\*" command)) + (qmark (string-match "\\?" command)) + ;; Get confirmation for wildcards that may have been meant + ;; to control substitution of a file name or the file name list. + (ok (cond ((not (or on-each no-subst)) + (error "You can not combine `*' and `?' substitution marks")) + ((need-confirm-p command "*") + (y-or-n-p (format-message + "Confirm--do you mean to use `*' as a wildcard? "))) + ((need-confirm-p command "?") + (y-or-n-p (format-message + "Confirm--do you mean to use `?' as a wildcard? "))) + (t)))) + (when ok + (if on-each + (dired-bunch-files (- 10000 (length command)) + (lambda (&rest files) + (dired-run-shell-command + (dired-shell-stuff-it command files t arg))) + nil file-list) + ;; execute the shell command + (dired-run-shell-command + (dired-shell-stuff-it command file-list nil arg))))))) ;; Might use {,} for bash or csh: (defvar dired-mark-prefix "" @@ -769,12 +804,10 @@ can be produced by `dired-get-marked-files', for example." ";" "&")) (stuff-it - (if (or (string-match-p dired-star-subst-regexp command) - (string-match-p dired-quark-subst-regexp command)) + (if (dired--star-or-qmark-p command nil 'keep) (lambda (x) (let ((retval (concat cmd-prefix command))) - (while (string-match - "\\(^\\|[ \t]\\)\\([*?]\\)\\([ \t]\\|$\\)" retval) + (while (dired--star-or-qmark-p retval nil) (setq retval (replace-match x t t retval 2))) retval)) (lambda (x) (concat cmd-prefix command dired-mark-separator x))))) @@ -1122,7 +1155,7 @@ Return nil if no change in files." (let ((files (dired-get-marked-files t arg nil t)) (string (if (eq op-symbol 'compress) "Compress or uncompress" (capitalize (symbol-name op-symbol))))) - (dired-mark-pop-up nil op-symbol files (function y-or-n-p) + (dired-mark-pop-up nil op-symbol files #'y-or-n-p (concat string " " (dired-mark-prompt arg files) "? "))))) @@ -1190,7 +1223,7 @@ return t; if SYM is q or ESC, return nil." (defun dired-do-compress (&optional arg) "Compress or uncompress marked (or next ARG) files." (interactive "P") - (dired-map-over-marks-check (function dired-compress) arg 'compress t)) + (dired-map-over-marks-check #'dired-compress arg 'compress t)) ;; Commands for Emacs Lisp files - load and byte compile @@ -1218,7 +1251,7 @@ return t; if SYM is q or ESC, return nil." (defun dired-do-byte-compile (&optional arg) "Byte compile marked (or next ARG) Emacs Lisp files." (interactive "P") - (dired-map-over-marks-check (function dired-byte-compile) arg 'byte-compile t)) + (dired-map-over-marks-check #'dired-byte-compile arg 'byte-compile t)) (defun dired-load () ;; Return nil for success, offending file name else. @@ -1235,7 +1268,7 @@ return t; if SYM is q or ESC, return nil." (defun dired-do-load (&optional arg) "Load the marked (or next ARG) Emacs Lisp files." (interactive "P") - (dired-map-over-marks-check (function dired-load) arg 'load t)) + (dired-map-over-marks-check #'dired-load arg 'load t)) ;;;###autoload (defun dired-do-redisplay (&optional arg test-for-subdir) @@ -1266,12 +1299,14 @@ See Info node `(emacs)Subdir switches' for more details." ;; message much faster than making dired-map-over-marks show progress (dired-uncache (if (consp dired-directory) (car dired-directory) dired-directory)) - (dired-map-over-marks (let ((fname (dired-get-filename)) + (dired-map-over-marks (let ((fname (dired-get-filename nil t)) ;; Postpone readin hook till we map ;; over all marked files (Bug#6810). (dired-after-readin-hook nil)) - (message "Redisplaying... %s" fname) - (dired-update-file-line fname)) + (if (not fname) + (error "No file on this line") + (message "Redisplaying... %s" fname) + (dired-update-file-line fname))) arg) (run-hooks 'dired-after-readin-hook) (dired-move-to-filename) @@ -1306,7 +1341,7 @@ See Info node `(emacs)Subdir switches' for more details." (defun dired-add-file (filename &optional marker-char) (dired-fun-in-all-buffers (file-name-directory filename) (file-name-nondirectory filename) - (function dired-add-entry) filename marker-char)) + #'dired-add-entry filename marker-char)) (defvar dired-omit-mode) (declare-function dired-omit-regexp "dired-x" ()) @@ -1364,7 +1399,7 @@ files matching `dired-omit-regexp'." ;; else try to find correct place to insert (if (dired-goto-subdir directory) (progn ;; unhide if necessary - (if (looking-at-p "\r") + (if (= (following-char) ?\r) ;; Point is at end of subdir line. (dired-unhide-subdir)) ;; found - skip subdir and `total' line @@ -1443,7 +1478,7 @@ files matching `dired-omit-regexp'." (defun dired-remove-file (file) (dired-fun-in-all-buffers (file-name-directory file) (file-name-nondirectory file) - (function dired-remove-entry) file)) + #'dired-remove-entry file)) (defun dired-remove-entry (file) (save-excursion @@ -1457,7 +1492,7 @@ files matching `dired-omit-regexp'." "Create or update the line for FILE in all Dired buffers it would belong in." (dired-fun-in-all-buffers (file-name-directory file) (file-name-nondirectory file) - (function dired-relist-entry) file)) + #'dired-relist-entry file)) (defun dired-relist-entry (file) ;; Relist the line for FILE, or just add it if it did not exist. @@ -1551,7 +1586,7 @@ Special value `always' suppresses confirmation." (setq from-dir (file-name-as-directory from-dir) to-dir (file-name-as-directory to-dir)) (dired-fun-in-all-buffers from-dir nil - (function dired-rename-subdir-1) from-dir to-dir) + #'dired-rename-subdir-1 from-dir to-dir) ;; Update visited file name of all affected buffers (let ((expanded-from-dir (expand-file-name from-dir)) (blist (buffer-list))) @@ -1786,7 +1821,7 @@ Optional arg HOW-TO determines how to treat the target. For any other return value, TARGET is treated as a directory." (or op1 (setq op1 operation)) (let* ((fn-list (dired-get-marked-files nil arg)) - (rfn-list (mapcar (function dired-make-relative) fn-list)) + (rfn-list (mapcar #'dired-make-relative fn-list)) (dired-one-file ; fluid variable inside dired-create-files (and (consp fn-list) (null (cdr fn-list)) (car fn-list))) (target-dir (dired-dwim-target-directory)) @@ -1836,10 +1871,9 @@ Optional arg HOW-TO determines how to treat the target. (if into-dir ; target is a directory ;; This function uses fluid variable target when called ;; inside dired-create-files: - (function - (lambda (from) - (expand-file-name (file-name-nondirectory from) target))) - (function (lambda (_from) target))) + (lambda (from) + (expand-file-name (file-name-nondirectory from) target)) + (lambda (_from) target)) marker-char)))) ;; Read arguments for a marked-files command that wants a file name, @@ -1855,7 +1889,7 @@ Optional arg HOW-TO determines how to treat the target. &optional default) (dired-mark-pop-up nil op-symbol files - (function read-file-name) + #'read-file-name (format prompt (dired-mark-prompt arg files)) dir default)) (defun dired-dwim-target-directory () @@ -1983,7 +2017,7 @@ This command copies symbolic links by creating new ones, similar to the \"-d\" option for the \"cp\" shell command." (interactive "P") (let ((dired-recursive-copies dired-recursive-copies)) - (dired-do-create-files 'copy (function dired-copy-file) + (dired-do-create-files 'copy #'dired-copy-file "Copy" arg dired-keep-marker-copy nil dired-copy-how-to-fn))) @@ -2000,7 +2034,7 @@ suggested for the target directory depends on the value of For relative symlinks, use \\[dired-do-relsymlink]." (interactive "P") - (dired-do-create-files 'symlink (function make-symbolic-link) + (dired-do-create-files 'symlink #'make-symbolic-link "Symlink" arg dired-keep-marker-symlink)) ;;;###autoload @@ -2013,7 +2047,7 @@ with the same names that the files currently have. The default suggested for the target directory depends on the value of `dired-dwim-target', which see." (interactive "P") - (dired-do-create-files 'hardlink (function dired-hardlink) + (dired-do-create-files 'hardlink #'dired-hardlink "Hardlink" arg dired-keep-marker-hardlink)) (defun dired-hardlink (file newname &optional ok-if-already-exists) @@ -2032,7 +2066,7 @@ This command also renames any buffers that are visiting the files. The default suggested for the target directory depends on the value of `dired-dwim-target', which see." (interactive "P") - (dired-do-create-files 'move (function dired-rename-file) + (dired-do-create-files 'move #'dired-rename-file "Move" arg dired-keep-marker-rename "Rename")) ;;;###end dired-cp.el @@ -2060,37 +2094,35 @@ Type SPC or `y' to %s one match, DEL or `n' to skip to next, (regexp-name-constructor ;; Function to construct new filename using REGEXP and NEWNAME: (if whole-name ; easy (but rare) case - (function - (lambda (from) - (let ((to (dired-string-replace-match regexp from newname)) - ;; must bind help-form directly around call to - ;; dired-query - (help-form rename-regexp-help-form)) - (if to - (and (dired-query 'rename-regexp-query - operation-prompt - from - to) - to) - (dired-log "%s: %s did not match regexp %s\n" - operation from regexp))))) - ;; not whole-name, replace non-directory part only - (function - (lambda (from) - (let* ((new (dired-string-replace-match - regexp (file-name-nondirectory from) newname)) - (to (and new ; nil means there was no match - (expand-file-name new - (file-name-directory from)))) + (lambda (from) + (let ((to (dired-string-replace-match regexp from newname)) + ;; must bind help-form directly around call to + ;; dired-query (help-form rename-regexp-help-form)) - (if to - (and (dired-query 'rename-regexp-query - operation-prompt - (dired-make-relative from) - (dired-make-relative to)) - to) - (dired-log "%s: %s did not match regexp %s\n" - operation (file-name-nondirectory from) regexp))))))) + (if to + (and (dired-query 'rename-regexp-query + operation-prompt + from + to) + to) + (dired-log "%s: %s did not match regexp %s\n" + operation from regexp)))) + ;; not whole-name, replace non-directory part only + (lambda (from) + (let* ((new (dired-string-replace-match + regexp (file-name-nondirectory from) newname)) + (to (and new ; nil means there was no match + (expand-file-name new + (file-name-directory from)))) + (help-form rename-regexp-help-form)) + (if to + (and (dired-query 'rename-regexp-query + operation-prompt + (dired-make-relative from) + (dired-make-relative to)) + to) + (dired-log "%s: %s did not match regexp %s\n" + operation (file-name-nondirectory from) regexp)))))) rename-regexp-query) (dired-create-files file-creator operation fn-list regexp-name-constructor marker-char))) @@ -2128,7 +2160,7 @@ With a zero prefix arg, renaming by regexp affects the absolute file name. Normally, only the non-directory part of the file name is used and changed." (interactive (dired-mark-read-regexp "Rename")) (dired-do-create-files-regexp - (function dired-rename-file) + #'dired-rename-file "Rename" arg regexp newname whole-name dired-keep-marker-rename)) ;;;###autoload @@ -2138,7 +2170,7 @@ See function `dired-do-rename-regexp' for more info." (interactive (dired-mark-read-regexp "Copy")) (let ((dired-recursive-copies nil)) ; No recursive copies. (dired-do-create-files-regexp - (function dired-copy-file) + #'dired-copy-file (if dired-copy-preserve-time "Copy [-p]" "Copy") arg regexp newname whole-name dired-keep-marker-copy))) @@ -2148,7 +2180,7 @@ See function `dired-do-rename-regexp' for more info." See function `dired-do-rename-regexp' for more info." (interactive (dired-mark-read-regexp "HardLink")) (dired-do-create-files-regexp - (function add-name-to-file) + #'add-name-to-file "HardLink" arg regexp newname whole-name dired-keep-marker-hardlink)) ;;;###autoload @@ -2157,7 +2189,7 @@ See function `dired-do-rename-regexp' for more info." See function `dired-do-rename-regexp' for more info." (interactive (dired-mark-read-regexp "SymLink")) (dired-do-create-files-regexp - (function make-symbolic-link) + #'make-symbolic-link "SymLink" arg regexp newname whole-name dired-keep-marker-symlink)) (defvar rename-non-directory-query) @@ -2172,39 +2204,38 @@ See function `dired-do-rename-regexp' for more info." file-creator operation (dired-get-marked-files nil arg) - (function - (lambda (from) - (let ((to (concat (file-name-directory from) - (funcall basename-constructor - (file-name-nondirectory from))))) - (and (let ((help-form (format-message "\ + (lambda (from) + (let ((to (concat (file-name-directory from) + (funcall basename-constructor + (file-name-nondirectory from))))) + (and (let ((help-form (format-message "\ Type SPC or `y' to %s one file, DEL or `n' to skip to next, `!' to %s all remaining matches with no more questions." - (downcase operation) - (downcase operation)))) - (dired-query 'rename-non-directory-query - (concat operation " `%s' to `%s'") - (dired-make-relative from) - (dired-make-relative to))) - to)))) + (downcase operation) + (downcase operation)))) + (dired-query 'rename-non-directory-query + (concat operation " `%s' to `%s'") + (dired-make-relative from) + (dired-make-relative to))) + to))) dired-keep-marker-rename))) (defun dired-rename-non-directory (basename-constructor operation arg) (dired-create-files-non-directory - (function dired-rename-file) + #'dired-rename-file basename-constructor operation arg)) ;;;###autoload (defun dired-upcase (&optional arg) "Rename all marked (or next ARG) files to upper case." (interactive "P") - (dired-rename-non-directory (function upcase) "Rename upcase" arg)) + (dired-rename-non-directory #'upcase "Rename upcase" arg)) ;;;###autoload (defun dired-downcase (&optional arg) "Rename all marked (or next ARG) files to lower case." (interactive "P") - (dired-rename-non-directory (function downcase) "Rename downcase" arg)) + (dired-rename-non-directory #'downcase "Rename downcase" arg)) ;;;###end dired-re.el @@ -2314,12 +2345,11 @@ This function takes some pains to conform to `ls -lR' output." (when real-switches (let (case-fold-search) (mapcar - (function - (lambda (x) - (or (eq (null (string-match-p x real-switches)) - (null (string-match-p x dired-actual-switches))) - (error - "Can't have dirs with and without -%s switches together" x)))) + (lambda (x) + (or (eq (null (string-match-p x real-switches)) + (null (string-match-p x dired-actual-switches))) + (error + "Can't have dirs with and without -%s switches together" x))) ;; all switches that make a difference to dired-get-filename: '("F" "b")))))) @@ -2332,9 +2362,9 @@ This function takes some pains to conform to `ls -lR' output." ;; Keep the alist sorted on buffer position. (setq dired-subdir-alist (sort dired-subdir-alist - (function (lambda (elt1 elt2) - (> (dired-get-subdir-min elt1) - (dired-get-subdir-min elt2))))))) + (lambda (elt1 elt2) + (> (dired-get-subdir-min elt1) + (dired-get-subdir-min elt2)))))) (defun dired-kill-tree (dirname &optional remember-marks kill-root) "Kill all proper subdirs of DIRNAME, excluding DIRNAME itself. @@ -2609,7 +2639,7 @@ Lower levels are unaffected." (and selective-display (save-excursion (dired-goto-subdir dir) - (looking-at-p "\r")))) + (= (following-char) ?\r)))) ;;;###autoload (defun dired-hide-subdir (arg) diff --git a/lisp/dired-x.el b/lisp/dired-x.el index 6c8fb0e7dae..7ceb672bf2f 100644 --- a/lisp/dired-x.el +++ b/lisp/dired-x.el @@ -332,46 +332,73 @@ See also the functions: ;;; EXTENSION MARKING FUNCTIONS. +(defun dired--mark-suffix-interactive-spec () + (let* ((default + (let ((file (dired-get-filename nil t))) + (when file + (file-name-extension file)))) + (suffix + (read-string (format "%s extension%s: " + (if (equal current-prefix-arg '(4)) + "UNmarking" + "Marking") + (if default + (format " (default %s)" default) + "")) nil nil default)) + (marker + (pcase current-prefix-arg + ('(4) ?\s) + ('(16) + (let* ((dflt (char-to-string dired-marker-char)) + (input (read-string + (format + "Marker character to use (default %s): " dflt) + nil nil dflt))) + (aref input 0))) + (_ dired-marker-char)))) + (list suffix marker))) + ;; Mark files with some extension. (defun dired-mark-extension (extension &optional marker-char) "Mark all files with a certain EXTENSION for use in later commands. -A `.' is *not* automatically prepended to the string entered. +A `.' is automatically prepended to EXTENSION when not present. EXTENSION may also be a list of extensions instead of a single one. Optional MARKER-CHAR is marker to use. Interactively, ask for EXTENSION. Prefixed with one C-u, unmark files instead. Prefixed with two C-u's, prompt for MARKER-CHAR and mark files with it." - (interactive - (let* ((default - (let ((file (dired-get-filename nil t))) - (when file - (file-name-extension file)))) - (suffix - (read-string (format "%s extension%s: " - (if (equal current-prefix-arg '(4)) - "UNmarking" - "Marking") - (if default - (format " (default %s)" default) - "")) nil nil default)) - (marker - (pcase current-prefix-arg - ('(4) ?\s) - ('(16) - (let* ((dflt (char-to-string dired-marker-char)) - (input (read-string - (format - "Marker character to use (default %s): " dflt) - nil nil dflt))) - (aref input 0))) - (_ dired-marker-char)))) - (list suffix marker))) - (or (listp extension) - (setq extension (list extension))) + (interactive (dired--mark-suffix-interactive-spec)) + (unless (listp extension) + (setq extension (list extension))) + (dired-mark-files-regexp + (concat ".";; don't match names with nothing but an extension + "\\(" + (mapconcat + (lambda (x) + (regexp-quote + (if (string-prefix-p "." x) x (concat "." x)))) + extension "\\|") + "\\)$") + marker-char)) + +;; Mark files ending with some suffix. +(defun dired-mark-suffix (suffix &optional marker-char) + "Mark all files with a certain SUFFIX for use in later commands. +A `.' is *not* automatically prepended to the string entered; see +also `dired-mark-extension', which is similar but automatically +prepends `.' when not present. +SUFFIX may also be a list of suffixes instead of a single one. +Optional MARKER-CHAR is marker to use. +Interactively, ask for SUFFIX. +Prefixed with one C-u, unmark files instead. +Prefixed with two C-u's, prompt for MARKER-CHAR and mark files with it." + (interactive (dired--mark-suffix-interactive-spec)) + (unless (listp suffix) + (setq suffix (list suffix))) (dired-mark-files-regexp (concat ".";; don't match names with nothing but an extension "\\(" - (mapconcat 'regexp-quote extension "\\|") + (mapconcat 'regexp-quote suffix "\\|") "\\)$") marker-char)) @@ -607,7 +634,7 @@ Optional fifth argument CASE-FOLD-P specifies the value of (dired-mark-if (and ;; not already marked - (looking-at-p " ") + (= (following-char) ?\s) ;; uninteresting (let ((fn (dired-get-filename localp t)) ;; Match patterns case-insensitively on case-insensitive @@ -1503,7 +1530,7 @@ refer at all to the underlying file system. Contrast this with (setq mode (buffer-substring (point) (+ mode-len (point)))) (forward-char mode-len) ;; Skip any extended attributes marker ("." or "+"). - (or (looking-at " ") + (or (= (following-char) ?\s) (forward-char 1)) (setq nlink (read (current-buffer))) ;; Karsten Wenger <kw@cis.uni-muenchen.de> fixed uid. diff --git a/lisp/dired.el b/lisp/dired.el index 8396652d50b..0c1f3e4af64 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -335,9 +335,8 @@ The directory name must be absolute, but need not be fully expanded.") (defvar dired-re-dir (concat dired-re-maybe-mark dired-re-inode-size "d[^:]")) (defvar dired-re-sym (concat dired-re-maybe-mark dired-re-inode-size "l[^:]")) (defvar dired-re-exe;; match ls permission string of an executable file - (mapconcat (function - (lambda (x) - (concat dired-re-maybe-mark dired-re-inode-size x))) + (mapconcat (lambda (x) + (concat dired-re-maybe-mark dired-re-inode-size x)) '("-[-r][-w][xs][-r][-w].[-r][-w]." "-[-r][-w].[-r][-w][xs][-r][-w]." "-[-r][-w].[-r][-w].[-r][-w][xst]") @@ -607,9 +606,9 @@ marked file, return (t FILENAME) instead of (FILENAME)." (progn ;; no save-excursion, want to move point. (dired-repeat-over-lines ,arg - (function (lambda () - (if ,show-progress (sit-for 0)) - (setq results (cons ,body results))))) + (lambda () + (if ,show-progress (sit-for 0)) + (setq results (cons ,body results)))) (if (< ,arg 0) (nreverse results) results)) @@ -1995,8 +1994,8 @@ Keybindings: ;; Ignore dired-hide-details-* value of invisible text property by default. (when (eq buffer-invisibility-spec t) (setq buffer-invisibility-spec (list t))) - (setq-local revert-buffer-function (function dired-revert)) - (setq-local buffer-stale-function (function dired-buffer-stale-p)) + (setq-local revert-buffer-function #'dired-revert) + (setq-local buffer-stale-function #'dired-buffer-stale-p) (setq-local page-delimiter "\n\n") (setq-local dired-directory (or dirname default-directory)) ;; list-buffers uses this to display the dir being edited in this buffer. @@ -2126,7 +2125,16 @@ directory in another window." (interactive) ;; Bind `find-file-run-dired' so that the command works on directories ;; too, independent of the user's setting. - (let ((find-file-run-dired t)) + (let ((find-file-run-dired t) + ;; This binding prevents problems with preserving point in + ;; windows displaying Dired buffers, because reverting a Dired + ;; buffer empties it, which changes the places where the + ;; markers used by switch-to-buffer-preserve-window-point + ;; point. + (switch-to-buffer-preserve-window-point + (if dired-auto-revert-buffer + nil + switch-to-buffer-preserve-window-point))) (find-file (dired-get-file-for-visit)))) (defun dired-find-alternate-file () @@ -2460,7 +2468,7 @@ You can then feed the file name(s) to other commands with \\[yank]." (interactive "P") (let ((string (or (dired-get-subdir) - (mapconcat (function identity) + (mapconcat #'identity (if arg (cond ((zerop (prefix-numeric-value arg)) (dired-get-marked-files)) @@ -2962,12 +2970,12 @@ non-empty directories is allowed." ;; lines still to be changed, so the (point) values in L stay valid. ;; Also, for subdirs in natural order, a subdir's files are deleted ;; before the subdir itself - the other way around would not work. - (let* ((files (mapcar (function car) l)) + (let* ((files (mapcar #'car l)) (count (length l)) (succ 0) (trashing (and trash delete-by-moving-to-trash))) ;; canonicalize file list for pop up - (setq files (nreverse (mapcar (function dired-make-relative) files))) + (setq files (nreverse (mapcar #'dired-make-relative files))) (if (dired-mark-pop-up " *Deletions*" 'delete files dired-deletion-confirmer (format "%s %s " @@ -2990,7 +2998,7 @@ non-empty directories is allowed." (progress-reporter-update progress-reporter succ) (dired-fun-in-all-buffers (file-name-directory fn) (file-name-nondirectory fn) - (function dired-delete-entry) fn)) + #'dired-delete-entry fn)) (error ;; catch errors from failed deletions (dired-log "%s\n" err) (setq failures (cons (car (car l)) failures))))) @@ -3284,7 +3292,7 @@ this subdir." (let ((inhibit-read-only t)) (dired-repeat-over-lines (prefix-numeric-value arg) - (function (lambda () (delete-char 1) (insert dired-marker-char)))))))) + (lambda () (delete-char 1) (insert dired-marker-char))))))) (defun dired-unmark (arg &optional interactive) "Unmark the file at point in the Dired buffer. @@ -3919,7 +3927,7 @@ Ask means pop up a menu for the user to select one of copy, move or link." (cdr (nreverse (mapcar - (function (lambda (f) (desktop-file-name (car f) dirname))) + (lambda (f) (desktop-file-name (car f) dirname)) dired-subdir-alist))))) (defun dired-restore-desktop-buffer (_file-name diff --git a/lisp/doc-view.el b/lisp/doc-view.el index 172ea163c18..2eb555821d9 100644 --- a/lisp/doc-view.el +++ b/lisp/doc-view.el @@ -140,7 +140,7 @@ (require 'dired) (require 'image-mode) (require 'jka-compr) -(require 'subr-x) +(eval-when-compile (require 'subr-x)) ;;;; Customization Options diff --git a/lisp/dos-fns.el b/lisp/dos-fns.el index e1d118a830b..1d48371912f 100644 --- a/lisp/dos-fns.el +++ b/lisp/dos-fns.el @@ -3,7 +3,7 @@ ;; Copyright (C) 1991, 1993, 1995-1996, 2001-2017 Free Software ;; Foundation, Inc. -;; Maintainer: Morten Welinder <terra@diku.dk> +;; Maintainer: emacs-devel@gnu.org ;; Keywords: internal ;; Package: emacs diff --git a/lisp/electric.el b/lisp/electric.el index 4078ef8193e..a71e79ff78a 100644 --- a/lisp/electric.el +++ b/lisp/electric.el @@ -443,49 +443,76 @@ quote, left double quote, and right double quote, respectively." :version "25.1" :type 'boolean :safe 'booleanp :group 'electricity) +(defcustom electric-quote-context-sensitive nil + "Non-nil means to replace \\=' with an electric quote depending on context. +If `electric-quote-context-sensitive' is non-nil, Emacs replaces +\\=' and \\='\\=' with an opening quote after a line break, +whitespace, opening parenthesis, or quote and leaves \\=` alone." + :version "26.1" + :type 'boolean :safe #'booleanp :group 'electricity) + +(defvar electric-quote-inhibit-functions () + "List of functions that should inhibit electric quoting. +When the variable `electric-quote-mode' is non-nil, Emacs will +call these functions in order after the user has typed an \\=` or +\\=' character. If one of them returns non-nil, electric quote +substitution is inhibited. The functions are called after the +\\=` or \\=' character has been inserted with point directly +after the inserted character. The functions in this hook should +not move point or change the current buffer.") + (defun electric-quote-post-self-insert-function () "Function that `electric-quote-mode' adds to `post-self-insert-hook'. This requotes when a quoting key is typed." (when (and electric-quote-mode - (memq last-command-event '(?\' ?\`))) - (let ((start - (if (and comment-start comment-use-syntax) - (when (or electric-quote-comment electric-quote-string) - (let* ((syntax (syntax-ppss)) - (beg (nth 8 syntax))) - (and beg - (or (and electric-quote-comment (nth 4 syntax)) - (and electric-quote-string (nth 3 syntax))) - ;; Do not requote a quote that starts or ends - ;; a comment or string. - (eq beg (nth 8 (save-excursion - (syntax-ppss (1- (point))))))))) - (and electric-quote-paragraph - (derived-mode-p 'text-mode) - (or (eq last-command-event ?\`) - (save-excursion (backward-paragraph) (point))))))) - (pcase electric-quote-chars - (`(,q< ,q> ,q<< ,q>>) - (when start - (save-excursion - (if (eq last-command-event ?\`) - (cond ((search-backward (string q< ?`) (- (point) 2) t) - (replace-match (string q<<)) - (when (and electric-pair-mode - (eq (cdr-safe - (assq q< electric-pair-text-pairs)) - (char-after))) - (delete-char 1)) - (setq last-command-event q<<)) - ((search-backward "`" (1- (point)) t) - (replace-match (string q<)) - (setq last-command-event q<))) - (cond ((search-backward (string q> ?') (- (point) 2) t) - (replace-match (string q>>)) - (setq last-command-event q>>)) - ((search-backward "'" (1- (point)) t) - (replace-match (string q>)) - (setq last-command-event q>))))))))))) + (or (eq last-command-event ?\') + (and (not electric-quote-context-sensitive) + (eq last-command-event ?\`))) + (not (run-hook-with-args-until-success + 'electric-quote-inhibit-functions)) + (if (derived-mode-p 'text-mode) + electric-quote-paragraph + (and comment-start comment-use-syntax + (or electric-quote-comment electric-quote-string) + (let* ((syntax (syntax-ppss)) + (beg (nth 8 syntax))) + (and beg + (or (and electric-quote-comment (nth 4 syntax)) + (and electric-quote-string (nth 3 syntax))) + ;; Do not requote a quote that starts or ends + ;; a comment or string. + (eq beg (nth 8 (save-excursion + (syntax-ppss (1- (point))))))))))) + (pcase electric-quote-chars + (`(,q< ,q> ,q<< ,q>>) + (save-excursion + (let ((backtick ?\`)) + (if (or (eq last-command-event ?\`) + (and electric-quote-context-sensitive + (save-excursion + (backward-char) + (or (bobp) (bolp) + (memq (char-before) (list q< q<<)) + (memq (char-syntax (char-before)) + '(?\s ?\()))) + (setq backtick ?\'))) + (cond ((search-backward (string q< backtick) (- (point) 2) t) + (replace-match (string q<<)) + (when (and electric-pair-mode + (eq (cdr-safe + (assq q< electric-pair-text-pairs)) + (char-after))) + (delete-char 1)) + (setq last-command-event q<<)) + ((search-backward (string backtick) (1- (point)) t) + (replace-match (string q<)) + (setq last-command-event q<))) + (cond ((search-backward (string q> ?') (- (point) 2) t) + (replace-match (string q>>)) + (setq last-command-event q>>)) + ((search-backward "'" (1- (point)) t) + (replace-match (string q>)) + (setq last-command-event q>)))))))))) (put 'electric-quote-post-self-insert-function 'priority 10) diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el index d1f3c359f37..8fe94013700 100644 --- a/lisp/emacs-lisp/autoload.el +++ b/lisp/emacs-lisp/autoload.el @@ -164,7 +164,8 @@ expression, in which case we want to handle forms differently." ((and (memq car '(easy-mmode-define-global-mode define-global-minor-mode define-globalized-minor-mode defun defmacro easy-mmode-define-minor-mode define-minor-mode - define-inline cl-defun cl-defmacro cl-defgeneric)) + define-inline cl-defun cl-defmacro cl-defgeneric + pcase-defmacro)) (macrop car) (setq expand (let ((load-file-name file)) (macroexpand form))) (memq (car expand) '(progn prog1 defalias))) @@ -254,30 +255,22 @@ expression, in which case we want to handle forms differently." ;; Those properties are now set in lisp-mode.el. (defun autoload-find-generated-file () - "Visit the autoload file for the current buffer, and return its buffer. -If a buffer is visiting the desired autoload file, return it." + "Visit the autoload file for the current buffer, and return its buffer." (let ((enable-local-variables :safe) - (enable-local-eval nil)) + (enable-local-eval nil) + (delay-mode-hooks t) + (file (autoload-generated-file))) ;; We used to use `raw-text' to read this file, but this causes ;; problems when the file contains non-ASCII characters. - (let* ((delay-mode-hooks t) - (file (autoload-generated-file)) - (file-missing (not (file-exists-p file)))) - (when file-missing - (autoload-ensure-default-file file)) - (with-current-buffer - (find-file-noselect - (autoload-ensure-file-writeable - file)) - ;; block backups when the file has just been created, since - ;; the backups will just be the auto-generated headers. - ;; bug#23203 - (when file-missing - (setq buffer-backed-up t) - (save-buffer)) - (current-buffer))))) + (with-current-buffer (find-file-noselect + (autoload-ensure-file-writeable file)) + (if (zerop (buffer-size)) (insert (autoload-rubric file nil t))) + (current-buffer)))) (defun autoload-generated-file () + "Return `generated-autoload-file' as an absolute name. +If local to the current buffer, expand using the default directory; +otherwise, using `source-directory'/lisp." (expand-file-name generated-autoload-file ;; File-local settings of generated-autoload-file should ;; be interpreted relative to the file's location, @@ -362,24 +355,28 @@ put the output in." (defun autoload-rubric (file &optional type feature) "Return a string giving the appropriate autoload rubric for FILE. TYPE (default \"autoloads\") is a string stating the type of -information contained in FILE. If FEATURE is non-nil, FILE -will provide a feature. FEATURE may be a string naming the -feature, otherwise it will be based on FILE's name. - -At present, a feature is in fact always provided, but this should -not be relied upon." - (let ((basename (file-name-nondirectory file))) +information contained in FILE. TYPE \"package\" acts like the default, +but adds an extra line to the output to modify `load-path'. + +If FEATURE is non-nil, FILE will provide a feature. FEATURE may +be a string naming the feature, otherwise it will be based on +FILE's name." + (let ((basename (file-name-nondirectory file)) + (lp (if (equal type "package") (setq type "autoloads")))) (concat ";;; " basename " --- automatically extracted " (or type "autoloads") "\n" ";;\n" ";;; Code:\n\n" + (if lp + ;; `load-path' should contain only directory names. + "(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path))))\n\n") " \n" ;; This is used outside of autoload.el, eg cus-dep, finder. - "(provide '" - (if (stringp feature) - feature - (file-name-sans-extension basename)) - ")\n" + (if feature + (format "(provide '%s)\n" + (if (stringp feature) feature + (file-name-sans-extension basename)))) ";; Local Variables:\n" ";; version-control: never\n" ";; no-byte-compile: t\n" @@ -390,7 +387,7 @@ not be relied upon." " ends here\n"))) (defvar autoload-ensure-writable nil - "Non-nil means `autoload-ensure-default-file' makes existing file writable.") + "Non-nil means `autoload-find-generated-file' makes existing file writable.") ;; Just in case someone tries to get you to overwrite a file that you ;; don't want to. ;;;###autoload @@ -400,6 +397,7 @@ not be relied upon." ;; Probably pointless, but replaces the old AUTOGEN_VCS in lisp/Makefile, ;; which was designed to handle CVSREAD=1 and equivalent. (and autoload-ensure-writable + (file-exists-p file) (let ((modes (file-modes file))) (if (zerop (logand modes #o0200)) ;; Ignore any errors here, and let subsequent attempts @@ -407,12 +405,6 @@ not be relied upon." (ignore-errors (set-file-modes file (logior modes #o0200)))))) file) -(defun autoload-ensure-default-file (file) - "Make sure that the autoload file FILE exists, creating it if needed. -If the file already exists and `autoload-ensure-writable' is non-nil, -make it writable." - (write-region (autoload-rubric file) nil file)) - (defun autoload-insert-section-header (outbuf autoloads load-name file time) "Insert the section-header line, which lists the file name and which functions are in it, etc." @@ -546,7 +538,9 @@ Don't try to split prefixes that are already longer than that.") ;; "cc-helper" and "c-mode", you'll get "c" in the root prefixes. (dolist (pair (prog1 prefixes (setq prefixes nil))) (let ((s (car pair))) - (if (or (> (length s) 2) ;Long enough! + (if (or (and (> (length s) 2) ; Long enough! + ;; But don't use "def" from deffoo-pkg-thing. + (not (string= "def" s))) (string-match ".[[:punct:]]\\'" s) ;A real (tho short) prefix? (radix-tree-lookup (cdr pair) "")) ;Nothing to expand! (push pair prefixes) ;Keep it as is. @@ -595,7 +589,8 @@ Don't try to split prefixes that are already longer than that.") (lambda (x) (let ((prefix (car x))) (if (or (> (length prefix) 2) ;Long enough! - (string-match ".[[:punct:]]\\'" prefix)) + (and (eq (length prefix) 2) + (string-match "[[:punct:]]" prefix))) prefix ;; Some packages really don't follow the rules. ;; Drop the most egregious cases such as the @@ -875,11 +870,26 @@ FILE's modification time." (error "%s:0:0: error: %s: %s" file (car err) (cdr err))) )) +;; For parallel builds, to stop another process reading a half-written file. +(defun autoload--save-buffer () + "Save current buffer to its file, atomically." + ;; Copied from byte-compile-file. + (let* ((version-control 'never) + (tempfile (make-temp-name buffer-file-name)) + (kill-emacs-hook + (cons (lambda () (ignore-errors (delete-file tempfile))) + kill-emacs-hook))) + (write-region (point-min) (point-max) tempfile nil 1) + (backup-buffer) + (rename-file tempfile buffer-file-name t) + (set-buffer-modified-p nil) + (set-visited-file-modtime) + (or noninteractive (message "Wrote %s" buffer-file-name)))) + (defun autoload-save-buffers () (while autoload-modified-buffers (with-current-buffer (pop autoload-modified-buffers) - (let ((version-control 'never)) - (save-buffer))))) + (autoload--save-buffer)))) ;; FIXME This command should be deprecated. ;; See http://debbugs.gnu.org/22213#41 @@ -1119,8 +1129,7 @@ write its autoloads into the specified file instead." ;; dependencies don't trigger unnecessarily. (if (not changed) (set-buffer-modified-p nil) - (let ((version-control 'never)) - (save-buffer))) + (autoload--save-buffer)) ;; In case autoload entries were added to other files because of ;; file-local autoload-generated-file settings. diff --git a/lisp/emacs-lisp/benchmark.el b/lisp/emacs-lisp/benchmark.el index 25eddf5f6b0..a2217d20953 100644 --- a/lisp/emacs-lisp/benchmark.el +++ b/lisp/emacs-lisp/benchmark.el @@ -1,4 +1,4 @@ -;;; benchmark.el --- support for benchmarking code +;;; benchmark.el --- support for benchmarking code -*- lexical-binding: t -*- ;; Copyright (C) 2003-2017 Free Software Foundation, Inc. @@ -33,6 +33,7 @@ (defmacro benchmark-elapse (&rest forms) "Return the time in seconds elapsed for execution of FORMS." + (declare (indent 0) (debug t)) (let ((t1 (make-symbol "t1")) (t2 (make-symbol "t2"))) `(let (,t1 ,t2) @@ -41,9 +42,6 @@ (setq ,t2 (current-time)) (float-time (time-subtract ,t2 ,t1))))) -(put 'benchmark-elapse 'edebug-form-spec t) -(put 'benchmark-elapse 'lisp-indent-function 0) - ;;;###autoload (defmacro benchmark-run (&optional repetitions &rest forms) "Time execution of FORMS. diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index 004f2e28653..962a7ae5cde 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -185,7 +185,7 @@ (require 'bytecomp) (eval-when-compile (require 'cl-lib)) (require 'macroexp) -(require 'subr-x) +(eval-when-compile (require 'subr-x)) (defun byte-compile-log-lap-1 (format &rest args) ;; Newer byte codes for stack-ref make the slot 0 non-nil again. @@ -1247,7 +1247,7 @@ hash-table-p identity ignore integerp integer-or-marker-p interactive-p invocation-directory invocation-name - keymapp + keymapp keywordp line-beginning-position line-end-position list listp make-marker mark mark-marker markerp max-char memory-limit minibuffer-window diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 25513bd0248..e5b9b47b1d0 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -124,11 +124,13 @@ (require 'backquote) (require 'macroexp) (require 'cconv) +(require 'cl-lib) ;; During bootstrap, cl-loaddefs.el is not created yet, so loading cl-lib ;; doesn't setup autoloads for things like cl-every, which is why we have to -;; require cl-extra instead (bug#18804). -(require 'cl-extra) +;; require cl-extra as well (bug#18804). +(or (fboundp 'cl-every) + (require 'cl-extra)) (or (fboundp 'defsubst) ;; This really ought to be loaded already! @@ -164,24 +166,19 @@ file name, and return the name of the compiled file." (funcall handler 'byte-compiler-base-file-name filename) filename))) -(or (fboundp 'byte-compile-dest-file) - ;; The user may want to redefine this along with emacs-lisp-file-regexp, - ;; so only define it if it is undefined. - ;; Note - redefining this function is obsolete as of 23.2. - ;; Customize byte-compile-dest-file-function instead. - (defun byte-compile-dest-file (filename) - "Convert an Emacs Lisp source file name to a compiled file name. +(defun byte-compile-dest-file (filename) + "Convert an Emacs Lisp source file name to a compiled file name. If `byte-compile-dest-file-function' is non-nil, uses that function to do the work. Otherwise, if FILENAME matches `emacs-lisp-file-regexp' (by default, files with the extension `.el'), adds `c' to it; otherwise adds `.elc'." - (if byte-compile-dest-file-function - (funcall byte-compile-dest-file-function filename) - (setq filename (file-name-sans-versions - (byte-compiler-base-file-name filename))) - (cond ((string-match emacs-lisp-file-regexp filename) - (concat (substring filename 0 (match-beginning 0)) ".elc")) - (t (concat filename ".elc")))))) + (if byte-compile-dest-file-function + (funcall byte-compile-dest-file-function filename) + (setq filename (file-name-sans-versions + (byte-compiler-base-file-name filename))) + (cond ((string-match emacs-lisp-file-regexp filename) + (concat (substring filename 0 (match-beginning 0)) ".elc")) + (t (concat filename ".elc"))))) ;; This can be the 'byte-compile property of any symbol. (autoload 'byte-compile-inline-expand "byte-opt") @@ -416,7 +413,8 @@ specify different fields to sort on." :type '(choice (const name) (const callers) (const calls) (const calls+callers) (const nil))) -(defvar byte-compile-debug nil) +(defvar byte-compile-debug nil + "If non-nil, byte compile errors will be raised as signals instead of logged.") (defvar byte-compile-jump-tables nil "List of all jump tables used during compilation of this form.") (defvar byte-compile-constants nil @@ -442,7 +440,7 @@ Return the compile-time value of FORM." ;; Macroexpand (not macroexpand-all!) form at toplevel in case it ;; expands into a toplevel-equivalent `progn'. See CLHS section ;; 3.2.3.1, "Processing of Top Level Forms". The semantics are very - ;; subtle: see test/automated/bytecomp-tests.el for interesting + ;; subtle: see test/lisp/emacs-lisp/bytecomp-tests.el for interesting ;; cases. (setf form (macroexp-macroexpand form byte-compile-macro-environment)) (if (eq (car-safe form) 'progn) @@ -1377,10 +1375,15 @@ extra args." (let ((nfields (with-temp-buffer (insert (nth 1 form)) (goto-char (point-min)) - (let ((n 0)) + (let ((i 0) (n 0)) (while (re-search-forward "%." nil t) - (unless (eq ?% (char-after (1+ (match-beginning 0)))) - (setq n (1+ n)))) + (backward-char) + (unless (eq ?% (char-after)) + (setq i (if (looking-at "\\([0-9]+\\)\\$") + (string-to-number (match-string 1) 10) + (1+ i)) + n (max n i))) + (forward-char)) n))) (nargs (- (length form) 2))) (unless (= nargs nfields) @@ -1661,7 +1664,12 @@ that already has a `.elc' file." (if arg (setq arg (prefix-numeric-value arg))) (if noninteractive nil - (save-some-buffers) + (save-some-buffers + nil (lambda () + (let ((file (buffer-file-name))) + (and file + (string-match-p emacs-lisp-file-regexp file) + (file-in-directory-p file directory))))) (force-mode-line-update)) (with-current-buffer (get-buffer-create byte-compile-log-buffer) (setq default-directory (expand-file-name directory)) @@ -2023,13 +2031,20 @@ With argument ARG, insert value in current buffer after the form." (not (eobp))) (setq byte-compile-read-position (point) byte-compile-last-position byte-compile-read-position) - (let* ((old-style-backquotes nil) + (let* ((lread--old-style-backquotes nil) + (lread--unescaped-character-literals nil) (form (read inbuffer))) ;; Warn about the use of old-style backquotes. - (when old-style-backquotes + (when lread--old-style-backquotes (byte-compile-warn "!! The file uses old-style backquotes !! This functionality has been obsolete for more than 10 years already and will be removed soon. See (elisp)Backquote in the manual.")) + (when lread--unescaped-character-literals + (byte-compile-warn + "unescaped character literals %s detected!" + (mapconcat (lambda (char) (format "`?%c'" char)) + (sort lread--unescaped-character-literals #'<) + ", "))) (byte-compile-toplevel-file-form form))) ;; Compile pending forms at end of file. (byte-compile-flush-pending) @@ -3201,47 +3216,53 @@ for symbols generated by the byte compiler itself." (fmax2 (if (numberp fargs) (lsh fargs -7))) ;2*max+rest. ;; (fmin (if (numberp fargs) (logand fargs 127))) (alen (length (cdr form))) - (dynbinds ())) + (dynbinds ()) + lap) (fetch-bytecode fun) - (mapc 'byte-compile-form (cdr form)) - (unless fmax2 - ;; Old-style byte-code. - (cl-assert (listp fargs)) - (while fargs - (pcase (car fargs) - (`&optional (setq fargs (cdr fargs))) - (`&rest (setq fmax2 (+ (* 2 (length dynbinds)) 1)) - (push (cadr fargs) dynbinds) - (setq fargs nil)) - (_ (push (pop fargs) dynbinds)))) - (unless fmax2 (setq fmax2 (* 2 (length dynbinds))))) - (cond - ((<= (+ alen alen) fmax2) - ;; Add missing &optional (or &rest) arguments. - (dotimes (_ (- (/ (1+ fmax2) 2) alen)) - (byte-compile-push-constant nil))) - ((zerop (logand fmax2 1)) - (byte-compile-report-error - (format "Too many arguments for inlined function %S" form)) - (byte-compile-discard (- alen (/ fmax2 2)))) - (t - ;; Turn &rest args into a list. - (let ((n (- alen (/ (1- fmax2) 2)))) - (cl-assert (> n 0) nil "problem: fmax2=%S alen=%S n=%S" fmax2 alen n) - (if (< n 5) - (byte-compile-out - (aref [byte-list1 byte-list2 byte-list3 byte-list4] (1- n)) - 0) - (byte-compile-out 'byte-listN n))))) - (mapc #'byte-compile-dynamic-variable-bind dynbinds) - (byte-compile-inline-lapcode - (byte-decompile-bytecode-1 (aref fun 1) (aref fun 2) t) - (1+ start-depth)) - ;; Unbind dynamic variables. - (when dynbinds - (byte-compile-out 'byte-unbind (length dynbinds))) - (cl-assert (eq byte-compile-depth (1+ start-depth)) - nil "Wrong depth start=%s end=%s" start-depth byte-compile-depth))) + (setq lap (byte-decompile-bytecode-1 (aref fun 1) (aref fun 2) t)) + ;; optimized switch bytecode makes it impossible to guess the correct + ;; `byte-compile-depth', which can result in incorrect inlined code. + ;; therefore, we do not inline code that uses the `byte-switch' + ;; instruction. + (if (assq 'byte-switch lap) + (byte-compile-normal-call form) + (mapc 'byte-compile-form (cdr form)) + (unless fmax2 + ;; Old-style byte-code. + (cl-assert (listp fargs)) + (while fargs + (pcase (car fargs) + (`&optional (setq fargs (cdr fargs))) + (`&rest (setq fmax2 (+ (* 2 (length dynbinds)) 1)) + (push (cadr fargs) dynbinds) + (setq fargs nil)) + (_ (push (pop fargs) dynbinds)))) + (unless fmax2 (setq fmax2 (* 2 (length dynbinds))))) + (cond + ((<= (+ alen alen) fmax2) + ;; Add missing &optional (or &rest) arguments. + (dotimes (_ (- (/ (1+ fmax2) 2) alen)) + (byte-compile-push-constant nil))) + ((zerop (logand fmax2 1)) + (byte-compile-report-error + (format "Too many arguments for inlined function %S" form)) + (byte-compile-discard (- alen (/ fmax2 2)))) + (t + ;; Turn &rest args into a list. + (let ((n (- alen (/ (1- fmax2) 2)))) + (cl-assert (> n 0) nil "problem: fmax2=%S alen=%S n=%S" fmax2 alen n) + (if (< n 5) + (byte-compile-out + (aref [byte-list1 byte-list2 byte-list3 byte-list4] (1- n)) + 0) + (byte-compile-out 'byte-listN n))))) + (mapc #'byte-compile-dynamic-variable-bind dynbinds) + (byte-compile-inline-lapcode lap (1+ start-depth)) + ;; Unbind dynamic variables. + (when dynbinds + (byte-compile-out 'byte-unbind (length dynbinds))) + (cl-assert (eq byte-compile-depth (1+ start-depth)) + nil "Wrong depth start=%s end=%s" start-depth byte-compile-depth)))) (defun byte-compile-check-variable (var access-type) "Do various error checks before a use of the variable VAR." @@ -4057,8 +4078,8 @@ Return a list of the form ((TEST . VAR) ((VALUE BODY) ...))" ;; discard duplicate clauses (not (assq obj2 cases))) (push (list (if (consp obj2) (eval obj2) obj2) body) cases) - (if (eq condition t) - (progn (push (list 'default body) cases) + (if (and (macroexp-const-p condition) condition) + (progn (push (list 'default (or body `(,condition))) cases) (throw 'break t)) (setq ok nil) (throw 'break nil)))))) @@ -4128,7 +4149,9 @@ Return a list of the form ((TEST . VAR) ((VALUE BODY) ...))" ;; depth/tag conflicts or violating asserts down the road. ;; To make sure `byte-compile-body' itself doesn't violate this, ;; we use `cl-assert'. - (byte-compile-body body byte-compile--for-effect) + (if (null body) + (byte-compile-form t byte-compile--for-effect) + (byte-compile-body body byte-compile--for-effect)) (cl-assert (or (= byte-compile-depth init-depth) (= byte-compile-depth (1+ init-depth)))) (byte-compile-goto 'byte-goto donetag) @@ -4942,6 +4965,10 @@ already up-to-date." (defvar command-line-args-left) ;Avoid 'free variable' warning (if (not noninteractive) (error "`batch-byte-compile' is to be used only with -batch")) + ;; Better crash loudly than attempting to recover from undefined + ;; behavior. + (setq attempt-stack-overflow-recovery nil + attempt-orderly-shutdown-on-fatal-signal nil) (let ((error nil)) (while command-line-args-left (if (file-directory-p (expand-file-name (car command-line-args-left))) @@ -5034,6 +5061,10 @@ and corresponding effects." (defvar command-line-args-left) ;Avoid 'free variable' warning (if (not noninteractive) (error "batch-byte-recompile-directory is to be used only with -batch")) + ;; Better crash loudly than attempting to recover from undefined + ;; behavior. + (setq attempt-stack-overflow-recovery nil + attempt-orderly-shutdown-on-fatal-signal nil) (or command-line-args-left (setq command-line-args-left '("."))) (while command-line-args-left diff --git a/lisp/emacs-lisp/cl-extra.el b/lisp/emacs-lisp/cl-extra.el index 8cba9137105..99df209d1a2 100644 --- a/lisp/emacs-lisp/cl-extra.el +++ b/lisp/emacs-lisp/cl-extra.el @@ -437,22 +437,38 @@ as an integer unless JUNK-ALLOWED is non-nil." ;; Random numbers. +(defun cl--random-time () + (let* ((time (copy-sequence (current-time-string))) (i (length time)) (v 0)) + (while (>= (cl-decf i) 0) (setq v (+ (* v 3) (aref time i)))) + v)) + +;;;###autoload (autoload 'cl-random-state-p "cl-extra") +(cl-defstruct (cl--random-state + (:copier nil) + (:predicate cl-random-state-p) + (:constructor nil) + (:constructor cl--make-random-state (vec))) + (i -1) (j 30) vec) + +(defvar cl--random-state (cl--make-random-state (cl--random-time))) + ;;;###autoload (defun cl-random (lim &optional state) "Return a random nonnegative number less than LIM, an integer or float. Optional second arg STATE is a random-state object." (or state (setq state cl--random-state)) ;; Inspired by "ran3" from Numerical Recipes. Additive congruential method. - (let ((vec (aref state 3))) + (let ((vec (cl--random-state-vec state))) (if (integerp vec) (let ((i 0) (j (- 1357335 (abs (% vec 1357333)))) (k 1)) - (aset state 3 (setq vec (make-vector 55 nil))) + (setf (cl--random-state-vec state) + (setq vec (make-vector 55 nil))) (aset vec 0 j) (while (> (setq i (% (+ i 21) 55)) 0) (aset vec i (setq j (prog1 k (setq k (- j k)))))) (while (< (setq i (1+ i)) 200) (cl-random 2 state)))) - (let* ((i (aset state 1 (% (1+ (aref state 1)) 55))) - (j (aset state 2 (% (1+ (aref state 2)) 55))) + (let* ((i (cl-callf (lambda (x) (% (1+ x) 55)) (cl--random-state-i state))) + (j (cl-callf (lambda (x) (% (1+ x) 55)) (cl--random-state-j state))) (n (logand 8388607 (aset vec i (- (aref vec i) (aref vec j)))))) (if (integerp lim) (if (<= lim 512) (% n lim) @@ -466,17 +482,10 @@ Optional second arg STATE is a random-state object." (defun cl-make-random-state (&optional state) "Return a copy of random-state STATE, or of the internal state if omitted. If STATE is t, return a new state object seeded from the time of day." - (cond ((null state) (cl-make-random-state cl--random-state)) - ((vectorp state) (copy-tree state t)) - ((integerp state) (vector 'cl--random-state-tag -1 30 state)) - (t (cl-make-random-state (cl--random-time))))) - -;;;###autoload -(defun cl-random-state-p (object) - "Return t if OBJECT is a random-state object." - (and (vectorp object) (= (length object) 4) - (eq (aref object 0) 'cl--random-state-tag))) - + (unless state (setq state cl--random-state)) + (if (cl-random-state-p state) + (copy-tree state t) + (cl--make-random-state (if (integerp state) state (cl--random-time))))) ;; Implementation limits. @@ -775,8 +784,7 @@ including `cl-block' and `cl-eval-when'." (defun cl--describe-class (type &optional class) (unless class (setq class (cl--find-class type))) (let ((location (find-lisp-object-file-name type 'define-type)) - ;; FIXME: Add a `cl-class-of' or `cl-typeof' or somesuch. - (metatype (cl--class-name (symbol-value (aref class 0))))) + (metatype (type-of class))) (insert (symbol-name type) (substitute-command-keys " is a type (of kind `")) (help-insert-xref-button (symbol-name metatype) @@ -865,19 +873,65 @@ including `cl-block' and `cl-eval-when'." "\n"))) "\n")) +(defun cl--print-table (header rows) + ;; FIXME: Isn't this functionality already implemented elsewhere? + (let ((cols (apply #'vector (mapcar #'string-width header))) + (col-space 2)) + (dolist (row rows) + (dotimes (i (length cols)) + (let* ((x (pop row)) + (curwidth (aref cols i)) + (newwidth (if x (string-width x) 0))) + (if (> newwidth curwidth) + (setf (aref cols i) newwidth))))) + (let ((formats '()) + (col 0)) + (dotimes (i (length cols)) + (push (concat (propertize " " + 'display + `(space :align-to ,(+ col col-space))) + "%s") + formats) + (cl-incf col (+ col-space (aref cols i)))) + (let ((format (mapconcat #'identity (nreverse formats) ""))) + (insert (apply #'format format + (mapcar (lambda (str) (propertize str 'face 'italic)) + header)) + "\n") + (insert (apply #'format format + (mapcar (lambda (str) (make-string (string-width str) ?—)) + header)) + "\n") + (dolist (row rows) + (insert (apply #'format format row) "\n")))))) + (defun cl--describe-class-slots (class) "Print help description for the slots in CLASS. Outputs to the current buffer." (let* ((slots (cl--class-slots class)) - ;; FIXME: Add a `cl-class-of' or `cl-typeof' or somesuch. - (metatype (cl--class-name (symbol-value (aref class 0)))) + (metatype (type-of class)) ;; ¡For EIEIO! (cslots (condition-case nil (cl-struct-slot-value metatype 'class-slots class) (cl-struct-unknown-slot nil)))) (insert (propertize "Instance Allocated Slots:\n\n" 'face 'bold)) - (mapc #'cl--describe-class-slot slots) + (let* ((has-doc nil) + (slots-strings + (mapcar + (lambda (slot) + (list (cl-prin1-to-string (cl--slot-descriptor-name slot)) + (cl-prin1-to-string (cl--slot-descriptor-type slot)) + (cl-prin1-to-string (cl--slot-descriptor-initform slot)) + (let ((doc (alist-get :documentation + (cl--slot-descriptor-props slot)))) + (if (not doc) "" + (setq has-doc t) + (substitute-command-keys doc))))) + slots))) + (cl--print-table `("Name" "Type" "Default" . ,(if has-doc '("Doc"))) + slots-strings)) + (insert "\n") (when (> (length cslots) 0) (insert (propertize "\nClass Allocated Slots:\n\n" 'face 'bold)) (mapc #'cl--describe-class-slot cslots)))) diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el index 8517e1ee643..c64376b940f 100644 --- a/lisp/emacs-lisp/cl-generic.el +++ b/lisp/emacs-lisp/cl-generic.el @@ -413,10 +413,12 @@ The set of acceptable TYPEs (also called \"specializers\") is defined (declare (doc-string 3) (indent 2) (debug (&define ; this means we are defining something - [&or name ("setf" :name setf name)] + [&or name ("setf" name :name setf)] ;; ^^ This is the methods symbol - [ &optional keywordp ] ; this is key :before etc - list ; arguments + [ &rest atom ] ; Multiple qualifiers are allowed. + ; Like in CLOS spec, we support + ; any non-list values. + cl-generic-method-args ; arguments [ &optional stringp ] ; documentation string def-body))) ; part to be debugged (let ((qualifiers nil)) @@ -1082,24 +1084,8 @@ These match if the argument is `eql' to VAL." ;;; Support for cl-defstructs specializers. (defun cl--generic-struct-tag (name &rest _) - ;; It's tempting to use (and (vectorp ,name) (aref ,name 0)) - ;; but that would suffer from some problems: - ;; - the vector may have size 0. - ;; - when called on an actual vector (rather than an object), we'd - ;; end up returning an arbitrary value, possibly colliding with - ;; other tagcode's values. - ;; - it can also result in returning all kinds of irrelevant - ;; values which would end up filling up the method-cache with - ;; lots of irrelevant/redundant entries. - ;; FIXME: We could speed this up by introducing a dedicated - ;; vector type at the C level, so we could do something like - ;; (and (vector-objectp ,name) (aref ,name 0)) - `(and (vectorp ,name) - (> (length ,name) 0) - (let ((tag (aref ,name 0))) - (and (symbolp tag) - (eq (symbol-function tag) :quick-object-witness-check) - tag)))) + ;; Use exactly the same code as for `typeof'. + `(if ,name (type-of ,name) 'null)) (defun cl--generic-class-parents (class) (let ((parents ()) @@ -1113,8 +1099,8 @@ These match if the argument is `eql' to VAL." (nreverse parents))) (defun cl--generic-struct-specializers (tag &rest _) - (and (symbolp tag) (boundp tag) - (let ((class (symbol-value tag))) + (and (symbolp tag) + (let ((class (get tag 'cl--class))) (when (cl-typep class 'cl-structure-class) (cl--generic-class-parents class))))) @@ -1154,7 +1140,8 @@ These match if the argument is `eql' to VAL." (process atom) (window atom) (subr atom) (compiled-function function atom) (buffer atom) (char-table array sequence atom) (bool-vector array sequence atom) - (frame atom) (hash-table atom) + (frame atom) (hash-table atom) (terminal atom) + (thread atom) (mutex atom) (condvar atom) (font-spec atom) (font-entity atom) (font-object atom) (vector array sequence atom) ;; Plus, really hand made: diff --git a/lisp/emacs-lisp/cl-indent.el b/lisp/emacs-lisp/cl-indent.el index 33ecf3f4542..df0e0a88583 100644 --- a/lisp/emacs-lisp/cl-indent.el +++ b/lisp/emacs-lisp/cl-indent.el @@ -1,4 +1,4 @@ -;;; cl-indent.el --- enhanced lisp-indent mode +;;; cl-indent.el --- Enhanced lisp-indent mode -*- lexical-binding:t -*- ;; Copyright (C) 1987, 2000-2017 Free Software Foundation, Inc. @@ -35,7 +35,7 @@ ;;; Code: -(eval-when-compile (require 'cl)) +(eval-when-compile (require 'cl-lib)) (defgroup lisp-indent nil "Indentation in Lisp." @@ -166,7 +166,7 @@ is set to `defun'.") (forward-char 1) (forward-sexp 2) (backward-sexp 1) - (looking-at "\\sw")) + (looking-at "\\(:\\|\\sw\\)")) (error t))) (defun lisp-indent-find-method (symbol &optional no-compat) @@ -187,13 +187,13 @@ the standard lisp indent package." (when (and (eq lisp-indent-backquote-substitution-mode 'corrected)) (save-excursion (goto-char (elt state 1)) - (incf loop-indentation - (cond ((eq (char-before) ?,) -1) - ((and (eq (char-before) ?@) - (progn (backward-char) - (eq (char-before) ?,))) - -2) - (t 0))))) + (cl-incf loop-indentation + (cond ((eq (char-before) ?,) -1) + ((and (eq (char-before) ?@) + (progn (backward-char) + (eq (char-before) ?,))) + -2) + (t 0))))) (goto-char indent-point) (beginning-of-line) @@ -315,7 +315,6 @@ instead." ;; If non-nil, this is an indentation to use ;; if nothing else specifies it more firmly. tentative-calculated - (last-point indent-point) ;; the position of the open-paren of the innermost containing list (containing-form-start (elt state 1)) ;; the column of the above @@ -410,9 +409,9 @@ instead." ;; ",(...)" or ",@(...)" (when (eq lisp-indent-backquote-substitution-mode 'corrected) - (incf sexp-column -1) + (cl-incf sexp-column -1) (when (eq (char-after (1- containing-sexp)) ?\@) - (incf sexp-column -1))) + (cl-incf sexp-column -1))) (cond (lisp-indent-backquote-substitution-mode (setf tentative-calculated normal-indent) (setq depth lisp-indent-maximum-backtracking) @@ -465,7 +464,6 @@ instead." function method path state indent-point sexp-column normal-indent))))) (goto-char containing-sexp) - (setq last-point containing-sexp) (unless calculated (condition-case () (progn (backward-up-list 1) @@ -474,6 +472,9 @@ instead." (or calculated tentative-calculated)))) +;; Dynamically bound in common-lisp-indent-call-method. +(defvar lisp-indent-error-function) + (defun common-lisp-indent-call-method (function method path state indent-point sexp-column normal-indent) (let ((lisp-indent-error-function function)) @@ -484,9 +485,6 @@ instead." (lisp-indent-259 method path state indent-point sexp-column normal-indent)))) -;; Dynamically bound in common-lisp-indent-call-method. -(defvar lisp-indent-error-function) - (defun lisp-indent-report-bad-format (m) (error "%s has a badly-formed %s property: %s" ;; Love those free variable references!! @@ -717,7 +715,7 @@ optional\\|rest\\|key\\|allow-other-keys\\|aux\\|whole\\|body\\|environment\ (forward-sexp 2) (skip-chars-forward " \t\n") (while (looking-at "\\sw\\|\\s_") - (incf nqual) + (cl-incf nqual) (forward-sexp) (skip-chars-forward " \t\n")) (> nqual 0))) @@ -726,7 +724,7 @@ optional\\|rest\\|key\\|allow-other-keys\\|aux\\|whole\\|body\\|environment\ path state indent-point sexp-column normal-indent)) -(defun lisp-indent-function-lambda-hack (path state indent-point +(defun lisp-indent-function-lambda-hack (path _state _indent-point sexp-column normal-indent) ;; indent (function (lambda () <newline> <body-forms>)) kludgily. (if (or (cdr path) ; wtf? diff --git a/lisp/emacs-lisp/cl-lib.el b/lisp/emacs-lisp/cl-lib.el index 8c4455a3dad..936c852526c 100644 --- a/lisp/emacs-lisp/cl-lib.el +++ b/lisp/emacs-lisp/cl-lib.el @@ -349,7 +349,6 @@ Call `cl-float-limits' to set this.") (declare-function cl--mapcar-many "cl-extra" (cl-func cl-seqs &optional acc)) -;;;###autoload (defun cl-mapcar (cl-func cl-x &rest cl-rest) "Apply FUNCTION to each element of SEQ, and make a list of the results. If there are several SEQs, FUNCTION is called with that many arguments, @@ -639,6 +638,42 @@ If ALIST is non-nil, the new pairs are prepended to it." (require 'cl-macs) (require 'cl-seq)) +(defun cl--old-struct-type-of (orig-fun object) + (or (and (vectorp object) + (let ((tag (aref object 0))) + (when (and (symbolp tag) + (string-prefix-p "cl-struct-" (symbol-name tag))) + (unless (eq (symbol-function tag) + :quick-object-witness-check) + ;; Old-style old-style struct: + ;; Convert to new-style old-style struct! + (let* ((type (intern (substring (symbol-name tag) + (length "cl-struct-")))) + (class (cl--struct-get-class type))) + ;; If the `cl-defstruct' was recompiled after the code + ;; which constructed `object', `cl--struct-get-class' may + ;; not have called `cl-struct-define' and setup the tag + ;; symbol for us. + (unless (eq (symbol-function tag) + :quick-object-witness-check) + (set tag class) + (fset tag :quick-object-witness-check)))) + (cl--class-name (symbol-value tag))))) + (funcall orig-fun object))) + +;;;###autoload +(define-minor-mode cl-old-struct-compat-mode + "Enable backward compatibility with old-style structs. +This can be needed when using code byte-compiled using the old +macro-expansion of `cl-defstruct' that used vectors objects instead +of record objects." + :global t + (cond + (cl-old-struct-compat-mode + (advice-add 'type-of :around #'cl--old-struct-type-of)) + (t + (advice-remove 'type-of #'cl--old-struct-type-of)))) + ;; Local variables: ;; byte-compile-dynamic: t ;; End: diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index 40342f3fe48..b1ada00f4a4 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -2052,15 +2052,17 @@ This is like `cl-flet', but for macros instead of functions. This function replaces `macroexpand' during macro expansion of `cl-symbol-macrolet', and does the same thing as `macroexpand' except that it additionally expands symbol macros." - (let ((macroexpand-all-environment env)) + (let ((macroexpand-all-environment env) + (venv (alist-get :cl-symbol-macros env))) (while (progn (setq exp (funcall cl--old-macroexpand exp env)) (pcase exp ((pred symbolp) ;; Perform symbol-macro expansion. - (when (cdr (assq (symbol-name exp) env)) - (setq exp (cadr (assq (symbol-name exp) env))))) + (let ((symval (assq exp venv))) + (when symval + (setq exp (cadr symval))))) (`(setq . ,_) ;; Convert setq to setf if required by symbol-macro expansion. (let* ((args (mapcar (lambda (f) (cl--sm-macroexpand f env)) @@ -2078,7 +2080,7 @@ except that it additionally expands symbol macros." (let ((letf nil) (found nil) (nbs ())) (dolist (binding bindings) (let* ((var (if (symbolp binding) binding (car binding))) - (sm (assq (symbol-name var) env))) + (sm (assq var venv))) (push (if (not (cdr sm)) binding (let ((nexp (cadr sm))) @@ -2136,29 +2138,28 @@ by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...). \(fn ((NAME EXPANSION) ...) FORM...)" (declare (indent 1) (debug ((&rest (symbolp sexp)) cl-declarations body))) - (cond - ((cdr bindings) - `(cl-symbol-macrolet (,(car bindings)) - (cl-symbol-macrolet ,(cdr bindings) ,@body))) - ((null bindings) (macroexp-progn body)) - (t - (let ((previous-macroexpand (symbol-function 'macroexpand))) - (unwind-protect - (progn - (fset 'macroexpand #'cl--sm-macroexpand) - (let ((expansion - ;; FIXME: For N bindings, this will traverse `body' N times! - (macroexpand-all (macroexp-progn body) - (cons (list (symbol-name (caar bindings)) - (cl-cadar bindings)) - macroexpand-all-environment)))) - (if (or (null (cdar bindings)) (cl-cddar bindings)) - (macroexp--warn-and-return - (format-message "Malformed `cl-symbol-macrolet' binding: %S" - (car bindings)) - expansion) - expansion))) - (fset 'macroexpand previous-macroexpand)))))) + (let ((previous-macroexpand (symbol-function 'macroexpand)) + (malformed-bindings nil)) + (dolist (binding bindings) + (unless (and (consp binding) (symbolp (car binding)) + (consp (cdr binding)) (null (cddr binding))) + (push binding malformed-bindings))) + (unwind-protect + (progn + (fset 'macroexpand #'cl--sm-macroexpand) + (let* ((venv (cdr (assq :cl-symbol-macros macroexpand-all-environment))) + (expansion + (macroexpand-all (macroexp-progn body) + (cons (cons :cl-symbol-macros + (append bindings venv)) + macroexpand-all-environment)))) + (if malformed-bindings + (macroexp--warn-and-return + (format-message "Malformed `cl-symbol-macrolet' binding(s): %S" + (nreverse malformed-bindings)) + expansion) + expansion))) + (fset 'macroexpand previous-macroexpand)))) ;;; Multiple values. @@ -2604,11 +2605,24 @@ non-nil value, that slot cannot be set via `setf'. (print-func nil) (print-auto nil) (safety (if (cl--compiling-file) cl--optimize-safety 3)) (include nil) - (tag (intern (format "cl-struct-%s" name))) + ;; There are 4 types of structs: + ;; - `vector' type: means we should use a vector, which can come + ;; with or without a tag `name', which is usually in slot 0 + ;; but obeys :initial-offset. + ;; - `list' type: same as `vector' but using lists. + ;; - `record' type: means we should use a record, which necessarily + ;; comes tagged in slot 0. Currently we'll use the `name' as + ;; the tag, but we may want to change it so that the class object + ;; is used as the tag. + ;; - nil type: this is the "pre-record default", which uses a vector + ;; with a tag in slot 0 which is a symbol of the form + ;; `cl-struct-NAME'. We need to still support this for backward + ;; compatibility with old .elc files. + (tag name) (tag-symbol (intern (format "cl-struct-%s-tags" name))) (include-descs nil) (include-name nil) - (type nil) + (type nil) ;nil here means not specified explicitly. (named nil) (forms nil) (docstring (if (stringp (car descs)) (pop descs))) @@ -2648,7 +2662,9 @@ non-nil value, that slot cannot be set via `setf'. ((eq opt :print-function) (setq print-func (car args))) ((eq opt :type) - (setq type (car args))) + (setq type (car args)) + (unless (memq type '(vector list)) + (error "Invalid :type specifier: %s" type))) ((eq opt :named) (setq named t)) ((eq opt :initial-offset) @@ -2680,13 +2696,11 @@ non-nil value, that slot cannot be set via `setf'. (pop include-descs))) (setq descs (append old-descs (delq (assq 'cl-tag-slot descs) descs)) type inc-type - named (if type (assq 'cl-tag-slot descs) 'true)) - (if (cl--struct-class-named include) (setq tag name named t))) - (if type - (progn - (or (memq type '(vector list)) - (error "Invalid :type specifier: %s" type)) - (if named (setq tag name))) + named (if (memq type '(vector list)) + (assq 'cl-tag-slot descs) + 'true)) + (if (cl--struct-class-named include) (setq named t))) + (unless type (setq named 'true))) (or named (setq descs (delq (assq 'cl-tag-slot descs) descs))) (when (and (null predicate) named) @@ -2696,7 +2710,9 @@ non-nil value, that slot cannot be set via `setf'. (length (memq (assq 'cl-tag-slot descs) descs))))) (cond - ((memq type '(nil vector)) + ((null type) ;Record type. + `(memq (type-of cl-x) ,tag-symbol)) + ((eq type 'vector) `(and (vectorp cl-x) (>= (length cl-x) ,(length descs)) (memq (aref cl-x ,pos) ,tag-symbol))) @@ -2793,7 +2809,8 @@ non-nil value, that slot cannot be set via `setf'. (setq slots (nreverse slots) defaults (nreverse defaults)) (and copier - (push `(defalias ',copier #'copy-sequence) forms)) + (push `(defalias ',copier #'copy-sequence) + forms)) (if constructor (push (list constructor (cons '&key (delq nil (copy-sequence slots)))) @@ -2808,7 +2825,7 @@ non-nil value, that slot cannot be set via `setf'. (format "Constructor for objects of type `%s'." name)) ,@(if (cl--safe-expr-p `(progn ,@(mapcar #'cl-second descs))) '((declare (side-effect-free t)))) - (,(or type #'vector) ,@make)) + (,(or type #'record) ,@make)) forms))) (if print-auto (nconc print-func (list '(princ ")" cl-s) t))) ;; Don't bother adding to cl-custom-print-functions since it's not used @@ -2830,8 +2847,8 @@ non-nil value, that slot cannot be set via `setf'. ;; struct as a parent. (eval-and-compile (cl-struct-define ',name ,docstring ',include-name - ',type ,(eq named t) ',descs ',tag-symbol ',tag - ',print-auto)) + ',(or type 'record) ,(eq named t) ',descs + ',tag-symbol ',tag ',print-auto)) ',name))) ;;; Add cl-struct support to pcase @@ -2866,6 +2883,15 @@ is a shorthand for (NAME NAME)." ,pat))) fields))) +(defun cl--defstruct-predicate (type) + (let ((cons (assq (cl-struct-sequence-type type) + `((list . consp) + (vector . vectorp) + (nil . recordp))))) + (if cons + (cdr cons) + 'recordp))) + (defun cl--pcase-mutually-exclusive-p (orig pred1 pred2) "Extra special cases for `cl-typep' predicates." (let* ((x1 pred1) (x2 pred2) @@ -2888,14 +2914,12 @@ is a shorthand for (NAME NAME)." (memq c2 (cl--struct-all-parents c1))))))) (let ((c1 (and (symbolp t1) (cl--find-class t1)))) (and c1 (cl--struct-class-p c1) - (funcall orig (if (eq 'list (cl-struct-sequence-type t1)) - 'consp 'vectorp) + (funcall orig (cl--defstruct-predicate t1) pred2))) (let ((c2 (and (symbolp t2) (cl--find-class t2)))) (and c2 (cl--struct-class-p c2) (funcall orig pred1 - (if (eq 'list (cl-struct-sequence-type t2)) - 'consp 'vectorp)))) + (cl--defstruct-predicate t2)))) (funcall orig pred1 pred2)))) (advice-add 'pcase--mutually-exclusive-p :around #'cl--pcase-mutually-exclusive-p) @@ -2903,8 +2927,8 @@ is a shorthand for (NAME NAME)." (defun cl-struct-sequence-type (struct-type) "Return the sequence used to build STRUCT-TYPE. -STRUCT-TYPE is a symbol naming a struct type. Return `vector' or -`list', or nil if STRUCT-TYPE is not a struct type. " +STRUCT-TYPE is a symbol naming a struct type. Return `record', +`vector`, or `list' if STRUCT-TYPE is a struct type, nil otherwise." (declare (side-effect-free t) (pure t)) (cl--struct-class-type (cl--struct-get-class struct-type))) diff --git a/lisp/emacs-lisp/cl-preloaded.el b/lisp/emacs-lisp/cl-preloaded.el index bba7b83a792..ab6354de7cd 100644 --- a/lisp/emacs-lisp/cl-preloaded.el +++ b/lisp/emacs-lisp/cl-preloaded.el @@ -45,7 +45,7 @@ (defun cl--assertion-failed (form &optional string sargs args) (if debug-on-error - (funcall debugger `(cl-assertion-failed ,form ,string ,@sargs)) + (funcall debugger 'error `(cl-assertion-failed (,form ,string ,@sargs))) (if string (apply #'error string (append sargs args)) (signal 'cl-assertion-failed `(,form ,@sargs))))) @@ -64,7 +64,7 @@ ;; cl--slot-descriptor. ;; BEWARE: Obviously, it's important to keep the two in sync! (lambda (name &optional initform type props) - (vector 'cl-struct-cl-slot-descriptor + (record 'cl-slot-descriptor name initform type props))) (defun cl--struct-get-class (name) @@ -101,7 +101,7 @@ (defun cl--struct-register-child (parent tag) ;; Can't use (cl-typep parent 'cl-structure-class) at this stage ;; because `cl-structure-class' is defined later. - (while (vectorp parent) + (while (recordp parent) (add-to-list (cl--struct-class-children-sym parent) tag) ;; Only register ourselves as a child of the leftmost parent since structs ;; can only only have one parent. @@ -110,6 +110,12 @@ ;;;###autoload (defun cl-struct-define (name docstring parent type named slots children-sym tag print) + (unless type + ;; Legacy defstruct, using tagged vectors. Enable backward compatibility. + (cl-old-struct-compat-mode 1)) + (if (eq type 'record) + ;; Defstruct using record objects. + (setq type nil)) (cl-assert (or type (not named))) (if (boundp children-sym) (add-to-list children-sym tag) @@ -150,7 +156,7 @@ parent name)))) (add-to-list 'current-load-list `(define-type . ,name)) (cl--struct-register-child parent-class tag) - (unless (eq named t) + (unless (or (eq named t) (eq tag name)) ;; We used to use `defconst' instead of `set' but that ;; has a side-effect of purecopying during the dump, so that the ;; class object stored in the tag ends up being a *copy* of the diff --git a/lisp/emacs-lisp/cl-print.el b/lisp/emacs-lisp/cl-print.el index b4ceefb9b1d..e9ca0412848 100644 --- a/lisp/emacs-lisp/cl-print.el +++ b/lisp/emacs-lisp/cl-print.el @@ -1,4 +1,4 @@ -;;; cl-print.el --- CL-style generic printer facilies -*- lexical-binding: t; -*- +;;; cl-print.el --- CL-style generic printing -*- lexical-binding: t; -*- ;; Copyright (C) 2017 Free Software Foundation, Inc. @@ -33,10 +33,13 @@ ;;; Code: +(require 'button) + (defvar cl-print-readably nil "If non-nil, try and make sure the result can be `read'.") (defvar cl-print--number-table nil) +(defvar cl-print--currently-printing nil) ;;;###autoload (cl-defgeneric cl-print-object (object stream) @@ -59,8 +62,9 @@ call other entry points instead, such as `cl-prin1'." (princ "(" stream) (cl-print-object car stream) (while (and (consp object) - (not (and cl-print--number-table - (numberp (gethash object cl-print--number-table))))) + (not (if cl-print--number-table + (numberp (gethash object cl-print--number-table)) + (memq object cl-print--currently-printing)))) (princ " " stream) (cl-print-object (pop object) stream)) (when object @@ -74,10 +78,69 @@ call other entry points instead, such as `cl-prin1'." (cl-print-object (aref object i) stream)) (princ "]" stream)) +(define-button-type 'help-byte-code + 'follow-link t + 'action (lambda (button) + (disassemble (button-get button 'byte-code-function))) + 'help-echo (purecopy "mouse-2, RET: disassemble this function")) + +(defvar cl-print-compiled nil + "Control how to print byte-compiled functions. Can be: +- `static' to print the vector of constants. +- `disassemble' to print the disassembly of the code. +- nil to skip printing any details about the code.") + +(defvar cl-print-compiled-button t + "Control how to print byte-compiled functions into buffers. +When the stream is a buffer, make the bytecode part of the output +into a button whose action shows the function's disassembly.") + +(autoload 'disassemble-1 "disass") + (cl-defmethod cl-print-object ((object compiled-function) stream) - (princ "#<compiled-function " stream) - (prin1 (help-function-arglist object 'preserve-names) stream) - (princ " #<bytecode> >" stream)) + (unless stream (setq stream standard-output)) + ;; We use "#f(...)" rather than "#<...>" so that pp.el gives better results. + (princ "#f(compiled-function " stream) + (let ((args (help-function-arglist object 'preserve-names))) + (if args + (prin1 args stream) + (princ "()" stream))) + (pcase (help-split-fundoc (documentation object 'raw) object) + ;; Drop args which `help-function-arglist' already printed. + (`(,_usage . ,(and doc (guard (stringp doc)))) + (princ " " stream) + (prin1 doc stream))) + (let ((inter (interactive-form object))) + (when inter + (princ " " stream) + (cl-print-object + (if (eq 'byte-code (car-safe (cadr inter))) + `(interactive ,(make-byte-code nil (nth 1 (cadr inter)) + (nth 2 (cadr inter)) + (nth 3 (cadr inter)))) + inter) + stream))) + (if (eq cl-print-compiled 'disassemble) + (princ + (with-temp-buffer + (insert "\n") + (disassemble-1 object 0) + (buffer-string)) + stream) + (princ " " stream) + (let ((button-start (and cl-print-compiled-button + (bufferp stream) + (with-current-buffer stream (point))))) + (princ "#<bytecode>" stream) + (when (eq cl-print-compiled 'static) + (princ " " stream) + (cl-print-object (aref object 2) stream)) + (when button-start + (with-current-buffer stream + (make-text-button button-start (point) + :type 'help-byte-code + 'byte-code-function object))))) + (princ ")" stream)) ;; This belongs in nadvice.el, of course, but some load-ordering issues make it ;; complicated: cl-generic uses macros from cl-macs and cl-macs uses advice-add @@ -87,7 +150,7 @@ call other entry points instead, such as `cl-prin1'." ((object compiled-function) stream) (if (not (advice--p object)) (cl-call-next-method) - (princ "#<advice-wrapper " stream) + (princ "#f(advice-wrapper " stream) (when (fboundp 'advice--where) (princ (advice--where object) stream) (princ " " stream)) @@ -98,11 +161,11 @@ call other entry points instead, such as `cl-prin1'." (when props (princ " " stream) (cl-print-object props stream))) - (princ ">" stream))) + (princ ")" stream))) (cl-defmethod cl-print-object ((object cl-structure-object) stream) (princ "#s(" stream) - (let* ((class (symbol-value (aref object 0))) + (let* ((class (cl-find-class (type-of object))) (slots (cl--struct-class-slots class))) (princ (cl--struct-class-name class) stream) (dotimes (i (length slots)) @@ -121,15 +184,26 @@ call other entry points instead, such as `cl-prin1'." (cl-defmethod cl-print-object :around (object stream) ;; FIXME: Only put such an :around method on types where it's relevant. - (let ((n (if cl-print--number-table (gethash object cl-print--number-table)))) - (if (not (numberp n)) - (cl-call-next-method) - (if (> n 0) - ;; Already printed. Just print a reference. - (progn (princ "#" stream) (princ n stream) (princ "#" stream)) - (puthash object (- n) cl-print--number-table) - (princ "#" stream) (princ (- n) stream) (princ "=" stream) - (cl-call-next-method))))) + (cond + (print-circle + (let ((n (gethash object cl-print--number-table))) + (if (not (numberp n)) + (cl-call-next-method) + (if (> n 0) + ;; Already printed. Just print a reference. + (progn (princ "#" stream) (princ n stream) (princ "#" stream)) + (puthash object (- n) cl-print--number-table) + (princ "#" stream) (princ (- n) stream) (princ "=" stream) + (cl-call-next-method))))) + ((let ((already-printing (memq object cl-print--currently-printing))) + (when already-printing + ;; Currently printing, just print reference to avoid endless + ;; recursion. + (princ "#" stream) + (princ (length (cdr already-printing)) stream)))) + (t (let ((cl-print--currently-printing + (cons object cl-print--currently-printing))) + (cl-call-next-method))))) (defvar cl-print--number-index nil) diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el index cb77148c285..2b8782590c4 100644 --- a/lisp/emacs-lisp/debug.el +++ b/lisp/emacs-lisp/debug.el @@ -49,6 +49,12 @@ the middle is discarded, and just the beginning and end are displayed." :group 'debugger :version "21.1") +(defcustom debugger-print-function #'cl-prin1 + "Function used to print values in the debugger backtraces." + :type 'function + :options '(cl-prin1 prin1) + :version "26.1") + (defcustom debugger-bury-or-kill 'bury "What to do with the debugger buffer when exiting `debug'. The value affects the behavior of operations on any window @@ -264,6 +270,40 @@ first will be printed into the backtrace buffer." (setq debug-on-next-call debugger-step-after-exit) debugger-value))) + +(defun debugger-insert-backtrace (frames do-xrefs) + "Format and insert the backtrace FRAMES at point. +Make functions into cross-reference buttons if DO-XREFS is non-nil." + (let ((standard-output (current-buffer)) + (eval-buffers eval-buffer-list)) + (require 'help-mode) ; Define `help-function-def' button type. + (pcase-dolist (`(,evald ,fun ,args ,flags) frames) + (insert (if (plist-get flags :debug-on-exit) + "* " " ")) + (let ((fun-file (and do-xrefs (symbol-file fun 'defun))) + (fun-pt (point))) + (cond + ((and evald (not debugger-stack-frame-as-list)) + (funcall debugger-print-function fun) + (if args (funcall debugger-print-function args) (princ "()"))) + (t + (funcall debugger-print-function (cons fun args)) + (cl-incf fun-pt))) + (when fun-file + (make-text-button fun-pt (+ fun-pt (length (symbol-name fun))) + :type 'help-function-def + 'help-args (list fun fun-file)))) + ;; After any frame that uses eval-buffer, insert a line that + ;; states the buffer position it's reading at. + (when (and eval-buffers (memq fun '(eval-buffer eval-region))) + (insert (format " ; Reading at buffer position %d" + ;; This will get the wrong result if there are + ;; two nested eval-region calls for the same + ;; buffer. That's not a very useful case. + (with-current-buffer (pop eval-buffers) + (point))))) + (insert "\n")))) + (defun debugger-setup-buffer (args) "Initialize the `*Backtrace*' buffer for entry to the debugger. That buffer should be current already." @@ -271,27 +311,20 @@ That buffer should be current already." (erase-buffer) (set-buffer-multibyte t) ;Why was it nil ? -stef (setq buffer-undo-list t) - (let ((standard-output (current-buffer)) - (print-escape-newlines t) - (print-level 8) - (print-length 50)) - ;; FIXME the debugger could pass a custom callback to mapbacktrace - ;; instead of manipulating printed results. - (mapbacktrace #'backtrace--print-frame 'debug)) - (goto-char (point-min)) - (delete-region (point) - (progn - (forward-line (if (eq (car args) 'debug) - ;; Remove debug--implement-debug-on-entry - ;; and the advice's `apply' frame. - 3 - 1)) - (point))) (insert "Debugger entered") - ;; lambda is for debug-on-call when a function call is next. - ;; debug is for debug-on-entry function called. - (let ((pos (point))) + (let ((frames (nthcdr + ;; Remove debug--implement-debug-on-entry and the + ;; advice's `apply' frame. + (if (eq (car args) 'debug) 3 1) + (backtrace-frames 'debug))) + (print-escape-newlines t) + (print-escape-control-characters t) + (print-level 8) + (print-length 50) + (pos (point))) (pcase (car args) + ;; lambda is for debug-on-call when a function call is next. + ;; debug is for debug-on-entry function called. ((or `lambda `debug) (insert "--entering a function:\n") (setq pos (1- (point)))) @@ -300,11 +333,9 @@ That buffer should be current already." (insert "--returning value: ") (setq pos (point)) (setq debugger-value (nth 1 args)) - (prin1 debugger-value (current-buffer)) - (insert ?\n) - (delete-char 1) - (insert ? ) - (beginning-of-line)) + (funcall debugger-print-function debugger-value (current-buffer)) + (setf (cl-getf (nth 3 (car frames)) :debug-on-exit) nil) + (insert ?\n)) ;; Watchpoint triggered. ((and `watchpoint (let `(,symbol ,newval . ,details) (cdr args))) (insert @@ -327,7 +358,7 @@ That buffer should be current already." (`error (insert "--Lisp error: ") (setq pos (point)) - (prin1 (nth 1 args) (current-buffer)) + (funcall debugger-print-function (nth 1 args) (current-buffer)) (insert ?\n)) ;; debug-on-call, when the next thing is an eval. (`t @@ -337,98 +368,15 @@ That buffer should be current already." (_ (insert ": ") (setq pos (point)) - (prin1 (if (eq (car args) 'nil) - (cdr args) args) - (current-buffer)) + (funcall debugger-print-function + (if (eq (car args) 'nil) + (cdr args) args) + (current-buffer)) (insert ?\n))) + (debugger-insert-backtrace frames t) ;; Place point on "stack frame 0" (bug#15101). - (goto-char pos)) - ;; After any frame that uses eval-buffer, - ;; insert a line that states the buffer position it's reading at. - (save-excursion - (let ((tem eval-buffer-list)) - (while (and tem - (re-search-forward "^ eval-\\(buffer\\|region\\)(" nil t)) - (end-of-line) - (insert (format " ; Reading at buffer position %d" - ;; This will get the wrong result - ;; if there are two nested eval-region calls - ;; for the same buffer. That's not a very useful case. - (with-current-buffer (car tem) - (point)))) - (pop tem)))) - (debugger-make-xrefs)) - -(defun debugger-make-xrefs (&optional buffer) - "Attach cross-references to function names in the `*Backtrace*' buffer." - (interactive "b") - (with-current-buffer (or buffer (current-buffer)) - (save-excursion - (setq buffer (current-buffer)) - (let ((inhibit-read-only t) - (old-end (point-min)) (new-end (point-min))) - ;; If we saved an old backtrace, find the common part - ;; between the new and the old. - ;; Compare line by line, starting from the end, - ;; because that's the part that is likely to be unchanged. - (if debugger-previous-backtrace - (let (old-start new-start (all-match t)) - (goto-char (point-max)) - (with-temp-buffer - (insert debugger-previous-backtrace) - (while (and all-match (not (bobp))) - (setq old-end (point)) - (forward-line -1) - (setq old-start (point)) - (with-current-buffer buffer - (setq new-end (point)) - (forward-line -1) - (setq new-start (point))) - (if (not (zerop - (let ((case-fold-search nil)) - (compare-buffer-substrings - (current-buffer) old-start old-end - buffer new-start new-end)))) - (setq all-match nil)))) - ;; Now new-end is the position of the start of the - ;; unchanged part in the current buffer, and old-end is - ;; the position of that same text in the saved old - ;; backtrace. But we must subtract (point-min) since strings are - ;; indexed in origin 0. - - ;; Replace the unchanged part of the backtrace - ;; with the text from debugger-previous-backtrace, - ;; since that already has the proper xrefs. - ;; With this optimization, we only need to scan - ;; the changed part of the backtrace. - (delete-region new-end (point-max)) - (goto-char (point-max)) - (insert (substring debugger-previous-backtrace - (- old-end (point-min)))) - ;; Make the unchanged part of the backtrace inaccessible - ;; so it won't be scanned. - (narrow-to-region (point-min) new-end))) - - ;; Scan the new part of the backtrace, inserting xrefs. - (goto-char (point-min)) - (while (progn - (goto-char (+ (point) 2)) - (skip-syntax-forward "^w_") - (not (eobp))) - (let* ((beg (point)) - (end (progn (skip-syntax-forward "w_") (point))) - (sym (intern-soft (buffer-substring-no-properties - beg end))) - (file (and sym (symbol-file sym 'defun)))) - (when file - (goto-char beg) - ;; help-xref-button needs to operate on something matched - ;; by a regexp, so set that up for it. - (re-search-forward "\\(\\sw\\|\\s_\\)+") - (help-xref-button 0 'help-function-def sym file))) - (forward-line 1)) - (widen)) - (setq debugger-previous-backtrace (buffer-string))))) + (goto-char pos))) + (defun debugger-step-through () "Proceed, stepping through subexpressions of this expression. @@ -727,6 +675,9 @@ Complete list of commands: \\{debugger-mode-map}" (setq truncate-lines t) (set-syntax-table emacs-lisp-mode-syntax-table) + (add-hook 'kill-buffer-hook + (lambda () (if (> (recursion-depth) 0) (top-level))) + nil t) (use-local-map debugger-mode-map)) (defcustom debugger-record-buffer "*Debugger-record*" @@ -863,9 +814,13 @@ To specify a nil argument interactively, exit with an empty minibuffer." 'type 'help-function 'help-args (list fun)) (terpri)) - (terpri) - (princ "Note: if you have redefined a function, then it may no longer\n") - (princ "be set to debug on entry, even if it is in the list.")))))) + ;; Now that debug--function-list uses advice-member-p, its + ;; output should be reliable (except for bugs and the exceptional + ;; case where some other advice ends up overriding ours). + ;;(terpri) + ;;(princ "Note: if you have redefined a function, then it may no longer\n") + ;;(princ "be set to debug on entry, even if it is in the list.") + ))))) (defun debug--implement-debug-watch (symbol newval op where) "Conditionally call the debugger. diff --git a/lisp/emacs-lisp/easymenu.el b/lisp/emacs-lisp/easymenu.el index 603bbcd9426..4fc9a783a5e 100644 --- a/lisp/emacs-lisp/easymenu.el +++ b/lisp/emacs-lisp/easymenu.el @@ -489,7 +489,7 @@ To implement dynamic menus, either call this from ;; XEmacs needs the following two functions to add and remove menus. ;; In Emacs this is done automatically when switching keymaps, so -;; here easy-menu-remove is a noop. +;; here easy-menu-remove and easy-menu-add are a noops. (defalias 'easy-menu-remove 'ignore "Remove MENU from the current menu bar. Contrary to XEmacs, this is a nop on Emacs since menus are automatically @@ -497,15 +497,16 @@ Contrary to XEmacs, this is a nop on Emacs since menus are automatically \(fn MENU)") -(defun easy-menu-add (_menu &optional _map) +(defalias 'easy-menu-add #'ignore "Add the menu to the menubar. -On Emacs, menus are already automatically activated when the -corresponding keymap is activated. On XEmacs this is needed to -actually add the menu to the current menubar. +On Emacs this is a nop, because menus are already automatically +activated when the corresponding keymap is activated. On XEmacs +this is needed to actually add the menu to the current menubar. You should call this once the menu and keybindings are set up -completely and menu filter functions can be expected to work." - ) +completely and menu filter functions can be expected to work. + +\(fn MENU &optional MAP)") (defun add-submenu (menu-path submenu &optional before in-menu) "Add submenu SUBMENU in the menu at MENU-PATH. diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index 60133055623..1494ed1d9c3 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el @@ -733,9 +733,9 @@ Maybe clear the markers and delete the symbol's edebug property?" ((eq class 'string) (read (current-buffer))) ((eq class 'quote) (forward-char 1) (list 'quote (edebug-read-sexp))) - ((eq class 'backquote) + ((eq class 'backquote) (forward-char 1) (list '\` (edebug-read-sexp))) - ((eq class 'comma) + ((eq class 'comma) (forward-char 1) (list '\, (edebug-read-sexp))) (t ; anything else, just read it. (read (current-buffer)))))) @@ -906,7 +906,7 @@ circular objects. Let `read' read everything else." ;; with the object itself, wherever it occurs. (forward-char 1) (let ((obj (edebug-read-storing-offsets stream))) - (substitute-object-in-subtree obj placeholder) + (lread--substitute-object-in-subtree obj placeholder t) (throw 'return (setf (cdr elem) obj))))) ((eq ?# (following-char)) ;; #n# returns a previously read object. @@ -1607,6 +1607,7 @@ expressions; a `progn' form will be returned enclosing these forms." ;; Less frequently used: ;; (function . edebug-match-function) (lambda-expr . edebug-match-lambda-expr) + (cl-generic-method-args . edebug-match-cl-generic-method-args) (¬ . edebug-match-¬) (&key . edebug-match-&key) (place . edebug-match-place) @@ -1900,6 +1901,16 @@ expressions; a `progn' form will be returned enclosing these forms." spec)) nil) +(defun edebug-match-cl-generic-method-args (cursor) + (let ((args (edebug-top-element-required cursor "Expected arguments"))) + (if (not (consp args)) + (edebug-no-match cursor "List expected")) + ;; Append the arguments to edebug-def-name. + (setq edebug-def-name + (intern (format "%s %s" edebug-def-name args))) + (edebug-move-cursor cursor) + (list args))) + (defun edebug-match-arg (cursor) ;; set the def-args bound in edebug-defining-form (let ((edebug-arg (edebug-top-element-required cursor "Expected arg"))) @@ -3186,8 +3197,11 @@ go to the end of the last sexp, or if that is the same point, then step." ))))) (defun edebug-instrument-function (func) - ;; Func should be a function symbol. - ;; Return the function symbol, or nil if not instrumented. + "Instrument the function or generic method FUNC. +Return the list of function symbols which were instrumented. +This may be simply (FUNC) for a normal function, or a list of +generated symbols for methods. If a function or method to +instrument cannot be found, signal an error." (let ((func-marker (get func 'edebug))) (cond ((and (markerp func-marker) (marker-buffer func-marker)) @@ -3195,10 +3209,24 @@ go to the end of the last sexp, or if that is the same point, then step." (with-current-buffer (marker-buffer func-marker) (goto-char func-marker) (edebug-eval-top-level-form) - func)) + (list func))) ((consp func-marker) (message "%s is already instrumented." func) - func) + (list func)) + ((get func 'cl--generic) + (let ((method-defs (method-files func)) + symbols) + (unless method-defs + (error "Could not find any method definitions for %s" func)) + (pcase-dolist (`(,file . ,spec) method-defs) + (let* ((loc (find-function-search-for-symbol spec 'cl-defmethod file))) + (unless (cdr loc) + (error "Could not find the definition for %s in its file" spec)) + (with-current-buffer (car loc) + (goto-char (cdr loc)) + (edebug-eval-top-level-form) + (push (edebug-form-data-symbol) symbols)))) + symbols)) (t (let ((loc (find-function-noselect func t))) (unless (cdr loc) @@ -3206,13 +3234,16 @@ go to the end of the last sexp, or if that is the same point, then step." (with-current-buffer (car loc) (goto-char (cdr loc)) (edebug-eval-top-level-form) - func)))))) + (list func))))))) (defun edebug-instrument-callee () "Instrument the definition of the function or macro about to be called. Do this when stopped before the form or it will be too late. One side effect of using this command is that the next time the -function or macro is called, Edebug will be called there as well." +function or macro is called, Edebug will be called there as well. +If the callee is a generic function, Edebug will instrument all +the methods, not just the one which is about to be called. Return +the list of symbols which were instrumented." (interactive) (if (not (looking-at "(")) (error "You must be before a list form") @@ -3227,15 +3258,15 @@ function or macro is called, Edebug will be called there as well." (defun edebug-step-in () - "Step into the definition of the function or macro about to be called. + "Step into the definition of the function, macro or method about to be called. This first does `edebug-instrument-callee' to ensure that it is instrumented. Then it does `edebug-on-entry' and switches to `go' mode." (interactive) - (let ((func (edebug-instrument-callee))) - (if func + (let ((funcs (edebug-instrument-callee))) + (if funcs (progn - (edebug-on-entry func 'temp) - (edebug-go-mode nil))))) + (mapc (lambda (func) (edebug-on-entry func 'temp)) funcs) + (edebug-go-mode nil))))) (defun edebug-on-entry (function &optional flag) "Cause Edebug to stop when FUNCTION is called. diff --git a/lisp/emacs-lisp/eieio-base.el b/lisp/emacs-lisp/eieio-base.el index 986d0285172..33c71ec5807 100644 --- a/lisp/emacs-lisp/eieio-base.el +++ b/lisp/emacs-lisp/eieio-base.el @@ -294,8 +294,7 @@ Second, any text properties will be stripped from strings." (cond ((consp proposed-value) ;; Lists with something in them need special treatment. (let* ((slot-idx (- (eieio--slot-name-index class slot) - (eval-when-compile - (length (cl-struct-slot-info 'eieio--object))))) + (eval-when-compile eieio--object-num-slots))) (type (cl--slot-descriptor-type (aref (eieio--class-slots class) slot-idx))) (classtype (eieio-persistent-slot-type-is-class-p type))) diff --git a/lisp/emacs-lisp/eieio-compat.el b/lisp/emacs-lisp/eieio-compat.el index 888d85f6038..e6e6d118709 100644 --- a/lisp/emacs-lisp/eieio-compat.el +++ b/lisp/emacs-lisp/eieio-compat.el @@ -105,10 +105,10 @@ Summary: (declare (doc-string 3) (obsolete cl-defmethod "25.1") (debug (&define ; this means we are defining something - [&or name ("setf" :name setf name)] + [&or name ("setf" name :name setf)] ;; ^^ This is the methods symbol [ &optional symbolp ] ; this is key :before etc - list ; arguments + cl-generic-method-args ; arguments [ &optional stringp ] ; documentation string def-body ; part to be debugged ))) @@ -145,7 +145,7 @@ Summary: ;; interleaved list comes before the class's non-interleaved list. 51 #'cl--generic-struct-tag (lambda (tag &rest _) - (and (symbolp tag) (boundp tag) (setq tag (symbol-value tag)) + (and (symbolp tag) (setq tag (cl--find-class tag)) (eieio--class-p tag) (let ((superclasses (eieio--class-precedence-list tag)) (specializers ())) diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el index 5cc6d020eaf..9d618e1dc81 100644 --- a/lisp/emacs-lisp/eieio-core.el +++ b/lisp/emacs-lisp/eieio-core.el @@ -32,8 +32,7 @@ ;;; Code: (require 'cl-lib) -(require 'pcase) -(require 'eieio-loaddefs) +(require 'eieio-loaddefs nil t) ;;; ;; A few functions that are better in the official EIEIO src, but @@ -85,7 +84,7 @@ Currently under control of this var: (progn ;; Arrange for field access not to bother checking if the access is indeed ;; made to an eieio--class object. - (cl-declaim (optimize (safety 0))) + (eval-when-compile (cl-declaim (optimize (safety 0)))) (cl-defstruct (eieio--class (:constructor nil) @@ -104,25 +103,22 @@ Currently under control of this var: options ;; storage location of tagged class option ; Stored outright without modifications or stripping ) - ;; Set it back to the default value. - (cl-declaim (optimize (safety 1)))) + ;; Set it back to the default value. NOTE: Using the default + ;; `safety' value does NOT give the default + ;; `byte-compile-delete-errors' value. Therefore limit this (and + ;; the above `cl-declaim') to compile time so that we don't affect + ;; code which only loads this library. + (eval-when-compile (cl-declaim (optimize (safety 1))))) -(cl-defstruct (eieio--object - (:type vector) ;We manage our own tagging system. - (:constructor nil) - (:copier nil)) - ;; `class-tag' holds a symbol, which is not the class name, but is instead - ;; properly prefixed as an internal EIEIO thingy and which holds the class - ;; object/struct in its `symbol-value' slot. - class-tag) +(eval-and-compile + (defconst eieio--object-num-slots 1)) -(eval-when-compile - (defconst eieio--object-num-slots - (length (cl-struct-slot-info 'eieio--object)))) +(defsubst eieio--object-class-tag (obj) + (aref obj 0)) (defsubst eieio--object-class (obj) - (symbol-value (eieio--object-class-tag obj))) + (eieio--object-class-tag obj)) ;;; Important macros used internally in eieio. @@ -166,13 +162,8 @@ Return nil if that option doesn't exist." (defun eieio-object-p (obj) "Return non-nil if OBJ is an EIEIO object." - (and (vectorp obj) - (> (length obj) 0) - (let ((tag (eieio--object-class-tag obj))) - (and (symbolp tag) - ;; (eq (symbol-function tag) :quick-object-witness-check) - (boundp tag) - (eieio--class-p (symbol-value tag)))))) + (and (recordp obj) + (eieio--class-p (eieio--object-class-tag obj)))) (define-obsolete-function-alias 'object-p 'eieio-object-p "25.1") @@ -496,18 +487,11 @@ See `defclass' for more information." (if clearparent (setf (eieio--class-parents newc) nil)) ;; Create the cached default object. - (let ((cache (make-vector (+ (length (eieio--class-slots newc)) - (eval-when-compile eieio--object-num-slots)) - nil)) - ;; We don't strictly speaking need to use a symbol, but the old - ;; code used the class's name rather than the class's object, so - ;; we follow this preference for using a symbol, which is probably - ;; convenient to keep the printed representation of such Elisp - ;; objects readable. - (tag (intern (format "eieio-class-tag--%s" cname)))) - (set tag newc) - (fset tag :quick-object-witness-check) - (setf (eieio--object-class-tag cache) tag) + (let ((cache (make-record newc + (+ (length (eieio--class-slots newc)) + (eval-when-compile eieio--object-num-slots) + -1) + nil))) (let ((eieio-skip-typecheck t)) ;; All type-checking has been done to our satisfaction ;; before this call. Don't waste our time in this call.. @@ -1060,9 +1044,10 @@ method invocation orders of the involved classes." ;; part of the dispatch code. 50 #'cl--generic-struct-tag (lambda (tag &rest _) - (and (symbolp tag) (boundp tag) (eieio--class-p (symbol-value tag)) - (mapcar #'eieio--class-name - (eieio--class-precedence-list (symbol-value tag)))))) + (let ((class (cl--find-class tag))) + (and (eieio--class-p class) + (mapcar #'eieio--class-name + (eieio--class-precedence-list class)))))) (cl-defmethod cl-generic-generalizers :extra "class" (specializer) "Support for dispatch on types defined by EIEIO's `defclass'." diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el index 1a6d5e9d7c1..1a7de55fcef 100644 --- a/lisp/emacs-lisp/eieio.el +++ b/lisp/emacs-lisp/eieio.el @@ -235,7 +235,7 @@ This method is obsolete." (let ((f (intern (format "%s-child-p" name)))) `((defalias ',f ',testsym2) (make-obsolete - ',f ,(format "use (cl-typep ... '%s) instead" name) + ',f ,(format "use (cl-typep ... \\='%s) instead" name) "25.1")))) ;; When using typep, (typep OBJ 'myclass) returns t for objects which @@ -337,14 +337,12 @@ variable name of the same name as the slot." ;; hard-coded in random .elc files. (defun eieio-pcase-slot-index-table (obj) "Return some data structure from which can be extracted the slot offset." - (eieio--class-index-table - (symbol-value (eieio--object-class-tag obj)))) + (eieio--class-index-table (eieio--object-class obj))) (defun eieio-pcase-slot-index-from-index-table (index-table slot) "Find the index to pass to `aref' to access SLOT." (let ((index (gethash slot index-table))) - (if index (+ (eval-when-compile - (length (cl-struct-slot-info 'eieio--object))) + (if index (+ (eval-when-compile eieio--object-num-slots) index)))) (pcase-defmacro eieio (&rest fields) diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el index 6cb8e6ce480..a05bd7cc4d4 100644 --- a/lisp/emacs-lisp/eldoc.el +++ b/lisp/emacs-lisp/eldoc.el @@ -186,8 +186,9 @@ expression point is on." :group 'eldoc :lighter eldoc-minor-mode-string (setq eldoc-last-message nil) (cond - ((memq eldoc-documentation-function '(nil ignore)) - (message "There is no ElDoc support in this buffer") + ((not (eldoc--supported-p)) + (when (called-interactively-p 'any) + (message "There is no ElDoc support in this buffer")) (setq eldoc-mode nil)) (eldoc-mode (when eldoc-print-after-edit @@ -203,29 +204,20 @@ expression point is on." (setq eldoc-timer nil))))) ;;;###autoload -(define-minor-mode global-eldoc-mode - "Toggle Global Eldoc mode on or off. -With a prefix argument ARG, enable Global Eldoc mode if ARG is -positive, and disable it otherwise. If called from Lisp, enable -the mode if ARG is omitted or nil, and toggle it if ARG is ‘toggle’. - -If Global Eldoc mode is on, `eldoc-mode' will be enabled in all -buffers where it's applicable. These are buffers that have modes -that have enabled eldoc support. See `eldoc-documentation-function'." +(define-globalized-minor-mode global-eldoc-mode eldoc-mode turn-on-eldoc-mode :group 'eldoc - :global t :initialize 'custom-initialize-delay - :init-value t - (setq eldoc-last-message nil) - (if global-eldoc-mode - (progn - (add-hook 'post-command-hook #'eldoc-schedule-timer) - (add-hook 'pre-command-hook #'eldoc-pre-command-refresh-echo-area)) - (remove-hook 'post-command-hook #'eldoc-schedule-timer) - (remove-hook 'pre-command-hook #'eldoc-pre-command-refresh-echo-area))) + :init-value t) ;;;###autoload -(define-obsolete-function-alias 'turn-on-eldoc-mode 'eldoc-mode "24.4") +(defun turn-on-eldoc-mode () + "Turn on `eldoc-mode' if the buffer has eldoc support enabled. +See `eldoc-documentation-function' for more detail." + (when (eldoc--supported-p) + (eldoc-mode 1))) + +(defun eldoc--supported-p () + (not (memq eldoc-documentation-function '(nil ignore)))) (defun eldoc-schedule-timer () @@ -426,7 +418,7 @@ return any documentation.") "down-list" "end-of-" "exchange-point-and-mark" "forward-" "goto-" "handle-select-window" "indent-for-tab-command" "left-" "mark-page" "mark-paragraph" "mouse-set-point" "move-" "move-beginning-of-" - "move-end-of-" "next-" "other-window" "pop-global-mark" "previous-" + "move-end-of-" "newline" "next-" "other-window" "pop-global-mark" "previous-" "recenter" "right-" "scroll-" "self-insert-command" "split-window-" "up-list") diff --git a/lisp/emacs-lisp/elint.el b/lisp/emacs-lisp/elint.el index a14bd0d7643..cce9553ff6a 100644 --- a/lisp/emacs-lisp/elint.el +++ b/lisp/emacs-lisp/elint.el @@ -105,7 +105,7 @@ are as follows, and suppress messages about the indicated features: :version "23.2" :group 'elint) -(defcustom elint-directory-skip-re "\\(ldefs-boot.*\\|loaddefs\\)\\.el\\'" +(defcustom elint-directory-skip-re "\\(ldefs-boot\\|loaddefs\\)\\.el\\'" "If nil, a regexp matching files to skip when linting a directory." :type '(choice (const :tag "Lint all files" nil) (regexp :tag "Regexp to skip")) diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el index 785f4aca1cc..eb2b2e3e11b 100644 --- a/lisp/emacs-lisp/ert.el +++ b/lisp/emacs-lisp/ert.el @@ -276,7 +276,8 @@ DATA is displayed to the user and should state the reason for skipping." (defun ert--expand-should-1 (whole form inner-expander) "Helper function for the `should' macro and its variants." (let ((form - (macroexpand form (append byte-compile-macro-environment + (macroexpand form (append (bound-and-true-p + byte-compile-macro-environment) (cond ((boundp 'macroexpand-all-environment) macroexpand-all-environment) @@ -669,48 +670,12 @@ and is displayed in front of the value of MESSAGE-FORM." (cl-defstruct (ert-test-aborted-with-non-local-exit (:include ert-test-result))) - -(defun ert--record-backtrace () - "Record the current backtrace (as a list) and return it." - ;; Since the backtrace is stored in the result object, result - ;; objects must only be printed with appropriate limits - ;; (`print-level' and `print-length') in place. For interactive - ;; use, the cost of ensuring this possibly outweighs the advantage - ;; of storing the backtrace for - ;; `ert-results-pop-to-backtrace-for-test-at-point' given that we - ;; already have `ert-results-rerun-test-debugging-errors-at-point'. - ;; For batch use, however, printing the backtrace may be useful. - (cl-loop - ;; 6 is the number of frames our own debugger adds (when - ;; compiled; more when interpreted). FIXME: Need to describe a - ;; procedure for determining this constant. - for i from 6 - for frame = (backtrace-frame i) - while frame - collect frame)) - -(defun ert--print-backtrace (backtrace) +(defun ert--print-backtrace (backtrace do-xrefs) "Format the backtrace BACKTRACE to the current buffer." - ;; This is essentially a reimplementation of Fbacktrace - ;; (src/eval.c), but for a saved backtrace, not the current one. (let ((print-escape-newlines t) (print-level 8) (print-length 50)) - (dolist (frame backtrace) - (pcase-exhaustive frame - (`(nil ,special-operator . ,arg-forms) - ;; Special operator. - (insert - (format " %S\n" (cons special-operator arg-forms)))) - (`(t ,fn . ,args) - ;; Function call. - (insert (format " %S(" fn)) - (cl-loop for firstp = t then nil - for arg in args do - (unless firstp - (insert " ")) - (insert (format "%S" arg))) - (insert ")\n")))))) + (debugger-insert-backtrace backtrace do-xrefs))) ;; A container for the state of the execution of a single test and ;; environment data needed during its execution. @@ -749,7 +714,19 @@ run. ARGS are the arguments to `debugger'." ((quit) 'quit) ((ert-test-skipped) 'skipped) (otherwise 'failed))) - (backtrace (ert--record-backtrace)) + ;; We store the backtrace in the result object for + ;; `ert-results-pop-to-backtrace-for-test-at-point'. + ;; This means we have to limit `print-level' and + ;; `print-length' when printing result objects. That + ;; might not be worth while when we can also use + ;; `ert-results-rerun-test-debugging-errors-at-point', + ;; (i.e., when running interactively) but having the + ;; backtrace ready for printing is important for batch + ;; use. + ;; + ;; Grab the frames starting from `signal', frames below + ;; that are all from the debugger. + (backtrace (backtrace-frames 'signal)) (infos (reverse ert--infos))) (setf (ert--test-execution-info-result info) (cl-ecase type @@ -1236,7 +1213,7 @@ SELECTOR is the selector that was used to select TESTS." (funcall listener 'test-ended stats test result)) (setf (ert--stats-current-test stats) nil)))) -(defun ert-run-tests (selector listener) +(defun ert-run-tests (selector listener &optional interactively) "Run the tests specified by SELECTOR, sending progress updates to LISTENER." (let* ((tests (ert-select-tests selector t)) (stats (ert--make-stats tests selector))) @@ -1247,10 +1224,14 @@ SELECTOR is the selector that was used to select TESTS." (let ((ert--current-run-stats stats)) (force-mode-line-update) (unwind-protect - (progn - (cl-loop for test in tests do - (ert-run-or-rerun-test stats test listener)) - (setq abortedp nil)) + (cl-loop for test in tests do + (ert-run-or-rerun-test stats test listener) + (when (and interactively + (ert-test-quit-p + (ert-test-most-recent-result test)) + (y-or-n-p "Abort testing? ")) + (cl-return)) + finally (setq abortedp nil)) (setf (ert--stats-aborted-p stats) abortedp) (setf (ert--stats-end-time stats) (current-time)) (funcall listener 'run-ended stats abortedp))) @@ -1404,8 +1385,9 @@ Returns the stats object." (ert-test-result-with-condition (message "Test %S backtrace:" (ert-test-name test)) (with-temp-buffer - (ert--print-backtrace (ert-test-result-with-condition-backtrace - result)) + (ert--print-backtrace + (ert-test-result-with-condition-backtrace result) + nil) (goto-char (point-min)) (while (not (eobp)) (let ((start (point)) @@ -1442,7 +1424,8 @@ Returns the stats object." (ert-test-result-expected-p test result)) (1+ (ert--stats-test-pos stats test)) - (ert-test-name test))))))))) + (ert-test-name test))))))) + nil)) ;;;###autoload (defun ert-run-tests-batch-and-exit (&optional selector) @@ -1452,6 +1435,12 @@ The exit status will be 0 if all test results were as expected, 1 on unexpected results, or 2 if the tool detected an error outside of the tests (e.g. invalid SELECTOR or bug in the code that runs the tests)." + (or noninteractive + (user-error "This function is only for use in batch mode")) + ;; Better crash loudly than attempting to recover from undefined + ;; behavior. + (setq attempt-stack-overflow-recovery nil + attempt-orderly-shutdown-on-fatal-signal nil) (unwind-protect (let ((stats (ert-run-tests-batch selector))) (kill-emacs (if (zerop (ert-stats-completed-unexpected stats)) 0 1))) @@ -1469,13 +1458,17 @@ The logfiles should have the `ert-run-tests-batch' format. When finished, this exits Emacs, with status as per `ert-run-tests-batch-and-exit'." (or noninteractive (user-error "This function is only for use in batch mode")) + ;; Better crash loudly than attempting to recover from undefined + ;; behavior. + (setq attempt-stack-overflow-recovery nil + attempt-orderly-shutdown-on-fatal-signal nil) (let ((nlogs (length command-line-args-left)) (ntests 0) (nrun 0) (nexpected 0) (nunexpected 0) (nskipped 0) nnotrun logfile notests badtests unexpected skipped) (with-temp-buffer (while (setq logfile (pop command-line-args-left)) (erase-buffer) - (insert-file-contents logfile) + (when (file-readable-p logfile) (insert-file-contents logfile)) (if (not (re-search-forward "^Running \\([0-9]+\\) tests" nil t)) (push logfile notests) (setq ntests (+ ntests (string-to-number (match-string 1)))) @@ -1597,7 +1590,7 @@ Signals an error if no test name was read." (let ((sym (intern-soft input))) (if (ert-test-boundp sym) sym - (error "Input does not name a test"))))) + (user-error "Input does not name a test"))))) (defun ert-read-test-name-at-point (prompt) "Read the name of a test and return it as a symbol. @@ -1623,7 +1616,7 @@ Nothing more than an interactive interface to `ert-make-test-unbound'." (interactive) (when (called-interactively-p 'any) (unless (y-or-n-p "Delete all tests? ") - (error "Aborted"))) + (user-error "Aborted"))) ;; We can't use `ert-select-tests' here since that gives us only ;; test objects, and going from them back to the test name symbols ;; can fail if the `ert-test' defstruct has been redefined. @@ -1812,12 +1805,23 @@ EWOC and STATS are arguments for `ert--results-update-stats-display'." BEGIN and END specify a region in the current buffer." (save-excursion - (save-restriction - (narrow-to-region begin end) - ;; Inhibit optimization in `debugger-make-xrefs' that would - ;; sometimes insert unrelated backtrace info into our buffer. - (let ((debugger-previous-backtrace nil)) - (debugger-make-xrefs))))) + (goto-char begin) + (while (progn + (goto-char (+ (point) 2)) + (skip-syntax-forward "^w_") + (< (point) end)) + (let* ((beg (point)) + (end (progn (skip-syntax-forward "w_") (point))) + (sym (intern-soft (buffer-substring-no-properties + beg end))) + (file (and sym (symbol-file sym 'defun)))) + (when file + (goto-char beg) + ;; help-xref-button needs to operate on something matched + ;; by a regexp, so set that up for it. + (re-search-forward "\\(\\sw\\|\\s_\\)+") + (help-xref-button 0 'help-function-def sym file))) + (forward-line 1)))) (defun ert--string-first-line (s) "Return the first line of S, or S if it contains no newlines. @@ -2033,9 +2037,8 @@ and how to display message." test result))) (ert--results-update-stats-display-maybe ewoc stats) (ewoc-invalidate ewoc node)))))))) - (ert-run-tests - selector - listener))) + (ert-run-tests selector listener t))) + ;;;###autoload (defalias 'ert 'ert-run-tests-interactively) @@ -2079,14 +2082,23 @@ and how to display message." '("ERT Results" ["Re-run all tests" ert-results-rerun-all-tests] "--" - ["Re-run test" ert-results-rerun-test-at-point] - ["Debug test" ert-results-rerun-test-at-point-debugging-errors] - ["Show test definition" ert-results-find-test-at-point-other-window] + ;; FIXME? Why are there (at least) 3 different ways to decide if + ;; there is a test at point? + ["Re-run test" ert-results-rerun-test-at-point + :active (car (ert--results-test-at-point-allow-redefinition))] + ["Debug test" ert-results-rerun-test-at-point-debugging-errors + :active (car (ert--results-test-at-point-allow-redefinition))] + ["Show test definition" ert-results-find-test-at-point-other-window + :active (ert-test-at-point)] "--" - ["Show backtrace" ert-results-pop-to-backtrace-for-test-at-point] - ["Show messages" ert-results-pop-to-messages-for-test-at-point] - ["Show `should' forms" ert-results-pop-to-should-forms-for-test-at-point] - ["Describe test" ert-results-describe-test-at-point] + ["Show backtrace" ert-results-pop-to-backtrace-for-test-at-point + :active (ert--results-test-at-point-no-redefinition)] + ["Show messages" ert-results-pop-to-messages-for-test-at-point + :active (ert--results-test-at-point-no-redefinition)] + ["Show `should' forms" ert-results-pop-to-should-forms-for-test-at-point + :active (ert--results-test-at-point-no-redefinition)] + ["Describe test" ert-results-describe-test-at-point + :active (ert--results-test-at-point-no-redefinition)] "--" ["Delete test" ert-delete-test] "--" @@ -2128,7 +2140,7 @@ To be used in the ERT results buffer." To be used in the ERT results buffer." (or (ert--results-test-node-or-null-at-point) - (error "No test at point"))) + (user-error "No test at point"))) (defun ert-results-next-test () "Move point to the next test. @@ -2178,7 +2190,7 @@ To be used in the ERT results buffer." (interactive) (let ((name (ert-test-at-point))) (unless name - (error "No test at point")) + (user-error "No test at point")) (ert-find-test-other-window name))) (defun ert--test-name-button-action (button) @@ -2237,22 +2249,24 @@ To be used in the ERT results buffer." (and (ert-test-boundp sym) sym)))) -(defun ert--results-test-at-point-no-redefinition () +(defun ert--results-test-at-point-no-redefinition (&optional error) "Return the test at point, or nil. - +If optional argument ERROR is non-nil, signal an error rather than return nil. To be used in the ERT results buffer." (cl-assert (eql major-mode 'ert-results-mode)) - (if (ert--results-test-node-or-null-at-point) - (let* ((node (ert--results-test-node-at-point)) - (test (ert--ewoc-entry-test (ewoc-data node)))) - test) - (let ((progress-bar-begin ert--results-progress-bar-button-begin)) - (when (and (<= progress-bar-begin (point)) - (< (point) (button-end (button-at progress-bar-begin)))) - (let* ((test-index (- (point) progress-bar-begin)) - (test (aref (ert--stats-tests ert--results-stats) + (or + (if (ert--results-test-node-or-null-at-point) + (let* ((node (ert--results-test-node-at-point)) + (test (ert--ewoc-entry-test (ewoc-data node)))) + test) + (let ((progress-bar-begin ert--results-progress-bar-button-begin)) + (when (and (<= progress-bar-begin (point)) + (< (point) (button-end (button-at progress-bar-begin)))) + (let* ((test-index (- (point) progress-bar-begin)) + (test (aref (ert--stats-tests ert--results-stats) test-index))) - test))))) + test)))) + (if error (user-error "No test at point")))) (defun ert--results-test-at-point-allow-redefinition () "Look up the test at point, and check whether it has been redefined. @@ -2337,7 +2351,7 @@ To be used in the ERT results buffer." (cl-destructuring-bind (test redefinition-state) (ert--results-test-at-point-allow-redefinition) (when (null test) - (error "No test at point")) + (user-error "No test at point")) (let* ((stats ert--results-stats) (progress-message (format "Running %stest %S" (cl-ecase redefinition-state @@ -2377,7 +2391,7 @@ To be used in the ERT results buffer." To be used in the ERT results buffer." (interactive) - (let* ((test (ert--results-test-at-point-no-redefinition)) + (let* ((test (ert--results-test-at-point-no-redefinition t)) (stats ert--results-stats) (pos (ert--stats-test-pos stats test)) (result (aref (ert--stats-test-results stats) pos))) @@ -2394,8 +2408,7 @@ To be used in the ERT results buffer." ;; Use unibyte because `debugger-setup-buffer' also does so. (set-buffer-multibyte nil) (setq truncate-lines t) - (ert--print-backtrace backtrace) - (debugger-make-xrefs) + (ert--print-backtrace backtrace t) (goto-char (point-min)) (insert (substitute-command-keys "Backtrace for test `")) (ert-insert-test-name-button (ert-test-name test)) @@ -2406,7 +2419,7 @@ To be used in the ERT results buffer." To be used in the ERT results buffer." (interactive) - (let* ((test (ert--results-test-at-point-no-redefinition)) + (let* ((test (ert--results-test-at-point-no-redefinition t)) (stats ert--results-stats) (pos (ert--stats-test-pos stats test)) (result (aref (ert--stats-test-results stats) pos))) @@ -2427,7 +2440,7 @@ To be used in the ERT results buffer." To be used in the ERT results buffer." (interactive) - (let* ((test (ert--results-test-at-point-no-redefinition)) + (let* ((test (ert--results-test-at-point-no-redefinition t)) (stats ert--results-stats) (pos (ert--stats-test-pos stats test)) (result (aref (ert--stats-test-results stats) pos))) @@ -2510,7 +2523,7 @@ To be used in the ERT results buffer." "Display the documentation for TEST-OR-TEST-NAME (a symbol or ert-test)." (interactive (list (ert-read-test-name-at-point "Describe test"))) (when (< emacs-major-version 24) - (error "Requires Emacs 24")) + (user-error "Requires Emacs 24 or later")) (let (test-name test-definition) (cl-etypecase test-or-test-name @@ -2554,7 +2567,7 @@ To be used in the ERT results buffer." To be used in the ERT results buffer." (interactive) - (ert-describe-test (ert--results-test-at-point-no-redefinition))) + (ert-describe-test (ert--results-test-at-point-no-redefinition t))) ;;; Actions on load/unload. diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el index 766dbe11852..866bc73ecd2 100644 --- a/lisp/emacs-lisp/find-func.el +++ b/lisp/emacs-lisp/find-func.el @@ -43,7 +43,7 @@ ;;; Code: -(require 'seq) +(eval-when-compile (require 'cl-lib)) ;;; User variables: @@ -203,43 +203,21 @@ LIBRARY should be a string (the name of the library)." (locate-file rel (or find-function-source-path load-path) load-file-rep-suffixes))))) - (find-library--from-load-path library) + (find-library--from-load-history library) (error "Can't find library %s" library))) -(defun find-library--from-load-path (library) +(defun find-library--from-load-history (library) ;; In `load-history', the file may be ".elc", ".el", ".el.gz", and - ;; LIBRARY may be "foo.el" or "foo", so make sure that we get all - ;; potential matches, and then see whether any of them lead us to an - ;; ".el" or an ".el.gz" file. - (let* ((elc-regexp "\\.el\\(c\\(\\..*\\)?\\)\\'") - (suffix-regexp - (concat "\\(" - (mapconcat 'regexp-quote (find-library-suffixes) "\\'\\|") - "\\|" elc-regexp "\\)\\'")) - (potentials - (mapcar - (lambda (entry) - (if (string-match suffix-regexp (car entry)) - (replace-match "" t t (car entry)) - (car entry))) - (seq-filter - (lambda (entry) - (string-match - (concat "\\`" - (regexp-quote - (replace-regexp-in-string suffix-regexp "" library)) - suffix-regexp) - (file-name-nondirectory (car entry)))) - load-history))) - result) - (dolist (file potentials) - (dolist (suffix (find-library-suffixes)) - (when (not result) - (cond ((file-exists-p file) - (setq result file)) - ((file-exists-p (concat file suffix)) - (setq result (concat file suffix))))))) - result)) + ;; LIBRARY may be "foo.el" or "foo". + (let ((load-re + (concat "\\(" (regexp-quote (file-name-sans-extension library)) "\\)" + (regexp-opt (get-load-suffixes)) "\\'"))) + (cl-loop + for (file . _) in load-history thereis + (and (stringp file) (string-match load-re file) + (let ((dir (substring file 0 (match-beginning 1))) + (basename (match-string 1 file))) + (locate-file basename (list dir) (find-library-suffixes))))))) (defvar find-function-C-source-directory (let ((dir (expand-file-name "src" source-directory))) @@ -330,43 +308,65 @@ TYPE should be nil to find a function, or `defvar' to find a variable." ;;;###autoload -(defun find-library (library &optional other-window) +(defun find-library (library) "Find the Emacs Lisp source of LIBRARY. -LIBRARY should be a string (the name of the library). If the -optional OTHER-WINDOW argument (i.e., the command argument) is -specified, pop to a different window before displaying the -buffer." - (interactive - (let* ((dirs (or find-function-source-path load-path)) - (suffixes (find-library-suffixes)) - (table (apply-partially 'locate-file-completion-table - dirs suffixes)) - (def (if (eq (function-called-at-point) 'require) - ;; `function-called-at-point' may return 'require - ;; with `point' anywhere on this line. So wrap the - ;; `save-excursion' below in a `condition-case' to - ;; avoid reporting a scan-error here. - (condition-case nil - (save-excursion - (backward-up-list) - (forward-char) - (forward-sexp 2) - (thing-at-point 'symbol)) - (error nil)) - (thing-at-point 'symbol)))) - (when (and def (not (test-completion def table))) - (setq def nil)) - (list - (completing-read (if def - (format "Library name (default %s): " def) - "Library name: ") - table nil nil nil nil def) - current-prefix-arg))) + +Interactively, prompt for LIBRARY using the one at or near point." + (interactive (list (read-library-name))) + (prog1 + (switch-to-buffer (find-file-noselect (find-library-name library))) + (run-hooks 'find-function-after-hook))) + +(defun read-library-name () + "Read and return a library name, defaulting to the one near point. + +A library name is the filename of an Emacs Lisp library located +in a directory under `load-path' (or `find-function-source-path', +if non-nil)." + (let* ((dirs (or find-function-source-path load-path)) + (suffixes (find-library-suffixes)) + (table (apply-partially 'locate-file-completion-table + dirs suffixes)) + (def (if (eq (function-called-at-point) 'require) + ;; `function-called-at-point' may return 'require + ;; with `point' anywhere on this line. So wrap the + ;; `save-excursion' below in a `condition-case' to + ;; avoid reporting a scan-error here. + (condition-case nil + (save-excursion + (backward-up-list) + (forward-char) + (forward-sexp 2) + (thing-at-point 'symbol)) + (error nil)) + (thing-at-point 'symbol)))) + (when (and def (not (test-completion def table))) + (setq def nil)) + (completing-read (if def + (format "Library name (default %s): " def) + "Library name: ") + table nil nil nil nil def))) + +;;;###autoload +(defun find-library-other-window (library) + "Find the Emacs Lisp source of LIBRARY in another window. + +See `find-library' for more details." + (interactive (list (read-library-name))) + (prog1 + (switch-to-buffer-other-window (find-file-noselect + (find-library-name library))) + (run-hooks 'find-function-after-hook))) + +;;;###autoload +(defun find-library-other-frame (library) + "Find the Emacs Lisp source of LIBRARY in another frame. + +See `find-library' for more details." + (interactive (list (read-library-name))) (prog1 - (funcall (if other-window - 'pop-to-buffer - 'pop-to-buffer-same-window) - (find-file-noselect (find-library-name library))) + (switch-to-buffer-other-frame (find-file-noselect + (find-library-name library))) (run-hooks 'find-function-after-hook))) (defun find-function-lisp-source (symbol type library) diff --git a/lisp/emacs-lisp/generator.el b/lisp/emacs-lisp/generator.el index 2ab01404bad..c96b400809b 100644 --- a/lisp/emacs-lisp/generator.el +++ b/lisp/emacs-lisp/generator.el @@ -77,7 +77,6 @@ ;;; Code: (require 'cl-lib) -(require 'pcase) (defvar cps--bindings nil) (defvar cps--states nil) diff --git a/lisp/emacs-lisp/lisp-mnt.el b/lisp/emacs-lisp/lisp-mnt.el index fc3caf3359a..a1c5b6977f8 100644 --- a/lisp/emacs-lisp/lisp-mnt.el +++ b/lisp/emacs-lisp/lisp-mnt.el @@ -326,12 +326,13 @@ Return argument is of the form (\"HOLDER\" \"YEAR1\" ... \"YEARN\")" (start (point)) (end (line-end-position))) ;; Cope with multi-line copyright `lines'. Assume the second - ;; line is indented (with the same commenting style). + ;; line is indented at least as much as the original, with the + ;; same commenting style. (save-excursion (beginning-of-line 2) - (let ((str (concat (match-string-no-properties 1) "[ \t]+"))) + (let ((str (match-string-no-properties 1))) (beginning-of-line) - (while (looking-at str) + (while (and (looking-at str) (not (looking-at lm-copyright-prefix))) (setq end (line-end-position)) (beginning-of-line 2)))) ;; Make a single line and parse that. diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index d720e0bc573..fa25a0c3975 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -164,6 +164,9 @@ (put 'defalias 'doc-string-elt 3) (put 'defvaralias 'doc-string-elt 3) (put 'define-category 'doc-string-elt 2) +;; CL +(put 'defconstant 'doc-string-elt 3) +(put 'defparameter 'doc-string-elt 3) (defvar lisp-doc-string-elt-property 'doc-string-elt "The symbol property that holds the docstring position info.") @@ -259,6 +262,24 @@ This will generate compile-time constants from BINDINGS." (funcall loop bindings))))))) (funcall loop bindings))) +(defun elisp--font-lock-backslash () + (let* ((beg0 (match-beginning 0)) + (end0 (match-end 0)) + (ppss (save-excursion (syntax-ppss beg0)))) + (and (nth 3 ppss) ;Inside a string. + (not (nth 5 ppss)) ;The \ is not itself \-escaped. + ;; Don't highlight the \( introduced because of + ;; `open-paren-in-column-0-is-defun-start'. + (not (eq ?\n (char-before beg0))) + (equal (ignore-errors + (car (read-from-string + (format "\"%s\"" + (buffer-substring-no-properties + beg0 end0))))) + (buffer-substring-no-properties (1+ beg0) end0)) + `(face ,font-lock-warning-face + help-echo "This \\ has no effect")))) + (let-when-compile ((lisp-fdefs '("defmacro" "defun")) (lisp-vdefs '("defvar")) @@ -411,6 +432,9 @@ This will generate compile-time constants from BINDINGS." ;; Words inside \\[] tend to be for `substitute-command-keys'. (,(concat "\\\\\\\\\\[\\(" lisp-mode-symbol-regexp "\\)\\]") (1 font-lock-constant-face prepend)) + ;; Ineffective backslashes (typically in need of doubling). + ("\\(\\\\\\)\\([^\"\\]\\)" + (1 (elisp--font-lock-backslash) prepend)) ;; Words inside ‘’ and `' tend to be symbol names. (,(concat "[`‘]\\(\\(?:\\sw\\|\\s_\\|\\\\.\\)" lisp-mode-symbol-regexp "\\)['’]") @@ -552,6 +576,13 @@ Lisp font lock syntactic face function." font-lock-string-face)))) font-lock-comment-face)) +(defun lisp-adaptive-fill () + "Return fill prefix found at point. +Value for `adaptive-fill-function'." + ;; Adaptive fill mode gets the fill wrong for a one-line paragraph made of + ;; a single docstring. Let's fix it here. + (if (looking-at "\\s-+\"[^\n\"]+\"\\s-*$") "")) + (defun lisp-mode-variables (&optional lisp-syntax keywords-case-insensitive elisp) "Common initialization routine for lisp modes. @@ -563,16 +594,15 @@ font-lock keywords will not be case sensitive." (set-syntax-table lisp-mode-syntax-table)) (setq-local paragraph-ignore-fill-prefix t) (setq-local fill-paragraph-function 'lisp-fill-paragraph) - ;; Adaptive fill mode gets the fill wrong for a one-line paragraph made of - ;; a single docstring. Let's fix it here. - (setq-local adaptive-fill-function - (lambda () (if (looking-at "\\s-+\"[^\n\"]+\"\\s-*$") ""))) + (setq-local adaptive-fill-function #'lisp-adaptive-fill) ;; Adaptive fill mode gets in the way of auto-fill, ;; and should make no difference for explicit fill ;; because lisp-fill-paragraph should do the job. ;; I believe that newcomment's auto-fill code properly deals with it -stef ;;(set (make-local-variable 'adaptive-fill-mode) nil) (setq-local indent-line-function 'lisp-indent-line) + (setq-local indent-region-function 'lisp-indent-region) + (setq-local comment-indent-function #'lisp-comment-indent) (setq-local outline-regexp ";;;\\(;* [^ \t\n]\\|###autoload\\)\\|(") (setq-local outline-level 'lisp-outline-level) (setq-local add-log-current-defun-function #'lisp-current-defun-name) @@ -704,15 +734,19 @@ or to switch back to an existing one." ;; Used in old LispM code. (defalias 'common-lisp-mode 'lisp-mode) -;; This will do unless inf-lisp.el is loaded. -(defun lisp-eval-defun (&optional _and-go) - "Send the current defun to the Lisp process made by \\[run-lisp]." - (interactive) - (error "Process lisp does not exist")) +(autoload 'lisp-eval-defun "inf-lisp" nil t) + +(defun lisp-comment-indent () + "Like `comment-indent-default', but don't put space after open paren." + (or (when (looking-at "\\s<\\s<") + (let ((pt (point))) + (skip-syntax-backward " ") + (if (eq (preceding-char) ?\() + (cons (current-column) (current-column)) + (goto-char pt) + nil))) + (comment-indent-default))) -;; May still be used by some external Lisp-mode variant. -(define-obsolete-function-alias 'lisp-comment-indent - 'comment-indent-default "22.1") (define-obsolete-function-alias 'lisp-mode-auto-fill 'do-auto-fill "23.1") (defcustom lisp-indent-offset nil @@ -731,14 +765,109 @@ function is `common-lisp-indent-function'." :type 'function :group 'lisp) -(defun lisp-indent-line (&optional _whole-exp) - "Indent current line as Lisp code. -With argument, indent any additional lines of the same expression -rigidly along with this one." - (interactive "P") - (let ((indent (calculate-lisp-indent)) shift-amt - (pos (- (point-max) (point))) - (beg (progn (beginning-of-line) (point)))) +(defun lisp-ppss (&optional pos) + "Return Parse-Partial-Sexp State at POS, defaulting to point. +Like `syntax-ppss' but includes the character address of the last +complete sexp in the innermost containing list at position +2 (counting from 0). This is important for lisp indentation." + (unless pos (setq pos (point))) + (let ((pss (syntax-ppss pos))) + (if (nth 9 pss) + (let ((sexp-start (car (last (nth 9 pss))))) + (parse-partial-sexp sexp-start pos nil nil (syntax-ppss sexp-start))) + pss))) + +(cl-defstruct (lisp-indent-state + (:constructor nil) + (:constructor lisp-indent-initial-state + (&aux (ppss (lisp-ppss)) + (ppss-point (point)) + (stack (make-list (1+ (car ppss)) nil))))) + stack ;; Cached indentation, per depth. + ppss + ppss-point) + +(defun lisp-indent-calc-next (state) + "Move to next line and return calculated indent for it. +STATE is updated by side effect, the first state should be +created by `lisp-indent-initial-state'. This function may move +by more than one line to cross a string literal." + (pcase-let* (((cl-struct lisp-indent-state + (stack indent-stack) ppss ppss-point) + state) + (indent-depth (car ppss)) ; Corresponding to indent-stack. + (depth indent-depth)) + ;; Parse this line so we can learn the state to indent the + ;; next line. + (while (let ((last-sexp (nth 2 ppss))) + (setq ppss (parse-partial-sexp + ppss-point (progn (end-of-line) (point)) + nil nil ppss)) + ;; Preserve last sexp of state (position 2) for + ;; `calculate-lisp-indent', if we're at the same depth. + (if (and (not (nth 2 ppss)) (= depth (car ppss))) + (setf (nth 2 ppss) last-sexp) + (setq last-sexp (nth 2 ppss))) + (setq depth (car ppss)) + ;; Skip over newlines within strings. + (nth 3 ppss)) + (let ((string-start (nth 8 ppss))) + (setq ppss (parse-partial-sexp (point) (point-max) + nil nil ppss 'syntax-table)) + (setf (nth 2 ppss) string-start) ; Finished a complete string. + (setq depth (car ppss))) + (setq ppss-point (point))) + (setq ppss-point (point)) + (let* ((depth-delta (- depth indent-depth))) + (cond ((< depth-delta 0) + (setq indent-stack (nthcdr (- depth-delta) indent-stack))) + ((> depth-delta 0) + (setq indent-stack (nconc (make-list depth-delta nil) + indent-stack))))) + (prog1 + (let (indent) + (cond ((= (forward-line 1) 1) nil) + ((car indent-stack)) + ((integerp (setq indent (calculate-lisp-indent ppss))) + (setf (car indent-stack) indent)) + ((consp indent) ; (COLUMN CONTAINING-SEXP-START) + (car indent)) + ;; This only happens if we're in a string. + (t (error "This shouldn't happen")))) + (setf (lisp-indent-state-stack state) indent-stack) + (setf (lisp-indent-state-ppss-point state) ppss-point) + (setf (lisp-indent-state-ppss state) ppss)))) + +(defun lisp-indent-region (start end) + "Indent region as Lisp code, efficiently." + (save-excursion + (setq end (copy-marker end)) + (goto-char start) + (beginning-of-line) + ;; The default `indent-region-line-by-line' doesn't hold a running + ;; parse state, which forces each indent call to reparse from the + ;; beginning. That has O(n^2) complexity. + (let* ((parse-state (lisp-indent-initial-state)) + (pr (unless (minibufferp) + (make-progress-reporter "Indenting region..." (point) end)))) + (let ((ppss (lisp-indent-state-ppss parse-state))) + (unless (or (and (bolp) (eolp)) (nth 3 ppss)) + (lisp-indent-line (calculate-lisp-indent ppss)))) + (let ((indent nil)) + (while (progn (setq indent (lisp-indent-calc-next parse-state)) + (< (point) end)) + (unless (or (and (bolp) (eolp)) (not indent)) + (lisp-indent-line indent)) + (and pr (progress-reporter-update pr (point))))) + (and pr (progress-reporter-done pr)) + (move-marker end nil)))) + +(defun lisp-indent-line (&optional indent) + "Indent current line as Lisp code." + (interactive) + (let ((pos (- (point-max) (point))) + (indent (progn (beginning-of-line) + (or indent (calculate-lisp-indent (lisp-ppss)))))) (skip-chars-forward " \t") (if (or (null indent) (looking-at "\\s<\\s<\\s<")) ;; Don't alter indentation of a ;;; comment line @@ -750,11 +879,7 @@ rigidly along with this one." ;; as comment lines, not as code. (progn (indent-for-comment) (forward-char -1)) (if (listp indent) (setq indent (car indent))) - (setq shift-amt (- indent (current-column))) - (if (zerop shift-amt) - nil - (delete-region beg (point)) - (indent-to indent))) + (indent-line-to indent)) ;; If initial point was within line's indentation, ;; position after the indentation. Else stay at same point in text. (if (> (- (point-max) pos) (point)) @@ -768,6 +893,10 @@ In usual case returns an integer: the column to indent to. If the value is nil, that means don't change the indentation because the line starts inside a string. +PARSE-START may be a buffer position to start parsing from, or a +parse state as returned by calling `parse-partial-sexp' up to the +beginning of the current line. + The value can also be a list of the form (COLUMN CONTAINING-SEXP-START). This means that following lines at the same level of indentation should not necessarily be indented the same as this line. @@ -781,12 +910,14 @@ is the buffer position of the start of the containing expression." (desired-indent nil) (retry t) calculate-lisp-indent-last-sexp containing-sexp) - (if parse-start - (goto-char parse-start) - (beginning-of-defun)) - ;; Find outermost containing sexp - (while (< (point) indent-point) - (setq state (parse-partial-sexp (point) indent-point 0))) + (cond ((or (markerp parse-start) (integerp parse-start)) + (goto-char parse-start)) + ((null parse-start) (beginning-of-defun)) + (t (setq state parse-start))) + (unless state + ;; Find outermost containing sexp + (while (< (point) indent-point) + (setq state (parse-partial-sexp (point) indent-point 0)))) ;; Find innermost containing sexp (while (and retry state @@ -1056,103 +1187,34 @@ Lisp function does not specify a special indentation." If optional arg ENDPOS is given, indent each line, stopping when ENDPOS is encountered." (interactive) - (let ((indent-stack (list nil)) - (next-depth 0) - ;; If ENDPOS is non-nil, use nil as STARTING-POINT - ;; so that calculate-lisp-indent will find the beginning of - ;; the defun we are in. - ;; If ENDPOS is nil, it is safe not to scan before point - ;; since every line we indent is more deeply nested than point is. - (starting-point (if endpos nil (point))) - (last-point (point)) - last-depth bol outer-loop-done inner-loop-done state this-indent) - (or endpos - ;; Get error now if we don't have a complete sexp after point. - (save-excursion (forward-sexp 1))) + (let* ((parse-state (lisp-indent-initial-state))) + ;; We need a marker because we modify the buffer + ;; text preceding endpos. + (setq endpos (copy-marker + (if endpos endpos + ;; Get error now if we don't have a complete sexp + ;; after point. + (save-excursion (forward-sexp 1) (point))))) (save-excursion - (setq outer-loop-done nil) - (while (if endpos (< (point) endpos) - (not outer-loop-done)) - (setq last-depth next-depth - inner-loop-done nil) - ;; Parse this line so we can learn the state - ;; to indent the next line. - ;; This inner loop goes through only once - ;; unless a line ends inside a string. - (while (and (not inner-loop-done) - (not (setq outer-loop-done (eobp)))) - (setq state (parse-partial-sexp (point) (progn (end-of-line) (point)) - nil nil state)) - (setq next-depth (car state)) - ;; If the line contains a comment other than the sort - ;; that is indented like code, - ;; indent it now with indent-for-comment. - ;; Comments indented like code are right already. - ;; In any case clear the in-comment flag in the state - ;; because parse-partial-sexp never sees the newlines. - (if (car (nthcdr 4 state)) - (progn (indent-for-comment) - (end-of-line) - (setcar (nthcdr 4 state) nil))) - ;; If this line ends inside a string, - ;; go straight to next line, remaining within the inner loop, - ;; and turn off the \-flag. - (if (car (nthcdr 3 state)) - (progn - (forward-line 1) - (setcar (nthcdr 5 state) nil)) - (setq inner-loop-done t))) - (and endpos - (<= next-depth 0) - (progn - (setq indent-stack (nconc indent-stack - (make-list (- next-depth) nil)) - last-depth (- last-depth next-depth) - next-depth 0))) - (forward-line 1) - ;; Decide whether to exit. - (if endpos - ;; If we have already reached the specified end, - ;; give up and do not reindent this line. - (if (<= endpos (point)) - (setq outer-loop-done t)) - ;; If no specified end, we are done if we have finished one sexp. - (if (<= next-depth 0) - (setq outer-loop-done t))) - (unless outer-loop-done - (while (> last-depth next-depth) - (setq indent-stack (cdr indent-stack) - last-depth (1- last-depth))) - (while (< last-depth next-depth) - (setq indent-stack (cons nil indent-stack) - last-depth (1+ last-depth))) - ;; Now indent the next line according - ;; to what we learned from parsing the previous one. - (setq bol (point)) - (skip-chars-forward " \t") - ;; But not if the line is blank, or just a comment - ;; (except for double-semi comments; indent them as usual). - (if (or (eobp) (looking-at "\\s<\\|\n")) - nil - (if (and (car indent-stack) - (>= (car indent-stack) 0)) - (setq this-indent (car indent-stack)) - (let ((val (calculate-lisp-indent - (if (car indent-stack) (- (car indent-stack)) - starting-point)))) - (if (null val) - (setq this-indent val) - (if (integerp val) - (setcar indent-stack - (setq this-indent val)) - (setcar indent-stack (- (car (cdr val)))) - (setq this-indent (car val)))))) - (if (and this-indent (/= (current-column) this-indent)) - (progn (delete-region bol (point)) - (indent-to this-indent))))) - (or outer-loop-done - (setq outer-loop-done (= (point) last-point)) - (setq last-point (point))))))) + (while (let ((indent (lisp-indent-calc-next parse-state)) + (ppss (lisp-indent-state-ppss parse-state))) + ;; If the line contains a comment indent it now with + ;; `indent-for-comment'. + (when (and (nth 4 ppss) (<= (nth 8 ppss) endpos)) + (save-excursion + (goto-char (lisp-indent-state-ppss-point parse-state)) + (indent-for-comment) + (setf (lisp-indent-state-ppss-point parse-state) + (line-end-position)))) + (when (< (point) endpos) + ;; Indent the next line, unless it's blank, or just a + ;; comment (we will `indent-for-comment' the latter). + (skip-chars-forward " \t") + (unless (or (eolp) (not indent) + (eq (char-syntax (char-after)) ?<)) + (indent-line-to indent)) + t)))) + (move-marker endpos nil))) (defun indent-pp-sexp (&optional arg) "Indent each line of the list starting just after point, or prettyprint it. diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el index 0172e3af261..0c1fe42fedb 100644 --- a/lisp/emacs-lisp/lisp.el +++ b/lisp/emacs-lisp/lisp.el @@ -398,6 +398,42 @@ is called as a function to find the defun's beginning." (goto-char (if arg-+ve floor ceiling)) nil)))))))) +(defun beginning-of-defun--in-emptyish-line-p () + "Return non-nil if the point is in an \"emptyish\" line. +This means a line that consists entirely of comments and/or +whitespace." +;; See http://lists.gnu.org/archive/html/help-gnu-emacs/2016-08/msg00141.html + (save-excursion + (forward-line 0) + (< (line-end-position) + (let ((ppss (syntax-ppss))) + (when (nth 4 ppss) + (goto-char (nth 8 ppss))) + (forward-comment (point-max)) + (point))))) + +(defun beginning-of-defun-comments (&optional arg) + "Move to the beginning of ARGth defun, including comments." + (interactive "^p") + (unless arg (setq arg 1)) + (beginning-of-defun arg) + (let (first-line-p) + (while (let ((ppss (progn (setq first-line-p (= (forward-line -1) -1)) + (syntax-ppss (line-end-position))))) + (while (and (nth 4 ppss) ; If eol is in a line-spanning comment, + (< (nth 8 ppss) (line-beginning-position))) + (goto-char (nth 8 ppss)) ; skip to comment start. + (setq ppss (syntax-ppss (line-end-position)))) + (and (not first-line-p) + (progn (skip-syntax-backward + "-" (line-beginning-position)) + (not (bolp))) ; Check for blank line. + (progn (parse-partial-sexp + (line-beginning-position) (line-end-position) + nil t (syntax-ppss (line-beginning-position))) + (eolp))))) ; Check for non-comment text. + (forward-line (if first-line-p 0 1)))) + (defvar end-of-defun-function (lambda () (forward-sexp 1)) "Function for `end-of-defun' to call. @@ -478,48 +514,72 @@ is called as a function to find the defun's end." (funcall end-of-defun-function) (funcall skip))))) -(defun mark-defun (&optional allow-extend) +(defun mark-defun (&optional arg) "Put mark at end of this defun, point at beginning. The defun marked is the one that contains point or follows point. +With positive ARG, mark this and that many next defuns; with negative +ARG, change the direction of marking. -Interactively, if this command is repeated -or (in Transient Mark mode) if the mark is active, -it marks the next defun after the ones already marked." +If the mark is active, it marks the next or previous defun(s) after +the one(s) already marked." (interactive "p") - (cond ((and allow-extend - (or (and (eq last-command this-command) (mark t)) - (and transient-mark-mode mark-active))) - (set-mark - (save-excursion - (goto-char (mark)) - (end-of-defun) - (point)))) - (t - (let ((opoint (point)) - beg end) - (push-mark opoint) - ;; Try first in this order for the sake of languages with nested - ;; functions where several can end at the same place as with - ;; the offside rule, e.g. Python. - (beginning-of-defun) - (setq beg (point)) - (end-of-defun) - (setq end (point)) - (while (looking-at "^\n") - (forward-line 1)) - (if (> (point) opoint) - (progn - ;; We got the right defun. - (push-mark beg nil t) - (goto-char end) - (exchange-point-and-mark)) - ;; beginning-of-defun moved back one defun - ;; so we got the wrong one. - (goto-char opoint) - (end-of-defun) - (push-mark (point) nil t) - (beginning-of-defun)) - (re-search-backward "^\n" (- (point) 1) t))))) + (setq arg (or arg 1)) + ;; There is no `mark-defun-back' function - see + ;; https://lists.gnu.org/archive/html/bug-gnu-emacs/2016-11/msg00079.html + ;; for explanation + (when (eq last-command 'mark-defun-back) + (setq arg (- arg))) + (when (< arg 0) + (setq this-command 'mark-defun-back)) + (cond ((use-region-p) + (if (>= arg 0) + (set-mark + (save-excursion + (goto-char (mark)) + ;; change the dotimes below to (end-of-defun arg) once bug #24427 is fixed + (dotimes (_ignore arg) + (end-of-defun)) + (point))) + (beginning-of-defun-comments (- arg)))) + (t + (let ((opoint (point)) + beg end) + (push-mark opoint) + ;; Try first in this order for the sake of languages with nested + ;; functions where several can end at the same place as with the + ;; offside rule, e.g. Python. + (beginning-of-defun-comments) + (setq beg (point)) + (end-of-defun) + (setq end (point)) + (when (or (and (<= (point) opoint) + (> arg 0)) + (= beg (point-min))) ; we were before the first defun! + ;; beginning-of-defun moved back one defun so we got the wrong + ;; one. If ARG < 0, however, we actually want to go back. + (goto-char opoint) + (end-of-defun) + (setq end (point)) + (beginning-of-defun-comments) + (setq beg (point))) + (goto-char beg) + (cond ((> arg 0) + ;; change the dotimes below to (end-of-defun arg) once bug #24427 is fixed + (dotimes (_ignore arg) + (end-of-defun)) + (setq end (point)) + (push-mark end nil t) + (goto-char beg)) + (t + (goto-char beg) + (unless (= arg -1) ; beginning-of-defun behaves + ; strange with zero arg - see + ; https://lists.gnu.org/archive/html/bug-gnu-emacs/2017-02/msg00196.html + (beginning-of-defun (1- (- arg)))) + (push-mark end nil t)))))) + (skip-chars-backward "[:space:]\n") + (unless (bobp) + (forward-line 1))) (defvar narrow-to-defun-include-comments nil "If non-nil, `narrow-to-defun' will also show comments preceding the defun.") diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 8d5fac96cfb..4245294457f 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -194,14 +194,16 @@ If VERSION is nil, the package is not loaded (it is \"disabled\")." :risky t :version "24.1") -(defcustom package-archives '(("gnu" . "http://elpa.gnu.org/packages/")) +(defcustom package-archives `(("gnu" . + ,(format "http%s://elpa.gnu.org/packages/" + (if (gnutls-available-p) "s" "")))) "An alist of archives from which to fetch. The default value points to the GNU Emacs package repository. Each element has the form (ID . LOCATION). ID is an archive name, as a string. LOCATION specifies the base location for the archive. - If it starts with \"http:\", it is treated as a HTTP URL; + If it starts with \"http(s):\", it is treated as an HTTP(S) URL; otherwise it should be an absolute directory name. (Other types of URL are currently not supported.) @@ -210,7 +212,7 @@ a package can run arbitrary code." :type '(alist :key-type (string :tag "Archive name") :value-type (string :tag "URL or directory name")) :risky t - :version "24.1") + :version "26.1") ; gnutls test (defcustom package-menu-hide-low-priority 'archive "If non-nil, hide low priority packages from the packages menu. @@ -305,6 +307,23 @@ contrast, `package-user-dir' contains packages for personal use." (declare-function epg-find-configuration "epg-config" (protocol &optional no-cache program-alist)) +(defcustom package-gnupghome-dir (expand-file-name "gnupg" package-user-dir) + "Directory containing GnuPG keyring or nil. +This variable specifies the GnuPG home directory used by package. +That directory is passed via the option \"--homedir\" to GnuPG. +If nil, do not use the option \"--homedir\", but stick with GnuPG's +default directory." + :type `(choice + (const + :tag "Default Emacs package management GnuPG home directory" + ,(expand-file-name "gnupg" package-user-dir)) + (const + :tag "Default GnuPG directory (GnuPG option --homedir not used)" + nil) + (directory :tag "A specific GnuPG --homedir")) + :risky t + :version "26.1") + (defcustom package-check-signature (if (and (require 'epg-config) (epg-find-configuration 'OpenPGP)) @@ -619,7 +638,7 @@ Return the max version (as a string) if the package is held at a lower version." (t (error "Invalid element in `package-load-list'"))))) (defun package-built-in-p (package &optional min-version) - "Return true if PACKAGE is built-in to Emacs. + "Return non-nil if PACKAGE is built-in to Emacs. Optional arg MIN-VERSION, if non-nil, should be a version list specifying the minimum acceptable version." (if (package-desc-p package) ;; was built-in and then was converted @@ -886,25 +905,13 @@ untar into a directory named DIR; otherwise, signal an error." nil pkg-file nil 'silent)))) ;;;; Autoload -;; From Emacs 22, but changed so it adds to load-path. +(declare-function autoload-rubric "autoload" (file &optional type feature)) + (defun package-autoload-ensure-default-file (file) "Make sure that the autoload file FILE exists and if not create it." (unless (file-exists-p file) - (write-region - (concat ";;; " (file-name-nondirectory file) - " --- automatically extracted autoloads\n" - ";;\n" - ";;; Code:\n" - ;; `load-path' should contain only directory names - "(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))\n" - " \n;; Local Variables:\n" - ";; version-control: never\n" - ";; no-byte-compile: t\n" - ";; no-update-autoloads: t\n" - ";; End:\n" - ";;; " (file-name-nondirectory file) - " ends here\n") - nil file nil 'silent)) + (require 'autoload) + (write-region (autoload-rubric file "package" nil) nil file nil 'silent)) file) (defvar generated-autoload-file) @@ -1207,9 +1214,9 @@ errors signaled by ERROR-FORM or by BODY). "Check signature CONTENT against STRING. SIG-FILE is the name of the signature file, used when signaling errors." - (let* ((context (epg-make-context 'OpenPGP)) - (homedir (expand-file-name "gnupg" package-user-dir))) - (setf (epg-context-home-directory context) homedir) + (let ((context (epg-make-context 'OpenPGP))) + (when package-gnupghome-dir + (setf (epg-context-home-directory context) package-gnupghome-dir)) (condition-case error (epg-verify-string context content string) (error (package--display-verify-error context sig-file) @@ -1236,7 +1243,7 @@ errors." "Check signature of the current buffer. Download the signature file from LOCATION by appending \".sig\" to FILE. -GnuPG keyring is located under \"gnupg\" in `package-user-dir'. +GnuPG keyring location depends on `package-gnupghome-dir'. STRING is the string to verify, it defaults to `buffer-string'. If ASYNC is non-nil, the download of the signature file is done asynchronously. @@ -1476,11 +1483,11 @@ taken care of by `package-initialize'." "Import keys from FILE." (interactive "fFile: ") (setq file (expand-file-name file)) - (let ((context (epg-make-context 'OpenPGP)) - (homedir (expand-file-name "gnupg" package-user-dir))) - (with-file-modes 448 - (make-directory homedir t)) - (setf (epg-context-home-directory context) homedir) + (let ((context (epg-make-context 'OpenPGP))) + (when package-gnupghome-dir + (with-file-modes 448 + (make-directory package-gnupghome-dir t)) + (setf (epg-context-home-directory context) package-gnupghome-dir)) (message "Importing %s..." (file-name-nondirectory file)) (epg-import-keys-from-file context file) (message "Importing %s...done" (file-name-nondirectory file)))) @@ -1522,7 +1529,7 @@ similar to an entry in `package-alist'. Save the cached copy to (when (listp (read-from-string content)) (make-directory dir t) (if (or (not package-check-signature) - (member archive package-unsigned-archives)) + (member name package-unsigned-archives)) ;; If we don't care about the signature, save the file and ;; we're done. (progn (write-region content nil local-file nil 'silent) @@ -1769,7 +1776,7 @@ destructively set to nil in ONLY." That is, any element of the returned list is guaranteed to not directly depend on any elements that come before it. -PACKAGE-LIST is a list of package-desc objects. +PACKAGE-LIST is a list of `package-desc' objects. Indirect dependencies are guaranteed to be returned in order only if all the in-between dependencies are also in PACKAGE-LIST." (let ((alist (mapcar (lambda (p) (cons (package-desc-name p) p)) package-list)) @@ -1838,11 +1845,11 @@ if all the in-between dependencies are also in PACKAGE-LIST." (setf (package-desc-signed (car pkg-descs)) t)))))))))) (defun package-installed-p (package &optional min-version) - "Return true if PACKAGE, of MIN-VERSION or newer, is installed. + "Return non-nil if PACKAGE, of MIN-VERSION or newer, is installed. If PACKAGE is a symbol, it is the package name and MIN-VERSION should be a version list. -If PACKAGE is a package-desc object, MIN-VERSION is ignored." +If PACKAGE is a `package-desc' object, MIN-VERSION is ignored." (unless package--initialized (error "package.el is not yet initialized!")) (if (package-desc-p package) (let ((dir (package-desc-dir package))) @@ -1858,7 +1865,7 @@ If PACKAGE is a package-desc object, MIN-VERSION is ignored." (defun package-download-transaction (packages) "Download and install all the packages in PACKAGES. -PACKAGES should be a list of package-desc. +PACKAGES should be a list of `package-desc'. This function assumes that all package requirements in PACKAGES are satisfied, i.e. that PACKAGES is computed using `package-compute-transaction'." @@ -1925,13 +1932,13 @@ add a call to it along with some explanatory comments." ;;;###autoload (defun package-install (pkg &optional dont-select) "Install the package PKG. -PKG can be a package-desc or a symbol naming one of the available packages +PKG can be a `package-desc' or a symbol naming one of the available packages in an archive in `package-archives'. Interactively, prompt for its name. If called interactively or if DONT-SELECT nil, add PKG to `package-selected-packages'. -If PKG is a package-desc and it is already installed, don't try +If PKG is a `package-desc' and it is already installed, don't try to install it but still mark it as selected." (interactive (progn @@ -2060,7 +2067,7 @@ If some packages are not installed propose to install them." ;;; Package Deletion (defun package--newest-p (pkg) - "Return t if PKG is the newest package with its name." + "Return non-nil if PKG is the newest package with its name." (equal (cadr (assq (package-desc-name pkg) package-alist)) pkg)) @@ -2120,11 +2127,16 @@ If NOSAVE is non-nil, the package is not removed from (package-desc-name pkg-used-elsewhere-by))) (t (add-hook 'post-command-hook #'package-menu--post-refresh) - (delete-directory dir t t) - ;; Remove NAME-VERSION.signed file. - (let ((signed-file (concat dir ".signed"))) - (if (file-exists-p signed-file) - (delete-file signed-file))) + (delete-directory dir t) + ;; Remove NAME-VERSION.signed and NAME-readme.txt files. + (dolist (suffix '(".signed" "readme.txt")) + (let* ((version (package-version-join (package-desc-version pkg-desc))) + (file (concat (if (string= suffix ".signed") + dir + (substring dir 0 (- (length version)))) + suffix))) + (when (file-exists-p file) + (delete-file file)))) ;; Update package-alist. (let ((pkgs (assq name package-alist))) (delete pkg-desc pkgs) @@ -2135,7 +2147,7 @@ If NOSAVE is non-nil, the package is not removed from ;;;###autoload (defun package-reinstall (pkg) "Reinstall package PKG. -PKG should be either a symbol, the package name, or a package-desc +PKG should be either a symbol, the package name, or a `package-desc' object." (interactive (list (intern (completing-read "Reinstall package: " @@ -2352,6 +2364,12 @@ Otherwise no newline is inserted." (package-desc-name pkg)))) (insert "\n"))) (when homepage + ;; Prefer https for the homepage of packages on gnu.org. + (if (string-match-p "^http://\\(elpa\\|www\\)\\.gnu\\.org/" homepage) + (let ((gnu (cdr (assoc "gnu" package-archives)))) + (and gnu (string-match-p "^https" gnu) + (setq homepage + (replace-regexp-in-string "^http" "https" homepage))))) (package--print-help-section "Homepage") (help-insert-xref-button homepage 'help-url homepage) (insert "\n")) @@ -2554,7 +2572,7 @@ package PKG-DESC, add one. The alist is keyed with PKG-DESC." (defun package--incompatible-p (pkg &optional shallow) "Return non-nil if PKG has no chance of being installable. -PKG is a package-desc object. +PKG is a `package-desc' object. If SHALLOW is non-nil, this only checks if PKG depends on a higher `emacs-version' than the one being used. Otherwise, also @@ -2638,7 +2656,7 @@ Installed obsolete packages are always displayed.") (defun package--remove-hidden (pkg-list) "Filter PKG-LIST according to `package-archive-priorities'. -PKG-LIST must be a list of package-desc objects, all with the +PKG-LIST must be a list of `package-desc' objects, all with the same name, sorted by decreasing `package-desc-priority-version'. Return a list of packages tied for the highest priority according to their archives." @@ -2879,7 +2897,7 @@ Return (PKG-DESC [NAME VERSION STATUS DOC])." :version "25.1") (defface package-status-incompat - '((t :inherit font-lock-comment-face)) + '((t :inherit error)) "Face used on the status and version of incompat packages." :version "25.1") @@ -2892,7 +2910,7 @@ Return (PKG-DESC [NAME VERSION STATUS DOC])." ;;; Package menu printing (defun package-menu--print-info-simple (pkg) "Return a package entry suitable for `tabulated-list-entries'. -PKG is a package-desc object. +PKG is a `package-desc' object. Return (PKG-DESC [NAME VERSION STATUS DOC])." (let* ((status (package-desc-status pkg)) (face (pcase status diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el index 289265abf27..4a06ab25d3e 100644 --- a/lisp/emacs-lisp/pcase.el +++ b/lisp/emacs-lisp/pcase.el @@ -175,8 +175,8 @@ Emacs Lisp manual for more information and examples." ;; (when (gethash (car cases) pcase--memoize-2) ;; (message "pcase-memoize failed because of eq test on %S" ;; (car cases))) - (when data - (message "pcase-memoize: equal first branch, yet different")) + ;; (when data + ;; (message "pcase-memoize: equal first branch, yet different")) (let ((expansion (pcase--expand exp cases))) (puthash (car cases) `(,exp ,cases ,@expansion) pcase--memoize) ;; (puthash (car cases) `(,exp ,cases ,@expansion) pcase--memoize-1) @@ -503,24 +503,30 @@ MATCH is the pattern that needs to be matched, of the form: (symbolp . vectorp) (symbolp . stringp) (symbolp . byte-code-function-p) + (symbolp . recordp) (integerp . consp) (integerp . arrayp) (integerp . vectorp) (integerp . stringp) (integerp . byte-code-function-p) + (integerp . recordp) (numberp . consp) (numberp . arrayp) (numberp . vectorp) (numberp . stringp) (numberp . byte-code-function-p) + (numberp . recordp) (consp . arrayp) (consp . atom) (consp . vectorp) (consp . stringp) (consp . byte-code-function-p) + (consp . recordp) (arrayp . byte-code-function-p) (vectorp . byte-code-function-p) + (vectorp . recordp) (stringp . vectorp) + (stringp . recordp) (stringp . byte-code-function-p))) (defun pcase--mutually-exclusive-p (pred1 pred2) diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el index 2938c37e8a8..7ef46a48bde 100644 --- a/lisp/emacs-lisp/pp.el +++ b/lisp/emacs-lisp/pp.el @@ -1,4 +1,4 @@ -;;; pp.el --- pretty printer for Emacs Lisp +;;; pp.el --- pretty printer for Emacs Lisp -*- lexical-binding: t -*- ;; Copyright (C) 1989, 1993, 2001-2017 Free Software Foundation, Inc. @@ -67,8 +67,7 @@ to make output that `read' can handle, whenever this is possible." (progn (skip-chars-backward " \t\n") (point))) (insert "\n")))) ((ignore-errors (up-list 1) t) - (while (looking-at-p "\\s)") - (forward-char 1)) + (skip-syntax-forward ")") (delete-region (point) (progn (skip-chars-forward " \t\n") (point))) @@ -129,7 +128,7 @@ Also add the value to the front of the list in the variable `values'." (interactive (list (read--expression "Eval: "))) (message "Evaluating...") - (setq values (cons (eval expression lexical-binding) values)) + (push (eval expression lexical-binding) values) (pp-display-expression (car values) "*Pp Eval Output*")) ;;;###autoload @@ -141,22 +140,21 @@ Also add the value to the front of the list in the variable `values'." (defun pp-last-sexp () "Read sexp before point. Ignores leading comment characters." - (let ((stab (syntax-table)) (pt (point)) start exp) - (set-syntax-table emacs-lisp-mode-syntax-table) - (save-excursion - (forward-sexp -1) - ;; If first line is commented, ignore all leading comments: - (if (save-excursion (beginning-of-line) (looking-at-p "[ \t]*;")) - (progn - (setq exp (buffer-substring (point) pt)) - (while (string-match "\n[ \t]*;+" exp start) - (setq start (1+ (match-beginning 0)) - exp (concat (substring exp 0 start) - (substring exp (match-end 0))))) - (setq exp (read exp))) - (setq exp (read (current-buffer))))) - (set-syntax-table stab) - exp)) + (with-syntax-table emacs-lisp-mode-syntax-table + (let ((pt (point))) + (save-excursion + (forward-sexp -1) + (read + ;; If first line is commented, ignore all leading comments: + (if (save-excursion (beginning-of-line) (looking-at-p "[ \t]*;")) + (let ((exp (buffer-substring (point) pt)) + (start nil)) + (while (string-match "\n[ \t]*;+" exp start) + (setq start (1+ (match-beginning 0)) + exp (concat (substring exp 0 start) + (substring exp (match-end 0))))) + exp) + (current-buffer))))))) ;;;###autoload (defun pp-eval-last-sexp (arg) @@ -178,19 +176,6 @@ Ignores leading comment characters." (insert (pp-to-string (macroexpand-1 (pp-last-sexp)))) (pp-macroexpand-expression (pp-last-sexp)))) -;;; Test cases for quote -;; (pp-eval-expression ''(quote quote)) -;; (pp-eval-expression ''((quote a) (quote b))) -;; (pp-eval-expression ''('a 'b)) ; same as above -;; (pp-eval-expression ''((quote (quote quote)) (quote quote))) -;; These do not satisfy the quote test. -;; (pp-eval-expression ''quote) -;; (pp-eval-expression ''(quote)) -;; (pp-eval-expression ''(quote . quote)) -;; (pp-eval-expression ''(quote a b)) -;; (pp-eval-expression ''(quotefoo)) -;; (pp-eval-expression ''(a b)) - (provide 'pp) ; so (require 'pp) works ;;; pp.el ends here diff --git a/lisp/emacs-lisp/re-builder.el b/lisp/emacs-lisp/re-builder.el index 5264dae52ae..f60d723a883 100644 --- a/lisp/emacs-lisp/re-builder.el +++ b/lisp/emacs-lisp/re-builder.el @@ -488,10 +488,10 @@ If the optional PAUSE is non-nil then pause at the end in any case." Optional argument SYNTAX must be specified if called non-interactively." (interactive (list (intern - (completing-read "Select syntax: " - (mapcar (lambda (el) (cons (symbol-name el) 1)) - '(read string sregex rx)) - nil t (symbol-name reb-re-syntax))))) + (completing-read + (format "Select syntax (default %s): " reb-re-syntax) + '(read string sregex rx) + nil t nil nil (symbol-name reb-re-syntax))))) (if (memq syntax '(read string sregex rx)) (let ((buffer (get-buffer reb-buffer))) diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el index 41187646624..23e444fe241 100644 --- a/lisp/emacs-lisp/seq.el +++ b/lisp/emacs-lisp/seq.el @@ -4,7 +4,7 @@ ;; Author: Nicolas Petton <nicolas@petton.fr> ;; Keywords: sequences -;; Version: 2.19 +;; Version: 2.20 ;; Package: seq ;; Maintainer: emacs-devel@gnu.org @@ -52,7 +52,7 @@ ;; - `seq-copy' ;; - `seq-into' ;; -;; All functions are tested in test/automated/seq-tests.el +;; All functions are tested in test/lisp/emacs-lisp/seq-tests.el ;;; Code: @@ -355,6 +355,12 @@ Equality is defined by TESTFN if non-nil or by `equal' if nil." e)) sequence)) +(cl-defgeneric seq-set-equal-p (sequence1 sequence2 &optional testfn) + "Return non-nil if SEQUENCE1 and SEQUENCE2 contain the same elements, regardless of order. +Equality is defined by TESTFN if non-nil or by `equal' if nil." + (and (seq-every-p (lambda (item1) (seq-contains sequence2 item1 testfn)) sequence1) + (seq-every-p (lambda (item2) (seq-contains sequence1 item2 testfn)) sequence2))) + (cl-defgeneric seq-position (sequence elt &optional testfn) "Return the index of the first element in SEQUENCE that is equal to ELT. Equality is defined by TESTFN if non-nil or by `equal' if nil." diff --git a/lisp/emacs-lisp/smie.el b/lisp/emacs-lisp/smie.el index 4d02b751afe..7baccbc7524 100644 --- a/lisp/emacs-lisp/smie.el +++ b/lisp/emacs-lisp/smie.el @@ -123,6 +123,8 @@ (eval-when-compile (require 'cl-lib)) +(require 'prog-mode) + (defgroup smie nil "Simple Minded Indentation Engine." :group 'languages) @@ -1455,7 +1457,7 @@ in order to figure out the indentation of some other (further down) point." ;; Start the file at column 0. (save-excursion (forward-comment (- (point))) - (if (bobp) 0))) + (if (bobp) (prog-first-column)))) (defun smie-indent-close () ;; Align close paren with opening paren. diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el index 1d729f94092..849ac19d6a5 100644 --- a/lisp/emacs-lisp/subr-x.el +++ b/lisp/emacs-lisp/subr-x.el @@ -30,9 +30,11 @@ ;; Do not document these functions in the lispref. ;; http://lists.gnu.org/archive/html/emacs-devel/2014-01/msg01006.html +;; NB If you want to use this library, it's almost always correct to use: +;; (eval-when-compile (require 'subr-x)) + ;;; Code: -(require 'pcase) (eval-when-compile (require 'cl-lib)) @@ -176,21 +178,27 @@ VARLIST can just be a plain tuple. (define-obsolete-function-alias 'string-reverse 'reverse "25.1") -(defsubst string-trim-left (string) - "Remove leading whitespace from STRING." - (if (string-match "\\`[ \t\n\r]+" string) +(defsubst string-trim-left (string &optional regexp) + "Trim STRING of leading string matching REGEXP. + +REGEXP defaults to \"[ \\t\\n\\r]+\"." + (if (string-match (concat "\\`\\(?:" (or regexp "[ \t\n\r]+")"\\)") string) (replace-match "" t t string) string)) -(defsubst string-trim-right (string) - "Remove trailing whitespace from STRING." - (if (string-match "[ \t\n\r]+\\'" string) +(defsubst string-trim-right (string &optional regexp) + "Trim STRING of trailing string matching REGEXP. + +REGEXP defaults to \"[ \\t\\n\\r]+\"." + (if (string-match (concat "\\(?:" (or regexp "[ \t\n\r]+") "\\)\\'") string) (replace-match "" t t string) string)) -(defsubst string-trim (string) - "Remove leading and trailing whitespace from STRING." - (string-trim-left (string-trim-right string))) +(defsubst string-trim (string &optional trim-left trim-right) + "Trim STRING of leading and trailing strings matching TRIM-LEFT and TRIM-RIGHT. + +TRIM-LEFT and TRIM-RIGHT default to \"[ \\t\\n\\r]+\"." + (string-trim-left (string-trim-right string trim-right) trim-left)) (defsubst string-blank-p (string) "Check whether STRING is either empty or only whitespace." diff --git a/lisp/emacs-lisp/thunk.el b/lisp/emacs-lisp/thunk.el index be0a90fefde..f4c075d22ce 100644 --- a/lisp/emacs-lisp/thunk.el +++ b/lisp/emacs-lisp/thunk.el @@ -42,8 +42,6 @@ ;; ;; (thunk-force delayed) -;; Tests are located at test/automated/thunk-tests.el - ;;; Code: (defmacro thunk-delay (&rest body) diff --git a/lisp/emulation/viper-cmd.el b/lisp/emulation/viper-cmd.el index aa31fac32cc..a697aa7d032 100644 --- a/lisp/emulation/viper-cmd.el +++ b/lisp/emulation/viper-cmd.el @@ -90,7 +90,7 @@ (defconst viper-movement-commands '(?b ?B ?e ?E ?f ?F ?G ?h ?j ?k ?l ?H ?M ?L ?n ?t ?T ?w ?W ?$ ?% - ?^ ?( ?) ?- ?+ ?| ?{ ?} ?[ ?] ?' ?` + ?^ ?\( ?\) ?- ?+ ?| ?{ ?} ?\[ ?\] ?' ?` ?\; ?, ?0 ?? ?/ ?\ ?\C-m space return delete backspace @@ -4346,7 +4346,7 @@ and regexp replace." (defun viper-mark-beginning-of-buffer () "Mark beginning of buffer." (interactive) - (push-mark (point)) + (push-mark) (goto-char (point-min)) (exchange-point-and-mark) (message "Mark set at the beginning of buffer")) @@ -4354,7 +4354,7 @@ and regexp replace." (defun viper-mark-end-of-buffer () "Mark end of buffer." (interactive) - (push-mark (point)) + (push-mark) (goto-char (point-max)) (exchange-point-and-mark) (message "Mark set at the end of buffer")) diff --git a/lisp/emulation/viper-ex.el b/lisp/emulation/viper-ex.el index edc71ea859b..ca067033e63 100644 --- a/lisp/emulation/viper-ex.el +++ b/lisp/emulation/viper-ex.el @@ -326,8 +326,7 @@ Don't put `-c' here, as it is added automatically." (t 'viper-glob-unix-files) ; presumably UNIX ) "Expand the file spec containing wildcard symbols. -The default tries to set this variable to work with Unix, Windows, -and OS/2. +The default tries to set this variable to work with Unix or MS Windows. However, if it doesn't work right for some types of Unix shells or some OS, the user should supply the appropriate function and set this variable to the diff --git a/lisp/emulation/viper-util.el b/lisp/emulation/viper-util.el index e6fd6095dc2..e32b41f5750 100644 --- a/lisp/emulation/viper-util.el +++ b/lisp/emulation/viper-util.el @@ -29,7 +29,6 @@ ;; Compiler pacifier (defvar viper-overriding-map) -(defvar pm-color-alist) (defvar viper-minibuffer-current-face) (defvar viper-minibuffer-insert-face) (defvar viper-minibuffer-vi-face) @@ -132,12 +131,6 @@ Otherwise return the normal value." (if fp (cdr fp) ,variable))))) -;; OS/2 -(cond ((eq (viper-device-type) 'pm) - (fset 'viper-color-defined-p - (lambda (color) (assoc color pm-color-alist))))) - - ;; cursor colors (defun viper-change-cursor-color (new-color &optional frame) (if (and (viper-window-display-p) (viper-color-display-p) diff --git a/lisp/emulation/viper.el b/lisp/emulation/viper.el index b03af9b0839..bded174b0d3 100644 --- a/lisp/emulation/viper.el +++ b/lisp/emulation/viper.el @@ -592,8 +592,8 @@ This startup message appears whenever you load Viper, unless you type `y' now." )) (viper-set-expert-level 'dont-change-unless))) - (or (memq major-mode viper-emacs-state-mode-list) ; don't switch to Vi - (memq major-mode viper-insert-state-mode-list) ; don't switch + (or (apply #'derived-mode-p viper-emacs-state-mode-list) ; don't switch to Vi + (apply #'derived-mode-p viper-insert-state-mode-list) ; don't switch (viper-change-state-to-vi)) )) @@ -605,11 +605,12 @@ This startup message appears whenever you load Viper, unless you type `y' now." ;; Apply a little heuristic to invoke vi state on major-modes ;; that are not listed in viper-vi-state-mode-list (defun this-major-mode-requires-vi-state (mode) - (cond ((memq mode viper-vi-state-mode-list) t) - ((memq mode viper-emacs-state-mode-list) nil) - ((memq mode viper-insert-state-mode-list) nil) - (t (and (eq (key-binding "a") 'self-insert-command) - (eq (key-binding " ") 'self-insert-command))))) + (let ((major-mode mode)) + (cond ((apply #'derived-mode-p viper-vi-state-mode-list) t) + ((apply #'derived-mode-p viper-emacs-state-mode-list) nil) + ((apply #'derived-mode-p viper-insert-state-mode-list) nil) + (t (and (eq (key-binding "a") 'self-insert-command) + (eq (key-binding " ") 'self-insert-command)))))) ;; This hook designed to enable Vi-style editing in comint-based modes." @@ -802,13 +803,14 @@ It also can't undo some Viper settings." (cond ((and (this-major-mode-requires-vi-state major-mode) (eq viper-current-state 'emacs-state)) (viper-mode)) - ((memq major-mode viper-emacs-state-mode-list) + ((cl-member-if #'derived-mode-p viper-emacs-state-mode-list) ;; not checking (eq viper-current-state 'emacs-state) ;; because viper-current-state could have gotten it by ;; default. We need viper-change-state-to-emacs here to have ;; the keymaps take effect. (viper-change-state-to-emacs)) - ((and (memq major-mode viper-insert-state-mode-list) + ((and (cl-member-if #'derived-mode-p + viper-insert-state-mode-list) (not (eq viper-current-state 'insert-state))) (viper-change-state-to-insert)) )) ; with-current-buffer diff --git a/lisp/epa.el b/lisp/epa.el index 4378c09738d..52963b6d3cd 100644 --- a/lisp/epa.el +++ b/lisp/epa.el @@ -628,7 +628,7 @@ If SECRET is non-nil, list secret keys instead of public keys." (`import-keys "Error while importing keys with \"%s\":") (`export-keys "Error while exporting keys with \"%s\":") (_ "Error while executing \"%s\":\n\n")) - epg-gpg-program) + (epg-context-program context)) "\n\n" (epg-context-error-output context))) (epa-info-mode) diff --git a/lisp/epg-config.el b/lisp/epg-config.el index ea1ae6c439f..7b963add881 100644 --- a/lisp/epg-config.el +++ b/lisp/epg-config.el @@ -83,9 +83,9 @@ Note that the buffer name starts with a space." (defconst epg-gpg-minimum-version "1.4.3") (defconst epg-config--program-alist - '((OpenPGP + `((OpenPGP epg-gpg-program - ("gpg2" . "2.1.6") ("gpg" . "1.4.3")) + ("gpg2" . "2.1.6") ("gpg" . ,epg-gpg-minimum-version)) (CMS epg-gpgsm-program ("gpgsm" . "2.0.4"))) @@ -129,7 +129,8 @@ version requirement is met." (or (and (not no-cache) (alist-get protocol epg--configurations)) ;; If the executable value is already set with M-x ;; customize, use it without checking. - (if (and symbol (get symbol 'saved-value)) + (if (and symbol (or (get symbol 'saved-value) + (get symbol 'customized-value))) (let ((configuration (funcall constructor (symbol-value symbol)))) (push (cons protocol configuration) epg--configurations) diff --git a/lisp/epg.el b/lisp/epg.el index 587271b0003..1e24b8d1169 100644 --- a/lisp/epg.el +++ b/lisp/epg.el @@ -1047,7 +1047,7 @@ callback data (if any)." (defun epg--status-TRUST_MARGINAL (context _string) (let ((signature (car (epg-context-result-for context 'verify)))) (if (and signature - (eq (epg-signature-status signature) 'marginal)) + (eq (epg-signature-status signature) 'good)) (setf (epg-signature-validity signature) 'marginal)))) (defun epg--status-TRUST_FULLY (context _string) diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index 8eac2e18aee..3368d6701ae 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -53,6 +53,7 @@ ;; CONTENTS --- `erc-response.contents' ;; SENDER --- `erc-response.sender' ;; LINE --- `erc-response.unparsed' +;; TAGS --- `erc-response.tags' ;; ;; WARNING, WARNING!! ;; It's probably not a good idea to destructively modify the list @@ -115,7 +116,8 @@ (sender "" :type string) (command "" :type string) (command-args '() :type list) - (contents "" :type string)) + (contents "" :type string) + (tags '() :type list)) ;;; User data @@ -955,16 +957,34 @@ See also `erc-server-send'." ;;;; Handling responses +(defun erc-parse-tags (string) + "Parse IRCv3 tags list in STRING to a (tag . value) alist." + (let ((tags) + (tag-strings (split-string string ";"))) + (dolist (tag-string tag-strings tags) + (let ((pair (split-string tag-string "="))) + (push (if (consp pair) + pair + `(,pair)) + tags))))) + (defun erc-parse-server-response (proc string) "Parse and act upon a complete line from an IRC server. PROC is the process (connection) from which STRING was received. PROCs `process-buffer' is `current-buffer' when this function is called." (unless (string= string "") ;; Ignore empty strings (save-match-data - (let ((posn (if (eq (aref string 0) ?:) - (string-match " " string) - 0)) - (msg (make-erc-response :unparsed string))) + (let* ((tag-list (when (eq (aref string 0) ?@) + (substring string 1 (string-match " " string)))) + (msg (make-erc-response :unparsed string :tags (when tag-list + (erc-parse-tags + tag-list)))) + (string (if tag-list + (substring string (+ 1 (string-match " " string))) + string)) + (posn (if (eq (aref string 0) ?:) + (string-match " " string) + 0))) (setf (erc-response.sender msg) (if (eq posn 0) diff --git a/lisp/erc/erc-join.el b/lisp/erc/erc-join.el index 151ea15f077..aa83ffe92ac 100644 --- a/lisp/erc/erc-join.el +++ b/lisp/erc/erc-join.el @@ -129,7 +129,7 @@ This function is run from `erc-nickserv-identified-hook'." (setq erc--autojoin-timer (erc-cancel-timer erc--autojoin-timer))) (when (eq erc-autojoin-timing 'ident) - (let ((server (or erc-server-announced-name erc-session-server)) + (let ((server (or erc-session-server erc-server-announced-name)) (joined (mapcar (lambda (buf) (with-current-buffer buf (erc-default-target))) (erc-channel-list erc-server-process)))) @@ -155,38 +155,24 @@ This function is run from `erc-nickserv-identified-hook'." ;; `erc-autojoin-timing' is `connect': (dolist (l erc-autojoin-channels-alist) (when (string-match (car l) server) - (dolist (chan (cdr l)) - (let ((buffer (erc-get-buffer chan))) - ;; Only auto-join the channels that we aren't already in - ;; using a different nick. - (when (or (not buffer) - (not (with-current-buffer buffer - (erc-server-process-alive)))) - (erc-server-join-channel server chan))))))) + (let ((server (or erc-session-server erc-server-announced-name))) + (dolist (chan (cdr l)) + (let ((buffer (erc-get-buffer chan))) + ;; Only auto-join the channels that we aren't already in + ;; using a different nick. + (when (or (not buffer) + (not (with-current-buffer buffer + (erc-server-process-alive)))) + (erc-server-join-channel server chan)))))))) ;; Return nil to avoid stomping on any other hook funcs. nil) -(defun erc-server-join-channel (server channel) - (let* ((secret (plist-get (nth 0 (auth-source-search - :max 1 - :host server - :port "irc" - :user channel)) - :secret)) - (password (if (functionp secret) - (funcall secret) - secret))) - (erc-server-send (concat "JOIN " channel - (if password - (concat " " password) - ""))))) - (defun erc-autojoin-add (proc parsed) "Add the channel being joined to `erc-autojoin-channels-alist'." (let* ((chnl (erc-response.contents parsed)) (nick (car (erc-parse-user (erc-response.sender parsed)))) (server (with-current-buffer (process-buffer proc) - (or erc-server-announced-name erc-session-server)))) + (or erc-session-server erc-server-announced-name)))) (when (erc-current-nick-p nick) (when (and erc-autojoin-domain-only (string-match "[^.\n]+\\.\\([^.\n]+\\.[^.\n]+\\)$" server)) @@ -209,7 +195,7 @@ This function is run from `erc-nickserv-identified-hook'." (let* ((chnl (car (erc-response.command-args parsed))) (nick (car (erc-parse-user (erc-response.sender parsed)))) (server (with-current-buffer (process-buffer proc) - (or erc-server-announced-name erc-session-server)))) + (or erc-session-server erc-server-announced-name)))) (when (erc-current-nick-p nick) (when (and erc-autojoin-domain-only (string-match "[^.\n]+\\.\\([^.\n]+\\.[^.\n]+\\)$" server)) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 488404d7341..8547821f080 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -2700,7 +2700,10 @@ See also `erc-format-message' and `erc-display-line'." (unless (erc-hide-current-message-p parsed) (erc-put-text-property 0 (length string) 'erc-parsed parsed string) (erc-put-text-property 0 (length string) 'rear-sticky t string) - (erc-display-line string buffer))))) + (when (erc-response.tags parsed) + (erc-put-text-property 0 (length string) 'tags (erc-response.tags parsed) + string)) + (erc-display-line string buffer))))) (defun erc-message-type-member (position list) "Return non-nil if the erc-parsed text-property at POSITION is in LIST. @@ -3027,6 +3030,23 @@ For a list of user commands (/join /part, ...): (defalias 'erc-cmd-H 'erc-cmd-HELP) (put 'erc-cmd-HELP 'process-not-needed t) +(defun erc-server-join-channel (server channel &optional secret) + (let* ((secret (or secret + (plist-get (nth 0 (auth-source-search + :max 1 + :host server + :port "irc" + :user channel)) + :secret))) + (password (if (functionp secret) + (funcall secret) + secret))) + (erc-log (format "cmd: JOIN: %s" channel)) + (erc-server-send (concat "JOIN " channel + (if password + (concat " " password) + ""))))) + (defun erc-cmd-JOIN (channel &optional key) "Join the channel given in CHANNEL, optionally with KEY. If CHANNEL is specified as \"-invite\", join the channel to which you @@ -3046,10 +3066,9 @@ were most recently invited. See also `invitation'." (if (erc-member-ignore-case chnl joined-channels) (switch-to-buffer (car (erc-member-ignore-case chnl joined-channels))) - (erc-log (format "cmd: JOIN: %s" chnl)) - (erc-server-send (if (and chnl key) - (format "JOIN %s %s" chnl key) - (format "JOIN %s" chnl))))))) + (let ((server (with-current-buffer (process-buffer erc-server-process) + (or erc-session-server erc-server-announced-name)))) + (erc-server-join-channel server chnl key)))))) t) (defalias 'erc-cmd-CHANNEL 'erc-cmd-JOIN) @@ -6735,9 +6754,10 @@ This function should be on `erc-kill-server-hook'." This function should be on `erc-kill-channel-hook'." (when (erc-server-process-alive) (let ((tgt (erc-default-target))) - (erc-server-send (format "PART %s :%s" tgt - (funcall erc-part-reason nil)) - nil tgt)))) + (if tgt + (erc-server-send (format "PART %s :%s" tgt + (funcall erc-part-reason nil)) + nil tgt))))) ;;; Dealing with `erc-parsed' diff --git a/lisp/eshell/em-basic.el b/lisp/eshell/em-basic.el index c570d7cca89..47c2cb4dab1 100644 --- a/lisp/eshell/em-basic.el +++ b/lisp/eshell/em-basic.el @@ -50,12 +50,6 @@ ;; ;; The umask command changes the default file permissions for newly ;; created files. It uses the same syntax as bash. -;; -;;;_* `version' -;; -;; This command reports the version number for Eshell and all its -;; dependent module, including the date when those modules were last -;; modified. ;;; Code: diff --git a/lisp/eshell/em-prompt.el b/lisp/eshell/em-prompt.el index 53a83e6a67b..8c81b43b1fa 100644 --- a/lisp/eshell/em-prompt.el +++ b/lisp/eshell/em-prompt.el @@ -117,6 +117,8 @@ arriving, or after." (defun eshell-emit-prompt () "Emit a prompt if eshell is being used interactively." + (when (boundp 'ansi-color-context-region) + (setq ansi-color-context-region nil)) (run-hooks 'eshell-before-prompt-hook) (if (not eshell-prompt-function) (set-marker eshell-last-output-end (point)) diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index 583ba6ac42f..24342208771 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -575,14 +575,9 @@ must be implemented via rewriting, rather than as a function." (defvar eshell-last-command-result) ;Defined in esh-io.el. (defun eshell-exit-success-p () - "Return non-nil if the last command was \"successful\". -For a bit of Lisp code, this means a return value of non-nil. -For an external command, it means an exit code of 0." - (if (save-match-data - (string-match "#<\\(Lisp object\\|function .*\\)>" - eshell-last-command-name)) - eshell-last-command-result - (= eshell-last-command-status 0))) + "Return non-nil if the last command was successful. +This means an exit code of 0." + (= eshell-last-command-status 0)) (defvar eshell--cmd) @@ -1153,6 +1148,8 @@ be finished later after the completion of an asynchronous subprocess." ;; command invocation +(declare-function help-fns-function-description-header "help-fns") + (defun eshell/which (command &rest names) "Identify the COMMAND, and where it is located." (dolist (name (cons command names)) @@ -1169,25 +1166,17 @@ be finished later after the completion of an asynchronous subprocess." (concat name " is an alias, defined as \"" (cadr alias) "\""))) (unless program - (setq program (eshell-search-path name)) - (let* ((esym (eshell-find-alias-function name)) - (sym (or esym (intern-soft name)))) - (if (and (or esym (and sym (fboundp sym))) - (or eshell-prefer-lisp-functions (not direct))) - (let ((desc (let ((inhibit-redisplay t)) - (save-window-excursion - (prog1 - (describe-function sym) - (message nil)))))) - (setq desc (if desc (substring desc 0 - (1- (or (string-match "\n" desc) - (length desc)))) - ;; This should not happen. - (format "%s is defined, \ -but no documentation was found" name))) - (if (buffer-live-p (get-buffer "*Help*")) - (kill-buffer "*Help*")) - (setq program (or desc name)))))) + (setq program + (let* ((esym (eshell-find-alias-function name)) + (sym (or esym (intern-soft name)))) + (if (and (or esym (and sym (fboundp sym))) + (or eshell-prefer-lisp-functions (not direct))) + (or (with-output-to-string + (require 'help-fns) + (princ (format "%s is " sym)) + (help-fns-function-description-header sym)) + name) + (eshell-search-path name))))) (if (not program) (eshell-error (format "which: no %s in (%s)\n" name (getenv "PATH"))) @@ -1257,6 +1246,7 @@ represent a lisp form; ARGS will be ignored in that case." (and result (funcall printer result)) result) (error + (setq eshell-last-command-status 1) (let ((msg (error-message-string err))) (if (and (not form-p) (string-match "^Wrong number of arguments" msg) diff --git a/lisp/eshell/esh-ext.el b/lisp/eshell/esh-ext.el index fb1fedc9c54..0b292306ff1 100644 --- a/lisp/eshell/esh-ext.el +++ b/lisp/eshell/esh-ext.el @@ -39,7 +39,9 @@ (require 'cl-lib) (require 'esh-io) (require 'esh-cmd)) +(require 'esh-arg) (require 'esh-opt) +(require 'esh-proc) (defgroup eshell-ext nil "External commands are invoked when operating system executables are @@ -299,11 +301,13 @@ line of the form #!<interp>." (let ((fullname (if (file-name-directory file) file (eshell-search-path file))) (suffixes eshell-binary-suffixes)) - (if (and fullname - (not (file-remote-p fullname)) - (file-remote-p default-directory)) - (setq fullname (expand-file-name - (concat "./" fullname) default-directory))) + (when (and fullname + (not (file-remote-p fullname)) + (file-remote-p default-directory)) + (setq fullname + (if (file-name-absolute-p fullname) + (concat (file-remote-p default-directory) fullname) + (expand-file-name fullname default-directory)))) (if (and fullname (not (or eshell-force-execution (file-executable-p fullname)))) (while suffixes diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el index 0fd0c183016..0999f9c4a88 100644 --- a/lisp/eshell/esh-mode.el +++ b/lisp/eshell/esh-mode.el @@ -726,7 +726,9 @@ This is done after all necessary filtering has been done." (setq obeg (+ obeg nchars))) (if (<= (point) oend) (setq oend (+ oend nchars))) - (insert-before-markers string) + ;; Let the ansi-color overlay hooks run. + (let ((inhibit-modification-hooks nil)) + (insert-before-markers string)) (if (= (window-start) (point)) (set-window-start (selected-window) (- (point) nchars))) diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el index fe1f1188c88..cdd05bd7e9a 100644 --- a/lisp/eshell/esh-var.el +++ b/lisp/eshell/esh-var.el @@ -563,6 +563,8 @@ For example, to retrieve the second element of a user's record in (defun eshell-index-value (value index) "Reference VALUE using the given INDEX." + (when (and (stringp index) (get-text-property 0 'number index)) + (setq index (string-to-number index))) (if (stringp index) (cdr (assoc index value)) (cond diff --git a/lisp/expand.el b/lisp/expand.el index b4bd266bf5f..d06287e6f9b 100644 --- a/lisp/expand.el +++ b/lisp/expand.el @@ -3,7 +3,7 @@ ;; Copyright (C) 1995-1996, 2001-2017 Free Software Foundation, Inc. ;; Author: Frederic Lepied <Frederic.Lepied@sugix.frmug.org> -;; Maintainer: Frederic Lepied <Frederic.Lepied@sugix.frmug.org> +;; Maintainer: emacs-devel@gnu.org ;; Keywords: abbrev ;; This file is part of GNU Emacs. diff --git a/lisp/faces.el b/lisp/faces.el index d4f2f08acf5..c3693d16631 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -1594,6 +1594,7 @@ If FRAME is nil, the current FRAME is used." (defun face-spec-choose (spec &optional frame no-match-retval) "Return the proper attributes for FRAME, out of SPEC. +Value is a plist of face attributes in the form of attribute-value pairs. If no match is found or SPEC is nil, return nil, unless NO-MATCH-RETVAL is given, in which case return its value instead." (unless frame @@ -1666,7 +1667,7 @@ is given, in which case return its value instead." face--attributes-unspecified))) (defun face-spec-set (face spec &optional spec-type) - "Set the face spec SPEC for FACE. + "Set the FACE's spec SPEC, define FACE, and recalculate its attributes. See `defface' for the format of SPEC. The appearance of each face is controlled by its specs (set via @@ -1677,10 +1678,11 @@ This function also defines FACE as a valid face name if it is not already one, and (re)calculates its attributes on existing frames. -The argument SPEC-TYPE determines which spec to set: - nil or `face-override-spec' means the override spec (which is - usually what you want if calling this function outside of - Custom code); +The optional argument SPEC-TYPE determines which spec to set: + nil, omitted or `face-override-spec' means the override spec, + which overrides all the other types of spec mentioned below + (this is usually what you want if calling this function + outside of Custom code); `customized-face' or `saved-face' means the customized spec or the saved custom spec; `face-defface-spec' means the default spec @@ -1688,7 +1690,7 @@ The argument SPEC-TYPE determines which spec to set: `reset' means to ignore SPEC, but clear the `customized-face' and `face-override-spec' specs; Any other value means not to set any spec, but to run the -function for its other effects." +function for defining FACE and recalculating its attributes." (if (get face 'face-alias) (setq face (get face 'face-alias))) ;; Save SPEC to the relevant symbol property. @@ -1734,32 +1736,34 @@ The following sources are applied in this order: ;; `theme-face' records. (let ((theme-faces (get face 'theme-face)) (no-match-found 0) - spec theme-face-applied) + face-attrs theme-face-applied) (if theme-faces (dolist (elt (reverse theme-faces)) - (setq spec (face-spec-choose (cadr elt) frame no-match-found)) - (unless (eq spec no-match-found) - (face-spec-set-2 face frame spec) + (setq face-attrs (face-spec-choose (cadr elt) frame no-match-found)) + (unless (eq face-attrs no-match-found) + (face-spec-set-2 face frame face-attrs) (setq theme-face-applied t)))) ;; If there was a spec applicable to FRAME, that overrides the ;; defface spec entirely (rather than inheriting from it). If ;; there was no spec applicable to FRAME, apply the defface spec ;; as well as any applicable X resources. (unless theme-face-applied - (setq spec (face-spec-choose (face-default-spec face) frame)) - (face-spec-set-2 face frame spec) + (setq face-attrs (face-spec-choose (face-default-spec face) frame)) + (face-spec-set-2 face frame face-attrs) (make-face-x-resource-internal face frame)) - (setq spec (face-spec-choose (get face 'face-override-spec) frame)) - (face-spec-set-2 face frame spec))) + (setq face-attrs (face-spec-choose (get face 'face-override-spec) frame)) + (face-spec-set-2 face frame face-attrs))) -(defun face-spec-set-2 (face frame spec) - "Set the face attributes of FACE on FRAME according to SPEC." +(defun face-spec-set-2 (face frame face-attrs) + "Set the face attributes of FACE on FRAME according to FACE-ATTRS. +FACE-ATTRS is a plist of face attributes in the form of attribute-value +pairs." (let (attrs) - (while spec - (when (assq (car spec) face-x-resources) - (push (car spec) attrs) - (push (cadr spec) attrs)) - (setq spec (cddr spec))) + (while face-attrs + (when (assq (car face-attrs) face-x-resources) + (push (car face-attrs) attrs) + (push (cadr face-attrs) attrs)) + (setq face-attrs (cddr face-attrs))) (apply 'set-face-attribute face frame (nreverse attrs)))) (defun face-attr-match-p (face attrs &optional frame) @@ -2349,10 +2353,13 @@ If you set `term-file-prefix' to nil, this function does nothing." (defface variable-pitch '((((type w32)) - ;; This is a kludgy workaround for an issue discussed in + ;; This is a workaround for an issue discussed in ;; http://lists.gnu.org/archive/html/emacs-devel/2016-04/msg00746.html. - :font "-outline-Arial-normal-normal-normal-sans-*-*-*-*-p-*-iso8859-1") - (t :family "Sans Serif")) + ;; We need (a) the splash screen not to pick up bold-italics variant of + ;; the font, and (b) still be able to request bold/italic/larger size + ;; variants in the likes of EWW. + :family "Arial" :foundry "outline") + (t :family "Sans Serif")) "The basic variable-pitch face." :group 'basic-faces) @@ -2458,6 +2465,33 @@ If you set `term-file-prefix' to nil, this function does nothing." :version "21.1" :group 'basic-faces) +;; Definition stolen from linum.el. +(defface line-number + '((t :inherit (shadow default))) + "Face for displaying line numbers. +This face is used when `display-line-numbers' is non-nil. + +If you customize the font of this face, make sure it is a +monospaced font, otherwise line numbers will not line up, +and text lines might move horizontally as you move through +the buffer." + :version "26.1" + :group 'basic-faces) + +(defface line-number-current-line + '((t :inherit line-number)) + "Face for displaying the current line number. +This face is used when `display-line-numbers' is non-nil. + +If you customize the font of this face, make sure it is a +monospaced font, otherwise line numbers will not line up, +and text lines might move horizontally as you move through +the buffer. Similarly, making this face's font different +from that of the `line-number' face could produce such +unwanted effects." + :version "26.1" + :group 'basic-faces) + (defface escape-glyph '((((background dark)) :foreground "cyan") ;; See the comment in minibuffer-prompt for @@ -2626,6 +2660,13 @@ the same as `window-divider' face." :group 'window-divider :group 'basic-faces) +(defface internal-border + '((t nil)) + "Basic face for the internal border." + :version "26.1" + :group 'frames + :group 'basic-faces) + (defface minibuffer-prompt '((((background dark)) :foreground "cyan") ;; Don't use blue because many users of the MS-DOS port customize diff --git a/lisp/ffap.el b/lisp/ffap.el index d7222bfb681..8bcfbfcdff7 100644 --- a/lisp/ffap.el +++ b/lisp/ffap.el @@ -1110,32 +1110,67 @@ The arguments CHARS, BEG and END are handled as described in (defun ffap-string-at-point (&optional mode) "Return a string of characters from around point. + MODE (defaults to value of `major-mode') is a symbol used to look up string syntax parameters in `ffap-string-at-point-mode-alist'. + If MODE is not found, we use `file' instead of MODE. + If the region is active, return a string from the region. -Set the variable `ffap-string-at-point' and the variable + +If the point is in a comment, ensure that the returned string does not +contain the comment start characters (especially for major modes that +have '//' as comment start characters). + +Set the variables `ffap-string-at-point' and `ffap-string-at-point-region'. + When the region is active and larger than `ffap-max-region-length', return an empty string, and set `ffap-string-at-point-region' to '(1 1)." (let* ((args (cdr (or (assq (or mode major-mode) ffap-string-at-point-mode-alist) (assq 'file ffap-string-at-point-mode-alist)))) + (region-selected (use-region-p)) (pt (point)) - (beg (if (use-region-p) + (beg (if region-selected (region-beginning) (save-excursion (skip-chars-backward (car args)) (skip-chars-forward (nth 1 args) pt) (point)))) - (end (if (use-region-p) + (end (if region-selected (region-end) (save-excursion (skip-chars-forward (car args)) (skip-chars-backward (nth 2 args) pt) (point)))) (region-len (- (max beg end) (min beg end)))) + + ;; If the initial characters of the to-be-returned string are the + ;; current major mode's comment starter characters, *and* are + ;; not part of a comment, remove those from the returned string + ;; (Bug#24057). + ;; Example comments in `c-mode' (which considers lines beginning + ;; with "//" as comments): + ;; //tmp - This is a comment. It does not contain any path reference. + ;; ///tmp - This is a comment. The "/tmp" portion in that is a path. + ;; ////tmp - This is a comment. The "//tmp" portion in that is a path. + (when (and + ;; Proceed if no region is selected by the user. + (null region-selected) + ;; Check if END character is part of a comment. + (save-excursion + (nth 4 (syntax-ppss end)))) + ;; Move BEG to beginning of comment (after the comment start + ;; characters), or END, whichever comes first. + (save-excursion + (let ((state (syntax-ppss beg))) + ;; (nth 4 (syntax-ppss)) will be nil for comment start chars. + (unless (nth 4 state) + (parse-partial-sexp beg end nil nil state :commentstop) + (setq beg (point)))))) + (if (and (natnump ffap-max-region-length) (< region-len ffap-max-region-length)) ; Bug#25243. (setf ffap-string-at-point-region (list beg end) @@ -1501,7 +1536,8 @@ If `ffap-url-regexp' is not nil, the FILENAME may also be an URL. With a prefix, this command behaves exactly like `ffap-file-finder'. If `ffap-require-prefix' is set, the prefix meaning is reversed. See also the variables `ffap-dired-wildcards', `ffap-newfile-prompt', -and the functions `ffap-file-at-point' and `ffap-url-at-point'." +`ffap-url-unwrap-local', `ffap-url-unwrap-remote', and the functions +`ffap-file-at-point' and `ffap-url-at-point'." (interactive) (if (and (called-interactively-p 'interactive) (if ffap-require-prefix (not current-prefix-arg) @@ -1733,14 +1769,9 @@ Return value: "Like `ffap', but put buffer in another window. Only intended for interactive use." (interactive) - (let (value) - (switch-to-buffer-other-window - (save-window-excursion - (setq value (call-interactively 'ffap)) - (unless (or (bufferp value) (bufferp (car-safe value))) - (setq value (current-buffer))) - (current-buffer))) - value)) + (pcase (save-window-excursion (call-interactively 'ffap)) + ((or (and (pred bufferp) b) `(,(and (pred bufferp) b) . ,_)) + (switch-to-buffer-other-window b)))) (defun ffap-other-frame () "Like `ffap', but put buffer in another frame. diff --git a/lisp/filenotify.el b/lisp/filenotify.el index 1de5420f1e7..64cfab143ec 100644 --- a/lisp/filenotify.el +++ b/lisp/filenotify.el @@ -28,6 +28,7 @@ ;;; Code: (require 'cl-lib) +(eval-when-compile (require 'subr-x)) (defconst file-notify--library (cond @@ -40,40 +41,43 @@ The value is the name of the low-level file notification package to be used for local file systems. Remote file notifications could use another implementation.") +(cl-defstruct (file-notify--watch + (:constructor nil) + (:constructor + file-notify--watch-make (directory filename callback))) + ;; Watched directory + directory + ;; Watched relative filename, nil if watching the directory. + filename + ;; Function to propagate events to + callback) + +(defun file-notify--watch-absolute-filename (watch) + "Return the absolute filename observed by WATCH." + (if (file-notify--watch-filename watch) + (expand-file-name + (file-notify--watch-filename watch) + (file-notify--watch-directory watch)) + (file-notify--watch-directory watch))) + (defvar file-notify-descriptors (make-hash-table :test 'equal) "Hash table for registered file notification descriptors. A key in this hash table is the descriptor as returned from `inotify', `kqueue', `gfilenotify', `w32notify' or a file name -handler. The value in the hash table is a list - - (DIR (FILE . CALLBACK) (FILE . CALLBACK) ...) - -Several values for a given DIR happen only for `inotify', when -different files from the same directory are watched.") +handler. The value in the hash table is `file-notify--watch' +struct.") (defun file-notify--rm-descriptor (descriptor) "Remove DESCRIPTOR from `file-notify-descriptors'. DESCRIPTOR should be an object returned by `file-notify-add-watch'. If it is registered in `file-notify-descriptors', a stopped event is sent." - (let* ((desc (if (consp descriptor) (car descriptor) descriptor)) - (registered (gethash desc file-notify-descriptors)) - (file (if (consp descriptor) (cdr descriptor) (cl-caadr registered))) - (dir (car registered))) - - (when (consp registered) - ;; Send `stopped' event. - (funcall - (cdr (assoc file (cdr registered))) - `(,descriptor stopped ,(if file (expand-file-name file dir) dir))) - - ;; Modify `file-notify-descriptors'. - (if (not file) - (remhash desc file-notify-descriptors) - (setcdr registered - (delete (assoc file (cdr registered)) (cdr registered))) - (if (null (cdr registered)) - (remhash desc file-notify-descriptors) - (puthash desc registered file-notify-descriptors)))))) + (when-let (watch (gethash descriptor file-notify-descriptors)) + ;; Send `stopped' event. + (unwind-protect + (funcall + (file-notify--watch-callback watch) + `(,descriptor stopped ,(file-notify--watch-absolute-filename watch))) + (remhash descriptor file-notify-descriptors)))) ;; This function is used by `inotify', `kqueue', `gfilenotify' and ;; `w32notify' events. @@ -87,7 +91,8 @@ If EVENT is a filewatch event, call its callback. It has the format Otherwise, signal a `file-notify-error'." (interactive "e") ;;(message "file-notify-handle-event %S" event) - (if (and (eq (car event) 'file-notify) + (if (and (consp event) + (eq (car event) 'file-notify) (>= (length event) 3)) (funcall (nth 2 event) (nth 1 event)) (signal 'file-notify-error @@ -95,33 +100,32 @@ Otherwise, signal a `file-notify-error'." ;; Needed for `inotify' and `w32notify'. In the latter case, COOKIE is nil. (defvar file-notify--pending-event nil - "A pending file notification events for a future `renamed' action. + "A pending file notification event for a future `renamed' action. It is a form ((DESCRIPTOR ACTION FILE [FILE1-OR-COOKIE]) CALLBACK).") (defun file-notify--event-watched-file (event) "Return file or directory being watched. Could be different from the directory watched by the backend library." - (let* ((desc (if (consp (car event)) (caar event) (car event))) - (registered (gethash desc file-notify-descriptors)) - (file (if (consp (car event)) (cdar event) (cl-caadr registered))) - (dir (car registered))) - (if file (expand-file-name file dir) dir))) + (when-let (watch (gethash (car event) file-notify-descriptors)) + (file-notify--watch-absolute-filename watch))) (defun file-notify--event-file-name (event) "Return file name of file notification event, or nil." - (directory-file-name - (expand-file-name - (or (and (stringp (nth 2 event)) (nth 2 event)) "") - (car (gethash (car event) file-notify-descriptors))))) + (when-let (watch (gethash (car event) file-notify-descriptors)) + (directory-file-name + (expand-file-name + (or (and (stringp (nth 2 event)) (nth 2 event)) "") + (file-notify--watch-directory watch))))) ;; Only `gfilenotify' could return two file names. (defun file-notify--event-file1-name (event) "Return second file name of file notification event, or nil. This is available in case a file has been moved." - (and (stringp (nth 3 event)) - (directory-file-name - (expand-file-name - (nth 3 event) (car (gethash (car event) file-notify-descriptors)))))) + (when-let (watch (gethash (car event) file-notify-descriptors)) + (and (stringp (nth 3 event)) + (directory-file-name + (expand-file-name + (nth 3 event) (file-notify--watch-directory watch)))))) ;; Cookies are offered by `inotify' only. (defun file-notify--event-cookie (event) @@ -129,21 +133,6 @@ This is available in case a file has been moved." This is available in case a file has been moved." (nth 3 event)) -;; `inotify' returns the same descriptor when the file (directory) -;; uses the same inode. We want to distinguish, and apply a virtual -;; descriptor which make the difference. -(defun file-notify--descriptor (desc file) - "Return the descriptor to be used in `file-notify-*-watch'. -For `gfilenotify' and `w32notify' it is the same descriptor as -used in the low-level file notification package." - (if (and (natnump desc) (eq file-notify--library 'inotify)) - (cons desc - (and (stringp file) - (car (assoc - (file-name-nondirectory file) - (gethash desc file-notify-descriptors))))) - desc)) - ;; The callback function used to map between specific flags of the ;; respective file notifications, and the ones we return. (defun file-notify-callback (event) @@ -151,138 +140,123 @@ used in the low-level file notification package." EVENT is the cadr of the event in `file-notify-handle-event' \(DESCRIPTOR ACTIONS FILE [FILE1-OR-COOKIE])." (let* ((desc (car event)) - (registered (gethash desc file-notify-descriptors)) + (watch (gethash desc file-notify-descriptors)) (actions (nth 1 event)) (file (file-notify--event-file-name event)) - file1 callback pending-event stopped) + file1 pending-event stopped) ;; Make actions a list. (unless (consp actions) (setq actions (cons actions nil))) - ;; Loop over registered entries. In fact, more than one entry - ;; happens only for `inotify'. - (dolist (entry (cdr registered)) - - ;; Check, that event is meant for us. - (unless (setq callback (cdr entry)) - (setq actions nil)) - + (when watch ;; Loop over actions. In fact, more than one action happens only ;; for `inotify' and `kqueue'. - (dolist (action actions) - - ;; Send pending event, if it doesn't match. - (when (and file-notify--pending-event - ;; The cookie doesn't match. - (not (eq (file-notify--event-cookie - (car file-notify--pending-event)) - (file-notify--event-cookie event))) - (or - ;; inotify. - (and (eq (nth 1 (car file-notify--pending-event)) - 'moved-from) - (not (eq action 'moved-to))) - ;; w32notify. - (and (eq (nth 1 (car file-notify--pending-event)) - 'renamed-from) - (not (eq action 'renamed-to))))) - (setq pending-event file-notify--pending-event - file-notify--pending-event nil) - (setcar (cdar pending-event) 'deleted)) - - ;; Map action. We ignore all events which cannot be mapped. - (setq action - (cond - ((memq action - '(attribute-changed changed created deleted renamed)) - action) - ((memq action '(moved rename)) - ;; The kqueue rename event does not return file1 in - ;; case a file monitor is established. - (if (setq file1 (file-notify--event-file1-name event)) - 'renamed 'deleted)) - ((eq action 'ignored) - (setq stopped t actions nil)) - ((memq action '(attrib link)) 'attribute-changed) - ((memq action '(create added)) 'created) - ((memq action '(modify modified write)) 'changed) - ((memq action '(delete delete-self move-self removed)) 'deleted) - ;; Make the event pending. - ((memq action '(moved-from renamed-from)) - (setq file-notify--pending-event - `((,desc ,action ,file ,(file-notify--event-cookie event)) - ,callback)) - nil) - ;; Look for pending event. - ((memq action '(moved-to renamed-to)) - (if (null file-notify--pending-event) - 'created - (setq file1 file - file (file-notify--event-file-name - (car file-notify--pending-event))) - ;; If the source is handled by another watch, we - ;; must fire the rename event there as well. - (when (not (equal (file-notify--descriptor desc file1) - (file-notify--descriptor - (caar file-notify--pending-event) - (file-notify--event-file-name - file-notify--pending-event)))) - (setq pending-event - `((,(caar file-notify--pending-event) - renamed ,file ,file1) - ,(cadr file-notify--pending-event)))) - (setq file-notify--pending-event nil) - 'renamed)))) - - ;; Apply pending callback. - (when pending-event - (setcar - (car pending-event) - (file-notify--descriptor - (caar pending-event) - (file-notify--event-file-name file-notify--pending-event))) - (funcall (cadr pending-event) (car pending-event)) - (setq pending-event nil)) - - ;; Apply callback. - (when (and action - (or - ;; If there is no relative file name for that watch, - ;; we watch the whole directory. - (null (nth 0 entry)) - ;; File matches. - (string-equal - (nth 0 entry) (file-name-nondirectory file)) - ;; Directory matches. - (string-equal - (file-name-nondirectory file) - (file-name-nondirectory (car registered))) - ;; File1 matches. - (and (stringp file1) - (string-equal - (nth 0 entry) (file-name-nondirectory file1))))) - ;;(message - ;;"file-notify-callback %S %S %S %S %S" - ;;(file-notify--descriptor desc (car entry)) - ;;action file file1 registered) - (if file1 - (funcall - callback - `(,(file-notify--descriptor desc (car entry)) - ,action ,file ,file1)) - (funcall - callback - `(,(file-notify--descriptor desc (car entry)) ,action ,file)))) - - ;; Send `stopped' event. - (when (or stopped - (and (memq action '(deleted renamed)) - ;; Not, when a file is backed up. - (not (and (stringp file1) (backup-file-name-p file1))) - ;; Watched file or directory is concerned. - (string-equal - file (file-notify--event-watched-file event)))) - (file-notify-rm-watch (file-notify--descriptor desc (car entry)))))))) + (while actions + (let ((action (pop actions))) + ;; Send pending event, if it doesn't match. + (when (and file-notify--pending-event + ;; The cookie doesn't match. + (not (equal (file-notify--event-cookie + (car file-notify--pending-event)) + (file-notify--event-cookie event))) + (or + ;; inotify. + (and (eq (nth 1 (car file-notify--pending-event)) + 'moved-from) + (not (eq action 'moved-to))) + ;; w32notify. + (and (eq (nth 1 (car file-notify--pending-event)) + 'renamed-from) + (not (eq action 'renamed-to))))) + (setq pending-event file-notify--pending-event + file-notify--pending-event nil) + (setcar (cdar pending-event) 'deleted)) + + ;; Map action. We ignore all events which cannot be mapped. + (setq action + (cond + ((memq action + '(attribute-changed changed created deleted renamed)) + action) + ((memq action '(moved rename)) + ;; The kqueue rename event does not return file1 in + ;; case a file monitor is established. + (if (setq file1 (file-notify--event-file1-name event)) + 'renamed 'deleted)) + ((eq action 'ignored) + (setq stopped t actions nil)) + ((memq action '(attrib link)) 'attribute-changed) + ((memq action '(create added)) 'created) + ((memq action '(modify modified write)) 'changed) + ((memq action '(delete delete-self move-self removed)) + 'deleted) + ;; Make the event pending. + ((memq action '(moved-from renamed-from)) + (setq file-notify--pending-event + `((,desc ,action ,file + ,(file-notify--event-cookie event)) + ,(file-notify--watch-callback watch))) + nil) + ;; Look for pending event. + ((memq action '(moved-to renamed-to)) + (if (null file-notify--pending-event) + 'created + (setq file1 file + file (file-notify--event-file-name + (car file-notify--pending-event))) + ;; If the source is handled by another watch, we + ;; must fire the rename event there as well. + (unless (equal desc (caar file-notify--pending-event)) + (setq pending-event + `((,(caar file-notify--pending-event) + renamed ,file ,file1) + ,(cadr file-notify--pending-event)))) + (setq file-notify--pending-event nil) + 'renamed)))) + + ;; Apply pending callback. + (when pending-event + (funcall (cadr pending-event) (car pending-event)) + (setq pending-event nil)) + + ;; Apply callback. + (when (and action + (or + ;; If there is no relative file name for that + ;; watch, we watch the whole directory. + (null (file-notify--watch-filename watch)) + ;; File matches. + (string-equal + (file-notify--watch-filename watch) + (file-name-nondirectory file)) + ;; Directory matches. + (string-equal + (file-name-nondirectory file) + (file-name-nondirectory + (file-notify--watch-directory watch))) + ;; File1 matches. + (and (stringp file1) + (string-equal + (file-notify--watch-filename watch) + (file-name-nondirectory file1))))) + ;;(message + ;;"file-notify-callback %S %S %S %S %S" + ;;desc action file file1 watch) + (if file1 + (funcall (file-notify--watch-callback watch) + `(,desc ,action ,file ,file1)) + (funcall (file-notify--watch-callback watch) + `(,desc ,action ,file)))) + + ;; Send `stopped' event. + (when (or stopped + (and (memq action '(deleted renamed)) + ;; Not, when a file is backed up. + (not (and (stringp file1) (backup-file-name-p file1))) + ;; Watched file or directory is concerned. + (string-equal + file (file-notify--event-watched-file event)))) + (file-notify-rm-watch desc))))))) ;; `kqueue', `gfilenotify' and `w32notify' return a unique descriptor ;; for every `file-notify-add-watch', while `inotify' returns a unique @@ -338,7 +312,7 @@ FILE is the name of the file whose event is being reported." (if (file-directory-p file) file (file-name-directory file)))) - desc func l-flags registered entry) + desc func l-flags) (unless (file-directory-p dir) (signal 'file-notify-error `("Directory does not exist" ,dir))) @@ -346,13 +320,7 @@ FILE is the name of the file whose event is being reported." (if handler ;; A file name handler could exist even if there is no local ;; file notification support. - (setq desc (funcall - handler 'file-notify-add-watch - ;; kqueue does not report file changes in - ;; directory monitor. So we must watch the file - ;; itself. - (if (eq file-notify--library 'kqueue) file dir) - flags callback)) + (setq desc (funcall handler 'file-notify-add-watch dir flags callback)) ;; Check, whether Emacs has been compiled with file notification ;; support. @@ -390,70 +358,52 @@ FILE is the name of the file whose event is being reported." ;; Call low-level function. (setq desc (funcall + ;; kqueue does not report file changes in directory + ;; monitor. So we must watch the file itself. func (if (eq file-notify--library 'kqueue) file dir) l-flags 'file-notify-callback))) ;; Modify `file-notify-descriptors'. - (setq file (unless (file-directory-p file) (file-name-nondirectory file)) - desc (if (consp desc) (car desc) desc) - registered (gethash desc file-notify-descriptors) - entry `(,file . ,callback)) - (unless (member entry (cdr registered)) - (puthash desc `(,dir ,entry . ,(cdr registered)) file-notify-descriptors)) - + (let ((watch (file-notify--watch-make + dir + (unless (file-directory-p file) (file-name-nondirectory file)) + callback))) + (puthash desc watch file-notify-descriptors)) ;; Return descriptor. - (file-notify--descriptor desc file))) + desc)) (defun file-notify-rm-watch (descriptor) "Remove an existing watch specified by its DESCRIPTOR. DESCRIPTOR should be an object returned by `file-notify-add-watch'." - (let* ((desc (if (consp descriptor) (car descriptor) descriptor)) - (file (if (consp descriptor) (cdr descriptor))) - (registered (gethash desc file-notify-descriptors)) - (dir (car registered)) - (handler (and (stringp dir) - (find-file-name-handler dir 'file-notify-rm-watch)))) - - (when (stringp dir) - ;; Call low-level function. - (when (or (not file) - (and (= (length (cdr registered)) 1) - (assoc file (cdr registered)))) - (condition-case nil - (if handler - ;; A file name handler could exist even if there is no local - ;; file notification support. - (funcall handler 'file-notify-rm-watch descriptor) - - (funcall - (cond - ((eq file-notify--library 'inotify) 'inotify-rm-watch) - ((eq file-notify--library 'kqueue) 'kqueue-rm-watch) - ((eq file-notify--library 'gfilenotify) 'gfile-rm-watch) - ((eq file-notify--library 'w32notify) 'w32notify-rm-watch)) - desc)) - (file-notify-error nil))) - - ;; Modify `file-notify-descriptors'. - (file-notify--rm-descriptor descriptor)))) + (when-let (watch (gethash descriptor file-notify-descriptors)) + (let ((handler (find-file-name-handler + (file-notify--watch-directory watch) + 'file-notify-rm-watch))) + (condition-case nil + (if handler + ;; A file name handler could exist even if there is no + ;; local file notification support. + (funcall handler 'file-notify-rm-watch descriptor) + + (funcall + (cond + ((eq file-notify--library 'inotify) 'inotify-rm-watch) + ((eq file-notify--library 'kqueue) 'kqueue-rm-watch) + ((eq file-notify--library 'gfilenotify) 'gfile-rm-watch) + ((eq file-notify--library 'w32notify) 'w32notify-rm-watch)) + descriptor)) + (file-notify-error nil))) + ;; Modify `file-notify-descriptors'. + (file-notify--rm-descriptor descriptor))) (defun file-notify-valid-p (descriptor) "Check a watch specified by its DESCRIPTOR. DESCRIPTOR should be an object returned by `file-notify-add-watch'." - (let* ((desc (if (consp descriptor) (car descriptor) descriptor)) - (file (if (consp descriptor) (cdr descriptor))) - (registered (gethash desc file-notify-descriptors)) - (dir (car registered)) - handler) - - (when (stringp dir) - (setq handler (find-file-name-handler dir 'file-notify-valid-p)) - - (and (or ;; It is a directory. - (not file) - ;; The file is registered. - (assoc file (cdr registered))) - (if handler + (when-let (watch (gethash descriptor file-notify-descriptors)) + (let ((handler (find-file-name-handler + (file-notify--watch-directory watch) + 'file-notify-valid-p))) + (and (if handler ;; A file name handler could exist even if there is no ;; local file notification support. (funcall handler 'file-notify-valid-p descriptor) @@ -463,9 +413,19 @@ DESCRIPTOR should be an object returned by `file-notify-add-watch'." ((eq file-notify--library 'kqueue) 'kqueue-valid-p) ((eq file-notify--library 'gfilenotify) 'gfile-valid-p) ((eq file-notify--library 'w32notify) 'w32notify-valid-p)) - desc)) + descriptor)) t)))) + +;; TODO: +;; * Watching a /dir/file may receive events for dir. +;; (This may be the desired behaviour.) +;; * Watching a file in a already watched directory +;; If the file is created and *then* a watch is added to that file, the +;; watch might receive events which occurred prior to it being created, +;; due to the way events are propagated during idle time. Note: This +;; may be perfectly acceptable. + ;; The end: (provide 'filenotify) diff --git a/lisp/files-x.el b/lisp/files-x.el index a0cad708425..b7c6f51e658 100644 --- a/lisp/files-x.el +++ b/lisp/files-x.el @@ -585,7 +585,7 @@ Return a new ordered plist list containing only property names from PROPERTIES." nil (mapcar (lambda (property) - (when (plist-member criteria property) + (when (and (plist-member criteria property) (plist-get criteria property)) (list property (plist-get criteria property)))) properties))) @@ -606,12 +606,10 @@ using this connection, see `connection-local-criteria-alist'." ;;;###autoload (defun connection-local-set-profiles (criteria &rest profiles) - "Add PROFILES for remote servers. -CRITERIA is either a regular expression identifying a remote -server, or a function with one argument IDENTIFICATION, which -returns non-nil when a remote server shall apply PROFILE's -variables. If CRITERIA is nil, it always applies. -PROFILES are the names of a connection profile (a symbol). + "Add PROFILES for CRITERIA. +CRITERIA is a plist identifying a connection and the application +using this connection, see `connection-local-criteria-alist'. +PROFILES are the names of connection profiles (a symbol). When a connection to a remote server is opened and CRITERIA matches to that server, the connection-local variables from @@ -678,7 +676,7 @@ will not be changed." ;;;###autoload (defmacro with-connection-local-profiles (profiles &rest body) "Apply connection-local variables according to PROFILES in current buffer. -Execute BODY, and unwind connection local variables." +Execute BODY, and unwind connection-local variables." (declare (indent 1) (debug t)) `(let ((enable-connection-local-variables t) (old-buffer-local-variables (buffer-local-variables)) diff --git a/lisp/files.el b/lisp/files.el index b7d104853c3..2f3efa33c28 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -28,6 +28,10 @@ ;;; Code: +(eval-when-compile + (require 'pcase) + (require 'easy-mmode)) ; For `define-minor-mode'. + (defvar font-lock-keywords) (defgroup backup nil @@ -279,8 +283,13 @@ The value `never' means do not make them." (const :tag "If existing" nil) (other :tag "Always" t)) :group 'backup) + +(defun version-control-safe-local-p (x) + "Return whether X is safe as local value for `version-control'." + (or (booleanp x) (equal x 'never))) + (put 'version-control 'safe-local-variable - (lambda (x) (or (booleanp x) (equal x 'never)))) + #'version-control-safe-local-p) (defcustom dired-kept-versions 2 "When cleaning directory, number of versions to keep." @@ -388,6 +397,49 @@ ignored." :initialize 'custom-initialize-delay :version "21.1") +(defvar auto-save--timer nil "Timer for `auto-save-visited-mode'.") + +(defcustom auto-save-visited-interval 5 + "Interval in seconds for `auto-save-visited-mode'. +If `auto-save-visited-mode' is enabled, Emacs will save all +buffers visiting a file to the visited file after it has been +idle for `auto-save-visited-interval' seconds." + :group 'auto-save + :type 'number + :version "26.1" + :set (lambda (symbol value) + (set-default symbol value) + (when auto-save--timer + (timer-set-idle-time auto-save--timer value :repeat)))) + +(define-minor-mode auto-save-visited-mode + "Toggle automatic saving to file-visiting buffers on or off. +With a prefix argument ARG, enable regular saving of all buffers +visiting a file if ARG is positive, and disable it otherwise. +Unlike `auto-save-mode', this mode will auto-save buffer contents +to the visited files directly and will also run all save-related +hooks. See Info node `Saving' for details of the save process. + +If called from Lisp, enable the mode if ARG is omitted or nil, +and toggle it if ARG is `toggle'." + :group 'auto-save + :global t + (when auto-save--timer (cancel-timer auto-save--timer)) + (setq auto-save--timer + (when auto-save-visited-mode + (run-with-idle-timer + auto-save-visited-interval :repeat + #'save-some-buffers :no-prompt + (lambda () + (not (and buffer-auto-save-file-name + auto-save-visited-file-name))))))) + +;; The 'set' part is so we don't get a warning for using this variable +;; above, while still catching code that _sets_ the variable to get +;; the same effect as the new auto-save-visited-mode. +(make-obsolete-variable 'auto-save-visited-file-name 'auto-save-visited-mode + "Emacs 26.1" 'set) + (defcustom save-abbrevs t "Non-nil means save word abbrevs too when files are saved. If `silently', don't ask the user before saving." @@ -439,7 +491,8 @@ functions are called." (define-obsolete-variable-alias 'write-file-hooks 'write-file-functions "22.1") (defvar write-file-functions nil - "List of functions to be called before writing out a buffer to a file. + "List of functions to be called before saving a buffer to a file. +Only used by `save-buffer'. If one of them returns non-nil, the file is considered already written and the rest are not called. These hooks are considered to pertain to the visited file. @@ -464,6 +517,7 @@ updates before the buffer is saved, use `before-save-hook'.") 'write-contents-functions "22.1") (defvar write-contents-functions nil "List of functions to be called before writing out a buffer to a file. +Only used by `save-buffer'. If one of them returns non-nil, the file is considered already written and the rest are not called and neither are the functions in `write-file-functions'. @@ -540,13 +594,14 @@ settings being applied, but still respect file-local ones.") ;; ignore. So AFAICS the only reason this variable exists is for a ;; minor convenience feature for handling of an obsolete Rmail file format. (defvar local-enable-local-variables t - "Like `enable-local-variables' but meant for buffer-local bindings. + "Like `enable-local-variables', except for major mode in a -*- line. The meaningful values are nil and non-nil. The default is non-nil. -If a major mode sets this to nil, buffer-locally, then any local -variables list in a file visited in that mode will be ignored. +It should be set in a buffer-local fashion. -This variable does not affect the use of major modes specified -in a -*- line.") +Setting this to nil has the same effect as setting `enable-local-variables' +to nil, except that it does not ignore any mode: setting in a -*- line. +Unless this difference matters to you, you should set `enable-local-variables' +instead of this variable.") (defcustom enable-local-eval 'maybe "Control processing of the \"variable\" `eval' in a file's local variables. @@ -2422,7 +2477,7 @@ since only a single case-insensitive search through the alist is made." (lambda (elt) (cons (purecopy (car elt)) (cdr elt))) `(;; do this first, so that .html.pl is Polish html, not Perl - ("\\.[sx]?html?\\(\\.[a-zA-Z_]+\\)?\\'" . html-mode) + ("\\.[sx]?html?\\(\\.[a-zA-Z_]+\\)?\\'" . mhtml-mode) ("\\.svgz?\\'" . image-mode) ("\\.svgz?\\'" . xml-mode) ("\\.x[bp]m\\'" . image-mode) @@ -2784,8 +2839,8 @@ If FUNCTION is nil, then it is not called. (That is a way of saying comment-re "*" "\\(?:!DOCTYPE[ \t\r\n]+[^>]*>[ \t\r\n]*<[ \t\r\n]*" comment-re "*\\)?" "[Hh][Tt][Mm][Ll]")) - . html-mode) - ("<!DOCTYPE[ \t\r\n]+[Hh][Tt][Mm][Ll]" . html-mode) + . mhtml-mode) + ("<!DOCTYPE[ \t\r\n]+[Hh][Tt][Mm][Ll]" . mhtml-mode) ;; These two must come after html, because they are more general: ("<\\?xml " . xml-mode) (,(let* ((incomment-re "\\(?:[^-]\\|-[^-]\\)") @@ -2909,11 +2964,18 @@ we don't actually set it to the same mode the buffer already has." (narrow-to-region (point-min) (min (point-max) (+ (point-min) magic-mode-regexp-match-limit))) - (assoc-default nil magic-mode-alist - (lambda (re _dummy) - (if (functionp re) - (funcall re) - (looking-at re))))))) + (assoc-default + nil magic-mode-alist + (lambda (re _dummy) + (cond + ((functionp re) + (funcall re)) + ((stringp re) + (looking-at re)) + (t + (error + "Problem in magic-mode-alist with element %s" + re)))))))) (set-auto-mode-0 done keep-mode-if-same))) ;; Next compare the filename against the entries in auto-mode-alist. (unless done @@ -2965,10 +3027,16 @@ we don't actually set it to the same mode the buffer already has." (min (point-max) (+ (point-min) magic-mode-regexp-match-limit))) (assoc-default nil magic-fallback-mode-alist - (lambda (re _dummy) - (if (functionp re) - (funcall re) - (looking-at re))))))) + (lambda (re _dummy) + (cond + ((functionp re) + (funcall re)) + ((stringp re) + (looking-at re)) + (t + (error + "Problem with magic-fallback-mode-alist element: %s" + re)))))))) (set-auto-mode-0 done keep-mode-if-same))) (unless done (set-buffer-major-mode (current-buffer))))) @@ -4842,13 +4910,15 @@ the last real save, but optional arg FORCE non-nil means delete anyway." "Normal hook run just before auto-saving.") (defcustom before-save-hook nil - "Normal hook that is run before a buffer is saved to its file." + "Normal hook that is run before a buffer is saved to its file. +Only used by `save-buffer'." :options '(copyright-update time-stamp) :type 'hook :group 'files) (defcustom after-save-hook nil - "Normal hook that is run after a buffer is saved to its file." + "Normal hook that is run after a buffer is saved to its file. +Only used by `save-buffer'." :options '(executable-make-buffer-file-executable-if-script-p) :type 'hook :group 'files) @@ -5411,7 +5481,7 @@ RECURSIVE if DIRECTORY is nonempty." (let ((handler (find-file-name-handler directory 'delete-directory))) (cond (handler - (funcall handler 'delete-directory directory recursive)) + (funcall handler 'delete-directory directory recursive trash)) ((and delete-by-moving-to-trash trash) ;; Only move non-empty dir to trash if recursive deletion was ;; requested. This mimics the non-`delete-by-moving-to-trash' @@ -5825,6 +5895,8 @@ an auto-save file." (defun recover-this-file () "Recover the visited file--get contents from its last auto-save file." (interactive) + (or buffer-file-name + (user-error "This buffer is not visiting a file")) (recover-file buffer-file-name)) (defun recover-file (file) @@ -6008,16 +6080,18 @@ specifies the list of buffers to kill, asking for approval for each one." (kill-buffer-ask buffer))) (setq list (cdr list)))) -(defun kill-matching-buffers (regexp &optional internal-too) +(defun kill-matching-buffers (regexp &optional internal-too no-ask) "Kill buffers whose name matches the specified REGEXP. -The optional second argument indicates whether to kill internal buffers too." +Ignores buffers whose name starts with a space, unless optional +prefix argument INTERNAL-TOO is non-nil. Asks before killing +each buffer, unless NO-ASK is non-nil." (interactive "sKill buffers matching this regular expression: \nP") (dolist (buffer (buffer-list)) (let ((name (buffer-name buffer))) (when (and name (not (string-equal name "")) (or internal-too (/= (aref name 0) ?\s)) (string-match regexp name)) - (kill-buffer-ask buffer))))) + (funcall (if no-ask 'kill-buffer 'kill-buffer-ask) buffer))))) (defun rename-auto-save-file () @@ -6891,7 +6965,15 @@ only these files will be asked to be saved." (defun file-name-non-special (operation &rest arguments) (let ((file-name-handler-alist nil) (default-directory - (if (eq operation 'insert-directory) + ;; Some operations respect file name handlers in + ;; `default-directory'. Because core function like + ;; `call-process' don't care about file name handlers in + ;; `default-directory', we here have to resolve the + ;; directory into a local one. For `process-file', + ;; `start-file-process', and `shell-command', this fixes + ;; Bug#25949. + (if (memq operation '(insert-directory process-file start-file-process + shell-command)) (directory-file-name (expand-file-name (unhandled-file-name-directory default-directory))) @@ -6955,8 +7037,18 @@ only these files will be asked to be saved." (when (and visit buffer-file-name) (setq buffer-file-name (concat "/:" buffer-file-name)))))) (`unquote-then-quote - (let ((buffer-file-name (substring buffer-file-name 2))) - (apply operation arguments))) + ;; We can't use `cl-letf' with `(buffer-local-value)' here + ;; because it wouldn't work during bootstrapping. + (let ((buffer (current-buffer))) + ;; `unquote-then-quote' is only used for the + ;; `verify-visited-file-modtime' action, which takes a buffer + ;; as only optional argument. + (with-current-buffer (or (car arguments) buffer) + (let ((buffer-file-name (substring buffer-file-name 2))) + ;; Make sure to hide the temporary buffer change from the + ;; underlying operation. + (with-current-buffer buffer + (apply operation arguments)))))) (_ (apply operation arguments))))) diff --git a/lisp/find-file.el b/lisp/find-file.el index e02bea06fc0..d3691694d17 100644 --- a/lisp/find-file.el +++ b/lisp/find-file.el @@ -242,11 +242,11 @@ the preceding slash. The star represents all the subdirectories except (defcustom cc-other-file-alist '(("\\.cc\\'" (".hh" ".h")) - ("\\.hh\\'" (".cc" ".C")) + ("\\.hh\\'" (".cc" ".C" ".CC" ".cxx" ".cpp" ".c++")) ("\\.c\\'" (".h")) ("\\.m\\'" (".h")) - ("\\.h\\'" (".c" ".cc" ".C" ".CC" ".cxx" ".cpp" ".m")) + ("\\.h\\'" (".c" ".cc" ".C" ".CC" ".cxx" ".cpp" ".c++" ".m")) ("\\.C\\'" (".H" ".hh" ".h")) ("\\.H\\'" (".C" ".CC")) diff --git a/lisp/finder.el b/lisp/finder.el index 5b019b2a04e..361572f7c2d 100644 --- a/lisp/finder.el +++ b/lisp/finder.el @@ -130,8 +130,8 @@ Keywords and package names both should be symbols.") ;; useful, and because in parallel builds of Emacs they may get ;; modified while we are trying to read them. ;; http://lists.gnu.org/archive/html/emacs-pretest-bug/2007-01/msg00469.html -;; ldefs-boot-* are not auto-generated during build, but has nothing useful. -(defvar finder-no-scan-regexp "\\(^\\.#\\|\\(loaddefs\\|ldefs-boot-.*\\|\ +;; ldefs-boot is not auto-generated, but has nothing useful. +(defvar finder-no-scan-regexp "\\(^\\.#\\|\\(loaddefs\\|ldefs-boot\\|\ cus-load\\|finder-inf\\|esh-groups\\|subdirs\\|leim-list\\)\\.el$\\)" "Regexp matching file names not to scan for keywords.") diff --git a/lisp/follow.el b/lisp/follow.el index db3b2821a56..5dd74f37a18 100644 --- a/lisp/follow.el +++ b/lisp/follow.el @@ -340,7 +340,7 @@ property `follow-mode-use-cache' to non-nil.") (defvar follow-inactive-menu nil "The menu visible when Follow mode is inactive.") -(defvar follow-inside-post-command-hook nil +(defvar follow-inside-post-command-hook-call nil "Non-nil when inside Follow modes `post-command-hook'. Used by `follow-window-size-change'.") @@ -1277,7 +1277,7 @@ non-first windows in Follow mode." (defun follow-post-command-hook () "Ensure that the windows in Follow mode are adjacent after each command." (unless (input-pending-p) - (let ((follow-inside-post-command-hook t) + (let ((follow-inside-post-command-hook-call t) (win (selected-window))) ;; Work in the selected window, not in the current buffer. (with-current-buffer (window-buffer win) @@ -1519,14 +1519,14 @@ non-first windows in Follow mode." ;; Since `follow-window-size-change' can be called indirectly from ;; `follow-post-command-hook' we have a potential infinite loop. To ;; avoid this, we simply do not do anything in this situation. The -;; variable `follow-inside-post-command-hook' contains information -;; about whether the execution actually is inside the +;; variable `follow-inside-post-command-hook-call' contains +;; information about whether the execution actually is inside the ;; post-command-hook or not. (defun follow-window-size-change (frame) "Redraw all windows in FRAME, when in Follow mode." ;; Below, we call `post-command-hook'. Avoid an infloop. - (unless follow-inside-post-command-hook + (unless follow-inside-post-command-hook-call (save-current-buffer (let ((orig-frame (selected-frame))) (select-frame frame) diff --git a/lisp/frame.el b/lisp/frame.el index 0a35b715b3d..7d571791e23 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -115,15 +115,16 @@ appended when the minibuffer frame is created." (defun handle-delete-frame (event) "Handle delete-frame events from the X server." (interactive "e") - (let ((frame (posn-window (event-start event))) - (i 0) - (tail (frame-list))) - (while tail - (and (frame-visible-p (car tail)) - (not (eq (car tail) frame)) - (setq i (1+ i))) - (setq tail (cdr tail))) - (if (> i 0) + (let* ((frame (posn-window (event-start event)))) + (if (catch 'other-frame + (dolist (frame-1 (frame-list)) + ;; A valid "other" frame is visible, has its `delete-before' + ;; parameter unset and is not a child frame. + (when (and (not (eq frame-1 frame)) + (frame-visible-p frame-1) + (not (frame-parent frame-1)) + (not (frame-parameter frame-1 'delete-before))) + (throw 'other-frame t)))) (delete-frame frame t) ;; Gildea@x.org says it is ok to ask questions before terminating. (save-buffers-kill-emacs)))) @@ -144,6 +145,13 @@ Focus-out events occur when no frame has focus. This function runs the hook `focus-out-hook'." (interactive "e") (run-hooks 'focus-out-hook)) + +(defun handle-move-frame (event) + "Handle a move-frame event. +This function runs the abnormal hook `move-frame-functions'." + (interactive "e") + (let ((frame (posn-window (event-start event)))) + (run-hook-with-args 'move-frame-functions frame))) ;;;; Arrangement of frames at startup @@ -827,21 +835,24 @@ All frames are arranged in a cyclic order. This command selects the frame ARG steps away in that order. A negative ARG moves in the opposite order. -To make this command work properly, you must tell Emacs -how the system (or the window manager) generally handles -focus-switching between windows. If moving the mouse onto a window -selects it (gives it focus), set `focus-follows-mouse' to t. -Otherwise, that variable should be nil." +To make this command work properly, you must tell Emacs how the +system (or the window manager) generally handles focus-switching +between windows. If moving the mouse onto a window selects +it (gives it focus), set `focus-follows-mouse' to t. Otherwise, +that variable should be nil." (interactive "p") - (let ((frame (selected-frame))) + (let ((sframe (selected-frame)) + (frame (selected-frame))) (while (> arg 0) (setq frame (next-frame frame)) - (while (not (eq (frame-visible-p frame) t)) + (while (and (not (eq frame sframe)) + (not (eq (frame-visible-p frame) t))) (setq frame (next-frame frame))) (setq arg (1- arg))) (while (< arg 0) (setq frame (previous-frame frame)) - (while (not (eq (frame-visible-p frame) t)) + (while (and (not (eq frame sframe)) + (not (eq (frame-visible-p frame) t))) (setq frame (previous-frame frame))) (setq arg (1+ arg))) (select-frame-set-input-focus frame))) @@ -1099,6 +1110,38 @@ differing font heights." If FRAME is omitted, describe the currently selected frame." (cdr (assq 'width (frame-parameters frame)))) +(defalias 'frame-border-width 'frame-internal-border-width) +(defalias 'frame-pixel-width 'frame-native-width) +(defalias 'frame-pixel-height 'frame-native-height) + +(defun frame-inner-width (&optional frame) + "Return inner width of FRAME in pixels. +FRAME defaults to the selected frame." + (setq frame (window-normalize-frame frame)) + (- (frame-native-width frame) + (* 2 (frame-internal-border-width frame)))) + +(defun frame-inner-height (&optional frame) + "Return inner height of FRAME in pixels. +FRAME defaults to the selected frame." + (setq frame (window-normalize-frame frame)) + (- (frame-native-height frame) + (* 2 (frame-internal-border-width frame)))) + +(defun frame-outer-width (&optional frame) + "Return outer width of FRAME in pixels. +FRAME defaults to the selected frame." + (setq frame (window-normalize-frame frame)) + (let ((edges (frame-edges frame 'outer-edges))) + (- (nth 2 edges) (nth 0 edges)))) + +(defun frame-outer-height (&optional frame) + "Return outer height of FRAME in pixels. +FRAME defaults to the selected frame." + (setq frame (window-normalize-frame frame)) + (let ((edges (frame-edges frame 'outer-edges))) + (- (nth 3 edges) (nth 1 edges)))) + (declare-function x-list-fonts "xfaces.c" (pattern &optional face frame maximum width)) @@ -1373,6 +1416,7 @@ and width values are in pixels. '(outer-position 0 . 0) (cons 'outer-size (cons (frame-width frame) (frame-height frame))) '(external-border-size 0 . 0) + '(outer-border-width . 0) '(title-bar-size 0 . 0) '(menu-bar-external . nil) (let ((menu-bar-lines (frame-parameter frame 'menu-bar-lines))) @@ -1453,6 +1497,7 @@ position (0, 0) of the selected frame's terminal." (t (cons 0 0))))) +(declare-function ns-set-mouse-absolute-pixel-position "nsfns.m" (x y)) (declare-function w32-set-mouse-absolute-pixel-position "w32fns.c" (x y)) (declare-function x-set-mouse-absolute-pixel-position "xfns.c" (x y)) @@ -1462,6 +1507,8 @@ The coordinates X and Y are interpreted in pixels relative to a position (0, 0) of the selected frame's terminal." (let ((frame-type (framep-on-display))) (cond + ((eq frame-type 'ns) + (ns-set-mouse-absolute-pixel-position x y)) ((eq frame-type 'x) (x-set-mouse-absolute-pixel-position x y)) ((eq frame-type 'w32) @@ -1483,6 +1530,157 @@ keys and their meanings." for frames = (cdr (assq 'frames attributes)) if (memq frame frames) return attributes)) +(defun frame-monitor-attribute (attribute &optional frame x y) + "Return the value of ATTRIBUTE on FRAME's monitor. +If FRAME is omitted or nil, use currently selected frame. + +By default, the current monitor is the physical monitor +dominating the selected frame. A frame is dominated by a +physical monitor when either the largest area of the frame +resides in the monitor, or the monitor is the closest to the +frame if the frame does not intersect any physical monitors. + +If X and Y are both numbers, then ignore the value of FRAME; the +monitor is determined to be the physical monitor that contains +the pixel coordinate (X, Y). + +See `display-monitor-attributes-list' for the list of attribute +keys and their meanings." + (if (and (numberp x) + (numberp y)) + (cl-loop for monitor in (display-monitor-attributes-list) + for geometry = (alist-get 'geometry monitor) + for min-x = (pop geometry) + for min-y = (pop geometry) + for max-x = (+ min-x (pop geometry)) + for max-y = (+ min-y (car geometry)) + when (and (<= min-x x) + (< x max-x) + (<= min-y y) + (< y max-y)) + return (alist-get attribute monitor)) + (alist-get attribute (frame-monitor-attributes frame)))) + +(defun frame-monitor-geometry (&optional frame x y) + "Return the geometry of FRAME's monitor. +FRAME can be a frame name, a terminal name, or a frame. +If FRAME is omitted or nil, use the currently selected frame. + +By default, the current monitor is said to be the physical +monitor dominating the selected frame. A frame is dominated by +a physical monitor when either the largest area of the frame resides +in the monitor, or the monitor is the closest to the frame if the +frame does not intersect any physical monitors. + +If X and Y are both numbers, then ignore the value of FRAME; the +monitor is determined to be the physical monitor that contains +the pixel coordinate (X, Y). + +See `display-monitor-attributes-list' for information on the +geometry attribute." + (frame-monitor-attribute 'geometry frame x y)) + +(defun frame-monitor-workarea (&optional frame x y) + "Return the workarea of FRAME's monitor. +FRAME can be a frame name, a terminal name, or a frame. +If FRAME is omitted or nil, use currently selected frame. + +By default, the current monitor is said to be the physical +monitor dominating the selected frame. A frame is dominated by +a physical monitor when either the largest area of the frame resides +in the monitor, or the monitor is the closest to the frame if the +frame does not intersect any physical monitors. + +If X and Y are both numbers, then ignore the value of FRAME; the +monitor is determined to be the physical monitor that contains +the pixel coordinate (X, Y). + +See `display-monitor-attributes-list' for information on the +workarea attribute." + (frame-monitor-attribute 'workarea frame x y)) + +(declare-function x-frame-list-z-order "xfns.c" (&optional display)) +(declare-function w32-frame-list-z-order "w32fns.c" (&optional display)) +(declare-function ns-frame-list-z-order "nsfns.m" (&optional display)) + +(defun frame-list-z-order (&optional display) + "Return list of Emacs' frames, in Z (stacking) order. +The optional argument DISPLAY specifies which display to poll. +DISPLAY should be either a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. + +Frames are listed from topmost (first) to bottommost (last). As +a special case, if DISPLAY is non-nil and specifies a live frame, +return the child frames of that frame in Z (stacking) order. + +Return nil if DISPLAY contains no Emacs frame." + (let ((frame-type (framep-on-display display))) + (cond + ((eq frame-type 'x) + (x-frame-list-z-order display)) + ((eq frame-type 'w32) + (w32-frame-list-z-order display)) + ((eq frame-type 'ns) + (ns-frame-list-z-order display))))) + +(declare-function x-frame-restack "xfns.c" (frame1 frame2 &optional above)) +(declare-function w32-frame-restack "w32fns.c" (frame1 frame2 &optional above)) +(declare-function ns-frame-restack "nsfns.m" (frame1 frame2 &optional above)) + +(defun frame-restack (frame1 frame2 &optional above) + "Restack FRAME1 below FRAME2. +This implies that if both frames are visible and the display +areas of these frames overlap, FRAME2 will (partially) obscure +FRAME1. If the optional third argument ABOVE is non-nil, restack +FRAME1 above FRAME2. This means that if both frames are visible +and the display areas of these frames overlap, FRAME1 will +\(partially) obscure FRAME2. + +This may be thought of as an atomic action performed in two +steps: The first step removes FRAME1's window-system window from +the display. The second step reinserts FRAME1's window +below (above if ABOVE is true) that of FRAME2. Hence the +position of FRAME2 in its display's Z (stacking) order relative +to all other frames excluding FRAME1 remains unaltered. + +Some window managers may refuse to restack windows. " + (if (and (frame-live-p frame1) + (frame-live-p frame2) + (equal (frame-parameter frame1 'display) + (frame-parameter frame2 'display))) + (let ((frame-type (framep-on-display frame1))) + (cond + ((eq frame-type 'x) + (x-frame-restack frame1 frame2 above)) + ((eq frame-type 'w32) + (w32-frame-restack frame1 frame2 above)) + ((eq frame-type 'ns) + (ns-frame-restack frame1 frame2 above)))) + (error "Cannot restack frames"))) + +(defun frame-size-changed-p (&optional frame) + "Return non-nil when the size of FRAME has changed. +More precisely, return non-nil when the inner width or height of +FRAME has changed since `window-size-change-functions' was run +for FRAME." + (let* ((frame (window-normalize-frame frame)) + (root (frame-root-window frame)) + (mini (minibuffer-window frame)) + (mini-height-before-size-change 0) + (mini-height 0)) + ;; FRAME's minibuffer window counts iff it's on FRAME and FRAME is + ;; not a minibuffer-only frame. + (when (and (eq (window-frame mini) frame) (not (eq mini root))) + (setq mini-height-before-size-change + (window-pixel-height-before-size-change mini)) + (setq mini-height (window-pixel-height mini))) + ;; Return non-nil when either the width of the root or the sum of + ;; the heights of root and minibuffer window changed. + (or (/= (window-pixel-width-before-size-change root) + (window-pixel-width root)) + (/= (+ (window-pixel-height-before-size-change root) + mini-height-before-size-change) + (+ (window-pixel-height root) mini-height))))) ;;;; Frame/display capabilities. @@ -1856,7 +2054,7 @@ A geometry specification equivalent to SPEC for FRAME is returned, where the value is a cons with car `+', not numeric. SPEC is a frame geometry spec: (left . VALUE) or (top . VALUE). If VALUE is a number, then it is converted to a cons value, perhaps - relative to the opposite frame edge from that in the original spec. +relative to the opposite frame edge from that in the original spec. FRAME defaults to the selected frame. Examples (measures in pixels) - @@ -1877,24 +2075,36 @@ the opposite frame edge from the edge indicated in the input spec." (defun delete-other-frames (&optional frame) "Delete all frames on FRAME's terminal, except FRAME. If FRAME uses another frame's minibuffer, the minibuffer frame is -left untouched. FRAME must be a live frame and defaults to the -selected one." +left untouched. Do not delete any of FRAME's child frames. If +FRAME is a child frame, delete its siblings only. FRAME must be +a live frame and defaults to the selected one." (interactive) (setq frame (window-normalize-frame frame)) (let ((minibuffer-frame (window-frame (minibuffer-window frame))) (this (next-frame frame t)) + (parent (frame-parent frame)) next) ;; In a first round consider minibuffer-less frames only. (while (not (eq this frame)) (setq next (next-frame this t)) - (unless (eq (window-frame (minibuffer-window this)) this) + (unless (or (eq (window-frame (minibuffer-window this)) this) + ;; When FRAME is a child frame, delete its siblings + ;; only. + (and parent (not (eq (frame-parent this) parent))) + ;; Do not delete a child frame of FRAME. + (eq (frame-parent this) frame)) (delete-frame this)) (setq this next)) ;; In a second round consider all remaining frames. (setq this (next-frame frame t)) (while (not (eq this frame)) (setq next (next-frame this t)) - (unless (eq this minibuffer-frame) + (unless (or (eq this minibuffer-frame) + ;; When FRAME is a child frame, delete its siblings + ;; only. + (and parent (not (eq (frame-parent this) parent))) + ;; Do not delete a child frame of FRAME. + (eq (frame-parent this) frame)) (delete-frame this)) (setq this next)))) @@ -2248,7 +2458,13 @@ See also `toggle-frame-maximized'." (make-obsolete-variable 'window-system-version "it does not give useful information." "24.3") -;; Variables which should trigger redisplay of the current buffer. +;; Variables whose change of value should trigger redisplay of the +;; current buffer. +;; To test whether a given variable needs to be added to this list, +;; write a simple interactive function that changes the variable's +;; value and bind that function to a simple key, like F5. If typing +;; F5 then produces the correct effect, the variable doesn't need +;; to be in this list; otherwise, it does. (mapc (lambda (var) (add-variable-watcher var (symbol-function 'set-buffer-redisplay))) '(line-spacing @@ -2256,6 +2472,10 @@ See also `toggle-frame-maximized'." line-prefix wrap-prefix truncate-lines + display-line-numbers + display-line-numbers-width + display-line-numbers-current-absolute + display-line-numbers-widen bidi-paragraph-direction bidi-display-reordering)) diff --git a/lisp/frameset.el b/lisp/frameset.el index 2dd3050ef76..ebf09d3ab5c 100644 --- a/lisp/frameset.el +++ b/lisp/frameset.el @@ -446,6 +446,7 @@ DO NOT MODIFY. See `frameset-filter-alist' for a full description.") (buffer-list . :never) (buffer-predicate . :never) (buried-buffer-list . :never) + (delete-before . :never) (font . frameset-filter-shelve-param) (foreground-color . frameset-filter-sanitize-color) (fullscreen . frameset-filter-shelve-param) @@ -455,7 +456,9 @@ DO NOT MODIFY. See `frameset-filter-alist' for a full description.") (GUI:width . frameset-filter-unshelve-param) (height . frameset-filter-shelve-param) (outer-window-id . :never) + (parent-frame . :never) (parent-id . :never) + (mouse-wheel-frame . :never) (tty . frameset-filter-tty-to-GUI) (tty-type . frameset-filter-tty-to-GUI) (width . frameset-filter-shelve-param) @@ -717,9 +720,18 @@ If nil, check all live frames." ;; Saving framesets -(defun frameset--record-minibuffer-relationships (frame-list) - "Process FRAME-LIST and record minibuffer relationships. -FRAME-LIST is a list of frames. Internal use only." +(defun frameset--record-relationships (frame-list) + "Process FRAME-LIST and record relationships. +FRAME-LIST is a list of frames. + +The relationships recorded for each frame are + +- `minibuffer' via `frameset--mini' +- `delete-before' via `frameset--delete-before' +- `parent-frame' via `frameset--parent-frame' +- `mouse-wheel-frame' via `frameset--mouse-wheel-frame' + +Internal use only." ;; Record frames with their own minibuffer (dolist (frame (minibuffer-frame-list)) (when (memq frame frame-list) @@ -730,22 +742,41 @@ FRAME-LIST is a list of frames. Internal use only." (set-frame-parameter frame 'frameset--mini (cons t (eq frame default-minibuffer-frame))))) - ;; Now link minibufferless frames with their minibuffer frames + ;; Now link minibufferless frames with their minibuffer frames and + ;; store `parent-frame', `delete-before' and `mouse-wheel-frame' + ;; relationships in a similar way. (dolist (frame frame-list) - (unless (frame-parameter frame 'frameset--mini) - (frameset--set-id frame) - (let ((mb-frame (window-frame (minibuffer-window frame)))) - ;; For minibufferless frames, frameset--mini is a cons - ;; (nil . FRAME-ID), where FRAME-ID is the frameset--id of - ;; the frame containing its minibuffer window. - ;; FRAME-ID can be set to nil, if FRAME-LIST doesn't contain - ;; the minibuffer frame of a minibufferless frame; we allow - ;; it without trying to second-guess the user. - (set-frame-parameter frame - 'frameset--mini - (cons nil - (and mb-frame - (frameset-frame-id mb-frame)))))))) + (let ((parent-frame (frame-parent frame)) + (delete-before (frame-parameter frame 'delete-before)) + (mouse-wheel-frame (frame-parameter frame 'mouse-wheel-frame)) + (nomini (not (frame-parameter frame 'frameset--mini)))) + (when (or nomini parent-frame delete-before mouse-wheel-frame) + (when nomini + (frameset--set-id frame)) + (when parent-frame + (set-frame-parameter + frame 'frameset--parent-frame (frameset-frame-id parent-frame))) + (when delete-before + (set-frame-parameter + frame 'frameset--delete-before (frameset-frame-id delete-before))) + (when mouse-wheel-frame + (set-frame-parameter + frame 'frameset--mouse-wheel-frame + (frameset-frame-id mouse-wheel-frame))) + (when nomini + (let ((mb-frame (window-frame (minibuffer-window frame)))) + ;; For minibufferless frames, frameset--mini is a cons + ;; (nil . FRAME-ID), where FRAME-ID is the frameset--id of + ;; the frame containing its minibuffer window. + ;; FRAME-ID can be set to nil, if FRAME-LIST doesn't contain + ;; the minibuffer frame of a minibufferless frame; we allow + ;; it without trying to second-guess the user. + (set-frame-parameter + frame + 'frameset--mini + (cons nil + (and mb-frame + (frameset-frame-id mb-frame)))))))))) ;;;###autoload (cl-defun frameset-save (frame-list @@ -768,7 +799,7 @@ PROPERTIES is a user-defined property list to add to the frameset." (cl-delete-if-not predicate list) list))) fs) - (frameset--record-minibuffer-relationships frames) + (frameset--record-relationships frames) (setq fs (frameset--make :app app :name name @@ -993,6 +1024,14 @@ Internal use only." (frameset--initial-params filtered-cfg)))) (puthash frame :created frameset--action-map)) + ;; Try to assign parent-frame right here - it will improve things + ;; for minibuffer-less child frames. + (let* ((frame-id (frame-parameter frame 'frameset--parent-frame)) + (parent-frame + (and frame-id (frameset-frame-with-id frame-id)))) + (when (frame-live-p parent-frame) + (set-frame-parameter frame 'parent-frame parent-frame))) + (modify-frame-parameters frame (if (eq (frame-parameter frame 'fullscreen) fullscreen) ;; Workaround for bug#14949 @@ -1205,6 +1244,29 @@ All keyword parameters default to nil." (error (delay-warning 'frameset (error-message-string err) :error)))))) + ;; Setting the parent frame after the frame has been created is a + ;; pain because one can see the frame move on the screen. Ideally, + ;; we would restore minibuffer equipped child frames after their + ;; respective parents have been made but this might interfere with + ;; the reordering of minibuffer frames. Left to the experts ... + (dolist (frame (frame-list)) + (let* ((frame-id (frame-parameter frame 'frameset--parent-frame)) + (parent-frame + (and frame-id (frameset-frame-with-id frame-id)))) + (when (and (not (eq (frame-parameter frame 'parent-frame) parent-frame)) + (frame-live-p parent-frame)) + (set-frame-parameter frame 'parent-frame parent-frame))) + (let* ((frame-id (frame-parameter frame 'frameset--delete-before)) + (delete-before + (and frame-id (frameset-frame-with-id frame-id)))) + (when (frame-live-p delete-before) + (set-frame-parameter frame 'delete-before delete-before))) + (let* ((frame-id (frame-parameter frame 'frameset--mouse-wheel-frame)) + (mouse-wheel-frame + (and frame-id (frameset-frame-with-id frame-id)))) + (when (frame-live-p mouse-wheel-frame) + (set-frame-parameter frame 'mouse-wheel-frame mouse-wheel-frame)))) + ;; In case we try to delete the initial frame, we want to make sure that ;; other frames are already visible (discussed in thread for bug#14841). (sit-for 0 t) diff --git a/lisp/gnus/canlock.el b/lisp/gnus/canlock.el index 9e13ced4670..5157256594d 100644 --- a/lisp/gnus/canlock.el +++ b/lisp/gnus/canlock.el @@ -72,8 +72,7 @@ buffer does not look like a news message." (defun canlock-sha1 (message) "Make a SHA-1 digest of MESSAGE as a unibyte string of length 20 bytes." - (let (sha1-maximum-internal-length) - (sha1 message nil nil 'binary))) + (sha1 message nil nil 'binary)) (defun canlock-make-cancel-key (message-id password) "Make a Cancel-Key header." @@ -87,10 +86,7 @@ buffer does not look like a news message." (char-to-string (logxor 92 byte))) password ""))) (base64-encode-string - (canlock-sha1 - (concat opad - (canlock-sha1 - (concat ipad (string-as-unibyte message-id)))))))) + (canlock-sha1 (concat opad (canlock-sha1 (concat ipad message-id))))))) (defun canlock-narrow-to-header () "Narrow the buffer to the head of the message." diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el index a4ff840f755..3f384c65ece 100644 --- a/lisp/gnus/gnus-art.el +++ b/lisp/gnus/gnus-art.el @@ -3430,13 +3430,20 @@ possible values." (progn (goto-char date-position) (setq date (get-text-property (point) 'original-date)) + (beginning-of-line) (when (looking-at "[^:]+:[\t ]*") (setq bface (get-text-property (match-beginning 0) 'face) eface (get-text-property (match-end 0) 'face))) - (delete-region (point) - (progn - (gnus-article-forward-header) - (point))) + (goto-char date-position) + (delete-region + (or (and (bolp) date-position) + ;; There might be space(s) added for line unfolding. + (and (get-text-property date-position 'gnus-date-type) + (< (skip-chars-backward "\t ") 0) + (text-property-any (point) date-position + 'gnus-date-type nil)) + date-position) + (progn (gnus-article-forward-header) (point))) (article-transform-date date type bface eface)) (save-restriction (widen) @@ -3455,9 +3462,14 @@ possible values." (when (looking-at "[^:]+:[\t ]*") (setq bface (get-text-property (match-beginning 0) 'face) eface (get-text-property (match-end 0) 'face))) - (delete-region pos (or (text-property-any pos (point-max) - 'gnus-date-type nil) - (point-max)))) + ;; Note: a feature like `gnus-treat-unfold-headers' breaks + ;; the continuity of text props of a multi-line Date header, + ;; that a user-defined date format might create, by adding + ;; spaces. So, don't rely on gnus-date-type or original-date + ;; text prop in case of searching for the header boundary. + (delete-region pos (progn + (gnus-article-forward-header) + (point)))) (unless date ;; the 1st time (goto-char (point-min)) (while (re-search-forward "^Date:[\t ]*" nil t) @@ -3477,32 +3489,48 @@ possible values." (widen))))))) (defun article-transform-date (date type bface eface) - (dolist (this-type (cond - ((null type) - (list 'ut)) - ((atom type) - (list type)) - (t - type))) - (goto-char - (prog1 - (point) - (add-text-properties - (point) - (progn - (insert (article-make-date-line date (or this-type 'ut)) "\n") - (point)) - (list 'original-date date 'gnus-date-type this-type)))) - ;; Do highlighting. - (when (looking-at - "\\([^:]+:\\)[\t ]*\\(\\(?:[^\t\n ]+[\t ]+\\)*[^\t\n ]+\\)?") - (put-text-property (match-beginning 1) (match-end 1) 'face bface) + (let (begin date-line) + (dolist (this-type (cond ((null type) + (list 'ut)) + ((atom type) + (list type)) + (t + type))) + (setq begin (point) + date-line (article-make-date-line date (or this-type 'ut))) + (if (and (eq this-type 'user-defined) (bolp) + ;; Test if this is not a continuation. + (not (get-text-property + (prog2 (end-of-line 0) (point) (goto-char begin)) + 'gnus-date-type))) + (progn + (string-match "\\`\\([^\t\n :]+:\\)?[\t ]*" date-line) + (if (match-beginning 1) + (insert date-line "\n") + ;; This user-defined date seems to intend to be a continuation + ;; line of a multi-line Date header like this: + ;; Date: Thu, Jan 1 00:00:00 1970 +0000 + ;; (47 years, 5 months, 20 days ago) + (insert "Date: " (substring date-line (match-end 0)) "\n"))) + (insert date-line "\n")) + (add-text-properties begin (point) (list 'original-date date + 'gnus-date-type this-type)) + (goto-char begin) + ;; Do highlighting. + (beginning-of-line) + (looking-at + "\\([^\n:]+:\\)?[\t ]*\\(\\(?:[^\t\n ]+[\t ]+\\)*[^\t\n ]+\\)?") + (when (and bface (match-beginning 1)) + (put-text-property (match-beginning 1) (match-end 1) 'face bface)) (when (match-beginning 2) - (put-text-property (match-beginning 2) (match-end 2) 'face eface)) - (while (and (zerop (forward-line 1)) - (looking-at "[\t ]+\\(\\(?:[^\t\n ]+[\t ]+\\)*[^\t\n ]+\\)?")) - (when (match-beginning 1) - (put-text-property (match-beginning 1) (match-end 1) 'face eface)))))) + (when eface + (put-text-property (match-beginning 2) (match-end 2) 'face eface)) + (while (and (zerop (forward-line 1)) + (looking-at + "[\t ]+\\(\\(?:[^\t\n ]+[\t ]+\\)*[^\t\n ]+\\)?")) + (when (and eface (match-beginning 1)) + (put-text-property (match-beginning 1) (match-end 1) + 'face eface))))))) (defun article-make-date-line (date type) "Return a DATE line of TYPE." @@ -3735,7 +3763,7 @@ is to run." "Convert the current article date to the user-defined format. This format is defined by the `gnus-article-time-format' variable." (interactive (list t)) - (article-date-ut 'user highlight)) + (article-date-ut 'user-defined highlight)) (defun article-date-iso8601 (&optional highlight) "Convert the current article date to ISO8601." @@ -6672,7 +6700,7 @@ not have a face in `gnus-article-boring-faces'." (interactive "P") (gnus-article-check-buffer) (let ((nosaves - '("q" "Q" "c" "r" "\C-c\C-f" "m" "a" "f" + '("q" "Q" "c" "r" "\C-c\C-f" "m" "a" "f" "WDD" "WDW" "Zc" "ZC" "ZE" "ZQ" "ZZ" "Zn" "ZR" "ZG" "ZN" "ZP" "=" "^" "\M-^" "|")) (nosave-but-article @@ -6993,10 +7021,10 @@ If given a prefix, show the hidden text instead." ((memq article gnus-newsgroup-sparse) ;; This is a sparse gap article. (setq do-update-line article) - (setq article (mail-header-id header)) - (setq sparse-header (gnus-read-header article)) (setq gnus-newsgroup-sparse - (delq article gnus-newsgroup-sparse))) + (delq article gnus-newsgroup-sparse)) + (setq article (mail-header-id header)) + (setq sparse-header (gnus-read-header article))) ((vectorp header) ;; It's a real article. (setq article (mail-header-id header))) diff --git a/lisp/gnus/gnus-diary.el b/lisp/gnus/gnus-diary.el index 99d3a2b38ee..b81c6d08f5e 100644 --- a/lisp/gnus/gnus-diary.el +++ b/lisp/gnus/gnus-diary.el @@ -159,7 +159,7 @@ There are currently two built-in format functions: ;; Code partly stolen from article-make-date-line (let* ((extras (mail-header-extra header)) (sched (gnus-diary-header-schedule extras)) - (occur (nndiary-next-occurence sched (current-time))) + (occur (nndiary-next-occurrence sched (current-time))) (now (current-time)) (real-time (time-subtract occur now))) (if (null real-time) @@ -194,7 +194,7 @@ There are currently two built-in format functions: ;; Returns a formatted time string for the next occurrence of this message. (let* ((extras (mail-header-extra header)) (sched (gnus-diary-header-schedule extras)) - (occur (nndiary-next-occurence sched (current-time)))) + (occur (nndiary-next-occurrence sched (current-time)))) (format-time-string gnus-diary-time-format occur))) @@ -206,8 +206,8 @@ There are currently two built-in format functions: (e2 (mail-header-extra h2)) (s1 (gnus-diary-header-schedule e1)) (s2 (gnus-diary-header-schedule e2)) - (o1 (nndiary-next-occurence s1 now)) - (o2 (nndiary-next-occurence s2 now))) + (o1 (nndiary-next-occurrence s1 now)) + (o2 (nndiary-next-occurrence s2 now))) (if (and (= (car o1) (car o2)) (= (cadr o1) (cadr o2))) (< (mail-header-number h1) (mail-header-number h2)) (time-less-p o1 o2)))) diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el index 2488cdb7060..8a061b70bf6 100644 --- a/lisp/gnus/gnus-group.el +++ b/lisp/gnus/gnus-group.el @@ -2464,14 +2464,33 @@ the bug number, and browsing the URL must return mbox output." (file-exists-p file)) (insert-file-contents file) (url-insert-file-contents (format mbox-url id))))) - (goto-char (point-min)) ;; Add the debbugs address so that we can respond to reports easily. - (while (re-search-forward "^To: " nil t) - (end-of-line) - (insert (format ", %s@%s" (car ids) - (replace-regexp-in-string - "/.*$" "" - (replace-regexp-in-string "^http://" "" mbox-url))))))) + (let ((address + (format "%s@%s" (car ids) + (replace-regexp-in-string + "/.*$" "" + (replace-regexp-in-string "^http://" "" mbox-url))))) + (goto-char (point-min)) + (while (re-search-forward (concat "^" message-unix-mail-delimiter) + nil t) + (narrow-to-region (point) + (if (search-forward "\n\n" nil t) + (1- (point)) + (point-max))) + (unless (string-match (concat "\\(?:\\`\\|[ ,<]\\)" + (regexp-quote address) + "\\(?:\\'\\|[ ,>]\\)") + (concat (message-fetch-field "to") " " + (message-fetch-field "cc"))) + (goto-char (point-min)) + (if (re-search-forward "^To:" nil t) + (progn + (message-next-header) + (skip-chars-backward "\t\n ") + (insert ", " address)) + (insert "To: " address "\n"))) + (goto-char (point-max)) + (widen))))) (gnus-group-read-ephemeral-group (format "nndoc+ephemeral:bug#%s" (mapconcat 'number-to-string ids ",")) diff --git a/lisp/gnus/gnus-registry.el b/lisp/gnus/gnus-registry.el index f728b191110..51f6459d2f8 100644 --- a/lisp/gnus/gnus-registry.el +++ b/lisp/gnus/gnus-registry.el @@ -968,12 +968,13 @@ Uses `gnus-registry-marks' to find what shortcuts to install." "Show the marks for an article by the :char property." (let* ((id (mail-header-message-id headers)) (marks (when id (gnus-registry-get-id-key id 'mark)))) - (mapconcat (lambda (mark) - (plist-get - (cdr-safe - (assoc mark gnus-registry-marks)) - :char)) - marks ""))) + (concat (delq nil + (mapcar + (lambda (m) + (plist-get + (cdr-safe (assoc m gnus-registry-marks)) + :char)) + marks))))) ;; use like this: ;; (defalias 'gnus-user-format-function-M 'gnus-registry-article-marks-to-names) diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el index be46339cd38..aaa8ab9a888 100644 --- a/lisp/gnus/gnus-start.el +++ b/lisp/gnus/gnus-start.el @@ -731,7 +731,13 @@ the first newsgroup." (kill-buffer (get-file-buffer (gnus-newsgroup-kill-file nil)))) (gnus-kill-buffer nntp-server-buffer) ;; Kill Gnus buffers. + (do-auto-save t) (dolist (buffer (gnus-buffers)) + (when (gnus-buffer-exists-p buffer) + (with-current-buffer buffer + (set-buffer-modified-p nil) + (when (local-variable-p 'kill-buffer-hook) + (setq kill-buffer-hook nil)))) (gnus-kill-buffer buffer)) ;; Remove Gnus frames. (gnus-kill-gnus-frames)) @@ -3196,7 +3202,7 @@ If this variable is nil, don't do anything." (defun gnus-display-time-event-handler () (if (and (fboundp 'display-time-event-handler) - (gnus-boundp 'display-time-timer)) + (bound-and-true-p display-time-timer)) (display-time-event-handler))) (defun gnus-check-reasonable-setup () diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el index 2631514e425..9bdd0c66f56 100644 --- a/lisp/gnus/gnus-sum.el +++ b/lisp/gnus/gnus-sum.el @@ -119,6 +119,14 @@ current group." :group 'gnus-thread :type 'boolean) +(defcustom gnus-refer-thread-limit-to-thread nil + "If non-nil referring a thread will limit the summary buffer to +articles in the thread. A nil value will add the thread articles +to the summary buffer." + :version "25.1" + :group 'gnus-thread + :type 'boolean) + (defcustom gnus-summary-make-false-root 'adopt "nil means that Gnus won't gather loose threads. If the root of a thread has expired or been read in a previous @@ -7045,8 +7053,9 @@ buffer." (interactive) (if (not (gnus-buffer-live-p gnus-article-buffer)) (error "There is no article buffer for this summary buffer") - (unless (get-buffer-window gnus-article-buffer) - (gnus-summary-show-article)) + (or (get-buffer-window gnus-article-buffer) + (eq gnus-current-article (gnus-summary-article-number)) + (gnus-summary-show-article)) (gnus-configure-windows (if gnus-widen-article-window 'only-article @@ -8567,10 +8576,11 @@ Returns how many articles were removed." (gnus-summary-limit gnus-newsgroup-unseen) (gnus-summary-position-point))) -(defun gnus-summary-limit-include-thread (id) - "Display all the hidden articles that is in the thread with ID in it. +(defun gnus-summary-limit-include-thread (id &optional thread-only) + "Display all hidden articles belonging to thread ID. When called interactively, ID is the Message-ID of the current -article." +article. If thread-only is non-nil limit the summary buffer to +these articles." (interactive (list (mail-header-id (gnus-summary-article-header)))) (let ((articles (gnus-articles-in-thread (gnus-id-to-thread (gnus-root-id id)))) @@ -8579,11 +8589,20 @@ article." (gnus-fetch-old-headers nil) (gnus-build-sparse-threads nil)) (prog1 - (gnus-summary-limit (nconc articles gnus-newsgroup-limit)) + (gnus-summary-limit (if thread-only articles + (nconc articles gnus-newsgroup-limit))) (gnus-summary-limit-include-matching-articles "subject" - (regexp-quote (gnus-simplify-subject-re + (regexp-quote (gnus-general-simplify-subject (mail-header-subject (gnus-id-to-header id))))) + ;; the previous two calls each push a limit onto the limit + ;; stack. the first pop remove the articles that match the + ;; subject, while the second pop gets us back to the state + ;; before we started to deal with the thread. presumably we want + ;; to think of the thread and its associated subject matches as + ;; a single thing so that we need to pop only once to get back + ;; to the original view. + (pop gnus-newsgroup-limits) (gnus-summary-position-point)))) (defun gnus-summary-limit-include-matching-articles (header regexp) @@ -8997,7 +9016,6 @@ LIMIT (the numerical prefix) old headers. If LIMIT is non-numeric or nil fetch the number specified by the `gnus-refer-thread-limit' variable." (interactive "P") - (gnus-warp-to-article) (let* ((header (gnus-summary-article-header)) (id (mail-header-id header)) (gnus-inhibit-demon t) @@ -9045,7 +9063,7 @@ non-numeric or nil fetch the number specified by the 'gnus-article-sort-by-number))) (setq gnus-newsgroup-articles (gnus-sorted-nunion gnus-newsgroup-articles article-ids)) - (gnus-summary-limit-include-thread id))) + (gnus-summary-limit-include-thread id gnus-refer-thread-limit-to-thread))) (gnus-summary-show-thread)) (defun gnus-summary-open-group-with-article (message-id) @@ -9086,7 +9104,6 @@ non-numeric or nil fetch the number specified by the (defun gnus-summary-refer-article (message-id) "Fetch an article specified by MESSAGE-ID." (interactive "sMessage-ID: ") - (gnus-warp-to-article) (when (and (stringp message-id) (not (zerop (length message-id)))) (setq message-id (replace-regexp-in-string " " "" message-id)) diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el index 20eceb58edd..b509d8ad448 100644 --- a/lisp/gnus/gnus-util.el +++ b/lisp/gnus/gnus-util.el @@ -84,11 +84,6 @@ This is a compatibility function for different Emacsen." (declare (obsolete replace-regexp-in-string "26.1")) (replace-regexp-in-string regexp newtext string nil literal)) -(defun gnus-boundp (variable) - "Return non-nil if VARIABLE is bound and non-nil." - (and (boundp variable) - (symbol-value variable))) - (defmacro gnus-eval-in-buffer-window (buffer &rest forms) "Pop to BUFFER, evaluate FORMS, and then return to the original window." (let ((tempvar (make-symbol "GnusStartBufferWindow")) diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index a8f2b143f21..0f8fdfc9c7f 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -49,7 +49,7 @@ (require 'mm-util) (require 'rfc2047) (require 'puny) -(require 'subr-x) +(require 'subr-x) ; read-multiple-choice (autoload 'mailclient-send-it "mailclient") diff --git a/lisp/gnus/mm-archive.el b/lisp/gnus/mm-archive.el index 5ac8761f6b5..103cc89c357 100644 --- a/lisp/gnus/mm-archive.el +++ b/lisp/gnus/mm-archive.el @@ -30,15 +30,18 @@ '(("application/ms-tnef" t "tnef" "-f" "-" "-C") ("application/zip" nil "unzip" "-j" "-x" "%f" "-d") ("application/x-gtar-compressed" nil "tar" "xzf" "-" "-C") + ("application/x-tar-gz" nil "tar" "xzf" "-" "-C") ("application/x-tar" nil "tar" "xf" "-" "-C"))) (defun mm-archive-decoders () mm-archive-decoders) (defun mm-dissect-archive (handle) - (let ((decoder (cddr (assoc (car (mm-handle-type handle)) - mm-archive-decoders))) - (dir (make-temp-file - (expand-file-name "emm." mm-tmp-directory) 'dir))) + (let* ((type (car (mm-handle-type handle))) + (decoder (cddr (assoc type mm-archive-decoders))) + dir) + (unless decoder + (error "No decoder found for %s" type)) + (setq dir (make-temp-file (expand-file-name "emm." mm-tmp-directory) 'dir)) (set-file-modes dir #o700) (unwind-protect (progn diff --git a/lisp/gnus/mm-decode.el b/lisp/gnus/mm-decode.el index 5b8aeb3ca31..c6a0be36c40 100644 --- a/lisp/gnus/mm-decode.el +++ b/lisp/gnus/mm-decode.el @@ -1555,6 +1555,8 @@ be determined." "xbm") ((equal type "x-portable-bitmap") "pbm") + ((equal type "svg+xml") + "svg") (t type))) (or (mm-handle-cache handle) (mm-with-unibyte-buffer diff --git a/lisp/gnus/mm-view.el b/lisp/gnus/mm-view.el index dd64bfed60a..9ff581da996 100644 --- a/lisp/gnus/mm-view.el +++ b/lisp/gnus/mm-view.el @@ -475,12 +475,12 @@ If MODE is not set, try to find mode automatically." (require 'font-lock) ;; I find font-lock a bit too verbose. (let ((font-lock-verbose nil) - (font-lock-support-mode nil)) + (font-lock-support-mode nil) + (enable-local-variables nil)) ;; Disable support modes, e.g., jit-lock, lazy-lock, etc. ;; Note: XEmacs people use `font-lock-mode-hook' to run those modes. (set (make-local-variable 'font-lock-mode-hook) nil) (setq buffer-file-name (mm-handle-filename handle)) - (set (make-local-variable 'enable-local-variables) nil) (with-demoted-errors (if mode (save-window-excursion diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el index 3a31349d378..ce28607a04a 100644 --- a/lisp/gnus/mml.el +++ b/lisp/gnus/mml.el @@ -606,38 +606,28 @@ be \"related\" or \"alternate\"." (intern (downcase charset)))))) (if (and (not raw) (member (car (split-string type "/")) '("text" "message"))) - ;; We have a text-like MIME part, so we need to do - ;; charset encoding. (progn (with-temp-buffer - (set-buffer-multibyte nil) - ;; First insert the data into the buffer. - (if (and filename - (not (equal (cdr (assq 'nofile cont)) "yes"))) - (mm-insert-file-contents filename) - (insert - (with-temp-buffer - (cond - ((cdr (assq 'buffer cont)) - (insert-buffer-substring (cdr (assq 'buffer cont)))) - ((eq 'mml (car cont)) - (insert (cdr (assq 'contents cont)))) - (t - (insert (cdr (assq 'contents cont))) - ;; Remove quotes from quoted tags. - (goto-char (point-min)) - (while (re-search-forward - "<#!+/?\\(part\\|multipart\\|external\\|mml\\|secure\\)" - nil t) - (delete-region (+ (match-beginning 0) 2) - (+ (match-beginning 0) 3))))) - (setq charset - (mm-coding-system-to-mime-charset - (detect-coding-region - (point-min) (point-max) t))) - (encode-coding-region (point-min) (point-max) - charset) - (buffer-string)))) + (cond + ((cdr (assq 'buffer cont)) + (insert-buffer-substring (cdr (assq 'buffer cont)))) + ((and filename + (not (equal (cdr (assq 'nofile cont)) "yes"))) + (let ((coding-system-for-read coding)) + (mm-insert-file-contents filename))) + ((eq 'mml (car cont)) + (insert (cdr (assq 'contents cont)))) + (t + (save-restriction + (narrow-to-region (point) (point)) + (insert (cdr (assq 'contents cont))) + ;; Remove quotes from quoted tags. + (goto-char (point-min)) + (while (re-search-forward + "<#!+/?\\(part\\|multipart\\|external\\|mml\\|secure\\)" + nil t) + (delete-region (+ (match-beginning 0) 2) + (+ (match-beginning 0) 3)))))) (cond ((eq (car cont) 'mml) (let ((mml-boundary (mml-compute-boundary cont)) @@ -665,7 +655,7 @@ be \"related\" or \"alternate\"." ;; actually are hard newlines in the text. (let (use-hard-newlines) (when (and mml-enable-flowed - (string= type "text/plain") + (string= type "text/plain") (not (string= (cdr (assq 'sign cont)) "pgp")) (or (null (assq 'format cont)) (string= (cdr (assq 'format cont)) @@ -678,14 +668,13 @@ be \"related\" or \"alternate\"." ;; insert a "; format=flowed" string unless the ;; user has already specified it. (setq flowed (null (assq 'format cont))))) - (unless charset - (setq charset - ;; Prefer `utf-8' for text/calendar parts. - (if (string= type "text/calendar") - 'utf-8 - (mm-coding-system-to-mime-charset - (detect-coding-region - (point-min) (point-max) t))))) + ;; Prefer `utf-8' for text/calendar parts. + (if (or charset + (not (string= type "text/calendar"))) + (setq charset (mm-encode-body charset)) + (let ((mm-coding-system-priorities + (cons 'utf-8 mm-coding-system-priorities))) + (setq charset (mm-encode-body)))) (setq encoding (mm-body-encoding charset (cdr (assq 'encoding cont)))))) (setq coded (buffer-string))) @@ -696,26 +685,33 @@ be \"related\" or \"alternate\"." (set-buffer-multibyte nil) (cond ((cdr (assq 'buffer cont)) - (insert (string-as-unibyte - (with-current-buffer (cdr (assq 'buffer cont)) - (buffer-string))))) + ;; multibyte string that inserted to a unibyte buffer + ;; will be converted to the unibyte version safely. + (insert (with-current-buffer (cdr (assq 'buffer cont)) + (buffer-string)))) ((and filename (not (equal (cdr (assq 'nofile cont)) "yes"))) (let ((coding-system-for-read mm-binary-coding-system)) - (mm-insert-file-contents filename nil nil nil nil t))) + (mm-insert-file-contents filename nil nil nil nil t)) + (unless charset + (setq charset (mm-coding-system-to-mime-charset + (mm-find-buffer-file-coding-system + filename))))) (t (let ((contents (cdr (assq 'contents cont)))) - (if (multibyte-string-p contents) + (if (if (featurep 'xemacs) + (string-match "[^\000-\377]" contents) + (multibyte-string-p contents)) (progn - (mm-enable-multibyte) + (set-buffer-multibyte t) (insert contents) (unless raw (setq charset (mm-encode-body charset)))) (insert contents))))) (if (setq encoding (cdr (assq 'encoding cont))) (setq encoding (intern (downcase encoding)))) - (setq encoding (mm-encode-buffer type encoding) - coded (string-as-multibyte (buffer-string)))) + (setq encoding (mm-encode-buffer type encoding)) + (setq coded (decode-coding-string (buffer-string) 'us-ascii))) (mml-insert-mime-headers cont type charset encoding nil) (insert "\n" coded)))) ((eq (car cont) 'external) diff --git a/lisp/gnus/nndiary.el b/lisp/gnus/nndiary.el index bed35b55b3a..0390b5b8d28 100644 --- a/lisp/gnus/nndiary.el +++ b/lisp/gnus/nndiary.el @@ -1304,9 +1304,7 @@ all. This may very well take some time.") res)) (sort res 'time-less-p))) -;; FIXME: "occurrence" is misspelled in this function name. - -(defun nndiary-last-occurence (sched) +(defun nndiary-last-occurrence (sched) ;; Returns the last occurrence of schedule SCHED as an Emacs time struct, or ;; nil for permanent schedule or errors. (let ((minute (nndiary-max (nth 0 sched))) @@ -1385,10 +1383,11 @@ all. This may very well take some time.") (nnheader-report 'nndiary "Undecidable schedule") nil)) )))) +(define-obsolete-function-alias + 'nndiary-last-occurence + 'nndiary-last-occurrence "26.1") -;; FIXME: "occurrence" is misspelled in this function name. - -(defun nndiary-next-occurence (sched now) +(defun nndiary-next-occurrence (sched now) ;; Returns the next occurrence of schedule SCHED, starting from time NOW. ;; If there's no next occurrence, returns the last one (if any) which is then ;; in the past. @@ -1517,10 +1516,13 @@ all. This may very well take some time.") )) ))) )) - (nndiary-last-occurence sched)) + (nndiary-last-occurrence sched)) ;; else - (nndiary-last-occurence sched)) + (nndiary-last-occurrence sched)) )) +(define-obsolete-function-alias + 'nndiary-next-occurence + 'nndiary-next-occurrence "26.1") (defun nndiary-expired-article-p (file) (with-temp-buffer @@ -1529,7 +1531,7 @@ all. This may very well take some time.") ;; An article has expired if its last schedule (if any) is in the ;; past. A permanent schedule never expires. (and sched - (setq sched (nndiary-last-occurence sched)) + (setq sched (nndiary-last-occurrence sched)) (time-less-p sched (current-time)))) ;; else (nnheader-report 'nndiary "Could not read file %s" file) @@ -1543,7 +1545,7 @@ all. This may very well take some time.") (sched (nndiary-schedule))) ;; The article should be re-considered as unread if there's a reminder ;; between the group timestamp and the current time. - (when (and sched (setq sched (nndiary-next-occurence sched now))) + (when (and sched (setq sched (nndiary-next-occurrence sched now))) (let ((reminders ;; add the next occurrence itself at the end. (append (nndiary-compute-reminders sched) (list sched)))) (while (and reminders (time-less-p (car reminders) timestamp)) diff --git a/lisp/gnus/nnheader.el b/lisp/gnus/nnheader.el index 648485b4f61..4440f17c2bb 100644 --- a/lisp/gnus/nnheader.el +++ b/lisp/gnus/nnheader.el @@ -40,7 +40,6 @@ (require 'mail-utils) (require 'mm-util) (require 'gnus-util) -(require 'subr-x) (autoload 'gnus-range-add "gnus-range") (autoload 'gnus-remove-from-range "gnus-range") ;; FIXME none of these are used explicitly in this file. @@ -82,8 +81,7 @@ Integer values will in effect be rounded up to the nearest multiple of :type 'integer) (defvar nnheader-read-timeout - (if (string-match "windows-nt\\|os/2\\|cygwin" - (symbol-name system-type)) + (if (memq system-type '(windows-nt cygwin)) ;; http://thread.gmane.org/v9655t3pjo.fsf@marauder.physik.uni-ulm.de ;; ;; IIRC, values lower than 1.0 didn't/don't work on Windows/DOS. @@ -105,17 +103,8 @@ Integer values will in effect be rounded up to the nearest multiple of Shorter values mean quicker response, but are more CPU intensive.") (defcustom nnheader-file-name-translation-alist - (let ((case-fold-search t)) - (cond - ((string-match "windows-nt\\|os/2\\|cygwin" - (symbol-name system-type)) - (append (mapcar (lambda (c) (cons c ?_)) - '(?: ?* ?\" ?< ?> ??)) - (if (string-match "windows-nt\\|cygwin" - (symbol-name system-type)) - nil - '((?+ . ?-))))) - (t nil))) + (if (memq system-type '(windows-nt cygwin)) + (mapcar (lambda (c) (cons c ?_)) '(?: ?* ?\" ?< ?> ??))) "Alist that says how to translate characters in file names. For instance, if \":\" is invalid as a file character in file names on your system, you could say something like: diff --git a/lisp/gnus/nnmail.el b/lisp/gnus/nnmail.el index 3f2e08171e0..71d9631776d 100644 --- a/lisp/gnus/nnmail.el +++ b/lisp/gnus/nnmail.el @@ -263,7 +263,7 @@ It scans low-level sorted spools even when not required." :type 'function) (defcustom nnmail-crosspost-link-function - (if (string-match "windows-nt" (symbol-name system-type)) + (if (eq 'windows-nt system-type) 'copy-file 'add-name-to-file) "Function called to create a copy of a file. diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 3daa7b0b6e4..ec4b002e4ad 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -73,7 +73,7 @@ The functions will receive the function name as argument.") (let* ((re (load-history-regexp file)) (done nil)) (dolist (x load-history) - (if (string-match-p re (car x)) (setq done t))) + (and (car x) (string-match-p re (car x)) (setq done t))) done))) (defun help--load-prefixes (prefixes) @@ -394,12 +394,12 @@ suitable file is found, return nil." ;; If lots of ordinary text characters run this command, ;; don't mention them one by one. (if (< (length non-modified-keys) 10) - (princ (mapconcat 'key-description keys ", ")) + (princ (mapconcat #'key-description keys ", ")) (dolist (key non-modified-keys) (setq keys (delq key keys))) (if keys (progn - (princ (mapconcat 'key-description keys ", ")) + (princ (mapconcat #'key-description keys ", ")) (princ ", and many ordinary text characters")) (princ "many ordinary text characters")))) (when (or remapped keys non-modified-keys) @@ -476,7 +476,8 @@ suitable file is found, return nil." (let ((fill-begin (point)) (high-usage (car high)) (high-doc (cdr high))) - (unless (get function 'reader-construct) + (unless (and (symbolp function) + (get function 'reader-construct)) (insert high-usage "\n")) (fill-region fill-begin (point)) high-doc))))) @@ -562,8 +563,9 @@ FILE is the file where FUNCTION was probably defined." (setq short rel)))) short)) -;;;###autoload -(defun describe-function-1 (function) +(defun help-fns--analyse-function (function) + "Return information about FUNCTION. +Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)." (let* ((advised (and (symbolp function) (featurep 'nadvice) (advice--p (advice--symbol-function function)))) @@ -596,27 +598,30 @@ FILE is the file where FUNCTION was probably defined." (setq f (symbol-function f))) f)) ((subrp def) (intern (subr-name def))) - (t def))) - (sig-key (if (subrp def) - (indirect-function real-def) - real-def)) - (file-name (find-lisp-object-file-name function (if aliased 'defun - def))) - (pt1 (with-current-buffer (help-buffer) (point))) - (beg (if (and (or (byte-code-function-p def) - (keymapp def) - (memq (car-safe def) '(macro lambda closure))) - (stringp file-name) - (help-fns--autoloaded-p function file-name)) - (if (commandp def) - "an interactive autoloaded " - "an autoloaded ") - (if (commandp def) "an interactive " "a ")))) + (t def)))) + (list real-function def aliased real-def))) + +(defun help-fns-function-description-header (function) + "Print a line describing FUNCTION to `standard-output'." + (pcase-let* ((`(,_real-function ,def ,aliased ,real-def) + (help-fns--analyse-function function)) + (file-name (find-lisp-object-file-name function (if aliased 'defun + def))) + (beg (if (and (or (byte-code-function-p def) + (keymapp def) + (memq (car-safe def) '(macro lambda closure))) + (stringp file-name) + (help-fns--autoloaded-p function file-name)) + (if (commandp def) + "an interactive autoloaded " + "an autoloaded ") + (if (commandp def) "an interactive " "a ")))) ;; Print what kind of function-like object FUNCTION is. (princ (cond ((or (stringp def) (vectorp def)) "a keyboard macro") - ((get function 'reader-construct) + ((and (symbolp function) + (get function 'reader-construct)) "a reader construct") ;; Aliases are Lisp functions, so we need to check ;; aliases before functions. @@ -677,34 +682,42 @@ FILE is the file where FUNCTION was probably defined." (re-search-backward (substitute-command-keys "`\\([^`']+\\)'") nil t) (help-xref-button 1 'help-function-def function file-name)))) - (princ ".") - (with-current-buffer (help-buffer) - (fill-region-as-paragraph (save-excursion (goto-char pt1) (forward-line 0) (point)) - (point))) - (terpri)(terpri) - - (let ((doc-raw (documentation function t)) - (key-bindings-buffer (current-buffer))) - - ;; If the function is autoloaded, and its docstring has - ;; key substitution constructs, load the library. - (and (autoloadp real-def) doc-raw - help-enable-auto-load - (string-match "\\([^\\]=\\|[^=]\\|\\`\\)\\\\[[{<]" doc-raw) - (autoload-do-load real-def)) - - (help-fns--key-bindings function) - (with-current-buffer standard-output - (let ((doc (help-fns--signature function doc-raw sig-key - real-function key-bindings-buffer))) - (run-hook-with-args 'help-fns-describe-function-functions function) - (insert "\n" - (or doc "Not documented.")) - ;; Avoid asking the user annoying questions if she decides - ;; to save the help buffer, when her locale's codeset - ;; isn't UTF-8. - (unless (memq text-quoting-style '(straight grave)) - (set-buffer-file-coding-system 'utf-8)))))))) + (princ ".")))) + +;;;###autoload +(defun describe-function-1 (function) + (let ((pt1 (with-current-buffer (help-buffer) (point)))) + (help-fns-function-description-header function) + (with-current-buffer (help-buffer) + (fill-region-as-paragraph (save-excursion (goto-char pt1) (forward-line 0) (point)) + (point)))) + (terpri)(terpri) + + (pcase-let ((`(,real-function ,def ,_aliased ,real-def) + (help-fns--analyse-function function)) + (doc-raw (documentation function t)) + (key-bindings-buffer (current-buffer))) + + ;; If the function is autoloaded, and its docstring has + ;; key substitution constructs, load the library. + (and (autoloadp real-def) doc-raw + help-enable-auto-load + (string-match "\\([^\\]=\\|[^=]\\|\\`\\)\\\\[[{<]" doc-raw) + (autoload-do-load real-def)) + + (help-fns--key-bindings function) + (with-current-buffer standard-output + (let ((doc (help-fns--signature + function doc-raw + (if (subrp def) (indirect-function real-def) real-def) + real-function key-bindings-buffer))) + (run-hook-with-args 'help-fns-describe-function-functions function) + (insert "\n" (or doc "Not documented."))) + ;; Avoid asking the user annoying questions if she decides + ;; to save the help buffer, when her locale's codeset + ;; isn't UTF-8. + (unless (memq text-quoting-style '(straight grave)) + (set-buffer-file-coding-system 'utf-8))))) ;; Add defaults to `help-fns-describe-function-functions'. (add-hook 'help-fns-describe-function-functions #'help-fns--obsolete) @@ -845,15 +858,22 @@ it is displayed along with the global value." (let ((line-beg (line-beginning-position)) (print-rep (let ((rep - (let ((print-quoted t)) - (prin1-to-string val)))) + (let ((print-quoted t) + (print-circle t)) + (cl-prin1-to-string val)))) (if (and (symbolp val) (not (booleanp val))) (format-message "`%s'" rep) rep)))) (if (< (+ (length print-rep) (point) (- line-beg)) 68) (insert " " print-rep) (terpri) - (pp val) + (let ((buf (current-buffer))) + (with-temp-buffer + (insert print-rep) + (pp-buffer) + (let ((pp-buffer (current-buffer))) + (with-current-buffer buf + (insert-buffer-substring pp-buffer))))) ;; Remove trailing newline. (and (= (char-before) ?\n) (delete-char -1))) (let* ((sv (get variable 'standard-value)) @@ -1092,8 +1112,8 @@ frame to show the information about SYMBOL; they default to the current buffer and the selected frame, respectively." (interactive (let* ((v-or-f (symbol-at-point)) - (found (cl-some (lambda (x) (funcall (nth 1 x) v-or-f)) - describe-symbol-backends)) + (found (if v-or-f (cl-some (lambda (x) (funcall (nth 1 x) v-or-f)) + describe-symbol-backends))) (v-or-f (if found v-or-f (function-called-at-point))) (found (or found v-or-f)) (enable-recursive-minibuffers t) @@ -1254,14 +1274,14 @@ BUFFER should be a buffer or a buffer name." (insert-file-contents file) (let (notfirst) (while (search-forward "" nil 'move) - (if (looking-at "S") + (if (= (following-char) ?S) (delete-region (1- (point)) (line-end-position)) (delete-char -1) (if notfirst (insert "\n.DE\n") (setq notfirst t)) (insert "\n.SH ") - (insert (if (looking-at "F") "Function " "Variable ")) + (insert (if (= (following-char) ?F) "Function " "Variable ")) (delete-char 1) (forward-line 1) (insert ".DS L\n")))) @@ -1287,7 +1307,7 @@ BUFFER should be a buffer or a buffer name." (forward-char 1)) (goto-char (point-min)) (while (search-forward "" nil t) - (unless (looking-at "S") + (when (/= (following-char) ?S) (setq type (char-after) name (buffer-substring (1+ (point)) (line-end-position)) doc (buffer-substring (line-beginning-position 2) diff --git a/lisp/help.el b/lisp/help.el index d3aaa1e251d..0fb1c2dab77 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -593,6 +593,39 @@ If INSERT (the prefix arg) is non-nil, insert the message in the buffer." string (format "%s (translated from %s)" string otherstring)))))) +(defun help--analyze-key (key untranslated) + "Get information about KEY its corresponding UNTRANSLATED events. +Returns a list of the form (BRIEF-DESC DEFN EVENT MOUSE-MSG)." + (if (numberp untranslated) + (setq untranslated (this-single-command-raw-keys))) + (let* ((event (aref key (if (and (symbolp (aref key 0)) + (> (length key) 1) + (consp (aref key 1))) + 1 + 0))) + (modifiers (event-modifiers event)) + (mouse-msg (if (or (memq 'click modifiers) (memq 'down modifiers) + (memq 'drag modifiers)) " at that spot" "")) + (defn (key-binding key t))) + ;; Handle the case where we faked an entry in "Select and Paste" menu. + (when (and (eq defn nil) + (stringp (aref key (1- (length key)))) + (eq (key-binding (substring key 0 -1)) 'yank-menu)) + (setq defn 'menu-bar-select-yank)) + ;; Don't bother user with strings from (e.g.) the select-paste menu. + (when (stringp (aref key (1- (length key)))) + (aset key (1- (length key)) "(any string)")) + (when (and untranslated + (stringp (aref untranslated (1- (length untranslated))))) + (aset untranslated (1- (length untranslated)) "(any string)")) + (list + ;; Now describe the key, perhaps as changed. + (let ((key-desc (help-key-description key untranslated))) + (if (or (null defn) (integerp defn) (equal defn 'undefined)) + (format "%s%s is undefined" key-desc mouse-msg) + (format "%s%s runs the command %S" key-desc mouse-msg defn))) + defn event mouse-msg))) + (defun describe-key-briefly (&optional key insert untranslated) "Print the name of the function KEY invokes. KEY is a string. If INSERT (the prefix arg) is non-nil, insert the message in the buffer. @@ -603,73 +636,12 @@ the last key hit are used. If KEY is a menu item or a tool-bar button that is disabled, this command temporarily enables it to allow getting help on disabled items and buttons." (interactive - (let ((enable-disabled-menus-and-buttons t) - (cursor-in-echo-area t) - saved-yank-menu) - (unwind-protect - (let (key) - ;; If yank-menu is empty, populate it temporarily, so that - ;; "Select and Paste" menu can generate a complete event. - (when (null (cdr yank-menu)) - (setq saved-yank-menu (copy-sequence yank-menu)) - (menu-bar-update-yank-menu "(any string)" nil)) - (while - (progn - (setq key (read-key-sequence "Describe the following key, mouse click, or menu item: ")) - (and (vectorp key) - (consp (aref key 0)) - (symbolp (car (aref key 0))) - (string-match "\\(mouse\\|down\\|click\\|drag\\)" - (symbol-name (car (aref key 0)))) - (not (sit-for (/ double-click-time 1000.0) t))))) - ;; Clear the echo area message (Bug#7014). - (message nil) - ;; If KEY is a down-event, read and discard the - ;; corresponding up-event. Note that there are also - ;; down-events on scroll bars and mode lines: the actual - ;; event then is in the second element of the vector. - (and (vectorp key) - (let ((last-idx (1- (length key)))) - (and (eventp (aref key last-idx)) - (memq 'down (event-modifiers (aref key last-idx))))) - (read-event)) - (list - key - (if current-prefix-arg (prefix-numeric-value current-prefix-arg)) - 1)) - ;; Put yank-menu back as it was, if we changed it. - (when saved-yank-menu - (setq yank-menu (copy-sequence saved-yank-menu)) - (fset 'yank-menu (cons 'keymap yank-menu)))))) - (if (numberp untranslated) - (setq untranslated (this-single-command-raw-keys))) - (let* ((event (if (and (symbolp (aref key 0)) - (> (length key) 1) - (consp (aref key 1))) - (aref key 1) - (aref key 0))) - (modifiers (event-modifiers event)) - (standard-output (if insert (current-buffer) standard-output)) - (mouse-msg (if (or (memq 'click modifiers) (memq 'down modifiers) - (memq 'drag modifiers)) " at that spot" "")) - (defn (key-binding key t)) - key-desc) - ;; Handle the case where we faked an entry in "Select and Paste" menu. - (if (and (eq defn nil) - (stringp (aref key (1- (length key)))) - (eq (key-binding (substring key 0 -1)) 'yank-menu)) - (setq defn 'menu-bar-select-yank)) - ;; Don't bother user with strings from (e.g.) the select-paste menu. - (if (stringp (aref key (1- (length key)))) - (aset key (1- (length key)) "(any string)")) - (if (and (> (length untranslated) 0) - (stringp (aref untranslated (1- (length untranslated))))) - (aset untranslated (1- (length untranslated)) "(any string)")) - ;; Now describe the key, perhaps as changed. - (setq key-desc (help-key-description key untranslated)) - (if (or (null defn) (integerp defn) (equal defn 'undefined)) - (princ (format "%s%s is undefined" key-desc mouse-msg)) - (princ (format "%s%s runs the command %S" key-desc mouse-msg defn))))) + ;; Ignore mouse movement events because it's too easy to miss the + ;; message while moving the mouse. + (pcase-let ((`(,key ,_up-event) (help-read-key-sequence 'no-mouse-movement))) + `(,key ,current-prefix-arg 1))) + (princ (car (help--analyze-key key untranslated)) + (if insert (current-buffer) standard-output))) (defun help--key-binding-keymap (key &optional accept-default no-remap position) "Return a keymap holding a binding for KEY within current keymaps. @@ -734,6 +706,59 @@ function `key-binding'." (throw 'found x)))) nil))))) +(defun help-read-key-sequence (&optional no-mouse-movement) + "Reads a key sequence from the user. +Returns a list of the form (KEY UP-EVENT), where KEY is the key +sequence, and UP-EVENT is the up-event that was discarded by +reading KEY, or nil. +If NO-MOUSE-MOVEMENT is non-nil, ignore key sequences starting +with `mouse-movement' events." + (let ((enable-disabled-menus-and-buttons t) + (cursor-in-echo-area t) + saved-yank-menu) + (unwind-protect + (let (key) + ;; If yank-menu is empty, populate it temporarily, so that + ;; "Select and Paste" menu can generate a complete event. + (when (null (cdr yank-menu)) + (setq saved-yank-menu (copy-sequence yank-menu)) + (menu-bar-update-yank-menu "(any string)" nil)) + (while + (pcase (setq key (read-key-sequence "\ +Describe the following key, mouse click, or menu item: ")) + ((and (pred vectorp) (let `(,key0 . ,_) (aref key 0)) + (guard (symbolp key0)) (let keyname (symbol-name key0))) + (if no-mouse-movement + (string-match "mouse-movement" keyname) + (and (string-match "\\(mouse\\|down\\|click\\|drag\\)" + keyname) + (not (sit-for (/ double-click-time 1000.0) t))))))) + (list + key + ;; If KEY is a down-event, read and include the + ;; corresponding up-event. Note that there are also + ;; down-events on scroll bars and mode lines: the actual + ;; event then is in the second element of the vector. + (and (vectorp key) + (let ((last-idx (1- (length key)))) + (and (eventp (aref key last-idx)) + (memq 'down (event-modifiers (aref key last-idx))))) + (or (and (eventp (aref key 0)) + (memq 'down (event-modifiers (aref key 0))) + ;; However, for the C-down-mouse-2 popup + ;; menu, there is no subsequent up-event. In + ;; this case, the up-event is the next + ;; element in the supplied vector. + (= (length key) 1)) + (and (> (length key) 1) + (eventp (aref key 1)) + (memq 'down (event-modifiers (aref key 1))))) + (read-event)))) + ;; Put yank-menu back as it was, if we changed it. + (when saved-yank-menu + (setq yank-menu (copy-sequence saved-yank-menu)) + (fset 'yank-menu (cons 'keymap yank-menu)))))) + (defun describe-key (&optional key untranslated up-event) "Display documentation of the function invoked by KEY. KEY can be any kind of a key sequence; it can include keyboard events, @@ -748,83 +773,20 @@ UP-EVENT is the up-event that was discarded by reading KEY, or nil. If KEY is a menu item or a tool-bar button that is disabled, this command temporarily enables it to allow getting help on disabled items and buttons." (interactive - (let ((enable-disabled-menus-and-buttons t) - (cursor-in-echo-area t) - saved-yank-menu) - (unwind-protect - (let (key) - ;; If yank-menu is empty, populate it temporarily, so that - ;; "Select and Paste" menu can generate a complete event. - (when (null (cdr yank-menu)) - (setq saved-yank-menu (copy-sequence yank-menu)) - (menu-bar-update-yank-menu "(any string)" nil)) - (while - (progn - (setq key (read-key-sequence "Describe the following key, mouse click, or menu item: ")) - (and (vectorp key) - (consp (aref key 0)) - (symbolp (car (aref key 0))) - (string-match "\\(mouse\\|down\\|click\\|drag\\)" - (symbol-name (car (aref key 0)))) - (not (sit-for (/ double-click-time 1000.0) t))))) - (list - key - (prefix-numeric-value current-prefix-arg) - ;; If KEY is a down-event, read and include the - ;; corresponding up-event. Note that there are also - ;; down-events on scroll bars and mode lines: the actual - ;; event then is in the second element of the vector. - (and (vectorp key) - (let ((last-idx (1- (length key)))) - (and (eventp (aref key last-idx)) - (memq 'down (event-modifiers (aref key last-idx))))) - (or (and (eventp (aref key 0)) - (memq 'down (event-modifiers (aref key 0))) - ;; However, for the C-down-mouse-2 popup - ;; menu, there is no subsequent up-event. In - ;; this case, the up-event is the next - ;; element in the supplied vector. - (= (length key) 1)) - (and (> (length key) 1) - (eventp (aref key 1)) - (memq 'down (event-modifiers (aref key 1))))) - (read-event)))) - ;; Put yank-menu back as it was, if we changed it. - (when saved-yank-menu - (setq yank-menu (copy-sequence saved-yank-menu)) - (fset 'yank-menu (cons 'keymap yank-menu)))))) - (if (numberp untranslated) - (setq untranslated (this-single-command-raw-keys))) - (let* ((event (aref key (if (and (symbolp (aref key 0)) - (> (length key) 1) - (consp (aref key 1))) - 1 - 0))) - (modifiers (event-modifiers event)) - (mouse-msg (if (or (memq 'click modifiers) (memq 'down modifiers) - (memq 'drag modifiers)) " at that spot" "")) - (defn (key-binding key t)) - key-locus key-locus-up key-locus-up-tricky - defn-up defn-up-tricky ev-type - mouse-1-remapped mouse-1-tricky) - - ;; Handle the case where we faked an entry in "Select and Paste" menu. - (when (and (eq defn nil) - (stringp (aref key (1- (length key)))) - (eq (key-binding (substring key 0 -1)) 'yank-menu)) - (setq defn 'menu-bar-select-yank)) - (if (or (null defn) (integerp defn) (equal defn 'undefined)) - (message "%s%s is undefined" - (help-key-description key untranslated) mouse-msg) + (pcase-let ((`(,key ,up-event) (help-read-key-sequence))) + `(,key ,(prefix-numeric-value current-prefix-arg) ,up-event))) + (pcase-let ((`(,brief-desc ,defn ,event ,mouse-msg) + (help--analyze-key key untranslated)) + (defn-up nil) (defn-up-tricky nil) + (key-locus-up nil) (key-locus-up-tricky nil) + (mouse-1-remapped nil) (mouse-1-tricky nil) + (ev-type nil)) + (if (or (null defn) + (integerp defn) + (equal defn 'undefined)) + (message "%s" brief-desc) (help-setup-xref (list #'describe-function defn) (called-interactively-p 'interactive)) - ;; Don't bother user with strings from (e.g.) the select-paste menu. - (when (stringp (aref key (1- (length key)))) - (aset key (1- (length key)) "(any string)")) - (when (and untranslated - (stringp (aref untranslated (1- (length untranslated))))) - (aset untranslated (1- (length untranslated)) - "(any string)")) ;; Need to do this before erasing *Help* buffer in case event ;; is a mouse click in an existing *Help* buffer. (when up-event @@ -849,13 +811,12 @@ temporarily enables it to allow getting help on disabled items and buttons." (aset sequence 0 'mouse-1) (setq defn-up-tricky (key-binding sequence nil nil (event-start up-event))) (setq key-locus-up-tricky (help--binding-locus sequence (event-start up-event)))))) - (setq key-locus (help--binding-locus key (event-start event))) (with-help-window (help-buffer) - (princ (help-key-description key untranslated)) - (princ (format "%s runs the command %S%s, which is " - mouse-msg defn (if key-locus - (format " (found in %s)" key-locus) - ""))) + (princ brief-desc) + (let ((key-locus (help--binding-locus key (event-start event)))) + (when key-locus + (princ (format " (found in %s)" key-locus)))) + (princ ", which is ") (describe-function-1 defn) (when up-event (unless (or (null defn-up) @@ -1419,7 +1380,7 @@ ARGLIST can also be t or a string of the form \"(FUN ARG1 ARG2 ...)\"." (defun help-function-arglist (def &optional preserve-names) "Return a formal argument list for the function DEF. -IF PRESERVE-NAMES is non-nil, return a formal arglist that uses +If PRESERVE-NAMES is non-nil, return a formal arglist that uses the same names as used in the original source code, when possible." ;; Handle symbols aliased to other symbols. (if (and (symbolp def) (fboundp def)) (setq def (indirect-function def))) @@ -1430,7 +1391,7 @@ the same names as used in the original source code, when possible." ((eq (car-safe def) 'lambda) (nth 1 def)) ((eq (car-safe def) 'closure) (nth 2 def)) ((or (and (byte-code-function-p def) (integerp (aref def 0))) - (subrp def)) + (subrp def) (module-function-p def)) (or (when preserve-names (let* ((doc (condition-case nil (documentation def) (error nil))) (docargs (if doc (car (help-split-fundoc doc nil)))) @@ -1446,25 +1407,18 @@ the same names as used in the original source code, when possible." (not (string-match "\\." name))))) (setq valid nil))) (when valid arglist))) - (let* ((args-desc (if (not (subrp def)) - (aref def 0) - (let ((a (subr-arity def))) - (logior (car a) - (if (numberp (cdr a)) - (lsh (cdr a) 8) - (lsh 1 7)))))) - (max (lsh args-desc -8)) - (min (logand args-desc 127)) - (rest (logand args-desc 128)) + (let* ((arity (func-arity def)) + (max (cdr arity)) + (min (car arity)) (arglist ())) (dotimes (i min) (push (intern (concat "arg" (number-to-string (1+ i)))) arglist)) - (when (> max min) + (when (and (integerp max) (> max min)) (push '&optional arglist) (dotimes (i (- max min)) (push (intern (concat "arg" (number-to-string (+ 1 i min)))) arglist))) - (unless (zerop rest) (push '&rest arglist) (push 'rest arglist)) + (unless (integerp max) (push '&rest arglist) (push 'rest arglist)) (nreverse arglist)))) ((and (autoloadp def) (not (eq (nth 4 def) 'keymap))) "[Arg list not available until function definition is loaded.]") diff --git a/lisp/hexl.el b/lisp/hexl.el index b5e9c1ff33d..0a598b22f66 100644 --- a/lisp/hexl.el +++ b/lisp/hexl.el @@ -730,13 +730,13 @@ If there is no byte at the target address move to the last byte in that line." Leaves `hexl-mark' at previous position. With prefix arg N, puts point N bytes of the way from the true beginning." (interactive "p") - (push-mark (point)) + (push-mark) (hexl-goto-address (+ 0 (1- arg)))) (defun hexl-end-of-buffer (arg) "Go to `hexl-max-address' minus ARG." (interactive "p") - (push-mark (point)) + (push-mark) (hexl-goto-address (- hexl-max-address (1- arg)))) (defun hexl-beginning-of-line () diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el index ebd18621ef9..5139e01fa84 100644 --- a/lisp/hi-lock.el +++ b/lisp/hi-lock.el @@ -695,7 +695,8 @@ with completion and history." (setq regexp (hi-lock--hashcons regexp)) (let ((pattern (list regexp (list 0 (list 'quote face) 'prepend)))) ;; Refuse to highlight a text that is already highlighted. - (unless (assoc regexp hi-lock-interactive-patterns) + (if (assoc regexp hi-lock-interactive-patterns) + (add-to-list 'hi-lock--unused-faces (face-name face)) (push pattern hi-lock-interactive-patterns) (if (and font-lock-mode (font-lock-specified-p major-mode)) (progn diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el index 66916b2bca1..c83c21315a1 100644 --- a/lisp/ibuffer.el +++ b/lisp/ibuffer.el @@ -1689,7 +1689,7 @@ If point is on a group name, this function operates on that group." ;; generate a call to the column function. (ibuffer-aif (assq sym ibuffer-inline-columns) (nth 1 it) - `(,sym buffer mark))) + `(or (,sym buffer mark) ""))) ;; You're not expected to understand this. Hell, I ;; don't even understand it, and I wrote it five ;; minutes ago. diff --git a/lisp/icomplete.el b/lisp/icomplete.el index cd352de65b4..a4153e806df 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -56,10 +56,6 @@ :link '(info-link "(emacs)Icomplete") :group 'minibuffer) -(defvar icomplete-prospects-length 80) -(make-obsolete-variable - 'icomplete-prospects-length 'icomplete-prospects-height "23.1") - (defcustom icomplete-separator " | " "String used by Icomplete to separate alternatives in the minibuffer." :type 'string @@ -91,13 +87,14 @@ Otherwise this should be a list of the completion tables (e.g., :version "24.4") ;;;_* User Customization variables -(defcustom icomplete-prospects-height - ;; 20 is an estimated common size for the prompt + minibuffer content, to - ;; try to guess the number of lines used up by icomplete-prospects-length. - (+ 1 (/ (+ icomplete-prospects-length 20) (window-width))) +(defcustom icomplete-prospects-height 2 + ;; We used to compute how many lines 100 characters would take in + ;; the current window width, but the return value of `window-width' + ;; is unreliable on startup (e.g., if we're in daemon mode), so now + ;; we simply base the default value on an 80 column window. "Maximum number of lines to use in the minibuffer." :type 'integer - :version "23.1") + :version "26.1") (defcustom icomplete-compute-delay .3 "Completions-computation stall, used only with large-number completions. diff --git a/lisp/ido.el b/lisp/ido.el index 561d6e7f081..07a5bcf7229 100644 --- a/lisp/ido.el +++ b/lisp/ido.el @@ -1582,19 +1582,11 @@ positive, and disable it otherwise. If called from Lisp, enable the mode if ARG is omitted or nil." :global t :group 'ido - (when (get 'ido-everywhere 'file) - (setq read-file-name-function (car (get 'ido-everywhere 'file))) - (put 'ido-everywhere 'file nil)) - (when (get 'ido-everywhere 'buffer) - (setq read-buffer-function (car (get 'ido-everywhere 'buffer))) - (put 'ido-everywhere 'buffer nil)) + (remove-function read-file-name-function #'ido-read-file-name) + (remove-function read-buffer-function #'ido-read-buffer) (when ido-everywhere - (when (memq ido-mode '(both file)) - (put 'ido-everywhere 'file (cons read-file-name-function nil)) - (setq read-file-name-function #'ido-read-file-name)) - (when (memq ido-mode '(both buffer)) - (put 'ido-everywhere 'buffer (cons read-buffer-function nil)) - (setq read-buffer-function #'ido-read-buffer)))) + (add-function :override read-file-name-function #'ido-read-file-name) + (add-function :override read-buffer-function #'ido-read-buffer))) (defvar ido-minor-mode-map-entry nil) @@ -1640,10 +1632,14 @@ This function also adds a hook to the minibuffer." 'ido-find-file-other-window) (define-key map [remap find-file-read-only-other-window] 'ido-find-file-read-only-other-window) + (define-key map [remap find-alternate-file-other-window] + #'ido-find-alternate-file-other-window) + (define-key map [remap dired-other-window] #'ido-dired-other-window) (define-key map [remap find-file-other-frame] 'ido-find-file-other-frame) (define-key map [remap find-file-read-only-other-frame] - 'ido-find-file-read-only-other-frame)) + 'ido-find-file-read-only-other-frame) + (define-key map [remap dired-other-frame] #'ido-dired-other-frame)) (when (memq ido-mode '(buffer both)) (define-key map [remap switch-to-buffer] 'ido-switch-buffer) @@ -1653,7 +1649,9 @@ This function also adds a hook to the minibuffer." 'ido-switch-buffer-other-frame) (define-key map [remap insert-buffer] 'ido-insert-buffer) (define-key map [remap kill-buffer] 'ido-kill-buffer) - (define-key map [remap display-buffer] 'ido-display-buffer)) + (define-key map [remap display-buffer] 'ido-display-buffer) + (define-key map [remap display-buffer-other-frame] + #'ido-display-buffer-other-frame)) (if ido-minor-mode-map-entry (setcdr ido-minor-mode-map-entry map) @@ -1882,7 +1880,6 @@ If INITIAL is non-nil, it specifies the initial input string." ido-selected ido-final-text (done nil) - (non-essential t) ;; prevent eager Tramp connection (icomplete-mode nil) ;; prevent icomplete starting up ;; Exported dynamic variables: ido-cur-list @@ -2444,7 +2441,14 @@ If cursor is not at the end of the user input, move to end of input." (ido-record-work-directory) (find-alternate-file filename)) - ((memq method '(dired list-directory)) + ((eq method 'alt-file-other-window) + (ido-record-work-file filename) + (setq default-directory ido-current-directory) + (ido-record-work-directory) + (find-alternate-file-other-window filename)) + + ((memq method '(dired dired-other-window dired-other-frame + list-directory)) (if (equal filename ".") (setq filename "")) (let* ((dirname (ido-final-slash @@ -2541,7 +2545,7 @@ If cursor is not at the end of the user input, move to end of input." (defun ido-complete () "Try and complete the current pattern amongst the file names." (interactive) - (let (non-essential res) + (let (res) (cond (ido-incomplete-regexp ;; Do nothing @@ -3798,9 +3802,10 @@ frame, rather than all frames, regardless of value of `ido-all-frames'." (lambda (item) (let ((name (ido-name item))) (if (and (or non-prefix-dot - (if (= (aref ido-text 0) ?.) - (= (aref name 0) ?.) - (/= (aref name 0) ?.))) + (and (> (length name) 0) + (if (= (aref ido-text 0) ?.) + (= (aref name 0) ?.) + (/= (aref name 0) ?.)))) (string-match re name)) (cond ((and (eq ido-cur-item 'buffer) @@ -4109,6 +4114,9 @@ Record command in `command-history' if optional RECORD is non-nil." (switch-to-buffer-other-frame buffer) (select-frame-set-input-focus (selected-frame))) + ((eq method 'display-other-frame) + (display-buffer-other-frame buffer)) + ((and (memq method '(raise-frame maybe-frame)) window-system (setq win (ido-buffer-window-other-frame buffer)) @@ -4193,6 +4201,15 @@ For details of keybindings, see `ido-switch-buffer'." (interactive) (ido-buffer-internal 'display 'display-buffer nil nil nil 'ignore)) +;;;###autoload +(defun ido-display-buffer-other-frame () + "Display a buffer preferably in another frame. +The buffer name is selected interactively by typing a substring. +For details of keybindings, see `ido-switch-buffer'." + (interactive) + (ido-buffer-internal 'display-other-frame #'display-buffer-other-frame + nil nil nil #'ignore)) + ;;;###autoload (defun ido-kill-buffer () "Kill a buffer. @@ -4291,6 +4308,14 @@ For details of keybindings, see `ido-find-file'." (interactive) (ido-file-internal 'alt-file 'find-alternate-file nil "Find alternate file: ")) +;;;###autoload +(defun ido-find-alternate-file-other-window () + "Find file as a replacement for the file in the next window. +The file name is selected interactively by typing a substring. +For details of keybindings, see `ido-find-file'." + (interactive) + (ido-file-internal 'alt-file-other-window #'find-alternate-file-other-window)) + ;;;###autoload (defun ido-find-file-read-only () "Edit file read-only with name obtained via minibuffer. @@ -4365,6 +4390,28 @@ For details of keybindings, see `ido-find-file'." (ido-auto-merge-work-directories-length -1)) (ido-file-internal 'dired 'dired nil "Dired: " 'dir))) +;;;###autoload +(defun ido-dired-other-window () + "\"Edit\" a directory. Like `ido-dired' but selects in another window. +The directory is selected interactively by typing a substring. +For details of keybindings, see `ido-find-file'." + (interactive) + (let ((ido-report-no-match nil) + (ido-auto-merge-work-directories-length -1)) + (ido-file-internal 'dired-other-window #'dired-other-window nil + "Dired: " 'dir))) + +;;;###autoload +(defun ido-dired-other-frame () + "\"Edit\" a directory. Like `ido-dired' but makes a new frame. +The directory is selected interactively by typing a substring. +For details of keybindings, see `ido-find-file'." + (interactive) + (let ((ido-report-no-match nil) + (ido-auto-merge-work-directories-length -1)) + (ido-file-internal 'dired-other-frame #'dired-other-frame nil + "Dired: " 'dir))) + (defun ido-list-directory () "Call `list-directory' the Ido way. The directory is selected interactively by typing a substring. diff --git a/lisp/iimage.el b/lisp/iimage.el index 36728112933..abb88ec5029 100644 --- a/lisp/iimage.el +++ b/lisp/iimage.el @@ -3,7 +3,7 @@ ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. ;; Author: KOSEKI Yoshinori <kose@meadowy.org> -;; Maintainer: KOSEKI Yoshinori <kose@meadowy.org> +;; Maintainer: emacs-devel@gnu.org ;; Keywords: multimedia ;; This file is part of GNU Emacs. diff --git a/lisp/imenu.el b/lisp/imenu.el index 0f47a92734e..c1fd4005ab6 100644 --- a/lisp/imenu.el +++ b/lisp/imenu.el @@ -499,7 +499,12 @@ An item looks like (NAME . POSITION)." (string-lessp (car item1) (car item2))) (defun imenu--sort-by-position (item1 item2) - (< (cdr item1) (cdr item2))) + "Comparison function to sort items depending on their position. +Return non-nil if and only if ITEM1's position is lower than ITEM2's +position." + (if (listp (cdr item1)) + (< (cadr item1) (cadr item2)) + (< (cdr item1) (cdr item2)))) (defun imenu--relative-position (&optional reverse) "Support function to calculate relative position in buffer. diff --git a/lisp/indent.el b/lisp/indent.el index fdd184c7998..e7a30b885d7 100644 --- a/lisp/indent.el +++ b/lisp/indent.el @@ -285,7 +285,7 @@ indentation by specifying a large negative ARG." "Indent current line to COLUMN. This function removes or adds spaces and tabs at beginning of line only if necessary. It leaves point at end of indentation." - (backward-to-indentation 0) + (back-to-indentation) (let ((cur-col (current-column))) (cond ((< cur-col column) (if (>= (- column (* (/ cur-col tab-width) tab-width)) tab-width) diff --git a/lisp/info-look.el b/lisp/info-look.el index 694bcb462ce..6963c782704 100644 --- a/lisp/info-look.el +++ b/lisp/info-look.el @@ -43,7 +43,7 @@ ;;; Code: (require 'info) -(require 'subr-x) +(eval-when-compile (require 'subr-x)) (defgroup info-lookup nil "Major mode sensitive help agent." diff --git a/lisp/info.el b/lisp/info.el index 5f4ae5f0b09..a2071533d8f 100644 --- a/lisp/info.el +++ b/lisp/info.el @@ -358,17 +358,17 @@ with wrapping around the current Info node." ;; Try to obey obsolete Info-fontify settings. (unless (and (boundp 'Info-fontify) (null Info-fontify)) '(turn-on-font-lock)) - "Hooks run when `Info-mode' is called." + "Hook run when activating Info Mode." :type 'hook :group 'info) (defcustom Info-selection-hook nil - "Hooks run when `Info-select-node' is called." + "Hook run when an Info node is selected as the current node." :type 'hook :group 'info) (defvar Info-edit-mode-hook nil - "Hooks run when `Info-edit-mode' is called.") + "Hook run when `Info-edit-mode' is activated.") (make-obsolete-variable 'Info-edit-mode-hook "editing Info nodes by hand is not recommended." "24.4") @@ -1869,7 +1869,7 @@ a node in FILENAME. \"(FILENAME)\" is a short format to go to the Top node in FILENAME." (let* ((completion-ignore-case t) (Info-read-node-completion-table (Info-build-node-completions)) - (nodename (completing-read prompt 'Info-read-node-name-1 nil t))) + (nodename (completing-read prompt #'Info-read-node-name-1 nil t))) (if (equal nodename "") (Info-read-node-name prompt) nodename))) @@ -1998,19 +1998,20 @@ If DIRECTION is `backward', search in the reverse direction." Info-isearch-initial-node bound (and found (> found opoint-min) (< found opoint-max))) - (signal 'search-failed (list regexp "end of node"))) + (signal 'user-search-failed (list regexp "(end of node)"))) ;; If no subfiles, give error now. (unless (or found Info-current-subfile) (if isearch-mode - (signal 'search-failed (list regexp "end of manual")) + (signal 'user-search-failed (list regexp "end of manual")) (let ((search-spaces-regexp Info-search-whitespace-regexp)) - (if backward - (re-search-backward regexp) - (re-search-forward regexp))))) + (unless (if backward + (re-search-backward regexp nil t) + (re-search-forward regexp nil t)) + (signal 'user-search-failed (list regexp)))))) (if (and bound (not found)) - (signal 'search-failed (list regexp))) + (signal 'user-search-failed (list regexp))) (unless (or found bound) (unwind-protect @@ -2054,9 +2055,8 @@ If DIRECTION is `backward', search in the reverse direction." (setq list nil))) (if found (message "") - (signal 'search-failed (if isearch-mode - (list regexp "end of manual") - (list regexp))))) + (signal 'user-search-failed + `(,regexp ,@(if isearch-mode '("end of manual")))))) (if (not found) (progn (Info-read-subfile osubfile) (goto-char opoint) @@ -2361,8 +2361,8 @@ If SAME-FILE is non-nil, do not move to a different Info file." "History-specific implementation of `Info-find-node-2'." (insert (format "\n\^_\nFile: %s, Node: %s, Up: (dir)\n\n" (or filename Info-current-file) nodename)) - (insert "Recently Visited Nodes\n") - (insert "**********************\n\n") + (insert "History of Visited Nodes\n") + (insert "************************\n\n") (insert "* Menu:\n\n") (let ((hl (remove '("*History*" "Top") Info-history-list))) (while hl @@ -2583,7 +2583,8 @@ new buffer." "Follow reference named: ") completions nil t))) (list (if (equal input "") - default input) current-prefix-arg)) + default input) + current-prefix-arg)) (user-error "No cross-references in this node")))) (unless footnotename @@ -2699,9 +2700,11 @@ Because of ambiguities, this should be concatenated with something like (orignode Info-current-node) nextnode) (goto-char (point-min)) - (search-forward "\n* Menu:") + (unless (search-forward "\n* Menu:" nil t) + (user-error "No menu in this node")) (cond ((eq (car-safe action) 'boundaries) nil) + ((eq action 'metadata) `(metadata (category . info-menu))) ((eq action 'lambda) (re-search-forward (concat "\n\\* +" (regexp-quote string) ":") nil t)) @@ -2782,15 +2785,7 @@ new buffer." default) "Menu item: ") #'Info-complete-menu-item nil t nil nil - default))) - ;; we rely on the fact that completing-read accepts an input - ;; of "" even when the require-match argument is true and "" - ;; is not a valid possibility - (if (string= item "") - (if default - (setq item default) - ;; ask again - (setq item nil)))) + default)))) (list item current-prefix-arg)))) ;; there is a problem here in that if several menu items have the same ;; name you can only go to the node of the first with this command. @@ -3307,7 +3302,7 @@ Give an empty topic name to go to the Index node itself." (unwind-protect (with-current-buffer Info-complete-menu-buffer (Info-goto-index) - (completing-read "Index topic: " 'Info-complete-menu-item)) + (completing-read "Index topic: " #'Info-complete-menu-item)) (kill-buffer Info-complete-menu-buffer))))) (if (equal Info-current-file "dir") (error "The Info directory node has no index; use m to select a manual")) @@ -3481,7 +3476,7 @@ search results." (unwind-protect (with-current-buffer Info-complete-menu-buffer (Info-goto-index) - (completing-read "Index topic: " 'Info-complete-menu-item)) + (completing-read "Index topic: " #'Info-complete-menu-item)) (kill-buffer Info-complete-menu-buffer))))) (if (equal topic "") (Info-find-node Info-current-file "*Index*") @@ -5237,9 +5232,6 @@ BUFFER is the buffer speedbar is requesting buttons for." (erase-buffer)) (Info-speedbar-hierarchy-buttons nil 0)) -;; FIXME: Really? Why here? -(add-to-list 'debug-ignored-errors 'search-failed) - ;;;; Desktop support (defun Info-desktop-buffer-misc-data (_desktop-dirname) diff --git a/lisp/international/README b/lisp/international/README deleted file mode 100644 index 92fc4a089ec..00000000000 --- a/lisp/international/README +++ /dev/null @@ -1,13 +0,0 @@ -The following files in this directory are derived from the Unicode -Data File at http://www.unicode.org/Public/UNIDATA/UnicodeData.txt: - - charprop.el uni-bidi.el uni-category.el uni-combining.el - uni-comment.el uni-decimal.el uni-decomposition.el uni-digit.el - uni-lowercase.el uni-mirrored.el uni-name.el uni-numeric.el - uni-old-name.el uni-titlecase.el uni-uppercase.el - -These files were generated from the version admin/unidata/UnicodeData.txt -in the Emacs sources, using the file unidata-gen.el in the same directory. - -The file UnicodeData.txt is used under the Unicode Terms of Use, -contained in the file admin/unidata/copyright.html. diff --git a/lisp/international/characters.el b/lisp/international/characters.el index 3eb287fd963..e48fc83c3df 100644 --- a/lisp/international/characters.el +++ b/lisp/international/characters.el @@ -148,6 +148,7 @@ with L, LRE, or LRO Unicode bidi character type.") (modify-category-entry '(#xF900 . #xFAFF) ?C) (modify-category-entry '(#xF900 . #xFAFF) ?c) (modify-category-entry '(#xF900 . #xFAFF) ?|) +(modify-category-entry '(#x1B170 . #x1B2FF) ?c) (modify-category-entry '(#x20000 . #x2FFFF) ?|) (modify-category-entry '(#x20000 . #x2FFFF) ?C) (modify-category-entry '(#x20000 . #x2FFFF) ?c) @@ -221,6 +222,8 @@ with L, LRE, or LRO Unicode bidi character type.") (modify-category-entry #x30A0 ?H) (modify-category-entry #x30FC ?H) +(modify-category-entry '(#x1B000 . #x1B1FF) ?j) + ;; JISX0208 (map-charset-chars #'modify-syntax-entry 'japanese-jisx0208 "_" #x2121 #x227E) @@ -881,9 +884,9 @@ with L, LRE, or LRO Unicode bidi character type.") (#x05C1 . #x05C2) (#x05C4 . #x05C5) (#x05C7 . #x05C7) - (#x0600 . #x0603) - (#x0610 . #x0615) - (#x064B . #x065E) + (#x0600 . #x0605) + (#x0610 . #x061C) + (#x064B . #x065F) (#x0670 . #x0670) (#x06D6 . #x06E4) (#x06E7 . #x06E8) @@ -893,11 +896,15 @@ with L, LRE, or LRO Unicode bidi character type.") (#x0730 . #x074A) (#x07A6 . #x07B0) (#x07EB . #x07F3) - (#x0901 . #x0902) + (#x0816 . #x0823) + (#x0825 . #x082D) + (#x0859 . #x085B) + (#x08D4 . #x0902) + (#x093A . #x093A) (#x093C . #x093C) (#x0941 . #x0948) (#x094D . #x094D) - (#x0951 . #x0954) + (#x0951 . #x0957) (#x0962 . #x0963) (#x0981 . #x0981) (#x09BC . #x09BC) @@ -907,7 +914,12 @@ with L, LRE, or LRO Unicode bidi character type.") (#x0A01 . #x0A02) (#x0A3C . #x0A3C) (#x0A41 . #x0A4D) + (#x0A41 . #x0A42) + (#x0A47 . #x0A48) + (#x0A4B . #x0A4D) + (#x0A51 . #x0A51) (#x0A70 . #x0A71) + (#x0A75 . #x0A75) (#x0A81 . #x0A82) (#x0ABC . #x0ABC) (#x0AC1 . #x0AC8) @@ -916,20 +928,24 @@ with L, LRE, or LRO Unicode bidi character type.") (#x0B01 . #x0B01) (#x0B3C . #x0B3C) (#x0B3F . #x0B3F) - (#x0B41 . #x0B43) + (#x0B41 . #x0B44) (#x0B4D . #x0B56) + (#x0B62 . #x0B63) (#x0B82 . #x0B82) (#x0BC0 . #x0BC0) (#x0BCD . #x0BCD) + (#x0C00 . #x0C00) (#x0C3E . #x0C40) (#x0C46 . #x0C56) + (#x0C62 . #x0C63) + (#x0C81 . #x0C81) (#x0CBC . #x0CBC) - (#x0CBF . #x0CBF) - (#x0CC6 . #x0CC6) (#x0CCC . #x0CCD) (#x0CE2 . #x0CE3) - (#x0D41 . #x0D43) + (#x0D01 . #x0D01) + (#x0D41 . #x0D44) (#x0D4D . #x0D4D) + (#x0D62 . #x0D63) (#x0DCA . #x0DCA) (#x0DD2 . #x0DD6) (#x0E31 . #x0E31) @@ -945,14 +961,20 @@ with L, LRE, or LRO Unicode bidi character type.") (#x0F71 . #x0F7E) (#x0F80 . #x0F84) (#x0F86 . #x0F87) - (#x0F90 . #x0FBC) + (#x0F8D . #x0FBC) (#x0FC6 . #x0FC6) (#x102D . #x1030) (#x1032 . #x1037) - (#x1039 . #x1039) + (#x1039 . #x103A) + (#x103D . #x103E) (#x1058 . #x1059) - (#x1160 . #x11FF) - (#x135F . #x135F) + (#x105E . #x1160) + (#x1171 . #x1074) + (#x1082 . #x1082) + (#x1085 . #x1086) + (#x108D . #x108D) + (#x109D . #x109D) + (#x135D . #x135F) (#x1712 . #x1714) (#x1732 . #x1734) (#x1752 . #x1753) @@ -962,84 +984,214 @@ with L, LRE, or LRO Unicode bidi character type.") (#x17C6 . #x17C6) (#x17C9 . #x17D3) (#x17DD . #x17DD) - (#x180B . #x180D) + (#x180B . #x180E) + (#x18A9 . #x18A9) + (#x1885 . #x1886) (#x18A9 . #x18A9) (#x1920 . #x1922) (#x1927 . #x1928) (#x1932 . #x1932) (#x1939 . #x193B) (#x1A17 . #x1A18) + (#x1A1B . #x1A1B) + (#x1A56 . #x1A56) + (#x1A58 . #x1A5E) + (#x1A60 . #x1A60) + (#x1A62 . #x1A62) + (#x1A65 . #x1A6C) + (#x1A73 . #x1A7C) + (#x1A7F . #x1A7F) + (#x1AB0 . #x1ABE) (#x1B00 . #x1B03) (#x1B34 . #x1B34) (#x1B36 . #x1B3A) (#x1B3C . #x1B3C) (#x1B42 . #x1B42) (#x1B6B . #x1B73) + (#x1B80 . #x1B81) + (#x1BA2 . #x1BA5) + (#x1BA8 . #x1BA9) + (#x1BAB . #x1BAD) + (#x1BE6 . #x1BE6) + (#x1BE8 . #x1BE9) + (#x1BED . #x1BED) + (#x1BEF . #x1BF1) + (#x1C2C . #x1C33) + (#x1C36 . #x1C37) + (#x1CD0 . #x1CD2) + (#x1CD4 . #x1CE0) + (#x1CE2 . #x1CE8) + (#x1CED . #x1CED) + (#x1CF4 . #x1CF4) + (#x1CF8 . #x1CF9) (#x1DC0 . #x1DFF) (#x200B . #x200F) (#x202A . #x202E) (#x2060 . #x206F) - (#x20D0 . #x20EF) - (#x302A . #x302F) - (#x3099 . #x309A) + (#x20D0 . #x20F0) + (#x2CEF . #x2CF1) + (#x2D7F . #x2D7F) + (#x2DE0 . #x2DFF) + (#xA66F . #xA672) + (#xA674 . #xA69F) + (#xA6F0 . #xA6F1) + (#xA802 . #xA802) (#xA806 . #xA806) (#xA80B . #xA80B) (#xA825 . #xA826) + (#xA8C4 . #xA8C5) + (#xA8E0 . #xA8F1) + (#xA926 . #xA92D) + (#xA947 . #xA951) + (#xA980 . #xA9B3) + (#xA9B6 . #xA9B9) + (#xA9BC . #xA9BC) + (#xA9E5 . #xA9E5) + (#xAA29 . #xAA2E) + (#xAA31 . #xAA32) + (#xAA35 . #xAA36) + (#xAA43 . #xAA43) + (#xAA4C . #xAA4C) + (#xAA7C . #xAA7C) + (#xAAB0 . #xAAB0) + (#xAAB2 . #xAAB4) + (#xAAB7 . #xAAB8) + (#xAABE . #xAABF) + (#xAAC1 . #xAAC1) + (#xAAEC . #xAAED) + (#xAAF6 . #xAAF6) + (#xABE5 . #xABE5) + (#xABE8 . #xABE8) + (#xABED . #xABED) (#xFB1E . #xFB1E) (#xFE00 . #xFE0F) - (#xFE20 . #xFE23) + (#xFE20 . #xFE2F) (#xFEFF . #xFEFF) (#xFFF9 . #xFFFB) + (#x101FD . #x101FD) + (#x102E0 . #x102E0) + (#x10376 . #x1037A) (#x10A01 . #x10A0F) (#x10A38 . #x10A3F) + (#x10AE5 . #x10AE6) + (#x11001 . #x11001) + (#x11038 . #x11046) + (#x1107F . #x11081) + (#x110B3 . #x110B6) + (#x110B9 . #x110BA) + (#x110BD . #x110BD) + (#x11100 . #x11102) + (#x11127 . #x1112B) + (#x1112D . #x11134) + (#x11173 . #x11173) + (#x11180 . #x11181) + (#x111B6 . #x111BE) + (#x111CA . #x111CC) + (#x1122F . #x11231) + (#x11234 . #x11234) + (#x11236 . #x11237) + (#x1123E . #x1123E) + (#x112DF . #x112DF) + (#x112E3 . #x112EA) + (#x11300 . #x11301) + (#x1133C . #x1133C) + (#x11340 . #x11340) + (#x11366 . #x1136C) + (#x11370 . #x11374) + (#x11438 . #x1143F) + (#x11442 . #x11444) + (#x11446 . #x11446) + (#x114B3 . #x114B8) + (#x114BA . #x114C0) + (#x114C2 . #x114C3) + (#x115B2 . #x115B5) + (#x115BC . #x115BD) + (#x115BF . #x115C0) + (#x115DC . #x115DD) + (#x11633 . #x1163A) + (#x1163D . #x1163D) + (#x1163F . #x11640) + (#x116AB . #x116AB) + (#x116AD . #x116AD) + (#x116B0 . #x116B5) + (#x116B7 . #x116B7) + (#x1171D . #x1171F) + (#x11722 . #x11725) + (#x11727 . #x1172B) + (#x11C30 . #x11C36) + (#x11C38 . #x11C3D) + (#x11C92 . #x11CA7) + (#x11CAA . #x11CB0) + (#x11CB2 . #x11CB3) + (#x11CB5 . #x11CB6) + (#x16AF0 . #x16AF4) + (#x16B30 . #x16B36) + (#x16F8F . #x16F92) + (#x1BC9D . #x1BC9E) + (#x1BCA0 . #x1BCA3) (#x1D167 . #x1D169) (#x1D173 . #x1D182) (#x1D185 . #x1D18B) (#x1D1AA . #x1D1AD) (#x1D242 . #x1D244) + (#x1DA00 . #x1DA36) + (#x1DA3B . #x1DA6C) + (#x1DA75 . #x1DA75) + (#x1DA84 . #x1DA84) + (#x1DA9B . #x1DA9F) + (#x1DAA1 . #x1DAAF) + (#x1E000 . #x1E006) + (#x1E008 . #x1E018) + (#x1E01B . #x1E021) + (#x1E023 . #x1E024) + (#x1E026 . #x1E02A) + (#x1E8D0 . #x1E8D6) + (#x1E944 . #x1E94A) (#xE0001 . #xE01EF)))) (dolist (elt l) (set-char-table-range char-width-table elt 0))) ;; 2: East Asian Wide and Full-width characters. (let ((l '((#x1100 . #x115F) - (#x231A . #x231B) + (#x231A . #x231B) (#x2329 . #x232A) - (#x23E9 . #x23EC) - (#x23F0 . #x23F0) - (#x23F3 . #x23F3) - (#x25FD . #x25FE) - (#x2614 . #x2615) - (#x2648 . #x2653) - (#x267F . #x267F) - (#x2693 . #x2693) - (#x26A1 . #x26A1) - (#x26AA . #x26AB) - (#x26BD . #x26BE) - (#x26C4 . #x26C5) - (#x26CE . #x26CE) - (#x26D4 . #x26D4) - (#x26EA . #x26EA) - (#x26F2 . #x26F3) - (#x26F5 . #x26F5) - (#x26FA . #x26FA) - (#x26FD . #x26FD) - (#x2705 . #x2705) - (#x270A . #x270B) - (#x2728 . #x2728) - (#x274C . #x274C) - (#x274E . #x274E) - (#x2753 . #x2755) - (#x2757 . #x2757) - (#x2795 . #x2797) - (#x27B0 . #x27B0) - (#x27BF . #x27BF) - (#x2B1B . #x2B1C) - (#x2B50 . #x2B50) - (#x2B55 . #x2B55) + (#x23E9 . #x23EC) + (#x23F0 . #x23F0) + (#x23F3 . #x23F3) + (#x25FD . #x25FE) + (#x2614 . #x2615) + (#x2648 . #x2653) + (#x267F . #x267F) + (#x2693 . #x2693) + (#x26A1 . #x26A1) + (#x26AA . #x26AB) + (#x26BD . #x26BE) + (#x26C4 . #x26C5) + (#x26CE . #x26CE) + (#x26D4 . #x26D4) + (#x26EA . #x26EA) + (#x26F2 . #x26F3) + (#x26F5 . #x26F5) + (#x26FA . #x26FA) + (#x26FD . #x26FD) + (#x2705 . #x2705) + (#x270A . #x270B) + (#x2728 . #x2728) + (#x274C . #x274C) + (#x274E . #x274E) + (#x2753 . #x2755) + (#x2757 . #x2757) + (#x2795 . #x2797) + (#x27B0 . #x27B0) + (#x27BF . #x27BF) + (#x2B1B . #x2B1C) + (#x2B50 . #x2B50) + (#x2B55 . #x2B55) (#x2E80 . #x303E) - (#x3040 . #x4DBF) + (#x3040 . #x3247) + (#x3250 . #x4DBF) (#x4E00 . #xA4CF) + (#xA490 . #xA4C6) (#xA960 . #xA97F) (#xAC00 . #xD7A3) (#xF900 . #xFAFF) @@ -1047,28 +1199,47 @@ with L, LRE, or LRO Unicode bidi character type.") (#xFE30 . #xFE6F) (#xFF01 . #xFF60) (#xFFE0 . #xFFE6) - (#x16FE0 . #x16FE0) - (#x17000 . #x187EC) - (#x18800 . #x18AF2) - (#x1B000 . #x1B001) - (#x1F18E . #x1F18E) - (#x1F191 . #x1F19A) - (#x1F200 . #x1F2FF) - (#x1F300 . #x1F5FF) - (#x1F600 . #x1F64F) - (#x1F680 . #x1F6C5) - (#x1F6CC . #x1F6CC) - (#x1F6D0 . #x1F6D2) - (#x1F6EB . #x1F6EC) - (#x1F6F4 . #x1F6F6) - (#x1F910 . #x1F91E) - (#x1F920 . #x1F927) - (#x1F930 . #x1F930) - (#x1F933 . #x1F93E) - (#x1F940 . #x1F94B) - (#x1F950 . #x1F95E) - (#x1F980 . #x1F991) - (#x1F9C0 . #x1F9C0) + (#x16FE0 . #x16FE1) + (#x17000 . #x187EC) + (#x18800 . #x18AF2) + (#x1B000 . #x1B11E) + (#x1B170 . #x1B2FB) + (#x1F004 . #x1F004) + (#x1F0CF . #x1F0CF) + (#x1F18E . #x1F18E) + (#x1F191 . #x1F19A) + (#x1F200 . #x1F320) + (#x1F32D . #x1F335) + (#x1F337 . #x1F37C) + (#x1F37E . #x1F393) + (#x1F3A0 . #x1F3CA) + (#x1F3CF . #x1F3D3) + (#x1F3E0 . #x1F3F0) + (#x1F3F4 . #x1F3F4) + (#x1F3F8 . #x1F3FA) + (#x1F3FB . #x1F3FF) + (#x1F400 . #x1F43E) + (#x1F440 . #x1F440) + (#x1F442 . #x1F4FC) + (#x1F4FF . #x1F53D) + (#x1F54B . #x1F54E) + (#x1F550 . #x1F567) + (#x1F57A . #x1F57A) + (#x1F595 . #x1F596) + (#x1F5A4 . #x1F5A4) + (#x1F5FB . #x1F5FF) + (#x1F600 . #x1F64F) + (#x1F680 . #x1F6C5) + (#x1F6CC . #x1F6CC) + (#x1F6D0 . #x1F6D2) + (#x1F6EB . #x1F6EC) + (#x1F6F4 . #x1F6F8) + (#x1F910 . #x1F93E) + (#x1F940 . #x1F94C) + (#x1F950 . #x1F96B) + (#x1F980 . #x1F997) + (#x1F9C0 . #x1F9C0) + (#x1F9D0 . #x1F9E6) (#x20000 . #x2FFFF) (#x30000 . #x3FFFF)))) (dolist (elt l) diff --git a/lisp/international/fontset.el b/lisp/international/fontset.el index e023d253693..8a1a9cfc58b 100644 --- a/lisp/international/fontset.el +++ b/lisp/international/fontset.el @@ -227,9 +227,12 @@ (modi #x11600) (takri #x11680) (warang-citi #x118A1) + (zanabazar-square #x11A00) + (soyombo #x11A50) (pau-cin-hau #x11AC0) (bhaiksuki #x11C00) (marchen #x11C72) + (masaram-gondi #x11D00) (cuneiform #x12000) (cuneiform-numbers-and-punctuation #x12400) (mro #x16A40) @@ -237,6 +240,7 @@ (pahawh-hmong #x16B11) (tangut #x17000) (tangut-components #x18800) + (nushu #x1B170) (duployan-shorthand #x1BC20) (byzantine-musical-symbol #x1D000) (musical-symbol #x1D100) diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el index bdba8eeb112..bcbc92844d6 100644 --- a/lisp/international/mule-cmds.el +++ b/lisp/international/mule-cmds.el @@ -2945,8 +2945,10 @@ on encoding." ;; (#x17000 . #x187FF) Tangut Ideographs ;; (#x18800 . #x18AFF) Tangut Components ;; (#x18B00 . #x1AFFF) unused - (#x1B000 . #x1B0FF) - ;; (#x1B100 . #x1BBFF) unused + (#x1B000 . #x1B12F) + ;; (#x1B130 . #x1B16F) unused + (#x1B170 . #x1B2FF) + ;; (#x1B300 . #x1BBFF) unused (#x1BC00 . #x1BCAF) ;; (#x1BCB0 . #x1CFFF) unused (#x1D000 . #x1FFFF) diff --git a/lisp/international/mule-util.el b/lisp/international/mule-util.el index 92a658655ac..e34b01c3064 100644 --- a/lisp/international/mule-util.el +++ b/lisp/international/mule-util.el @@ -342,7 +342,7 @@ QUALITY can be: `approximate', in which case we may cut some corners to avoid excessive work. `exact', in which case we may end up re-(en/de)coding a large - part of the file/buffer. + part of the file/buffer, this can be expensive and slow. nil, in which case we may return nil rather than an approximation." (unless coding-system (setq coding-system buffer-file-coding-system)) (let ((eol (coding-system-eol-type coding-system)) @@ -418,7 +418,7 @@ QUALITY can be: `approximate', in which case we may cut some corners to avoid excessive work. `exact', in which case we may end up re-(en/de)coding a large - part of the file/buffer. + part of the file/buffer, this can be expensive and slow. nil, in which case we may return nil rather than an approximation." (unless coding-system (setq coding-system buffer-file-coding-system)) (let* ((eol (coding-system-eol-type coding-system)) diff --git a/lisp/international/mule.el b/lisp/international/mule.el index 8754f7f27d7..6cfb7e6d457 100644 --- a/lisp/international/mule.el +++ b/lisp/international/mule.el @@ -1311,8 +1311,8 @@ Internal use only.") preferred)))))) (completion-ignore-case t) (completion-pcm--delim-wild-regex ; Let "u8" complete to "utf-8". - (concat completion-pcm--delim-wild-regex - "\\|\\([[:alpha:]]\\)[[:digit:]]")) + (concat "\\(?:" completion-pcm--delim-wild-regex + "\\|\\([[:alpha:]]\\)[[:digit:]]\\)")) (cs (completing-read (format "Coding system for saving file (default %s): " default) combined-table @@ -1970,7 +1970,7 @@ use \"coding: 'raw-text\" instead." (goto-char tail-start) (re-search-forward "[\r\n]\^L" tail-end t) (if (re-search-forward - "[\r\n]\\([^[\r\n]*\\)[ \t]*Local Variables:[ \t]*\\([^\r\n]*\\)[\r\n]" + "[\r\n]\\([^\r\n]*\\)[ \t]*Local Variables:[ \t]*\\([^\r\n]*\\)[\r\n]" tail-end t) ;; The prefix is what comes before "local variables:" in its ;; line. The suffix is what comes after "local variables:" diff --git a/lisp/international/ogonek.el b/lisp/international/ogonek.el index cef11db042f..ef3a980f19a 100644 --- a/lisp/international/ogonek.el +++ b/lisp/international/ogonek.el @@ -4,7 +4,7 @@ ;; Author: Włodek Bzyl ;; Ryszard Kubiak -;; Maintainer: Ryszard Kubiak <rysiek@ipipan.gda.pl> +;; Maintainer: emacs-devel@gnu.org ;; Keywords: i18n ;; This file is part of GNU Emacs. diff --git a/lisp/international/rfc1843.el b/lisp/international/rfc1843.el index c1343274c93..9b918547141 100644 --- a/lisp/international/rfc1843.el +++ b/lisp/international/rfc1843.el @@ -1,4 +1,4 @@ -;;; rfc1843.el --- HZ (rfc1843) decoding +;;; rfc1843.el --- HZ (rfc1843) decoding -*- lexical-binding:t -*- ;; Copyright (C) 1998-2017 Free Software Foundation, Inc. @@ -27,7 +27,7 @@ ;;; Code: -(eval-when-compile (require 'cl)) +(eval-when-compile (require 'cl-lib)) (defvar rfc1843-word-regexp "~\\({\\([\041-\167][\041-\176]\\| \\)+\\)\\(~}\\|$\\)") @@ -115,15 +115,15 @@ ftp://ftp.math.psu.edu/pub/simpson/chinese/hzp/hzp.doc" "Decode HZ WORD and return it." (let ((i -1) (s (substring word 0)) v) (if (or (not firstc) (eq firstc ?{)) - (while (< (incf i) (length s)) + (while (< (cl-incf i) (length s)) (if (eq (setq v (aref s i)) ? ) nil (aset s i (+ 128 v)))) - (while (< (incf i) (length s)) + (while (< (cl-incf i) (length s)) (if (eq (setq v (aref s i)) ? ) nil (setq v (+ (* 94 v) (aref s (1+ i)) -3135)) (aset s i (+ (/ v 157) (if (eq firstc ?<) 201 161))) (setq v (% v 157)) - (aset s (incf i) (+ v (if (< v 63) 64 98)))))) + (aset s (cl-incf i) (+ v (if (< v 63) 64 98)))))) s)) (provide 'rfc1843) diff --git a/lisp/international/titdic-cnv.el b/lisp/international/titdic-cnv.el index 6f65d491ed4..130bc742a51 100644 --- a/lisp/international/titdic-cnv.el +++ b/lisp/international/titdic-cnv.el @@ -1167,11 +1167,14 @@ the generated Quail package is saved." (if (eq coding 'iso-2022-cn-ext) "Chinese-CNS" "Chinese-GB")) "\" \"" title "\" t\n") - (let* ((coding-system-for-read - (coding-system-change-eol-conversion coding 'unix)) - (dicbuf (find-file-noselect filename))) - (funcall converter dicbuf name title) - (kill-buffer dicbuf)) + (let ((coding-system-for-read + (coding-system-change-eol-conversion coding 'unix)) + (dstbuf (current-buffer))) + (with-temp-buffer + (insert-file-contents filename) + (let ((dicbuf (current-buffer))) + (with-current-buffer dstbuf + (funcall converter dicbuf name title))))) (insert ";; Local Variables:\n" ";; version-control: never\n" ";; no-update-autoloads: t\n" diff --git a/lisp/international/utf7.el b/lisp/international/utf7.el index 82dad3da6eb..f245d7eb696 100644 --- a/lisp/international/utf7.el +++ b/lisp/international/utf7.el @@ -1,4 +1,4 @@ -;;; utf7.el --- UTF-7 encoding/decoding for Emacs -*-coding: utf-8;-*- +;;; utf7.el --- UTF-7 encoding/decoding for Emacs -*- lexical-binding:t -*- ;; Copyright (C) 1999-2017 Free Software Foundation, Inc. @@ -64,7 +64,6 @@ ;;; Code: (require 'base64) -(eval-when-compile (require 'cl)) (require 'mm-util) (defconst utf7-direct-encoding-chars " -%'-*,-[]-}" @@ -140,8 +139,7 @@ Use IMAP modification if FOR-IMAP is non-nil." (defun utf7-decode-internal (&optional for-imap) "Decode UTF-7 text in (temporary) buffer. Use IMAP modification if FOR-IMAP is non-nil." - (let ((start (point-min)) - (end (point-max))) + (let ((start (point-min))) (goto-char start) (let* ((esc-pattern (concat "^" (char-to-string (if for-imap ?& ?+)))) (base64-chars (concat "A-Za-z0-9+" diff --git a/lisp/isearch.el b/lisp/isearch.el index c34739d6386..5f34dcadb5d 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -2036,9 +2036,9 @@ For a click in the echo area, invoke `isearch-yank-x-selection'. Otherwise invoke whatever the calling mouse-2 command sequence is bound to outside of Isearch." (interactive "e") - (let* ((w (posn-window (event-start click))) - (overriding-terminal-local-map nil) - (binding (key-binding (this-command-keys-vector) t))) + (let ((w (posn-window (event-start click))) + (binding (let ((overriding-terminal-local-map nil)) + (key-binding (this-command-keys-vector) t)))) (if (and (window-minibuffer-p w) (not (minibuffer-window-active-p w))) ; in echo area (isearch-yank-x-selection) diff --git a/lisp/json.el b/lisp/json.el index 049c9b1951a..3def94ce042 100644 --- a/lisp/json.el +++ b/lisp/json.el @@ -2,7 +2,7 @@ ;; Copyright (C) 2006-2017 Free Software Foundation, Inc. -;; Author: Edward O'Connor <ted@oconnor.cx> +;; Author: Theresa O'Connor <ted@oconnor.cx> ;; Version: 1.4 ;; Keywords: convenience @@ -206,7 +206,11 @@ Unlike `reverse', this keeps the property-value pairs intact." (defun json-skip-whitespace () "Skip past the whitespace at point." - (skip-chars-forward "\t\r\n\f\b ")) + ;; See + ;; https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf + ;; or https://tools.ietf.org/html/rfc7159#section-2 for the + ;; definition of whitespace in JSON. + (skip-chars-forward "\t\r\n ")) diff --git a/lisp/language/japan-util.el b/lisp/language/japan-util.el index abc8d7d6bcd..01cdd8bef9e 100644 --- a/lisp/language/japan-util.el +++ b/lisp/language/japan-util.el @@ -102,7 +102,7 @@ HANKAKU-KATAKANA belongs to `japanese-jisx0201-kana'.") (?$B!'(B ?:) (?$B!((B ?\;) (?$B!)(B ??) (?$B!*(B ?!) (?$B!+(B nil ?(I^(B) (?$B!,(B nil ?(I_(B) (?$B!-(B ?') (?$B!.(B ?`) (?$B!0(B ?^) (?$B!2(B ?_) (?$B!<(B ?- ?(I0(B) (?$B!=(B ?-) (?$B!>(B ?-) (?$B!?(B ?/) (?$B!@(B ?\\) (?$B!A(B ?~) (?$B!C(B ?|) (?$B!F(B ?`) (?$B!G(B ?') (?$B!H(B ?\") (?$B!I(B ?\") - (?\$B!J(B ?\() (?\$B!K(B ?\)) (?\$B!N(B ?[) (?\$B!O(B ?]) (?\$B!P(B ?{) (?\$B!Q(B ?}) + (?\$B!J(B ?\() (?\$B!K(B ?\)) (?\$B!N(B ?\[) (?\$B!O(B ?\]) (?\$B!P(B ?{) (?\$B!Q(B ?}) (?$B!R(B ?<) (?$B!S(B ?>) (?\$B!V(B nil ?\(I"(B) (?\$B!W(B nil ?\(I#(B) (?$B!\(B ?+) (?$B!](B ?-) (?$B!a(B ?=) (?$B!c(B ?<) (?$B!d(B ?>) (?$B!l(B ?') (?$B!m(B ?\") (?$B!o(B ?\\) (?$B!p(B ?$) (?$B!s(B ?%) (?$B!t(B ?#) (?$B!u(B ?&) (?$B!v(B ?*) diff --git a/lisp/ldefs-boot-auto.el b/lisp/ldefs-boot-auto.el deleted file mode 100644 index 020c6707a00..00000000000 --- a/lisp/ldefs-boot-auto.el +++ /dev/null @@ -1,159 +0,0 @@ -;; This file is autogenerated by admin/ldefs-clean.el -;; Do not edit -(autoload 'Info-directory "info" nil nil nil) -(autoload 'Info-index "info" nil nil nil) -(autoload 'View-exit-and-edit "view" nil nil nil) -(autoload 'add-change-log-entry "add-log" nil nil nil) -(autoload 'add-log-current-defun "add-log" nil nil nil) -(autoload 'batch-byte-compile "bytecomp" nil nil nil) -(autoload 'batch-update-autoloads "autoload" nil nil nil) -(autoload 'bounds-of-thing-at-point "thingatpt" nil nil nil) -(autoload 'browse-url "browse-url" nil nil nil) -(autoload 'buffer-face-mode "face-remap" nil nil nil) -(autoload 'byte-compile "bytecomp" nil nil nil) -(autoload 'byte-compile-disable-warning "bytecomp" nil nil nil) -(autoload 'byte-compile-enable-warning "bytecomp" nil nil nil) -(autoload 'byte-compile-file "bytecomp" nil nil nil) -(autoload 'byte-compile-inline-expand "byte-opt" nil nil nil) -(autoload 'byte-compile-unfold-lambda "byte-opt" nil nil nil) -(autoload 'byte-optimize-form "byte-opt" nil nil nil) -(autoload 'byte-optimize-lapcode "byte-opt" nil nil nil) -(autoload 'byte-recompile-directory "bytecomp" nil nil nil) -(autoload 'char-displayable-p "mule-util" nil nil nil) -(autoload 'color-name-to-rgb "color" nil nil nil) -(autoload 'comint-redirect-results-list-from-process "comint" nil nil nil) -(autoload 'comint-redirect-send-command-to-process "comint" nil nil nil) -(autoload 'compilation-mode "compile" nil nil nil) -(autoload 'compilation-shell-minor-mode "compile" nil nil nil) -(autoload 'compilation-start "compile" nil nil nil) -(autoload 'completing-read-multiple "crm" nil nil nil) -(autoload 'conf-mode "conf-mode" nil nil nil) -(autoload 'create-glyph "disp-table" nil nil nil) -(autoload 'create-image "image" nil nil nil) -(autoload 'cursor-sensor-mode "cursor-sensor" nil nil nil) -(autoload 'custom-save-all "cus-edit" nil nil nil) -(autoload 'customize-face "cus-edit" nil nil nil) -(autoload 'customize-group "cus-edit" nil nil nil) -(autoload 'customize-option "cus-edit" nil nil nil) -(autoload 'customize-push-and-save "cus-edit" nil nil nil) -(autoload 'customize-set-variable "cus-edit" nil nil nil) -(autoload 'debug "debug" nil nil nil) -(autoload 'define-ccl-program "ccl" nil nil t) -(autoload 'define-derived-mode "derived" nil nil t) -(autoload 'define-minor-mode "easy-mmode" nil nil t) -(autoload 'delete-extract-rectangle "rect" nil nil nil) -(autoload 'describe-char "descr-text" nil nil nil) -(autoload 'describe-coding-system "mule-diag" nil nil nil) -(autoload 'describe-display-table "disp-table" nil nil nil) -(autoload 'describe-function "help-fns" nil nil nil) -(autoload 'describe-function-1 "help-fns" nil nil nil) -(autoload 'describe-package "package" nil nil nil) -(autoload 'describe-variable "help-fns" nil nil nil) -(autoload 'desktop-save "desktop" nil nil nil) -(autoload 'diff-mode "diff-mode" nil nil nil) -(autoload 'dired "dired" nil nil nil) -(autoload 'dired-copy-file "dired-aux" nil nil nil) -(autoload 'dired-goto-subdir "dired-aux" nil nil nil) -(autoload 'dired-hide-subdir "dired-aux" nil nil nil) -(autoload 'dired-insert-subdir "dired-aux" nil nil nil) -(autoload 'dired-kill-subdir "dired-aux" nil nil nil) -(autoload 'dired-mark-subdir-files "dired-aux" nil nil nil) -(autoload 'dired-mode "dired" nil nil nil) -(autoload 'dired-noselect "dired" nil nil nil) -(autoload 'dired-query "dired-aux" nil nil nil) -(autoload 'dired-rename-file "dired-aux" nil nil nil) -(autoload 'display-call-tree "bytecomp" nil nil nil) -(autoload 'display-table-slot "disp-table" nil nil nil) -(autoload 'display-warning "warnings" nil nil nil) -(autoload 'easy-menu-create-menu "easymenu" nil nil nil) -(autoload 'edebug-basic-spec "edebug" nil nil nil) -(autoload 'ediff-patch-file "ediff" nil nil nil) -(autoload 'edit-kbd-macro "edmacro" nil nil nil) -(autoload 'extract-rectangle "rect" nil nil nil) -(autoload 'find-definition-noselect "find-func" nil nil nil) -(autoload 'find-function-search-for-symbol "find-func" nil nil nil) -(autoload 'find-lisp-object-file-name "help-fns" nil nil nil) -(autoload 'find-variable-noselect "find-func" nil nil nil) -(autoload 'format-kbd-macro "edmacro" nil nil nil) -(autoload 'goto-address-mode "goto-addr" nil nil nil) -(autoload 'grep-compute-defaults "grep" nil nil nil) -(autoload 'help-C-file-name "help-fns" nil nil nil) -(autoload 'help-buffer "help-mode" nil nil nil) -(autoload 'help-insert-xref-button "help-mode" nil nil nil) -(autoload 'help-make-xrefs "help-mode" nil nil nil) -(autoload 'help-mode "help-mode" nil nil nil) -(autoload 'help-setup-xref "help-mode" nil nil nil) -(autoload 'help-with-tutorial "tutorial" nil nil nil) -(autoload 'help-xref-button "help-mode" nil nil nil) -(autoload 'hi-lock-face-buffer "hi-lock" nil nil nil) -(autoload 'html-mode "sgml-mode" nil nil nil) -(autoload 'image-type-available-p "image" nil nil nil) -(autoload 'info "info" nil nil nil) -(autoload 'info-complete-symbol "info-look" nil nil nil) -(autoload 'info-emacs-manual "info" nil nil nil) -(autoload 'insert-image "image" nil nil nil) -(autoload 'insert-rectangle "rect" nil nil nil) -(autoload 'isearch-process-search-multibyte-characters "isearch-x" nil nil nil) -(autoload 'jka-compr-uninstall "jka-compr" nil nil nil) -(autoload 'log-edit "log-edit" nil nil nil) -(autoload 'log-view-mode "log-view" nil nil nil) -(autoload 'lookup-nested-alist "mule-util" nil nil nil) -(autoload 'make-display-table "disp-table" nil nil nil) -(autoload 'make-glyph-code "disp-table" nil nil nil) -(autoload 'multi-isearch-buffers "misearch" nil nil nil) -(autoload 'multi-isearch-buffers-regexp "misearch" nil nil nil) -(autoload 'multi-isearch-files "misearch" nil nil nil) -(autoload 'multi-isearch-files-regexp "misearch" nil nil nil) -(autoload 'nxml-mode "nxml-mode" nil nil nil) -(autoload 'open-network-stream "network-stream" nil nil nil) -(autoload 'package-initialize "package" nil nil nil) -(autoload 'parse-time-string "parse-time" nil nil nil) -(autoload 'pp "pp" nil nil nil) -(autoload 'pp-buffer "pp" nil nil nil) -(autoload 'print-buffer "lpr" nil nil nil) -(autoload 'quail-defrule-internal "quail" nil nil nil) -(autoload 'read-kbd-macro "edmacro" nil nil nil) -(autoload 'regexp-opt "regexp-opt" nil nil nil) -(autoload 'rx "rx" nil nil t) -(autoload 'seconds-to-string "time-date" nil nil nil) -(autoload 'seconds-to-time "time-date" nil nil nil) -(autoload 'server-save-buffers-kill-terminal "server" nil nil nil) -(autoload 'server-start "server" nil nil nil) -(autoload 'set-nested-alist "mule-util" nil nil nil) -(autoload 'skeleton-insert "skeleton" nil nil nil) -(autoload 'smerge-mode "smerge-mode" nil nil nil) -(autoload 'smerge-start-session "smerge-mode" nil nil nil) -(autoload 'standard-display-8bit "disp-table" nil nil nil) -(autoload 'standard-display-default "disp-table" nil nil nil) -(autoload 'tags-query-replace "etags" nil nil nil) -(autoload 'tags-search "etags" nil nil nil) -(autoload 'text-scale-increase "face-remap" nil nil nil) -(autoload 'thing-at-point "thingatpt" nil nil nil) -(autoload 'time-to-days "time-date" nil nil nil) -(autoload 'timezone-make-date-arpa-standard "timezone" nil nil nil) -(autoload 'tmm-menubar "tmm" nil nil nil) -(autoload 'truncate-string-to-width "mule-util" nil nil nil) -(autoload 'ucs-normalize-HFS-NFC-region "ucs-normalize" nil nil nil) -(autoload 'ucs-normalize-HFS-NFD-region "ucs-normalize" nil nil nil) -(autoload 'ucs-normalize-NFC-region "ucs-normalize" nil nil nil) -(autoload 'ucs-normalize-NFD-region "ucs-normalize" nil nil nil) -(autoload 'ucs-normalize-NFKC-region "ucs-normalize" nil nil nil) -(autoload 'ucs-normalize-NFKD-region "ucs-normalize" nil nil nil) -(autoload 'url-handler-mode "url-handlers" nil nil nil) -(autoload 'variable-at-point "help-fns" nil nil nil) -(autoload 'vc-register "vc" nil nil nil) -(autoload 'vc-responsible-backend "vc" nil nil nil) -(autoload 'vc-transfer-file "vc" nil nil nil) -(autoload 'view-buffer "view" nil nil nil) -(autoload 'view-buffer-other-window "view" nil nil nil) -(autoload 'view-file "view" nil nil nil) -(autoload 'view-mode "view" nil nil nil) -(autoload 'view-mode-enter "view" nil nil nil) -(autoload 'visit-tags-table "etags" nil nil nil) -(autoload 'warn "warnings" nil nil nil) -(autoload 'wdired-change-to-wdired-mode "wdired" nil nil nil) -(autoload 'widget-value "wid-edit" nil nil nil) -;; Local Variables: -;; no-byte-compile: t -;; no-update-autoloads: t -;; End: diff --git a/lisp/ldefs-boot-manual.el b/lisp/ldefs-boot-manual.el deleted file mode 100644 index 183703d25e8..00000000000 --- a/lisp/ldefs-boot-manual.el +++ /dev/null @@ -1,19 +0,0 @@ -;; These appear to be necessary as they are used elsewhere in macro definitions. -(load "emacs-lisp/gv.el") -(load "emacs-lisp/nadvice.el") -(load "emacs-lisp/inline.el") - -;; This variable is used by bytecomp.el -(defvar warning-series nil) - -;; This variable is used by emacs-lisp-mode which is used heavily -;; during the byte-compile phase -(defvar electric-pair-text-pairs '((34 . 34))) - - -(load "ldefs-boot-auto.el") - -;; Local Variables: -;; no-byte-compile: t -;; no-update-autoloads: t -;; End: diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el new file mode 100644 index 00000000000..1cba083cb41 --- /dev/null +++ b/lisp/ldefs-boot.el @@ -0,0 +1,38301 @@ +;;; loaddefs.el --- automatically extracted autoloads +;; +;;; Code: + + +;;;### (autoloads nil "5x5" "play/5x5.el" (0 0 0 0)) +;;; Generated autoloads from play/5x5.el + +(autoload '5x5 "5x5" "\ +Play 5x5. + +The object of 5x5 is very simple, by moving around the grid and flipping +squares you must fill the grid. + +5x5 keyboard bindings are: +\\<5x5-mode-map> +Flip \\[5x5-flip-current] +Move up \\[5x5-up] +Move down \\[5x5-down] +Move left \\[5x5-left] +Move right \\[5x5-right] +Start new game \\[5x5-new-game] +New game with random grid \\[5x5-randomize] +Random cracker \\[5x5-crack-randomly] +Mutate current cracker \\[5x5-crack-mutating-current] +Mutate best cracker \\[5x5-crack-mutating-best] +Mutate xor cracker \\[5x5-crack-xor-mutate] +Solve with Calc \\[5x5-solve-suggest] +Rotate left Calc Solutions \\[5x5-solve-rotate-left] +Rotate right Calc Solutions \\[5x5-solve-rotate-right] +Quit current game \\[5x5-quit-game] + +\(fn &optional SIZE)" t nil) + +(autoload '5x5-crack-randomly "5x5" "\ +Attempt to crack 5x5 using random solutions. + +\(fn)" t nil) + +(autoload '5x5-crack-mutating-current "5x5" "\ +Attempt to crack 5x5 by mutating the current solution. + +\(fn)" t nil) + +(autoload '5x5-crack-mutating-best "5x5" "\ +Attempt to crack 5x5 by mutating the best solution. + +\(fn)" t nil) + +(autoload '5x5-crack-xor-mutate "5x5" "\ +Attempt to crack 5x5 by xoring the current and best solution. +Mutate the result. + +\(fn)" t nil) + +(autoload '5x5-crack "5x5" "\ +Attempt to find a solution for 5x5. + +5x5-crack takes the argument BREEDER which should be a function that takes +two parameters, the first will be a grid vector array that is the current +solution and the second will be the best solution so far. The function +should return a grid vector array that is the new solution. + +\(fn BREEDER)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "5x5" '("5x5-"))) + +;;;*** + +;;;### (autoloads nil "ada-mode" "progmodes/ada-mode.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/ada-mode.el + +(autoload 'ada-add-extensions "ada-mode" "\ +Define SPEC and BODY as being valid extensions for Ada files. +Going from body to spec with `ff-find-other-file' used these +extensions. +SPEC and BODY are two regular expressions that must match against +the file name. + +\(fn SPEC BODY)" nil nil) + +(autoload 'ada-mode "ada-mode" "\ +Ada mode is the major mode for editing Ada code. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ada-mode" '("ada-"))) + +;;;*** + +;;;### (autoloads nil "ada-prj" "progmodes/ada-prj.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/ada-prj.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ada-prj" '("ada-"))) + +;;;*** + +;;;### (autoloads nil "ada-stmt" "progmodes/ada-stmt.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/ada-stmt.el + +(autoload 'ada-header "ada-stmt" "\ +Insert a descriptive header at the top of the file. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ada-stmt" '("ada-"))) + +;;;*** + +;;;### (autoloads nil "ada-xref" "progmodes/ada-xref.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/ada-xref.el + +(autoload 'ada-find-file "ada-xref" "\ +Open FILENAME, from anywhere in the source path. +Completion is available. + +\(fn FILENAME)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ada-xref" '("ada-"))) + +;;;*** + +;;;### (autoloads nil "add-log" "vc/add-log.el" (0 0 0 0)) +;;; Generated autoloads from vc/add-log.el + +(put 'change-log-default-name 'safe-local-variable 'string-or-null-p) + +(defvar add-log-current-defun-function nil "\ +If non-nil, function to guess name of surrounding function. +It is called by `add-log-current-defun' with no argument, and +should return the function's name as a string, or nil if point is +outside a function.") + +(custom-autoload 'add-log-current-defun-function "add-log" t) + +(defvar add-log-full-name nil "\ +Full name of user, for inclusion in ChangeLog daily headers. +This defaults to the value returned by the function `user-full-name'.") + +(custom-autoload 'add-log-full-name "add-log" t) + +(defvar add-log-mailing-address nil "\ +Email addresses of user, for inclusion in ChangeLog headers. +This defaults to the value of `user-mail-address'. In addition to +being a simple string, this value can also be a list. All elements +will be recognized as referring to the same user; when creating a new +ChangeLog entry, one element will be chosen at random.") + +(custom-autoload 'add-log-mailing-address "add-log" t) + +(autoload 'prompt-for-change-log-name "add-log" "\ +Prompt for a change log name. + +\(fn)" nil nil) + +(autoload 'find-change-log "add-log" "\ +Find a change log file for \\[add-change-log-entry] and return the name. + +Optional arg FILE-NAME specifies the file to use. +If FILE-NAME is nil, use the value of `change-log-default-name'. +If `change-log-default-name' is nil, behave as though it were \"ChangeLog\" +\(or whatever we use on this operating system). + +If `change-log-default-name' contains a leading directory component, then +simply find it in the current directory. Otherwise, search in the current +directory and its successive parents for a file so named. Stop at the first +such file that exists (or has a buffer visiting it), or the first directory +that contains any of `change-log-directory-files'. If no match is found, +use the current directory. To override the choice of this function, +simply create an empty ChangeLog file first by hand in the desired place. + +Once a file is found, `change-log-default-name' is set locally in the +current buffer to the complete file name. +Optional arg BUFFER-FILE overrides `buffer-file-name'. + +\(fn &optional FILE-NAME BUFFER-FILE)" nil nil) + +(autoload 'add-change-log-entry "add-log" "\ +Find change log file, and add an entry for today and an item for this file. +Optional arg WHOAMI (interactive prefix) non-nil means prompt for user +name and email (stored in `add-log-full-name' and `add-log-mailing-address'). + +Second arg FILE-NAME is file name of the change log. +If nil, use the value of `change-log-default-name'. + +Third arg OTHER-WINDOW non-nil means visit in other window. + +Fourth arg NEW-ENTRY non-nil means always create a new entry at the front; +never append to an existing entry. Option `add-log-keep-changes-together' +otherwise affects whether a new entry is created. + +Fifth arg PUT-NEW-ENTRY-ON-NEW-LINE non-nil means that if a new +entry is created, put it on a new line by itself, do not put it +after a comma on an existing line. + +Option `add-log-always-start-new-record' non-nil means always create a +new record, even when the last record was made on the same date and by +the same person. + +The change log file can start with a copyright notice and a copying +permission notice. The first blank line indicates the end of these +notices. + +Today's date is calculated according to `add-log-time-zone-rule' if +non-nil, otherwise in local time. + +\(fn &optional WHOAMI FILE-NAME OTHER-WINDOW NEW-ENTRY PUT-NEW-ENTRY-ON-NEW-LINE)" t nil) + +(autoload 'add-change-log-entry-other-window "add-log" "\ +Find change log file in other window and add entry and item. +This is just like `add-change-log-entry' except that it displays +the change log file in another window. + +\(fn &optional WHOAMI FILE-NAME)" t nil) + +(autoload 'change-log-mode "add-log" "\ +Major mode for editing change logs; like Indented Text mode. +Prevents numeric backups and sets `left-margin' to 8 and `fill-column' to 74. +New log entries are usually made with \\[add-change-log-entry] or \\[add-change-log-entry-other-window]. +Each entry behaves as a paragraph, and the entries for one day as a page. +Runs `change-log-mode-hook'. + +\\{change-log-mode-map} + +\(fn)" t nil) + +(autoload 'add-log-current-defun "add-log" "\ +Return name of function definition point is in, or nil. + +Understands C, Lisp, LaTeX (\"functions\" are chapters, sections, ...), +Texinfo (@node titles) and Perl. + +Other modes are handled by a heuristic that looks in the 10K before +point for uppercase headings starting in the first column or +identifiers followed by `:' or `='. See variables +`add-log-current-defun-header-regexp' and +`add-log-current-defun-function'. + +Has a preference of looking backwards. + +\(fn)" nil nil) + +(autoload 'change-log-merge "add-log" "\ +Merge the contents of change log file OTHER-LOG with this buffer. +Both must be found in Change Log mode (since the merging depends on +the appropriate motion commands). OTHER-LOG can be either a file name +or a buffer. + +Entries are inserted in chronological order. Both the current and +old-style time formats for entries are supported. + +\(fn OTHER-LOG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "add-log" '("change-log-" "add-log-"))) + +;;;*** + +;;;### (autoloads nil "advice" "emacs-lisp/advice.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/advice.el + +(defvar ad-redefinition-action 'warn "\ +Defines what to do with redefinitions during Advice de/activation. +Redefinition occurs if a previously activated function that already has an +original definition associated with it gets redefined and then de/activated. +In such a case we can either accept the current definition as the new +original definition, discard the current definition and replace it with the +old original, or keep it and raise an error. The values `accept', `discard', +`error' or `warn' govern what will be done. `warn' is just like `accept' but +it additionally prints a warning message. All other values will be +interpreted as `error'.") + +(custom-autoload 'ad-redefinition-action "advice" t) + +(defvar ad-default-compilation-action 'maybe "\ +Defines whether to compile advised definitions during activation. +A value of `always' will result in unconditional compilation, `never' will +always avoid compilation, `maybe' will compile if the byte-compiler is already +loaded, and `like-original' will compile if the original definition of the +advised function is compiled or a built-in function. Every other value will +be interpreted as `maybe'. This variable will only be considered if the +COMPILE argument of `ad-activate' was supplied as nil.") + +(custom-autoload 'ad-default-compilation-action "advice" t) + +(autoload 'ad-enable-advice "advice" "\ +Enables the advice of FUNCTION with CLASS and NAME. + +\(fn FUNCTION CLASS NAME)" t nil) + +(autoload 'ad-disable-advice "advice" "\ +Disable the advice of FUNCTION with CLASS and NAME. + +\(fn FUNCTION CLASS NAME)" t nil) + +(autoload 'ad-add-advice "advice" "\ +Add a piece of ADVICE to FUNCTION's list of advices in CLASS. + +ADVICE has the form (NAME PROTECTED ENABLED DEFINITION), where +NAME is the advice name; PROTECTED is a flag specifying whether +to protect against non-local exits; ENABLED is a flag specifying +whether to initially enable the advice; and DEFINITION has the +form (advice . LAMBDA), where LAMBDA is a lambda expression. + +If FUNCTION already has a piece of advice with the same name, +then POSITION is ignored, and the old advice is overwritten with +the new one. + +If FUNCTION already has one or more pieces of advice of the +specified CLASS, then POSITION determines where the new piece +goes. POSITION can either be `first', `last' or a number (where +0 corresponds to `first', and numbers outside the valid range are +mapped to the closest extremal position). + +If FUNCTION was not advised already, its advice info will be +initialized. Redefining a piece of advice whose name is part of +the cache-id will clear the cache. + +\(fn FUNCTION ADVICE CLASS POSITION)" nil nil) + +(autoload 'ad-activate "advice" "\ +Activate all the advice information of an advised FUNCTION. +If FUNCTION has a proper original definition then an advised +definition will be generated from FUNCTION's advice info and the +definition of FUNCTION will be replaced with it. If a previously +cached advised definition was available, it will be used. +The optional COMPILE argument determines whether the resulting function +or a compilable cached definition will be compiled. If it is negative +no compilation will be performed, if it is positive or otherwise non-nil +the resulting function will be compiled, if it is nil the behavior depends +on the value of `ad-default-compilation-action' (which see). +Activation of an advised function that has an advice info but no actual +pieces of advice is equivalent to a call to `ad-unadvise'. Activation of +an advised function that has actual pieces of advice but none of them are +enabled is equivalent to a call to `ad-deactivate'. The current advised +definition will always be cached for later usage. + +\(fn FUNCTION &optional COMPILE)" t nil) + +(autoload 'defadvice "advice" "\ +Define a piece of advice for FUNCTION (a symbol). +The syntax of `defadvice' is as follows: + + (defadvice FUNCTION (CLASS NAME [POSITION] [ARGLIST] FLAG...) + [DOCSTRING] [INTERACTIVE-FORM] + BODY...) + +FUNCTION ::= Name of the function to be advised. +CLASS ::= `before' | `around' | `after' | `activation' | `deactivation'. +NAME ::= Non-nil symbol that names this piece of advice. +POSITION ::= `first' | `last' | NUMBER. Optional, defaults to `first', + see also `ad-add-advice'. +ARGLIST ::= An optional argument list to be used for the advised function + instead of the argument list of the original. The first one found in + before/around/after-advices will be used. +FLAG ::= `protect'|`disable'|`activate'|`compile'|`preactivate'. + All flags can be specified with unambiguous initial substrings. +DOCSTRING ::= Optional documentation for this piece of advice. +INTERACTIVE-FORM ::= Optional interactive form to be used for the advised + function. The first one found in before/around/after-advices will be used. +BODY ::= Any s-expression. + +Semantics of the various flags: +`protect': The piece of advice will be protected against non-local exits in +any code that precedes it. If any around-advice of a function is protected +then automatically all around-advices will be protected (the complete onion). + +`activate': All advice of FUNCTION will be activated immediately if +FUNCTION has been properly defined prior to this application of `defadvice'. + +`compile': In conjunction with `activate' specifies that the resulting +advised function should be compiled. + +`disable': The defined advice will be disabled, hence, it will not be used +during activation until somebody enables it. + +`preactivate': Preactivates the advised FUNCTION at macro-expansion/compile +time. This generates a compiled advised definition according to the current +advice state that will be used during activation if appropriate. Only use +this if the `defadvice' gets actually compiled. + +usage: (defadvice FUNCTION (CLASS NAME [POSITION] [ARGLIST] FLAG...) + [DOCSTRING] [INTERACTIVE-FORM] + BODY...) + +\(fn FUNCTION ARGS &rest BODY)" nil t) + +(function-put 'defadvice 'doc-string-elt '3) + +(function-put 'defadvice 'lisp-indent-function '2) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "advice" '("ad-"))) + +;;;*** + +;;;### (autoloads nil "align" "align.el" (0 0 0 0)) +;;; Generated autoloads from align.el + +(autoload 'align "align" "\ +Attempt to align a region based on a set of alignment rules. +BEG and END mark the region. If BEG and END are specifically set to +nil (this can only be done programmatically), the beginning and end of +the current alignment section will be calculated based on the location +of point, and the value of `align-region-separate' (or possibly each +rule's `separate' attribute). + +If SEPARATE is non-nil, it overrides the value of +`align-region-separate' for all rules, except those that have their +`separate' attribute set. + +RULES and EXCLUDE-RULES, if either is non-nil, will replace the +default rule lists defined in `align-rules-list' and +`align-exclude-rules-list'. See `align-rules-list' for more details +on the format of these lists. + +\(fn BEG END &optional SEPARATE RULES EXCLUDE-RULES)" t nil) + +(autoload 'align-regexp "align" "\ +Align the current region using an ad-hoc rule read from the minibuffer. +BEG and END mark the limits of the region. Interactively, this function +prompts for the regular expression REGEXP to align with. + +For example, let's say you had a list of phone numbers, and wanted to +align them so that the opening parentheses would line up: + + Fred (123) 456-7890 + Alice (123) 456-7890 + Mary-Anne (123) 456-7890 + Joe (123) 456-7890 + +There is no predefined rule to handle this, but you could easily do it +using a REGEXP like \"(\". Interactively, all you would have to do is +to mark the region, call `align-regexp' and enter that regular expression. + +REGEXP must contain at least one parenthesized subexpression, typically +whitespace of the form \"\\\\(\\\\s-*\\\\)\". In normal interactive use, +this is automatically added to the start of your regular expression after +you enter it. You only need to supply the characters to be lined up, and +any preceding whitespace is replaced. + +If you specify a prefix argument (or use this function non-interactively), +you must enter the full regular expression, including the subexpression. +The function also then prompts for which subexpression parenthesis GROUP +\(default 1) within REGEXP to modify, the amount of SPACING (default +`align-default-spacing') to use, and whether or not to REPEAT the rule +throughout the line. + +See `align-rules-list' for more information about these options. + +The non-interactive form of the previous example would look something like: + (align-regexp (point-min) (point-max) \"\\\\(\\\\s-*\\\\)(\") + +This function is a nothing more than a small wrapper that helps you +construct a rule to pass to `align-region', which does the real work. + +\(fn BEG END REGEXP &optional GROUP SPACING REPEAT)" t nil) + +(autoload 'align-entire "align" "\ +Align the selected region as if it were one alignment section. +BEG and END mark the extent of the region. If RULES or EXCLUDE-RULES +is set to a list of rules (see `align-rules-list'), it can be used to +override the default alignment rules that would have been used to +align that section. + +\(fn BEG END &optional RULES EXCLUDE-RULES)" t nil) + +(autoload 'align-current "align" "\ +Call `align' on the current alignment section. +This function assumes you want to align only the current section, and +so saves you from having to specify the region. If RULES or +EXCLUDE-RULES is set to a list of rules (see `align-rules-list'), it +can be used to override the default alignment rules that would have +been used to align that section. + +\(fn &optional RULES EXCLUDE-RULES)" t nil) + +(autoload 'align-highlight-rule "align" "\ +Highlight the whitespace which a given rule would have modified. +BEG and END mark the extent of the region. TITLE identifies the rule +that should be highlighted. If RULES or EXCLUDE-RULES is set to a +list of rules (see `align-rules-list'), it can be used to override the +default alignment rules that would have been used to identify the text +to be colored. + +\(fn BEG END TITLE &optional RULES EXCLUDE-RULES)" t nil) + +(autoload 'align-unhighlight-rule "align" "\ +Remove any highlighting that was added by `align-highlight-rule'. + +\(fn)" t nil) + +(autoload 'align-newline-and-indent "align" "\ +A replacement function for `newline-and-indent', aligning as it goes. +The alignment is done by calling `align' on the region that was +indented. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "align" '("align-"))) + +;;;*** + +;;;### (autoloads nil "allout" "allout.el" (0 0 0 0)) +;;; Generated autoloads from allout.el +(push (purecopy '(allout 2 3)) package--builtin-versions) + +(autoload 'allout-auto-activation-helper "allout" "\ +Institute `allout-auto-activation'. + +Intended to be used as the `allout-auto-activation' :set function. + +\(fn VAR VALUE)" nil nil) + +(autoload 'allout-setup "allout" "\ +Do fundamental Emacs session for allout auto-activation. + +Establishes allout processing as part of visiting a file if +`allout-auto-activation' is non-nil, or removes it otherwise. + +The proper way to use this is through customizing the setting of +`allout-auto-activation'. + +\(fn)" nil nil) + +(defvar allout-auto-activation nil "\ +Configure allout outline mode auto-activation. + +Control whether and how allout outline mode is automatically +activated when files are visited with non-nil buffer-specific +file variable `allout-layout'. + +When allout-auto-activation is \"On\" (t), allout mode is +activated in buffers with non-nil `allout-layout', and the +specified layout is applied. + +With value \"ask\", auto-mode-activation is enabled, and endorsement for +performing auto-layout is asked of the user each time. + +With value \"activate\", only auto-mode-activation is enabled. +Auto-layout is not. + +With value nil, inhibit any automatic allout-mode activation.") + +(custom-autoload 'allout-auto-activation "allout" nil) + +(put 'allout-use-hanging-indents 'safe-local-variable (if (fboundp 'booleanp) 'booleanp (lambda (x) (member x '(t nil))))) + +(put 'allout-reindent-bodies 'safe-local-variable (lambda (x) (memq x '(nil t text force)))) + +(put 'allout-show-bodies 'safe-local-variable (if (fboundp 'booleanp) 'booleanp (lambda (x) (member x '(t nil))))) + +(put 'allout-header-prefix 'safe-local-variable 'stringp) + +(put 'allout-primary-bullet 'safe-local-variable 'stringp) + +(put 'allout-plain-bullets-string 'safe-local-variable 'stringp) + +(put 'allout-distinctive-bullets-string 'safe-local-variable 'stringp) + +(put 'allout-use-mode-specific-leader 'safe-local-variable (lambda (x) (or (memq x '(t nil allout-mode-leaders comment-start)) (stringp x)))) + +(put 'allout-old-style-prefixes 'safe-local-variable (if (fboundp 'booleanp) 'booleanp (lambda (x) (member x '(t nil))))) + +(put 'allout-stylish-prefixes 'safe-local-variable (if (fboundp 'booleanp) 'booleanp (lambda (x) (member x '(t nil))))) + +(put 'allout-numbered-bullet 'safe-local-variable (if (fboundp 'string-or-null-p) 'string-or-null-p (lambda (x) (or (stringp x) (null x))))) + +(put 'allout-file-xref-bullet 'safe-local-variable (if (fboundp 'string-or-null-p) 'string-or-null-p (lambda (x) (or (stringp x) (null x))))) + +(put 'allout-presentation-padding 'safe-local-variable 'integerp) + +(put 'allout-layout 'safe-local-variable (lambda (x) (or (numberp x) (listp x) (memq x '(: * + -))))) + +(put 'allout-passphrase-verifier-string 'safe-local-variable 'stringp) + +(put 'allout-passphrase-hint-string 'safe-local-variable 'stringp) + +(autoload 'allout-mode-p "allout" "\ +Return t if `allout-mode' is active in current buffer. + +\(fn)" nil t) + +(autoload 'allout-mode "allout" "\ +Toggle Allout outline mode. +With a prefix argument ARG, enable Allout outline mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +\\<allout-mode-map-value> +Allout outline mode is a minor mode that provides extensive +outline oriented formatting and manipulation. It enables +structural editing of outlines, as well as navigation and +exposure. It also is specifically aimed at accommodating +syntax-sensitive text like programming languages. (For example, +see the allout code itself, which is organized as an allout +outline.) + +In addition to typical outline navigation and exposure, allout includes: + + - topic-oriented authoring, including keystroke-based topic creation, + repositioning, promotion/demotion, cut, and paste + - incremental search with dynamic exposure and reconcealment of hidden text + - adjustable format, so programming code can be developed in outline-structure + - easy topic encryption and decryption, symmetric or key-pair + - \"Hot-spot\" operation, for single-keystroke maneuvering and exposure control + - integral outline layout, for automatic initial exposure when visiting a file + - independent extensibility, using comprehensive exposure and authoring hooks + +and many other features. + +Below is a description of the key bindings, and then description +of special `allout-mode' features and terminology. See also the +outline menubar additions for quick reference to many of the +features. Customize `allout-auto-activation' to prepare your +Emacs session for automatic activation of `allout-mode'. + +The bindings are those listed in `allout-prefixed-keybindings' +and `allout-unprefixed-keybindings'. We recommend customizing +`allout-command-prefix' to use just `\\C-c' as the command +prefix, if the allout bindings don't conflict with any personal +bindings you have on \\C-c. In any case, outline structure +navigation and authoring is simplified by positioning the cursor +on an item's bullet character, the \"hot-spot\" -- then you can +invoke allout commands with just the un-prefixed, +un-control-shifted command letters. This is described further in +the HOT-SPOT Operation section. + + Exposure Control: + ---------------- +\\[allout-hide-current-subtree] `allout-hide-current-subtree' +\\[allout-show-children] `allout-show-children' +\\[allout-show-current-subtree] `allout-show-current-subtree' +\\[allout-show-current-entry] `allout-show-current-entry' +\\[allout-show-all] `allout-show-all' + + Navigation: + ---------- +\\[allout-next-visible-heading] `allout-next-visible-heading' +\\[allout-previous-visible-heading] `allout-previous-visible-heading' +\\[allout-up-current-level] `allout-up-current-level' +\\[allout-forward-current-level] `allout-forward-current-level' +\\[allout-backward-current-level] `allout-backward-current-level' +\\[allout-end-of-entry] `allout-end-of-entry' +\\[allout-beginning-of-current-entry] `allout-beginning-of-current-entry' (alternately, goes to hot-spot) +\\[allout-beginning-of-line] `allout-beginning-of-line' -- like regular beginning-of-line, but + if immediately repeated cycles to the beginning of the current item + and then to the hot-spot (if `allout-beginning-of-line-cycles' is set). + + + Topic Header Production: + ----------------------- +\\[allout-open-sibtopic] `allout-open-sibtopic' Create a new sibling after current topic. +\\[allout-open-subtopic] `allout-open-subtopic' ... an offspring of current topic. +\\[allout-open-supertopic] `allout-open-supertopic' ... a sibling of the current topic's parent. + + Topic Level and Prefix Adjustment: + --------------------------------- +\\[allout-shift-in] `allout-shift-in' Shift current topic and all offspring deeper +\\[allout-shift-out] `allout-shift-out' ... less deep +\\[allout-rebullet-current-heading] `allout-rebullet-current-heading' Prompt for alternate bullet for + current topic +\\[allout-rebullet-topic] `allout-rebullet-topic' Reconcile bullets of topic and + its offspring -- distinctive bullets are not changed, others + are alternated according to nesting depth. +\\[allout-number-siblings] `allout-number-siblings' Number bullets of topic and siblings -- + the offspring are not affected. + With repeat count, revoke numbering. + + Topic-oriented Killing and Yanking: + ---------------------------------- +\\[allout-kill-topic] `allout-kill-topic' Kill current topic, including offspring. +\\[allout-copy-topic-as-kill] `allout-copy-topic-as-kill' Copy current topic, including offspring. +\\[allout-kill-line] `allout-kill-line' Kill line, attending to outline structure. +\\[allout-copy-line-as-kill] `allout-copy-line-as-kill' Copy line but don't delete it. +\\[allout-yank] `allout-yank' Yank, adjusting depth of yanked topic to + depth of heading if yanking into bare topic + heading (ie, prefix sans text). +\\[allout-yank-pop] `allout-yank-pop' Is to `allout-yank' as `yank-pop' is to `yank'. + + Topic-oriented Encryption: + ------------------------- +\\[allout-toggle-current-subtree-encryption] `allout-toggle-current-subtree-encryption' + Encrypt/Decrypt topic content + + Misc commands: + ------------- +M-x outlineify-sticky Activate outline mode for current buffer, + and establish a default file-var setting + for `allout-layout'. +\\[allout-mark-topic] `allout-mark-topic' +\\[allout-copy-exposed-to-buffer] `allout-copy-exposed-to-buffer' + Duplicate outline, sans concealed text, to + buffer with name derived from derived from that + of current buffer -- \"*BUFFERNAME exposed*\". +\\[allout-flatten-exposed-to-buffer] `allout-flatten-exposed-to-buffer' + Like above `copy-exposed', but convert topic + prefixes to section.subsection... numeric + format. +\\[customize-variable] allout-auto-activation + Prepare Emacs session for allout outline mode + auto-activation. + + Topic Encryption + +Outline mode supports gpg encryption of topics, with support for +symmetric and key-pair modes, and auto-encryption of topics +pending encryption on save. + +Topics pending encryption are, by default, automatically +encrypted during file saves, including checkpoint saves, to avoid +exposing the plain text of encrypted topics in the file system. +If the content of the topic containing the cursor was encrypted +for a save, it is automatically decrypted for continued editing. + +NOTE: A few GnuPG v2 versions improperly preserve incorrect +symmetric decryption keys, preventing entry of the correct key on +subsequent decryption attempts until the cache times-out. That +can take several minutes. (Decryption of other entries is not +affected.) Upgrade your EasyPG version, if you can, and you can +deliberately clear your gpg-agent's cache by sending it a `-HUP' +signal. + +See `allout-toggle-current-subtree-encryption' function docstring +and `allout-encrypt-unencrypted-on-saves' customization variable +for details. + + HOT-SPOT Operation + +Hot-spot operation provides a means for easy, single-keystroke outline +navigation and exposure control. + +When the text cursor is positioned directly on the bullet character of +a topic, regular characters (a to z) invoke the commands of the +corresponding allout-mode keymap control chars. For example, \"f\" +would invoke the command typically bound to \"C-c<space>C-f\" +\(\\[allout-forward-current-level] `allout-forward-current-level'). + +Thus, by positioning the cursor on a topic bullet, you can +execute the outline navigation and manipulation commands with a +single keystroke. Regular navigation keys (eg, \\[forward-char], \\[next-line]) don't get +this special translation, so you can use them to get out of the +hot-spot and back to normal editing operation. + +In allout-mode, the normal beginning-of-line command (\\[allout-beginning-of-line]) is +replaced with one that makes it easy to get to the hot-spot. If you +repeat it immediately it cycles (if `allout-beginning-of-line-cycles' +is set) to the beginning of the item and then, if you hit it again +immediately, to the hot-spot. Similarly, `allout-beginning-of-current-entry' +\(\\[allout-beginning-of-current-entry]) moves to the hot-spot when the cursor is already located +at the beginning of the current entry. + + Extending Allout + +Allout exposure and authoring activities all have associated +hooks, by which independent code can cooperate with allout +without changes to the allout core. Here are key ones: + +`allout-mode-hook' +`allout-mode-deactivate-hook' (deprecated) +`allout-mode-off-hook' +`allout-exposure-change-functions' +`allout-structure-added-functions' +`allout-structure-deleted-functions' +`allout-structure-shifted-functions' +`allout-after-copy-or-kill-hook' +`allout-post-undo-hook' + + Terminology + +Topic hierarchy constituents -- TOPICS and SUBTOPICS: + +ITEM: A unitary outline element, including the HEADER and ENTRY text. +TOPIC: An ITEM and any ITEMs contained within it, ie having greater DEPTH + and with no intervening items of lower DEPTH than the container. +CURRENT ITEM: + The visible ITEM most immediately containing the cursor. +DEPTH: The degree of nesting of an ITEM; it increases with containment. + The DEPTH is determined by the HEADER PREFIX. The DEPTH is also + called the: +LEVEL: The same as DEPTH. + +ANCESTORS: + Those ITEMs whose TOPICs contain an ITEM. +PARENT: An ITEM's immediate ANCESTOR. It has a DEPTH one less than that + of the ITEM. +OFFSPRING: + The ITEMs contained within an ITEM's TOPIC. +SUBTOPIC: + An OFFSPRING of its ANCESTOR TOPICs. +CHILD: + An immediate SUBTOPIC of its PARENT. +SIBLINGS: + TOPICs having the same PARENT and DEPTH. + +Topic text constituents: + +HEADER: The first line of an ITEM, include the ITEM PREFIX and HEADER + text. +ENTRY: The text content of an ITEM, before any OFFSPRING, but including + the HEADER text and distinct from the ITEM PREFIX. +BODY: Same as ENTRY. +PREFIX: The leading text of an ITEM which distinguishes it from normal + ENTRY text. Allout recognizes the outline structure according + to the strict PREFIX format. It consists of a PREFIX-LEAD string, + PREFIX-PADDING, and a BULLET. The BULLET might be followed by a + number, indicating the ordinal number of the topic among its + siblings, or an asterisk indicating encryption, plus an optional + space. After that is the ITEM HEADER text, which is not part of + the PREFIX. + + The relative length of the PREFIX determines the nesting DEPTH + of the ITEM. +PREFIX-LEAD: + The string at the beginning of a HEADER PREFIX, by default a `.'. + It can be customized by changing the setting of + `allout-header-prefix' and then reinitializing `allout-mode'. + + When the PREFIX-LEAD is set to the comment-string of a + programming language, outline structuring can be embedded in + program code without interfering with processing of the text + (by Emacs or the language processor) as program code. This + setting happens automatically when allout mode is used in + programming-mode buffers. See `allout-use-mode-specific-leader' + docstring for more detail. +PREFIX-PADDING: + Spaces or asterisks which separate the PREFIX-LEAD and the + bullet, determining the ITEM's DEPTH. +BULLET: A character at the end of the ITEM PREFIX, it must be one of + the characters listed on `allout-plain-bullets-string' or + `allout-distinctive-bullets-string'. When creating a TOPIC, + plain BULLETs are by default used, according to the DEPTH of the + TOPIC. Choice among the distinctive BULLETs is offered when you + provide a universal argument (\\[universal-argument]) to the + TOPIC creation command, or when explicitly rebulleting a TOPIC. The + significance of the various distinctive bullets is purely by + convention. See the documentation for the above bullet strings for + more details. +EXPOSURE: + The state of a TOPIC which determines the on-screen visibility + of its OFFSPRING and contained ENTRY text. +CONCEALED: + TOPICs and ENTRY text whose EXPOSURE is inhibited. Concealed + text is represented by \"...\" ellipses. + + CONCEALED TOPICs are effectively collapsed within an ANCESTOR. +CLOSED: A TOPIC whose immediate OFFSPRING and body-text is CONCEALED. +OPEN: A TOPIC that is not CLOSED, though its OFFSPRING or BODY may be. + +\(fn &optional ARG)" t nil) + +(defalias 'outlinify-sticky 'outlineify-sticky) + +(autoload 'outlineify-sticky "allout" "\ +Activate outline mode and establish file var so it is started subsequently. + +See `allout-layout' and customization of `allout-auto-activation' +for details on preparing Emacs for automatic allout activation. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "allout" '("allout-"))) + +;;;*** + +;;;### (autoloads nil "allout-widgets" "allout-widgets.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from allout-widgets.el +(push (purecopy '(allout-widgets 1 0)) package--builtin-versions) + +(autoload 'allout-widgets-setup "allout-widgets" "\ +Commission or decommission allout-widgets-mode along with allout-mode. + +Meant to be used by customization of `allout-widgets-auto-activation'. + +\(fn VARNAME VALUE)" nil nil) + +(defvar allout-widgets-auto-activation nil "\ +Activate to enable allout icon graphics wherever allout mode is active. + +Also enable `allout-auto-activation' for this to take effect upon +visiting an outline. + +When this is set you can disable allout widgets in select files +by setting `allout-widgets-mode-inhibit' + +Instead of setting `allout-widgets-auto-activation' you can +explicitly invoke `allout-widgets-mode' in allout buffers where +you want allout widgets operation. + +See `allout-widgets-mode' for allout widgets mode features.") + +(custom-autoload 'allout-widgets-auto-activation "allout-widgets" nil) + +(put 'allout-widgets-mode-inhibit 'safe-local-variable (if (fboundp 'booleanp) 'booleanp (lambda (x) (member x '(t nil))))) + +(autoload 'allout-widgets-mode "allout-widgets" "\ +Toggle Allout Widgets mode. +With a prefix argument ARG, enable Allout Widgets mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Allout Widgets mode is an extension of Allout mode that provides +graphical decoration of outline structure. It is meant to +operate along with `allout-mode', via `allout-mode-hook'. + +The graphics include: + +- guide lines connecting item bullet-icons with those of their subitems. + +- icons for item bullets, varying to indicate whether or not the item + has subitems, and if so, whether or not the item is expanded. + +- cue area between the bullet-icon and the start of the body headline, + for item numbering, encryption indicator, and distinctive bullets. + +The bullet-icon and guide line graphics provide keybindings and mouse +bindings for easy outline navigation and exposure control, extending +outline hot-spot navigation (see `allout-mode'). + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "allout-widgets" '("allout-"))) + +;;;*** + +;;;### (autoloads nil "ange-ftp" "net/ange-ftp.el" (0 0 0 0)) +;;; Generated autoloads from net/ange-ftp.el + +(defalias 'ange-ftp-re-read-dir 'ange-ftp-reread-dir) + +(autoload 'ange-ftp-reread-dir "ange-ftp" "\ +Reread remote directory DIR to update the directory cache. +The implementation of remote FTP file names caches directory contents +for speed. Therefore, when new remote files are created, Emacs +may not know they exist. You can use this command to reread a specific +directory, so that Emacs will know its current contents. + +\(fn &optional DIR)" t nil) + +(autoload 'ange-ftp-hook-function "ange-ftp" "\ + + +\(fn OPERATION &rest ARGS)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ange-ftp" '("ange-ftp-" "internal-ange-ftp-mode" "ftp-error"))) + +;;;*** + +;;;### (autoloads nil "animate" "play/animate.el" (0 0 0 0)) +;;; Generated autoloads from play/animate.el + +(autoload 'animate-string "animate" "\ +Display STRING animations starting at position VPOS, HPOS. +The characters start at randomly chosen places, +and all slide in parallel to their final positions, +passing through `animate-n-steps' positions before the final ones. +If HPOS is nil (or omitted), center the string horizontally +in the current window. + +\(fn STRING VPOS &optional HPOS)" nil nil) + +(autoload 'animate-sequence "animate" "\ +Display animation strings from LIST-OF-STRING with buffer *Animation*. +Strings will be separated from each other by SPACE lines. + When the variable `animation-buffer-name' is non-nil display +animation in the buffer named by variable's value, creating the +buffer if one does not exist. + +\(fn LIST-OF-STRINGS SPACE)" nil nil) + +(autoload 'animate-birthday-present "animate" "\ +Return a birthday present in the buffer *Birthday-Present*. +When optional arg NAME is non-nil or called-interactively, prompt for +NAME of birthday present receiver and return a birthday present in +the buffer *Birthday-Present-for-Name*. + +\(fn &optional NAME)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "animate" '("animat"))) + +;;;*** + +;;;### (autoloads nil "ansi-color" "ansi-color.el" (0 0 0 0)) +;;; Generated autoloads from ansi-color.el +(push (purecopy '(ansi-color 3 4 2)) package--builtin-versions) + +(autoload 'ansi-color-for-comint-mode-on "ansi-color" "\ +Set `ansi-color-for-comint-mode' to t. + +\(fn)" t nil) + +(autoload 'ansi-color-process-output "ansi-color" "\ +Maybe translate SGR control sequences of comint output into text properties. + +Depending on variable `ansi-color-for-comint-mode' the comint output is +either not processed, SGR control sequences are filtered using +`ansi-color-filter-region', or SGR control sequences are translated into +text properties using `ansi-color-apply-on-region'. + +The comint output is assumed to lie between the marker +`comint-last-output-start' and the process-mark. + +This is a good function to put in `comint-output-filter-functions'. + +\(fn IGNORED)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ansi-color" '("ansi-color-"))) + +;;;*** + +;;;### (autoloads nil "antlr-mode" "progmodes/antlr-mode.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from progmodes/antlr-mode.el +(push (purecopy '(antlr-mode 2 2 3)) package--builtin-versions) + +(autoload 'antlr-show-makefile-rules "antlr-mode" "\ +Show Makefile rules for all grammar files in the current directory. +If the `major-mode' of the current buffer has the value `makefile-mode', +the rules are directory inserted at point. Otherwise, a *Help* buffer +is shown with the rules which are also put into the `kill-ring' for +\\[yank]. + +This command considers import/export vocabularies and grammar +inheritance and provides a value for the \"-glib\" option if necessary. +Customize variable `antlr-makefile-specification' for the appearance of +the rules. + +If the file for a super-grammar cannot be determined, special file names +are used according to variable `antlr-unknown-file-formats' and a +commentary with value `antlr-help-unknown-file-text' is added. The +*Help* buffer always starts with the text in `antlr-help-rules-intro'. + +\(fn)" t nil) + +(autoload 'antlr-mode "antlr-mode" "\ +Major mode for editing ANTLR grammar files. + +\(fn)" t nil) + +(autoload 'antlr-set-tabs "antlr-mode" "\ +Use ANTLR's convention for TABs according to `antlr-tab-offset-alist'. +Used in `antlr-mode'. Also a useful function in `java-mode-hook'. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "antlr-mode" '("antlr-"))) + +;;;*** + +;;;### (autoloads nil "appt" "calendar/appt.el" (0 0 0 0)) +;;; Generated autoloads from calendar/appt.el + +(autoload 'appt-add "appt" "\ +Add an appointment for today at TIME with message MSG. +The time should be in either 24 hour format or am/pm format. +Optional argument WARNTIME is an integer (or string) giving the number +of minutes before the appointment at which to start warning. +The default is `appt-message-warning-time'. + +\(fn TIME MSG &optional WARNTIME)" t nil) + +(autoload 'appt-activate "appt" "\ +Toggle checking of appointments. +With optional numeric argument ARG, turn appointment checking on if +ARG is positive, otherwise off. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "appt" '("appt-"))) + +;;;*** + +;;;### (autoloads nil "apropos" "apropos.el" (0 0 0 0)) +;;; Generated autoloads from apropos.el + +(autoload 'apropos-read-pattern "apropos" "\ +Read an apropos pattern, either a word list or a regexp. +Returns the user pattern, either a list of words which are matched +literally, or a string which is used as a regexp to search for. + +SUBJECT is a string that is included in the prompt to identify what +kind of objects to search. + +\(fn SUBJECT)" nil nil) + +(autoload 'apropos-user-option "apropos" "\ +Show user options that match PATTERN. +PATTERN can be a word, a list of words (separated by spaces), +or a regexp (using some regexp special characters). If it is a word, +search for matches for that word as a substring. If it is a list of words, +search for matches for any two (or more) of those words. + +With \\[universal-argument] prefix, or if `apropos-do-all' is non-nil, also show +variables, not just user options. + +\(fn PATTERN &optional DO-ALL)" t nil) + +(autoload 'apropos-variable "apropos" "\ +Show variables that match PATTERN. +With the optional argument DO-NOT-ALL non-nil (or when called +interactively with the prefix \\[universal-argument]), show user +options only, i.e. behave like `apropos-user-option'. + +\(fn PATTERN &optional DO-NOT-ALL)" t nil) + +(defalias 'command-apropos 'apropos-command) + +(autoload 'apropos-command "apropos" "\ +Show commands (interactively callable functions) that match PATTERN. +PATTERN can be a word, a list of words (separated by spaces), +or a regexp (using some regexp special characters). If it is a word, +search for matches for that word as a substring. If it is a list of words, +search for matches for any two (or more) of those words. + +With \\[universal-argument] prefix, or if `apropos-do-all' is non-nil, also show +noninteractive functions. + +If VAR-PREDICATE is non-nil, show only variables, and only those that +satisfy the predicate VAR-PREDICATE. + +When called from a Lisp program, a string PATTERN is used as a regexp, +while a list of strings is used as a word list. + +\(fn PATTERN &optional DO-ALL VAR-PREDICATE)" t nil) + +(autoload 'apropos-documentation-property "apropos" "\ +Like (documentation-property SYMBOL PROPERTY RAW) but handle errors. + +\(fn SYMBOL PROPERTY RAW)" nil nil) + +(autoload 'apropos "apropos" "\ +Show all meaningful Lisp symbols whose names match PATTERN. +Symbols are shown if they are defined as functions, variables, or +faces, or if they have nonempty property lists. + +PATTERN can be a word, a list of words (separated by spaces), +or a regexp (using some regexp special characters). If it is a word, +search for matches for that word as a substring. If it is a list of words, +search for matches for any two (or more) of those words. + +With \\[universal-argument] prefix, or if `apropos-do-all' is non-nil, +consider all symbols (if they match PATTERN). + +Returns list of symbols and documentation found. + +\(fn PATTERN &optional DO-ALL)" t nil) + +(autoload 'apropos-library "apropos" "\ +List the variables and functions defined by library FILE. +FILE should be one of the libraries currently loaded and should +thus be found in `load-history'. If `apropos-do-all' is non-nil, +the output includes key-bindings of commands. + +\(fn FILE)" t nil) + +(autoload 'apropos-value "apropos" "\ +Show all symbols whose value's printed representation matches PATTERN. +PATTERN can be a word, a list of words (separated by spaces), +or a regexp (using some regexp special characters). If it is a word, +search for matches for that word as a substring. If it is a list of words, +search for matches for any two (or more) of those words. + +With \\[universal-argument] prefix, or if `apropos-do-all' is non-nil, also looks +at function definitions (arguments, documentation and body) and at the +names and values of properties. + +Returns list of symbols and values found. + +\(fn PATTERN &optional DO-ALL)" t nil) + +(autoload 'apropos-documentation "apropos" "\ +Show symbols whose documentation contains matches for PATTERN. +PATTERN can be a word, a list of words (separated by spaces), +or a regexp (using some regexp special characters). If it is a word, +search for matches for that word as a substring. If it is a list of words, +search for matches for any two (or more) of those words. + +Note that by default this command only searches in the file specified by +`internal-doc-file-name'; i.e., the etc/DOC file. With \\[universal-argument] prefix, +or if `apropos-do-all' is non-nil, it searches all currently defined +documentation strings. + +Returns list of symbols and documentation found. + +\(fn PATTERN &optional DO-ALL)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "apropos" '("apropos-"))) + +;;;*** + +;;;### (autoloads nil "arc-mode" "arc-mode.el" (0 0 0 0)) +;;; Generated autoloads from arc-mode.el + +(autoload 'archive-mode "arc-mode" "\ +Major mode for viewing an archive file in a dired-like way. +You can move around using the usual cursor motion commands. +Letters no longer insert themselves. +Type `e' to pull a file out of the archive and into its own buffer; +or click mouse-2 on the file's line in the archive mode buffer. + +If you edit a sub-file of this archive (as with the `e' command) and +save it, the contents of that buffer will be saved back into the +archive. + +\\{archive-mode-map} + +\(fn &optional FORCE)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "arc-mode" '("archive-"))) + +;;;*** + +;;;### (autoloads nil "array" "array.el" (0 0 0 0)) +;;; Generated autoloads from array.el + +(autoload 'array-mode "array" "\ +Major mode for editing arrays. + + Array mode is a specialized mode for editing arrays. An array is +considered to be a two-dimensional set of strings. The strings are +NOT recognized as integers or real numbers. + + The array MUST reside at the top of the buffer. + + TABs are not respected, and may be converted into spaces at any time. +Setting the variable `array-respect-tabs' to non-nil will prevent TAB conversion, +but will cause many functions to give errors if they encounter one. + + Upon entering array mode, you will be prompted for the values of +several variables. Others will be calculated based on the values you +supply. These variables are all local to the buffer. Other buffer +in array mode may have different values assigned to the variables. +The variables are: + +Variables you assign: + array-max-row: The number of rows in the array. + array-max-column: The number of columns in the array. + array-columns-per-line: The number of columns in the array per line of buffer. + array-field-width: The width of each field, in characters. + array-rows-numbered: A logical variable describing whether to ignore + row numbers in the buffer. + +Variables which are calculated: + array-line-length: The number of characters in a buffer line. + array-lines-per-row: The number of buffer lines used to display each row. + + The following commands are available (an asterisk indicates it may +take a numeric prefix argument): + + * \\<array-mode-map>\\[array-forward-column] Move forward one column. + * \\[array-backward-column] Move backward one column. + * \\[array-next-row] Move down one row. + * \\[array-previous-row] Move up one row. + + * \\[array-copy-forward] Copy the current field into the column to the right. + * \\[array-copy-backward] Copy the current field into the column to the left. + * \\[array-copy-down] Copy the current field into the row below. + * \\[array-copy-up] Copy the current field into the row above. + + * \\[array-copy-column-forward] Copy the current column into the column to the right. + * \\[array-copy-column-backward] Copy the current column into the column to the left. + * \\[array-copy-row-down] Copy the current row into the row below. + * \\[array-copy-row-up] Copy the current row into the row above. + + \\[array-fill-rectangle] Copy the field at mark into every cell with row and column + between that of point and mark. + + \\[array-what-position] Display the current array row and column. + \\[array-goto-cell] Go to a particular array cell. + + \\[array-make-template] Make a template for a new array. + \\[array-reconfigure-rows] Reconfigure the array. + \\[array-expand-rows] Expand the array (remove row numbers and + newlines inside rows) + + \\[array-display-local-variables] Display the current values of local variables. + +Entering array mode calls the function `array-mode-hook'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "array" '("array-" "untabify-backward" "move-to-column-untabify" "current-line" "xor" "limit-index"))) + +;;;*** + +;;;### (autoloads nil "artist" "textmodes/artist.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/artist.el +(push (purecopy '(artist 1 2 6)) package--builtin-versions) + +(autoload 'artist-mode "artist" "\ +Toggle Artist mode. +With argument ARG, turn Artist mode on if ARG is positive. +Artist lets you draw lines, squares, rectangles and poly-lines, +ellipses and circles with your mouse and/or keyboard. + +How to quit Artist mode + + Type \\[artist-mode-off] to quit artist-mode. + + +How to submit a bug report + + Type \\[artist-submit-bug-report] to submit a bug report. + + +Drawing with the mouse: + + mouse-2 + shift mouse-2 Pops up a menu where you can select what to draw with + mouse-1, and where you can do some settings (described + below). + + mouse-1 + shift mouse-1 Draws lines, rectangles or poly-lines, erases, cuts, copies + or pastes: + + Operation Not shifted Shifted + -------------------------------------------------------------- + Pen fill-char at point line from last point + to new point + -------------------------------------------------------------- + Line Line in any direction Straight line + -------------------------------------------------------------- + Rectangle Rectangle Square + -------------------------------------------------------------- + Poly-line Poly-line in any dir Straight poly-lines + -------------------------------------------------------------- + Ellipses Ellipses Circles + -------------------------------------------------------------- + Text Text (see thru) Text (overwrite) + -------------------------------------------------------------- + Spray-can Spray-can Set size for spray + -------------------------------------------------------------- + Erase Erase character Erase rectangle + -------------------------------------------------------------- + Vaporize Erase single line Erase connected + lines + -------------------------------------------------------------- + Cut Cut rectangle Cut square + -------------------------------------------------------------- + Copy Copy rectangle Copy square + -------------------------------------------------------------- + Paste Paste Paste + -------------------------------------------------------------- + Flood-fill Flood-fill Flood-fill + -------------------------------------------------------------- + + * Straight lines can only go horizontally, vertically + or diagonally. + + * Poly-lines are drawn while holding mouse-1 down. When you + release the button, the point is set. If you want a segment + to be straight, hold down shift before pressing the + mouse-1 button. Click mouse-2 or mouse-3 to stop drawing + poly-lines. + + * See thru for text means that text already in the buffer + will be visible through blanks in the text rendered, while + overwrite means the opposite. + + * Vaporizing connected lines only vaporizes lines whose + _endpoints_ are connected. See also the variable + `artist-vaporize-fuzziness'. + + * Cut copies, then clears the rectangle/square. + + * When drawing lines or poly-lines, you can set arrows. + See below under \"Arrows\" for more info. + + * The mode line shows the currently selected drawing operation. + In addition, if it has an asterisk (*) at the end, you + are currently drawing something. + + * Be patient when flood-filling -- large areas take quite + some time to fill. + + + mouse-3 Erases character under pointer + shift mouse-3 Erases rectangle + + +Settings + + Set fill Sets the character used when filling rectangles/squares + + Set line Sets the character used when drawing lines + + Erase char Sets the character used when erasing + + Rubber-banding Toggles rubber-banding + + Trimming Toggles trimming of line-endings (that is: when the shape + is drawn, extraneous white-space at end of lines is removed) + + Borders Toggles the drawing of line borders around filled shapes + + +Drawing with keys + + \\[artist-key-set-point] Does one of the following: + For lines/rectangles/squares: sets the first/second endpoint + For poly-lines: sets a point (use C-u \\[artist-key-set-point] to set last point) + When erase characters: toggles erasing + When cutting/copying: Sets first/last endpoint of rect/square + When pasting: Pastes + + \\[artist-select-operation] Selects what to draw + + Move around with \\[artist-next-line], \\[artist-previous-line], \\[artist-forward-char] and \\[artist-backward-char]. + + \\[artist-select-fill-char] Sets the character to use when filling + \\[artist-select-line-char] Sets the character to use when drawing + \\[artist-select-erase-char] Sets the character to use when erasing + \\[artist-toggle-rubber-banding] Toggles rubber-banding + \\[artist-toggle-trim-line-endings] Toggles trimming of line-endings + \\[artist-toggle-borderless-shapes] Toggles borders on drawn shapes + + +Arrows + + \\[artist-toggle-first-arrow] Sets/unsets an arrow at the beginning + of the line/poly-line + + \\[artist-toggle-second-arrow] Sets/unsets an arrow at the end + of the line/poly-line + + +Selecting operation + + There are some keys for quickly selecting drawing operations: + + \\[artist-select-op-line] Selects drawing lines + \\[artist-select-op-straight-line] Selects drawing straight lines + \\[artist-select-op-rectangle] Selects drawing rectangles + \\[artist-select-op-square] Selects drawing squares + \\[artist-select-op-poly-line] Selects drawing poly-lines + \\[artist-select-op-straight-poly-line] Selects drawing straight poly-lines + \\[artist-select-op-ellipse] Selects drawing ellipses + \\[artist-select-op-circle] Selects drawing circles + \\[artist-select-op-text-see-thru] Selects rendering text (see thru) + \\[artist-select-op-text-overwrite] Selects rendering text (overwrite) + \\[artist-select-op-spray-can] Spray with spray-can + \\[artist-select-op-spray-set-size] Set size for the spray-can + \\[artist-select-op-erase-char] Selects erasing characters + \\[artist-select-op-erase-rectangle] Selects erasing rectangles + \\[artist-select-op-vaporize-line] Selects vaporizing single lines + \\[artist-select-op-vaporize-lines] Selects vaporizing connected lines + \\[artist-select-op-cut-rectangle] Selects cutting rectangles + \\[artist-select-op-copy-rectangle] Selects copying rectangles + \\[artist-select-op-paste] Selects pasting + \\[artist-select-op-flood-fill] Selects flood-filling + + +Variables + + This is a brief overview of the different variables. For more info, + see the documentation for the variables (type \\[describe-variable] <variable> RET). + + artist-rubber-banding Interactively do rubber-banding or not + artist-first-char What to set at first/second point... + artist-second-char ...when not rubber-banding + artist-interface-with-rect If cut/copy/paste should interface with rect + artist-arrows The arrows to use when drawing arrows + artist-aspect-ratio Character height-to-width for squares + artist-trim-line-endings Trimming of line endings + artist-flood-fill-right-border Right border when flood-filling + artist-flood-fill-show-incrementally Update display while filling + artist-pointer-shape Pointer shape to use while drawing + artist-ellipse-left-char Character to use for narrow ellipses + artist-ellipse-right-char Character to use for narrow ellipses + artist-borderless-shapes If shapes should have borders + artist-picture-compatibility Whether or not to be picture mode compatible + artist-vaporize-fuzziness Tolerance when recognizing lines + artist-spray-interval Seconds between repeated sprayings + artist-spray-radius Size of the spray-area + artist-spray-chars The spray-\"color\" + artist-spray-new-chars Initial spray-\"color\" + +Hooks + + Turning the mode on or off runs `artist-mode-hook'. + + +Keymap summary + +\\{artist-mode-map} + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "artist" '("artist-"))) + +;;;*** + +;;;### (autoloads nil "asm-mode" "progmodes/asm-mode.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/asm-mode.el + +(autoload 'asm-mode "asm-mode" "\ +Major mode for editing typical assembler code. +Features a private abbrev table and the following bindings: + +\\[asm-colon] outdent a preceding label, tab to next tab stop. +\\[tab-to-tab-stop] tab to next tab stop. +\\[asm-newline] newline, then tab to next tab stop. +\\[asm-comment] smart placement of assembler comments. + +The character used for making comments is set by the variable +`asm-comment-char' (which defaults to `?\\;'). + +Alternatively, you may set this variable in `asm-mode-set-comment-hook', +which is called near the beginning of mode initialization. + +Turning on Asm mode runs the hook `asm-mode-hook' at the end of initialization. + +Special commands: +\\{asm-mode-map} + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "asm-mode" '("asm-"))) + +;;;*** + +;;;### (autoloads nil "auth-source" "auth-source.el" (0 0 0 0)) +;;; Generated autoloads from auth-source.el + +(defvar auth-source-cache-expiry 7200 "\ +How many seconds passwords are cached, or nil to disable +expiring. Overrides `password-cache-expiry' through a +let-binding.") + +(custom-autoload 'auth-source-cache-expiry "auth-source" t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "auth-source" '("auth-source"))) + +;;;*** + +;;;### (autoloads nil "auth-source-pass" "auth-source-pass.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from auth-source-pass.el +(push (purecopy '(auth-source-pass 2 0 0)) package--builtin-versions) + +(autoload 'auth-source-pass-enable "auth-source-pass" "\ +Enable auth-source-password-store. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "auth-source-pass" '("auth-source-pass-"))) + +;;;*** + +;;;### (autoloads nil "autoarg" "autoarg.el" (0 0 0 0)) +;;; Generated autoloads from autoarg.el + +(defvar autoarg-mode nil "\ +Non-nil if Autoarg mode is enabled. +See the `autoarg-mode' command +for a description of this minor mode.") + +(custom-autoload 'autoarg-mode "autoarg" nil) + +(autoload 'autoarg-mode "autoarg" "\ +Toggle Autoarg mode, a global minor mode. +With a prefix argument ARG, enable Autoarg mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +\\<autoarg-mode-map> +In Autoarg mode, digits are bound to `digit-argument', i.e. they +supply prefix arguments as C-DIGIT and M-DIGIT normally do. +Furthermore, C-DIGIT inserts DIGIT. +\\[autoarg-terminate] terminates the prefix sequence and inserts +the digits of the autoarg sequence into the buffer. +Without a numeric prefix arg, the normal binding of \\[autoarg-terminate] +is invoked, i.e. what it would be with Autoarg mode off. + +For example: +`6 9 \\[autoarg-terminate]' inserts `69' into the buffer, as does `C-6 C-9'. +`6 9 a' inserts 69 `a's into the buffer. +`6 9 \\[autoarg-terminate] \\[autoarg-terminate]' inserts `69' into the buffer and +then invokes the normal binding of \\[autoarg-terminate]. +`C-u \\[autoarg-terminate]' invokes the normal binding of \\[autoarg-terminate] four times. + +\\{autoarg-mode-map} + +\(fn &optional ARG)" t nil) + +(defvar autoarg-kp-mode nil "\ +Non-nil if Autoarg-Kp mode is enabled. +See the `autoarg-kp-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `autoarg-kp-mode'.") + +(custom-autoload 'autoarg-kp-mode "autoarg" nil) + +(autoload 'autoarg-kp-mode "autoarg" "\ +Toggle Autoarg-KP mode, a global minor mode. +With a prefix argument ARG, enable Autoarg-KP mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +\\<autoarg-kp-mode-map> +This is similar to `autoarg-mode' but rebinds the keypad keys +`kp-1' etc. to supply digit arguments. + +\\{autoarg-kp-mode-map} + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "autoarg" '("autoarg-"))) + +;;;*** + +;;;### (autoloads nil "autoconf" "progmodes/autoconf.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/autoconf.el + +(autoload 'autoconf-mode "autoconf" "\ +Major mode for editing Autoconf configure.ac files. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "autoconf" '("autoconf-"))) + +;;;*** + +;;;### (autoloads nil "autoinsert" "autoinsert.el" (0 0 0 0)) +;;; Generated autoloads from autoinsert.el + +(autoload 'auto-insert "autoinsert" "\ +Insert default contents into new files if variable `auto-insert' is non-nil. +Matches the visited file name against the elements of `auto-insert-alist'. + +\(fn)" t nil) + +(autoload 'define-auto-insert "autoinsert" "\ +Associate CONDITION with (additional) ACTION in `auto-insert-alist'. +Optional AFTER means to insert action after all existing actions for CONDITION, +or if CONDITION had no actions, after all other CONDITIONs. + +\(fn CONDITION ACTION &optional AFTER)" nil nil) + +(defvar auto-insert-mode nil "\ +Non-nil if Auto-Insert mode is enabled. +See the `auto-insert-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `auto-insert-mode'.") + +(custom-autoload 'auto-insert-mode "autoinsert" nil) + +(autoload 'auto-insert-mode "autoinsert" "\ +Toggle Auto-insert mode, a global minor mode. +With a prefix argument ARG, enable Auto-insert mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +When Auto-insert mode is enabled, when new files are created you can +insert a template for the file depending on the mode of the buffer. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "autoinsert" '("auto-insert"))) + +;;;*** + +;;;### (autoloads nil "autoload" "emacs-lisp/autoload.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from emacs-lisp/autoload.el + +(put 'generated-autoload-file 'safe-local-variable 'stringp) + +(put 'generated-autoload-load-name 'safe-local-variable 'stringp) + +(put 'autoload-ensure-writable 'risky-local-variable t) + +(autoload 'update-file-autoloads "autoload" "\ +Update the autoloads for FILE. +If prefix arg SAVE-AFTER is non-nil, save the buffer too. + +If FILE binds `generated-autoload-file' as a file-local variable, +autoloads are written into that file. Otherwise, the autoloads +file is determined by OUTFILE. If called interactively, prompt +for OUTFILE; if called from Lisp with OUTFILE nil, use the +existing value of `generated-autoload-file'. + +Return FILE if there was no autoload cookie in it, else nil. + +\(fn FILE &optional SAVE-AFTER OUTFILE)" t nil) + +(autoload 'update-directory-autoloads "autoload" "\ +Update autoload definitions for Lisp files in the directories DIRS. +In an interactive call, you must give one argument, the name of a +single directory. In a call from Lisp, you can supply multiple +directories as separate arguments, but this usage is discouraged. + +The function does NOT recursively descend into subdirectories of the +directory or directories specified. + +In an interactive call, prompt for a default output file for the +autoload definitions, and temporarily bind the variable +`generated-autoload-file' to this value. When called from Lisp, +use the existing value of `generated-autoload-file'. If any Lisp +file binds `generated-autoload-file' as a file-local variable, +write its autoloads into the specified file instead. + +\(fn &rest DIRS)" t nil) + +(autoload 'batch-update-autoloads "autoload" "\ +Update loaddefs.el autoloads in batch mode. +Calls `update-directory-autoloads' on the command line arguments. +Definitions are written to `generated-autoload-file' (which +should be non-nil). + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "autoload" '("autoload-" "generate" "no-update-autoloads" "make-autoload"))) + +;;;*** + +;;;### (autoloads nil "autorevert" "autorevert.el" (0 0 0 0)) +;;; Generated autoloads from autorevert.el + +(autoload 'auto-revert-mode "autorevert" "\ +Toggle reverting buffer when the file changes (Auto-Revert Mode). +With a prefix argument ARG, enable Auto-Revert Mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Auto-Revert Mode is a minor mode that affects only the current +buffer. When enabled, it reverts the buffer when the file on +disk changes. + +When a buffer is reverted, a message is generated. This can be +suppressed by setting `auto-revert-verbose' to nil. + +Use `global-auto-revert-mode' to automatically revert all buffers. +Use `auto-revert-tail-mode' if you know that the file will only grow +without being changed in the part that is already in the buffer. + +\(fn &optional ARG)" t nil) + +(autoload 'turn-on-auto-revert-mode "autorevert" "\ +Turn on Auto-Revert Mode. + +This function is designed to be added to hooks, for example: + (add-hook \\='c-mode-hook #\\='turn-on-auto-revert-mode) + +\(fn)" nil nil) + +(autoload 'auto-revert-tail-mode "autorevert" "\ +Toggle reverting tail of buffer when the file grows. +With a prefix argument ARG, enable Auto-Revert Tail Mode if ARG +is positive, and disable it otherwise. If called from Lisp, +enable the mode if ARG is omitted or nil. + +When Auto-Revert Tail Mode is enabled, the tail of the file is +constantly followed, as with the shell command `tail -f'. This +means that whenever the file grows on disk (presumably because +some background process is appending to it from time to time), +this is reflected in the current buffer. + +You can edit the buffer and turn this mode off and on again as +you please. But make sure the background process has stopped +writing before you save the file! + +When a buffer is reverted, a message is generated. This can be +suppressed by setting `auto-revert-verbose' to nil. + +Use `auto-revert-mode' for changes other than appends! + +\(fn &optional ARG)" t nil) + +(autoload 'turn-on-auto-revert-tail-mode "autorevert" "\ +Turn on Auto-Revert Tail Mode. + +This function is designed to be added to hooks, for example: + (add-hook \\='my-logfile-mode-hook #\\='turn-on-auto-revert-tail-mode) + +\(fn)" nil nil) + +(defvar global-auto-revert-mode nil "\ +Non-nil if Global Auto-Revert mode is enabled. +See the `global-auto-revert-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `global-auto-revert-mode'.") + +(custom-autoload 'global-auto-revert-mode "autorevert" nil) + +(autoload 'global-auto-revert-mode "autorevert" "\ +Toggle Global Auto-Revert Mode. +With a prefix argument ARG, enable Global Auto-Revert Mode if ARG +is positive, and disable it otherwise. If called from Lisp, +enable the mode if ARG is omitted or nil. + +Global Auto-Revert Mode is a global minor mode that reverts any +buffer associated with a file when the file changes on disk. Use +`auto-revert-mode' to revert a particular buffer. + +If `global-auto-revert-non-file-buffers' is non-nil, this mode +may also revert some non-file buffers, as described in the +documentation of that variable. It ignores buffers with modes +matching `global-auto-revert-ignore-modes', and buffers with a +non-nil vale of `global-auto-revert-ignore-buffer'. + +When a buffer is reverted, a message is generated. This can be +suppressed by setting `auto-revert-verbose' to nil. + +This function calls the hook `global-auto-revert-mode-hook'. +It displays the text that `global-auto-revert-mode-text' +specifies in the mode line. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "autorevert" '("auto-revert-" "global-auto-revert-"))) + +;;;*** + +;;;### (autoloads nil "avl-tree" "emacs-lisp/avl-tree.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from emacs-lisp/avl-tree.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "avl-tree" '("avl-tree-"))) + +;;;*** + +;;;### (autoloads nil "avoid" "avoid.el" (0 0 0 0)) +;;; Generated autoloads from avoid.el + +(defvar mouse-avoidance-mode nil "\ +Activate Mouse Avoidance mode. +See function `mouse-avoidance-mode' for possible values. +Setting this variable directly does not take effect; +use either \\[customize] or the function `mouse-avoidance-mode'.") + +(custom-autoload 'mouse-avoidance-mode "avoid" nil) + +(autoload 'mouse-avoidance-mode "avoid" "\ +Set Mouse Avoidance mode to MODE. +MODE should be one of the symbols `banish', `exile', `jump', `animate', +`cat-and-mouse', `proteus', or `none'. + +If MODE is nil, toggle mouse avoidance between `none' and `banish' +modes. Positive numbers and symbols other than the above are treated +as equivalent to `banish'; negative numbers and `-' are equivalent to `none'. + +Effects of the different modes: + * banish: Move the mouse to the upper-right corner on any keypress. + * exile: Move the mouse to the corner only if the cursor gets too close, + and allow it to return once the cursor is out of the way. + * jump: If the cursor gets too close to the mouse, displace the mouse + a random distance & direction. + * animate: As `jump', but shows steps along the way for illusion of motion. + * cat-and-mouse: Same as `animate'. + * proteus: As `animate', but changes the shape of the mouse pointer too. + +\(See `mouse-avoidance-threshold' for definition of \"too close\", +and `mouse-avoidance-nudge-dist' and `mouse-avoidance-nudge-var' for +definition of \"random distance\".) + +\(fn &optional MODE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "avoid" '("mouse-avoidance-"))) + +;;;*** + +;;;### (autoloads nil "bat-mode" "progmodes/bat-mode.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/bat-mode.el + +(add-to-list 'auto-mode-alist '("\\.\\(bat\\|cmd\\)\\'" . bat-mode)) + +(autoload 'bat-mode "bat-mode" "\ +Major mode for editing DOS/Windows batch files. + +Start a new script from `bat-template'. Read help pages for DOS commands +with `bat-cmd-help'. Navigate between sections using `imenu'. +Run script using `bat-run' and `bat-run-args'. + +\\{bat-mode-map} + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "bat-mode" '("bat-"))) + +;;;*** + +;;;### (autoloads nil "battery" "battery.el" (0 0 0 0)) +;;; Generated autoloads from battery.el + (put 'battery-mode-line-string 'risky-local-variable t) + +(autoload 'battery "battery" "\ +Display battery status information in the echo area. +The text being displayed in the echo area is controlled by the variables +`battery-echo-area-format' and `battery-status-function'. + +\(fn)" t nil) + +(defvar display-battery-mode nil "\ +Non-nil if Display-Battery mode is enabled. +See the `display-battery-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `display-battery-mode'.") + +(custom-autoload 'display-battery-mode "battery" nil) + +(autoload 'display-battery-mode "battery" "\ +Toggle battery status display in mode line (Display Battery mode). +With a prefix argument ARG, enable Display Battery mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +The text displayed in the mode line is controlled by +`battery-mode-line-format' and `battery-status-function'. +The mode line is be updated every `battery-update-interval' +seconds. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "battery" '("battery-"))) + +;;;*** + +;;;### (autoloads nil "benchmark" "emacs-lisp/benchmark.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from emacs-lisp/benchmark.el + +(autoload 'benchmark-run "benchmark" "\ +Time execution of FORMS. +If REPETITIONS is supplied as a number, run forms that many times, +accounting for the overhead of the resulting loop. Otherwise run +FORMS once. +Return a list of the total elapsed time for execution, the number of +garbage collections that ran, and the time taken by garbage collection. +See also `benchmark-run-compiled'. + +\(fn &optional REPETITIONS &rest FORMS)" nil t) + +(function-put 'benchmark-run 'lisp-indent-function '1) + +(autoload 'benchmark-run-compiled "benchmark" "\ +Time execution of compiled version of FORMS. +This is like `benchmark-run', but what is timed is a funcall of the +byte code obtained by wrapping FORMS in a `lambda' and compiling the +result. The overhead of the `lambda's is accounted for. + +\(fn &optional REPETITIONS &rest FORMS)" nil t) + +(function-put 'benchmark-run-compiled 'lisp-indent-function '1) + +(autoload 'benchmark "benchmark" "\ +Print the time taken for REPETITIONS executions of FORM. +Interactively, REPETITIONS is taken from the prefix arg. +For non-interactive use see also `benchmark-run' and +`benchmark-run-compiled'. + +\(fn REPETITIONS FORM)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "benchmark" '("benchmark-elapse"))) + +;;;*** + +;;;### (autoloads nil "bib-mode" "textmodes/bib-mode.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/bib-mode.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "bib-mode" '("bib-" "unread-bib" "mark-bib" "return-key-bib" "addbib"))) + +;;;*** + +;;;### (autoloads nil "bibtex" "textmodes/bibtex.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/bibtex.el + +(autoload 'bibtex-initialize "bibtex" "\ +(Re)Initialize BibTeX buffers. +Visit the BibTeX files defined by `bibtex-files' and return a list +of corresponding buffers. +Initialize in these buffers `bibtex-reference-keys' if not yet set. +List of BibTeX buffers includes current buffer if CURRENT is non-nil +and the current buffer visits a file using `bibtex-mode'. +If FORCE is non-nil, (re)initialize `bibtex-reference-keys' even if +already set. If SELECT is non-nil interactively select a BibTeX buffer. + +When called interactively, FORCE is t, CURRENT is t if current buffer +visits a file using `bibtex-mode', and SELECT is t if current buffer +does not use `bibtex-mode', + +\(fn &optional CURRENT FORCE SELECT)" t nil) + +(autoload 'bibtex-mode "bibtex" "\ +Major mode for editing BibTeX files. + +General information on working with BibTeX mode: + +Use commands such as \\<bibtex-mode-map>\\[bibtex-Book] to get a template for a specific entry. +Then fill in all desired fields using \\[bibtex-next-field] to jump from field +to field. After having filled in all desired fields in the entry, clean the +new entry with the command \\[bibtex-clean-entry]. + +Some features of BibTeX mode are available only by setting the variable +`bibtex-maintain-sorted-entries' to non-nil. However, then BibTeX mode +works only with buffers containing valid (syntactically correct) and sorted +entries. This is usually the case, if you have created a buffer completely +with BibTeX mode and finished every new entry with \\[bibtex-clean-entry]. + +For third party BibTeX files, call the command \\[bibtex-convert-alien] +to fully take advantage of all features of BibTeX mode. + + +Special information: + +A command such as \\[bibtex-Book] outlines the fields for a BibTeX book entry. + +The names of optional fields start with the string OPT, and are thus ignored +by BibTeX. The names of alternative fields from which only one is required +start with the string ALT. The OPT or ALT string may be removed from +the name of a field with \\[bibtex-remove-OPT-or-ALT]. +\\[bibtex-make-field] inserts a new field after the current one. +\\[bibtex-kill-field] kills the current field entirely. +\\[bibtex-yank] yanks the last recently killed field after the current field. +\\[bibtex-remove-delimiters] removes the double-quotes or braces around the text of the current field. +\\[bibtex-empty-field] replaces the text of the current field with the default \"\" or {}. +\\[bibtex-find-text] moves point to the end of the current field. +\\[completion-at-point] completes word fragment before point according to context. + +The command \\[bibtex-clean-entry] cleans the current entry, i.e. it removes OPT/ALT +from the names of all non-empty optional or alternative fields, checks that +no required fields are empty, and does some formatting dependent on the value +of `bibtex-entry-format'. Furthermore, it can automatically generate a key +for the BibTeX entry, see `bibtex-generate-autokey'. +Note: some functions in BibTeX mode depend on entries being in a special +format (all fields beginning on separate lines), so it is usually a bad +idea to remove `realign' from `bibtex-entry-format'. + +BibTeX mode supports Imenu and hideshow minor mode (`hs-minor-mode'). + +---------------------------------------------------------- +Entry to BibTeX mode calls the value of `bibtex-mode-hook' +if that value is non-nil. + +\\{bibtex-mode-map} + +\(fn)" t nil) + +(autoload 'bibtex-search-entry "bibtex" "\ +Move point to the beginning of BibTeX entry named KEY. +Return position of entry if KEY is found or nil if not found. +With GLOBAL non-nil, search KEY in `bibtex-files'. Otherwise the search +is limited to the current buffer. Optional arg START is buffer position +where the search starts. If it is nil, start search at beginning of buffer. +If DISPLAY is non-nil, display the buffer containing KEY. +Otherwise, use `set-buffer'. +When called interactively, START is nil, DISPLAY is t. +Also, GLOBAL is t if the current mode is not `bibtex-mode' +or `bibtex-search-entry-globally' is non-nil. +A prefix arg negates the value of `bibtex-search-entry-globally'. + +\(fn KEY &optional GLOBAL START DISPLAY)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "bibtex" '("bibtex-"))) + +;;;*** + +;;;### (autoloads nil "bibtex-style" "textmodes/bibtex-style.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from textmodes/bibtex-style.el + +(autoload 'bibtex-style-mode "bibtex-style" "\ +Major mode for editing BibTeX style files. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "bibtex-style" '("bibtex-style-"))) + +;;;*** + +;;;### (autoloads nil "bindat" "emacs-lisp/bindat.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/bindat.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "bindat" '("bindat-"))) + +;;;*** + +;;;### (autoloads nil "binhex" "mail/binhex.el" (0 0 0 0)) +;;; Generated autoloads from mail/binhex.el + +(defconst binhex-begin-line "^:...............................................................$" "\ +Regular expression matching the start of a BinHex encoded region.") + +(autoload 'binhex-decode-region-internal "binhex" "\ +Binhex decode region between START and END without using an external program. +If HEADER-ONLY is non-nil only decode header and return filename. + +\(fn START END &optional HEADER-ONLY)" t nil) + +(autoload 'binhex-decode-region-external "binhex" "\ +Binhex decode region between START and END using external decoder. + +\(fn START END)" t nil) + +(autoload 'binhex-decode-region "binhex" "\ +Binhex decode region between START and END. + +\(fn START END)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "binhex" '("binhex-"))) + +;;;*** + +;;;### (autoloads nil "blackbox" "play/blackbox.el" (0 0 0 0)) +;;; Generated autoloads from play/blackbox.el + +(autoload 'blackbox "blackbox" "\ +Play blackbox. +Optional prefix argument is the number of balls; the default is 4. + +What is blackbox? + +Blackbox is a game of hide and seek played on an 8 by 8 grid (the +Blackbox). Your opponent (Emacs, in this case) has hidden several +balls (usually 4) within this box. By shooting rays into the box and +observing where they emerge it is possible to deduce the positions of +the hidden balls. The fewer rays you use to find the balls, the lower +your score. + +Overview of play: + +\\<blackbox-mode-map>To play blackbox, type \\[blackbox]. An optional prefix argument +specifies the number of balls to be hidden in the box; the default is +four. + +The cursor can be moved around the box with the standard cursor +movement keys. + +To shoot a ray, move the cursor to the edge of the box and press SPC. +The result will be determined and the playfield updated. + +You may place or remove balls in the box by moving the cursor into the +box and pressing \\[bb-romp]. + +When you think the configuration of balls you have placed is correct, +press \\[bb-done]. You will be informed whether you are correct or +not, and be given your score. Your score is the number of letters and +numbers around the outside of the box plus five for each incorrectly +placed ball. If you placed any balls incorrectly, they will be +indicated with `x', and their actual positions indicated with `o'. + +Details: + +There are three possible outcomes for each ray you send into the box: + + Detour: the ray is deflected and emerges somewhere other than + where you sent it in. On the playfield, detours are + denoted by matching pairs of numbers -- one where the + ray went in, and the other where it came out. + + Reflection: the ray is reflected and emerges in the same place + it was sent in. On the playfield, reflections are + denoted by the letter `R'. + + Hit: the ray strikes a ball directly and is absorbed. It does + not emerge from the box. On the playfield, hits are + denoted by the letter `H'. + +The rules for how balls deflect rays are simple and are best shown by +example. + +As a ray approaches a ball it is deflected ninety degrees. Rays can +be deflected multiple times. In the diagrams below, the dashes +represent empty box locations and the letter `O' represents a ball. +The entrance and exit points of each ray are marked with numbers as +described under \"Detour\" above. Note that the entrance and exit +points are always interchangeable. `*' denotes the path taken by the +ray. + +Note carefully the relative positions of the ball and the ninety +degree deflection it causes. + + 1 + - * - - - - - - - - - - - - - - - - - - - - - - + - * - - - - - - - - - - - - - - - - - - - - - - +1 * * - - - - - - - - - - - - - - - O - - - - O - + - - O - - - - - - - O - - - - - - - * * * * - - + - - - - - - - - - - - * * * * * 2 3 * * * - - * - - + - - - - - - - - - - - * - - - - - - - O - * - - + - - - - - - - - - - - * - - - - - - - - * * - - + - - - - - - - - - - - * - - - - - - - - * - O - + 2 3 + +As mentioned above, a reflection occurs when a ray emerges from the same point +it was sent in. This can happen in several ways: + + + - - - - - - - - - - - - - - - - - - - - - - - - + - - - - O - - - - - O - O - - - - - - - - - - - +R * * * * - - - - - - - * - - - - O - - - - - - - + - - - - O - - - - - - * - - - - R - - - - - - - - + - - - - - - - - - - - * - - - - - - - - - - - - + - - - - - - - - - - - * - - - - - - - - - - - - + - - - - - - - - R * * * * - - - - - - - - - - - - + - - - - - - - - - - - - O - - - - - - - - - - - + +In the first example, the ray is deflected downwards by the upper +ball, then left by the lower ball, and finally retraces its path to +its point of origin. The second example is similar. The third +example is a bit anomalous but can be rationalized by realizing the +ray never gets a chance to get into the box. Alternatively, the ray +can be thought of as being deflected downwards and immediately +emerging from the box. + +A hit occurs when a ray runs straight into a ball: + + - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - O - - - + - - - - - - - - - - - - O - - - H * * * * - - - - + - - - - - - - - H * * * * O - - - - - - * - - - - + - - - - - - - - - - - - O - - - - - - O - - - - +H * * * O - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - + +Be sure to compare the second example of a hit with the first example of +a reflection. + +\(fn NUM)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "blackbox" '("blackbox-" "bb-"))) + +;;;*** + +;;;### (autoloads nil "bookmark" "bookmark.el" (0 0 0 0)) +;;; Generated autoloads from bookmark.el + (define-key ctl-x-r-map "b" 'bookmark-jump) + (define-key ctl-x-r-map "m" 'bookmark-set) + (define-key ctl-x-r-map "M" 'bookmark-set-no-overwrite) + (define-key ctl-x-r-map "l" 'bookmark-bmenu-list) + +(defvar bookmark-map (let ((map (make-sparse-keymap))) (define-key map "x" 'bookmark-set) (define-key map "m" 'bookmark-set) (define-key map "M" 'bookmark-set-no-overwrite) (define-key map "j" 'bookmark-jump) (define-key map "g" 'bookmark-jump) (define-key map "o" 'bookmark-jump-other-window) (define-key map "i" 'bookmark-insert) (define-key map "e" 'edit-bookmarks) (define-key map "f" 'bookmark-insert-location) (define-key map "r" 'bookmark-rename) (define-key map "d" 'bookmark-delete) (define-key map "l" 'bookmark-load) (define-key map "w" 'bookmark-write) (define-key map "s" 'bookmark-save) map) "\ +Keymap containing bindings to bookmark functions. +It is not bound to any key by default: to bind it +so that you have a bookmark prefix, just use `global-set-key' and bind a +key of your choice to `bookmark-map'. All interactive bookmark +functions have a binding in this keymap.") + (fset 'bookmark-map bookmark-map) + +(autoload 'bookmark-set "bookmark" "\ +Set a bookmark named NAME at the current location. +If NAME is nil, then prompt the user. + +With a prefix arg (non-nil NO-OVERWRITE), do not overwrite any +existing bookmark that has the same name as NAME, but instead push the +new bookmark onto the bookmark alist. The most recently set bookmark +with name NAME is thus the one in effect at any given time, but the +others are still there, should the user decide to delete the most +recent one. + +To yank words from the text of the buffer and use them as part of the +bookmark name, type C-w while setting a bookmark. Successive C-w's +yank successive words. + +Typing C-u inserts (at the bookmark name prompt) the name of the last +bookmark used in the document where the new bookmark is being set; +this helps you use a single bookmark name to track progress through a +large document. If there is no prior bookmark for this document, then +C-u inserts an appropriate name based on the buffer or file. + +Use \\[bookmark-delete] to remove bookmarks (you give it a name and +it removes only the first instance of a bookmark with that name from +the list of bookmarks.) + +\(fn &optional NAME NO-OVERWRITE)" t nil) + +(autoload 'bookmark-set-no-overwrite "bookmark" "\ +Set a bookmark named NAME at the current location. +If NAME is nil, then prompt the user. + +If a bookmark named NAME already exists and prefix argument +PUSH-BOOKMARK is non-nil, then push the new bookmark onto the +bookmark alist. Pushing it means that among bookmarks named +NAME, this one becomes the one in effect, but the others are +still there, in order, and become effective again if the user +ever deletes the most recent one. + +Otherwise, if a bookmark named NAME already exists but PUSH-BOOKMARK +is nil, raise an error. + +To yank words from the text of the buffer and use them as part of the +bookmark name, type C-w while setting a bookmark. Successive C-w's +yank successive words. + +Typing C-u inserts (at the bookmark name prompt) the name of the last +bookmark used in the document where the new bookmark is being set; +this helps you use a single bookmark name to track progress through a +large document. If there is no prior bookmark for this document, then +C-u inserts an appropriate name based on the buffer or file. + +Use \\[bookmark-delete] to remove bookmarks (you give it a name and +it removes only the first instance of a bookmark with that name from +the list of bookmarks.) + +\(fn &optional NAME PUSH-BOOKMARK)" t nil) + +(autoload 'bookmark-jump "bookmark" "\ +Jump to bookmark BOOKMARK (a point in some file). +You may have a problem using this function if the value of variable +`bookmark-alist' is nil. If that happens, you need to load in some +bookmarks. See help on function `bookmark-load' for more about +this. + +If the file pointed to by BOOKMARK no longer exists, you will be asked +if you wish to give the bookmark a new location, and `bookmark-jump' +will then jump to the new location, as well as recording it in place +of the old one in the permanent bookmark record. + +BOOKMARK is usually a bookmark name (a string). It can also be a +bookmark record, but this is usually only done by programmatic callers. + +If DISPLAY-FUNC is non-nil, it is a function to invoke to display the +bookmark. It defaults to `switch-to-buffer'. A typical value for +DISPLAY-FUNC would be `switch-to-buffer-other-window'. + +\(fn BOOKMARK &optional DISPLAY-FUNC)" t nil) + +(autoload 'bookmark-jump-other-window "bookmark" "\ +Jump to BOOKMARK in another window. See `bookmark-jump' for more. + +\(fn BOOKMARK)" t nil) + +(autoload 'bookmark-relocate "bookmark" "\ +Relocate BOOKMARK-NAME to another file, reading file name with minibuffer. + +This makes an already existing bookmark point to that file, instead of +the one it used to point at. Useful when a file has been renamed +after a bookmark was set in it. + +\(fn BOOKMARK-NAME)" t nil) + +(autoload 'bookmark-insert-location "bookmark" "\ +Insert the name of the file associated with BOOKMARK-NAME. + +Optional second arg NO-HISTORY means don't record this in the +minibuffer history list `bookmark-history'. + +\(fn BOOKMARK-NAME &optional NO-HISTORY)" t nil) + +(defalias 'bookmark-locate 'bookmark-insert-location) + +(autoload 'bookmark-rename "bookmark" "\ +Change the name of OLD-NAME bookmark to NEW-NAME name. +If called from keyboard, prompt for OLD-NAME and NEW-NAME. +If called from menubar, select OLD-NAME from a menu and prompt for NEW-NAME. + +If called from Lisp, prompt for NEW-NAME if only OLD-NAME was passed +as an argument. If called with two strings, then no prompting is done. +You must pass at least OLD-NAME when calling from Lisp. + +While you are entering the new name, consecutive C-w's insert +consecutive words from the text of the buffer into the new bookmark +name. + +\(fn OLD-NAME &optional NEW-NAME)" t nil) + +(autoload 'bookmark-insert "bookmark" "\ +Insert the text of the file pointed to by bookmark BOOKMARK-NAME. +BOOKMARK-NAME is a bookmark name (a string), not a bookmark record. + +You may have a problem using this function if the value of variable +`bookmark-alist' is nil. If that happens, you need to load in some +bookmarks. See help on function `bookmark-load' for more about +this. + +\(fn BOOKMARK-NAME)" t nil) + +(autoload 'bookmark-delete "bookmark" "\ +Delete BOOKMARK-NAME from the bookmark list. + +Removes only the first instance of a bookmark with that name. If +there are one or more other bookmarks with the same name, they will +not be deleted. Defaults to the \"current\" bookmark (that is, the +one most recently used in this file, if any). +Optional second arg BATCH means don't update the bookmark list buffer, +probably because we were called from there. + +\(fn BOOKMARK-NAME &optional BATCH)" t nil) + +(autoload 'bookmark-write "bookmark" "\ +Write bookmarks to a file (reading the file name with the minibuffer). + +\(fn)" t nil) + +(function-put 'bookmark-write 'interactive-only 'bookmark-save) + +(autoload 'bookmark-save "bookmark" "\ +Save currently defined bookmarks. +Saves by default in the file defined by the variable +`bookmark-default-file'. With a prefix arg, save it in file FILE +\(second argument). + +If you are calling this from Lisp, the two arguments are PARG and +FILE, and if you just want it to write to the default file, then +pass no arguments. Or pass in nil and FILE, and it will save in FILE +instead. If you pass in one argument, and it is non-nil, then the +user will be interactively queried for a file to save in. + +When you want to load in the bookmarks from a file, use +`bookmark-load', \\[bookmark-load]. That function will prompt you +for a file, defaulting to the file defined by variable +`bookmark-default-file'. + +\(fn &optional PARG FILE)" t nil) + +(autoload 'bookmark-load "bookmark" "\ +Load bookmarks from FILE (which must be in bookmark format). +Appends loaded bookmarks to the front of the list of bookmarks. If +optional second argument OVERWRITE is non-nil, existing bookmarks are +destroyed. Optional third arg NO-MSG means don't display any messages +while loading. + +If you load a file that doesn't contain a proper bookmark alist, you +will corrupt Emacs's bookmark list. Generally, you should only load +in files that were created with the bookmark functions in the first +place. Your own personal bookmark file, specified by the variable +`bookmark-default-file', is maintained automatically by Emacs; you +shouldn't need to load it explicitly. + +If you load a file containing bookmarks with the same names as +bookmarks already present in your Emacs, the new bookmarks will get +unique numeric suffixes \"<2>\", \"<3>\", etc. + +\(fn FILE &optional OVERWRITE NO-MSG)" t nil) + +(autoload 'bookmark-bmenu-list "bookmark" "\ +Display a list of existing bookmarks. +The list is displayed in a buffer named `*Bookmark List*'. +The leftmost column displays a D if the bookmark is flagged for +deletion, or > if it is flagged for displaying. + +\(fn)" t nil) + +(defalias 'list-bookmarks 'bookmark-bmenu-list) + +(defalias 'edit-bookmarks 'bookmark-bmenu-list) + +(autoload 'bookmark-bmenu-search "bookmark" "\ +Incremental search of bookmarks, hiding the non-matches as we go. + +\(fn)" t nil) + +(defvar menu-bar-bookmark-map (let ((map (make-sparse-keymap "Bookmark functions"))) (bindings--define-key map [load] '(menu-item "Load a Bookmark File..." bookmark-load :help "Load bookmarks from a bookmark file)")) (bindings--define-key map [write] '(menu-item "Save Bookmarks As..." bookmark-write :help "Write bookmarks to a file (reading the file name with the minibuffer)")) (bindings--define-key map [save] '(menu-item "Save Bookmarks" bookmark-save :help "Save currently defined bookmarks")) (bindings--define-key map [edit] '(menu-item "Edit Bookmark List" bookmark-bmenu-list :help "Display a list of existing bookmarks")) (bindings--define-key map [delete] '(menu-item "Delete Bookmark..." bookmark-delete :help "Delete a bookmark from the bookmark list")) (bindings--define-key map [rename] '(menu-item "Rename Bookmark..." bookmark-rename :help "Change the name of a bookmark")) (bindings--define-key map [locate] '(menu-item "Insert Location..." bookmark-locate :help "Insert the name of the file associated with a bookmark")) (bindings--define-key map [insert] '(menu-item "Insert Contents..." bookmark-insert :help "Insert the text of the file pointed to by a bookmark")) (bindings--define-key map [set] '(menu-item "Set Bookmark..." bookmark-set :help "Set a bookmark named inside a file.")) (bindings--define-key map [jump] '(menu-item "Jump to Bookmark..." bookmark-jump :help "Jump to a bookmark (a point in some file)")) map)) + +(defalias 'menu-bar-bookmark-map menu-bar-bookmark-map) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "bookmark" '("bookmark" "with-buffer-modified-unmodified"))) + +;;;*** + +;;;### (autoloads nil "browse-url" "net/browse-url.el" (0 0 0 0)) +;;; Generated autoloads from net/browse-url.el + +(defvar browse-url-browser-function 'browse-url-default-browser "\ +Function to display the current buffer in a WWW browser. +This is used by the `browse-url-at-point', `browse-url-at-mouse', and +`browse-url-of-file' commands. + +If the value is not a function it should be a list of pairs +\(REGEXP . FUNCTION). In this case the function called will be the one +associated with the first REGEXP which matches the current URL. The +function is passed the URL and any other args of `browse-url'. The last +regexp should probably be \".\" to specify a default browser.") + +(custom-autoload 'browse-url-browser-function "browse-url" t) + +(autoload 'browse-url-of-file "browse-url" "\ +Ask a WWW browser to display FILE. +Display the current buffer's file if FILE is nil or if called +interactively. Turn the filename into a URL with function +`browse-url-file-url'. Pass the URL to a browser using the +`browse-url' function then run `browse-url-of-file-hook'. + +\(fn &optional FILE)" t nil) + +(autoload 'browse-url-of-buffer "browse-url" "\ +Ask a WWW browser to display BUFFER. +Display the current buffer if BUFFER is nil. Display only the +currently visible part of BUFFER (from a temporary file) if buffer is +narrowed. + +\(fn &optional BUFFER)" t nil) + +(autoload 'browse-url-of-dired-file "browse-url" "\ +In Dired, ask a WWW browser to display the file named on this line. + +\(fn)" t nil) + +(autoload 'browse-url-of-region "browse-url" "\ +Ask a WWW browser to display the current region. + +\(fn MIN MAX)" t nil) + +(autoload 'browse-url "browse-url" "\ +Ask a WWW browser to load URL. +Prompt for a URL, defaulting to the URL at or before point. +Invokes a suitable browser function which does the actual job. +The variable `browse-url-browser-function' says which browser function to +use. If the URL is a mailto: URL, consult `browse-url-mailto-function' +first, if that exists. + +The additional ARGS are passed to the browser function. See the doc +strings of the actual functions, starting with `browse-url-browser-function', +for information about the significance of ARGS (most of the functions +ignore it). +If ARGS are omitted, the default is to pass `browse-url-new-window-flag' +as ARGS. + +\(fn URL &rest ARGS)" t nil) + +(autoload 'browse-url-at-point "browse-url" "\ +Ask a WWW browser to load the URL at or before point. +Variable `browse-url-browser-function' says which browser to use. +Optional prefix argument ARG non-nil inverts the value of the option +`browse-url-new-window-flag'. + +\(fn &optional ARG)" t nil) + +(autoload 'browse-url-at-mouse "browse-url" "\ +Ask a WWW browser to load a URL clicked with the mouse. +The URL is the one around or before the position of the mouse click +but point is not changed. Variable `browse-url-browser-function' +says which browser to use. + +\(fn EVENT)" t nil) + +(autoload 'browse-url-xdg-open "browse-url" "\ +Pass the specified URL to the \"xdg-open\" command. +xdg-open is a desktop utility that calls your preferred web browser. +The optional argument IGNORED is not used. + +\(fn URL &optional IGNORED)" t nil) + +(autoload 'browse-url-netscape "browse-url" "\ +Ask the Netscape WWW browser to load URL. +Default to the URL around or before point. The strings in variable +`browse-url-netscape-arguments' are also passed to Netscape. + +When called interactively, if variable `browse-url-new-window-flag' is +non-nil, load the document in a new Netscape window, otherwise use a +random existing one. A non-nil interactive prefix argument reverses +the effect of `browse-url-new-window-flag'. + +If `browse-url-netscape-new-window-is-tab' is non-nil, then +whenever a document would otherwise be loaded in a new window, it +is loaded in a new tab in an existing window instead. + +When called non-interactively, optional second argument NEW-WINDOW is +used instead of `browse-url-new-window-flag'. + +\(fn URL &optional NEW-WINDOW)" t nil) + +(make-obsolete 'browse-url-netscape 'nil '"25.1") + +(autoload 'browse-url-mozilla "browse-url" "\ +Ask the Mozilla WWW browser to load URL. +Default to the URL around or before point. The strings in variable +`browse-url-mozilla-arguments' are also passed to Mozilla. + +When called interactively, if variable `browse-url-new-window-flag' is +non-nil, load the document in a new Mozilla window, otherwise use a +random existing one. A non-nil interactive prefix argument reverses +the effect of `browse-url-new-window-flag'. + +If `browse-url-mozilla-new-window-is-tab' is non-nil, then whenever a +document would otherwise be loaded in a new window, it is loaded in a +new tab in an existing window instead. + +When called non-interactively, optional second argument NEW-WINDOW is +used instead of `browse-url-new-window-flag'. + +\(fn URL &optional NEW-WINDOW)" t nil) + +(autoload 'browse-url-firefox "browse-url" "\ +Ask the Firefox WWW browser to load URL. +Defaults to the URL around or before point. Passes the strings +in the variable `browse-url-firefox-arguments' to Firefox. + +Interactively, if the variable `browse-url-new-window-flag' is non-nil, +loads the document in a new Firefox window. A non-nil prefix argument +reverses the effect of `browse-url-new-window-flag'. + +If `browse-url-firefox-new-window-is-tab' is non-nil, then +whenever a document would otherwise be loaded in a new window, it +is loaded in a new tab in an existing window instead. + +Non-interactively, this uses the optional second argument NEW-WINDOW +instead of `browse-url-new-window-flag'. + +\(fn URL &optional NEW-WINDOW)" t nil) + +(autoload 'browse-url-chromium "browse-url" "\ +Ask the Chromium WWW browser to load URL. +Default to the URL around or before point. The strings in +variable `browse-url-chromium-arguments' are also passed to +Chromium. +The optional argument NEW-WINDOW is not used. + +\(fn URL &optional NEW-WINDOW)" t nil) + +(autoload 'browse-url-galeon "browse-url" "\ +Ask the Galeon WWW browser to load URL. +Default to the URL around or before point. The strings in variable +`browse-url-galeon-arguments' are also passed to Galeon. + +When called interactively, if variable `browse-url-new-window-flag' is +non-nil, load the document in a new Galeon window, otherwise use a +random existing one. A non-nil interactive prefix argument reverses +the effect of `browse-url-new-window-flag'. + +If `browse-url-galeon-new-window-is-tab' is non-nil, then whenever a +document would otherwise be loaded in a new window, it is loaded in a +new tab in an existing window instead. + +When called non-interactively, optional second argument NEW-WINDOW is +used instead of `browse-url-new-window-flag'. + +\(fn URL &optional NEW-WINDOW)" t nil) + +(make-obsolete 'browse-url-galeon 'nil '"25.1") + +(autoload 'browse-url-emacs "browse-url" "\ +Ask Emacs to load URL into a buffer and show it in another window. + +\(fn URL &optional NEW-WINDOW)" t nil) + +(autoload 'browse-url-gnome-moz "browse-url" "\ +Ask Mozilla/Netscape to load URL via the GNOME program `gnome-moz-remote'. +Default to the URL around or before point. The strings in variable +`browse-url-gnome-moz-arguments' are also passed. + +When called interactively, if variable `browse-url-new-window-flag' is +non-nil, load the document in a new browser window, otherwise use an +existing one. A non-nil interactive prefix argument reverses the +effect of `browse-url-new-window-flag'. + +When called non-interactively, optional second argument NEW-WINDOW is +used instead of `browse-url-new-window-flag'. + +\(fn URL &optional NEW-WINDOW)" t nil) + +(make-obsolete 'browse-url-gnome-moz 'nil '"25.1") + +(autoload 'browse-url-mosaic "browse-url" "\ +Ask the XMosaic WWW browser to load URL. + +Default to the URL around or before point. The strings in variable +`browse-url-mosaic-arguments' are also passed to Mosaic and the +program is invoked according to the variable +`browse-url-mosaic-program'. + +When called interactively, if variable `browse-url-new-window-flag' is +non-nil, load the document in a new Mosaic window, otherwise use a +random existing one. A non-nil interactive prefix argument reverses +the effect of `browse-url-new-window-flag'. + +When called non-interactively, optional second argument NEW-WINDOW is +used instead of `browse-url-new-window-flag'. + +\(fn URL &optional NEW-WINDOW)" t nil) + +(make-obsolete 'browse-url-mosaic 'nil '"25.1") + +(autoload 'browse-url-cci "browse-url" "\ +Ask the XMosaic WWW browser to load URL. +Default to the URL around or before point. + +This function only works for XMosaic version 2.5 or later. You must +select `CCI' from XMosaic's File menu, set the CCI Port Address to the +value of variable `browse-url-CCI-port', and enable `Accept requests'. + +When called interactively, if variable `browse-url-new-window-flag' is +non-nil, load the document in a new browser window, otherwise use a +random existing one. A non-nil interactive prefix argument reverses +the effect of `browse-url-new-window-flag'. + +When called non-interactively, optional second argument NEW-WINDOW is +used instead of `browse-url-new-window-flag'. + +\(fn URL &optional NEW-WINDOW)" t nil) + +(make-obsolete 'browse-url-cci 'nil '"25.1") + +(autoload 'browse-url-conkeror "browse-url" "\ +Ask the Conkeror WWW browser to load URL. +Default to the URL around or before point. Also pass the strings +in the variable `browse-url-conkeror-arguments' to Conkeror. + +When called interactively, if variable +`browse-url-new-window-flag' is non-nil, load the document in a +new Conkeror window, otherwise use a random existing one. A +non-nil interactive prefix argument reverses the effect of +`browse-url-new-window-flag'. + +If variable `browse-url-conkeror-new-window-is-buffer' is +non-nil, then whenever a document would otherwise be loaded in a +new window, load it in a new buffer in an existing window instead. + +When called non-interactively, use optional second argument +NEW-WINDOW instead of `browse-url-new-window-flag'. + +\(fn URL &optional NEW-WINDOW)" t nil) + +(autoload 'browse-url-w3 "browse-url" "\ +Ask the w3 WWW browser to load URL. +Default to the URL around or before point. + +When called interactively, if variable `browse-url-new-window-flag' is +non-nil, load the document in a new window. A non-nil interactive +prefix argument reverses the effect of `browse-url-new-window-flag'. + +When called non-interactively, optional second argument NEW-WINDOW is +used instead of `browse-url-new-window-flag'. + +\(fn URL &optional NEW-WINDOW)" t nil) + +(autoload 'browse-url-w3-gnudoit "browse-url" "\ +Ask another Emacs running gnuserv to load the URL using the W3 browser. +The `browse-url-gnudoit-program' program is used with options given by +`browse-url-gnudoit-args'. Default to the URL around or before point. + +\(fn URL &optional NEW-WINDOW)" t nil) + +(make-obsolete 'browse-url-w3-gnudoit 'nil '"25.1") + +(autoload 'browse-url-text-xterm "browse-url" "\ +Ask a text browser to load URL. +URL defaults to the URL around or before point. +This runs the text browser specified by `browse-url-text-browser'. +in an Xterm window using the Xterm program named by `browse-url-xterm-program' +with possible additional arguments `browse-url-xterm-args'. +The optional argument NEW-WINDOW is not used. + +\(fn URL &optional NEW-WINDOW)" t nil) + +(autoload 'browse-url-text-emacs "browse-url" "\ +Ask a text browser to load URL. +URL defaults to the URL around or before point. +This runs the text browser specified by `browse-url-text-browser'. +With a prefix argument, it runs a new browser process in a new buffer. + +When called interactively, if variable `browse-url-new-window-flag' is +non-nil, load the document in a new browser process in a new term window, +otherwise use any existing one. A non-nil interactive prefix argument +reverses the effect of `browse-url-new-window-flag'. + +When called non-interactively, optional second argument NEW-WINDOW is +used instead of `browse-url-new-window-flag'. + +\(fn URL &optional NEW-BUFFER)" t nil) + +(autoload 'browse-url-mail "browse-url" "\ +Open a new mail message buffer within Emacs for the RFC 2368 URL. +Default to using the mailto: URL around or before point as the +recipient's address. Supplying a non-nil interactive prefix argument +will cause the mail to be composed in another window rather than the +current one. + +When called interactively, if variable `browse-url-new-window-flag' is +non-nil use `compose-mail-other-window', otherwise `compose-mail'. A +non-nil interactive prefix argument reverses the effect of +`browse-url-new-window-flag'. + +When called non-interactively, optional second argument NEW-WINDOW is +used instead of `browse-url-new-window-flag'. + +\(fn URL &optional NEW-WINDOW)" t nil) + +(autoload 'browse-url-generic "browse-url" "\ +Ask the WWW browser defined by `browse-url-generic-program' to load URL. +Default to the URL around or before point. A fresh copy of the +browser is started up in a new process with possible additional arguments +`browse-url-generic-args'. This is appropriate for browsers which +don't offer a form of remote control. + +\(fn URL &optional NEW-WINDOW)" t nil) + +(autoload 'browse-url-kde "browse-url" "\ +Ask the KDE WWW browser to load URL. +Default to the URL around or before point. +The optional argument NEW-WINDOW is not used. + +\(fn URL &optional NEW-WINDOW)" t nil) + +(autoload 'browse-url-elinks "browse-url" "\ +Ask the Elinks WWW browser to load URL. +Default to the URL around the point. + +The document is loaded in a new tab of a running Elinks or, if +none yet running, a newly started instance. + +The Elinks command will be prepended by the program+arguments +from `browse-url-elinks-wrapper'. + +\(fn URL &optional NEW-WINDOW)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "browse-url" '("browse-url-"))) + +;;;*** + +;;;### (autoloads nil "bs" "bs.el" (0 0 0 0)) +;;; Generated autoloads from bs.el +(push (purecopy '(bs 1 17)) package--builtin-versions) + +(autoload 'bs-cycle-next "bs" "\ +Select next buffer defined by buffer cycling. +The buffers taking part in buffer cycling are defined +by buffer configuration `bs-cycle-configuration-name'. + +\(fn)" t nil) + +(autoload 'bs-cycle-previous "bs" "\ +Select previous buffer defined by buffer cycling. +The buffers taking part in buffer cycling are defined +by buffer configuration `bs-cycle-configuration-name'. + +\(fn)" t nil) + +(autoload 'bs-customize "bs" "\ +Customization of group bs for Buffer Selection Menu. + +\(fn)" t nil) + +(autoload 'bs-show "bs" "\ +Make a menu of buffers so you can manipulate buffers or the buffer list. +\\<bs-mode-map> +There are many key commands similar to `Buffer-menu-mode' for +manipulating the buffer list and the buffers themselves. +User can move with [up] or [down], select a buffer +by \\[bs-select] or [SPC] + +Type \\[bs-kill] to leave Buffer Selection Menu without a selection. +Type \\[bs-help] after invocation to get help on commands available. +With prefix argument ARG show a different buffer list. Function +`bs--configuration-name-for-prefix-arg' determine accordingly +name of buffer configuration. + +\(fn ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "bs" '("bs-"))) + +;;;*** + +;;;### (autoloads nil "bubbles" "play/bubbles.el" (0 0 0 0)) +;;; Generated autoloads from play/bubbles.el + +(autoload 'bubbles "bubbles" "\ +Play Bubbles game. +\\<bubbles-mode-map> +The goal is to remove all bubbles with as few moves as possible. +\\[bubbles-plop] on a bubble removes that bubble and all +connected bubbles of the same color. Unsupported bubbles fall +down, and columns that do not contain any bubbles suck the +columns on its right towards the left. + +\\[bubbles-set-game-easy] sets the difficulty to easy. +\\[bubbles-set-game-medium] sets the difficulty to medium. +\\[bubbles-set-game-difficult] sets the difficulty to difficult. +\\[bubbles-set-game-hard] sets the difficulty to hard. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "bubbles" '("bubbles-"))) + +;;;*** + +;;;### (autoloads nil "bug-reference" "progmodes/bug-reference.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from progmodes/bug-reference.el + +(put 'bug-reference-url-format 'safe-local-variable (lambda (s) (or (stringp s) (and (symbolp s) (get s 'bug-reference-url-format))))) + +(autoload 'bug-reference-mode "bug-reference" "\ +Toggle hyperlinking bug references in the buffer (Bug Reference mode). +With a prefix argument ARG, enable Bug Reference mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +\(fn &optional ARG)" t nil) + +(autoload 'bug-reference-prog-mode "bug-reference" "\ +Like `bug-reference-mode', but only buttonize in comments and strings. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "bug-reference" '("bug-reference-"))) + +;;;*** + +;;;### (autoloads nil "byte-opt" "emacs-lisp/byte-opt.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from emacs-lisp/byte-opt.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "byte-opt" '("byte-" "disassemble-offset"))) + +;;;*** + +;;;### (autoloads nil "bytecomp" "emacs-lisp/bytecomp.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from emacs-lisp/bytecomp.el +(put 'byte-compile-dynamic 'safe-local-variable 'booleanp) +(put 'byte-compile-disable-print-circle 'safe-local-variable 'booleanp) +(put 'byte-compile-dynamic-docstrings 'safe-local-variable 'booleanp) + +(put 'byte-compile-warnings 'safe-local-variable (lambda (v) (or (symbolp v) (null (delq nil (mapcar (lambda (x) (not (symbolp x))) v)))))) + +(autoload 'byte-compile-disable-warning "bytecomp" "\ +Change `byte-compile-warnings' to disable WARNING. +If `byte-compile-warnings' is t, set it to `(not WARNING)'. +Otherwise, if the first element is `not', add WARNING, else remove it. +Normally you should let-bind `byte-compile-warnings' before calling this, +else the global value will be modified. + +\(fn WARNING)" nil nil) + +(autoload 'byte-compile-enable-warning "bytecomp" "\ +Change `byte-compile-warnings' to enable WARNING. +If `byte-compile-warnings' is t, do nothing. Otherwise, if the +first element is `not', remove WARNING, else add it. +Normally you should let-bind `byte-compile-warnings' before calling this, +else the global value will be modified. + +\(fn WARNING)" nil nil) + +(autoload 'byte-force-recompile "bytecomp" "\ +Recompile every `.el' file in DIRECTORY that already has a `.elc' file. +Files in subdirectories of DIRECTORY are processed also. + +\(fn DIRECTORY)" t nil) + +(autoload 'byte-recompile-directory "bytecomp" "\ +Recompile every `.el' file in DIRECTORY that needs recompilation. +This happens when a `.elc' file exists but is older than the `.el' file. +Files in subdirectories of DIRECTORY are processed also. + +If the `.elc' file does not exist, normally this function *does not* +compile the corresponding `.el' file. However, if the prefix argument +ARG is 0, that means do compile all those files. A nonzero +ARG means ask the user, for each such `.el' file, whether to +compile it. A nonzero ARG also means ask about each subdirectory +before scanning it. + +If the third argument FORCE is non-nil, recompile every `.el' file +that already has a `.elc' file. + +\(fn DIRECTORY &optional ARG FORCE)" t nil) +(put 'no-byte-compile 'safe-local-variable 'booleanp) + +(autoload 'byte-compile-file "bytecomp" "\ +Compile a file of Lisp code named FILENAME into a file of byte code. +The output file's name is generated by passing FILENAME to the +function `byte-compile-dest-file' (which see). +With prefix arg (noninteractively: 2nd arg), LOAD the file after compiling. +The value is non-nil if there were no errors, nil if errors. + +\(fn FILENAME &optional LOAD)" t nil) + +(autoload 'compile-defun "bytecomp" "\ +Compile and evaluate the current top-level form. +Print the result in the echo area. +With argument ARG, insert value in current buffer after the form. + +\(fn &optional ARG)" t nil) + +(autoload 'byte-compile "bytecomp" "\ +If FORM is a symbol, byte-compile its function definition. +If FORM is a lambda or a macro, byte-compile it as a function. + +\(fn FORM)" nil nil) + +(autoload 'display-call-tree "bytecomp" "\ +Display a call graph of a specified file. +This lists which functions have been called, what functions called +them, and what functions they call. The list includes all functions +whose definitions have been compiled in this Emacs session, as well as +all functions called by those functions. + +The call graph does not include macros, inline functions, or +primitives that the byte-code interpreter knows about directly +\(`eq', `cons', etc.). + +The call tree also lists those functions which are not known to be called +\(that is, to which no calls have been compiled), and which cannot be +invoked interactively. + +\(fn &optional FILENAME)" t nil) + +(autoload 'batch-byte-compile-if-not-done "bytecomp" "\ +Like `byte-compile-file' but doesn't recompile if already up to date. +Use this from the command line, with `-batch'; +it won't work in an interactive Emacs. + +\(fn)" nil nil) + +(autoload 'batch-byte-compile "bytecomp" "\ +Run `byte-compile-file' on the files remaining on the command line. +Use this from the command line, with `-batch'; +it won't work in an interactive Emacs. +Each file is processed even if an error occurred previously. +For example, invoke \"emacs -batch -f batch-byte-compile $emacs/ ~/*.el\". +If NOFORCE is non-nil, don't recompile a file that seems to be +already up-to-date. + +\(fn &optional NOFORCE)" nil nil) + +(autoload 'batch-byte-recompile-directory "bytecomp" "\ +Run `byte-recompile-directory' on the dirs remaining on the command line. +Must be used only with `-batch', and kills Emacs on completion. +For example, invoke `emacs -batch -f batch-byte-recompile-directory .'. + +Optional argument ARG is passed as second argument ARG to +`byte-recompile-directory'; see there for its possible values +and corresponding effects. + +\(fn &optional ARG)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "bytecomp" '("batch-byte-compile-file" "byte-" "no-byte-compile" "displaying-byte-compile-warnings" "emacs-lisp-file-regexp"))) + +;;;*** + +;;;### (autoloads nil "cal-bahai" "calendar/cal-bahai.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from calendar/cal-bahai.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cal-bahai" '("diary-bahai-" "calendar-bahai-" "holiday-bahai"))) + +;;;*** + +;;;### (autoloads nil "cal-china" "calendar/cal-china.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from calendar/cal-china.el + +(put 'calendar-chinese-time-zone 'risky-local-variable t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cal-china" '("diary-chinese-" "calendar-chinese-" "holiday-chinese"))) + +;;;*** + +;;;### (autoloads nil "cal-coptic" "calendar/cal-coptic.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from calendar/cal-coptic.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cal-coptic" '("diary-" "calendar-"))) + +;;;*** + +;;;### (autoloads nil "cal-dst" "calendar/cal-dst.el" (0 0 0 0)) +;;; Generated autoloads from calendar/cal-dst.el + +(put 'calendar-daylight-savings-starts 'risky-local-variable t) + +(put 'calendar-daylight-savings-ends 'risky-local-variable t) + +(put 'calendar-current-time-zone-cache 'risky-local-variable t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cal-dst" '("dst-" "calendar-"))) + +;;;*** + +;;;### (autoloads nil "cal-french" "calendar/cal-french.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from calendar/cal-french.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cal-french" '("diary-french-date" "calendar-french-"))) + +;;;*** + +;;;### (autoloads nil "cal-hebrew" "calendar/cal-hebrew.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from calendar/cal-hebrew.el + +(autoload 'calendar-hebrew-list-yahrzeits "cal-hebrew" "\ +List Yahrzeit dates for *Gregorian* DEATH-DATE from START-YEAR to END-YEAR. +When called interactively from the calendar window, the date of death is taken +from the cursor position. + +\(fn DEATH-DATE START-YEAR END-YEAR)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cal-hebrew" '("diary-hebrew-" "calendar-hebrew-" "holiday-hebrew"))) + +;;;*** + +;;;### (autoloads nil "cal-html" "calendar/cal-html.el" (0 0 0 0)) +;;; Generated autoloads from calendar/cal-html.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cal-html" '("cal-html-"))) + +;;;*** + +;;;### (autoloads nil "cal-islam" "calendar/cal-islam.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from calendar/cal-islam.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cal-islam" '("diary-islamic-" "calendar-islamic-" "holiday-islamic"))) + +;;;*** + +;;;### (autoloads nil "cal-iso" "calendar/cal-iso.el" (0 0 0 0)) +;;; Generated autoloads from calendar/cal-iso.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cal-iso" '("diary-iso-date" "calendar-iso-"))) + +;;;*** + +;;;### (autoloads nil "cal-julian" "calendar/cal-julian.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from calendar/cal-julian.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cal-julian" '("diary-" "calendar-" "holiday-julian"))) + +;;;*** + +;;;### (autoloads nil "cal-mayan" "calendar/cal-mayan.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from calendar/cal-mayan.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cal-mayan" '("diary-mayan-date" "calendar-mayan-"))) + +;;;*** + +;;;### (autoloads nil "cal-menu" "calendar/cal-menu.el" (0 0 0 0)) +;;; Generated autoloads from calendar/cal-menu.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cal-menu" '("cal"))) + +;;;*** + +;;;### (autoloads nil "cal-move" "calendar/cal-move.el" (0 0 0 0)) +;;; Generated autoloads from calendar/cal-move.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cal-move" '("calendar-"))) + +;;;*** + +;;;### (autoloads nil "cal-persia" "calendar/cal-persia.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from calendar/cal-persia.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cal-persia" '("diary-persian-date" "calendar-persian-"))) + +;;;*** + +;;;### (autoloads nil "cal-tex" "calendar/cal-tex.el" (0 0 0 0)) +;;; Generated autoloads from calendar/cal-tex.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cal-tex" '("cal-tex-"))) + +;;;*** + +;;;### (autoloads nil "cal-x" "calendar/cal-x.el" (0 0 0 0)) +;;; Generated autoloads from calendar/cal-x.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cal-x" '("calendar-" "diary-frame"))) + +;;;*** + +;;;### (autoloads nil "calc" "calc/calc.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc.el + (define-key ctl-x-map "*" 'calc-dispatch) + +(autoload 'calc-dispatch "calc" "\ +Invoke the GNU Emacs Calculator. See \\[calc-dispatch-help] for details. + +\(fn &optional ARG)" t nil) + +(autoload 'calc "calc" "\ +The Emacs Calculator. Full documentation is listed under \"calc-mode\". + +\(fn &optional ARG FULL-DISPLAY INTERACTIVE)" t nil) + +(autoload 'full-calc "calc" "\ +Invoke the Calculator and give it a full-sized window. + +\(fn &optional INTERACTIVE)" t nil) + +(autoload 'quick-calc "calc" "\ +Do a quick calculation in the minibuffer without invoking full Calculator. +With prefix argument INSERT, insert the result in the current +buffer. Otherwise, the result is copied into the kill ring. + +\(fn &optional INSERT)" t nil) + +(autoload 'calc-eval "calc" "\ +Do a quick calculation and return the result as a string. +Return value will either be the formatted result in string form, +or a list containing a character position and an error message in string form. + +\(fn STR &optional SEPARATOR &rest ARGS)" nil nil) + +(autoload 'calc-keypad "calc" "\ +Invoke the Calculator in \"visual keypad\" mode. +This is most useful in the X window system. +In this mode, click on the Calc \"buttons\" using the left mouse button. +Or, position the cursor manually and do M-x calc-keypad-press. + +\(fn &optional INTERACTIVE)" t nil) + +(autoload 'full-calc-keypad "calc" "\ +Invoke the Calculator in full-screen \"visual keypad\" mode. +See calc-keypad for details. + +\(fn &optional INTERACTIVE)" t nil) + +(autoload 'calc-grab-region "calc" "\ +Parse the region as a vector of numbers and push it on the Calculator stack. + +\(fn TOP BOT ARG)" t nil) + +(autoload 'calc-grab-rectangle "calc" "\ +Parse a rectangle as a matrix of numbers and push it on the Calculator stack. + +\(fn TOP BOT ARG)" t nil) + +(autoload 'calc-embedded "calc" "\ +Start Calc Embedded mode on the formula surrounding point. + +\(fn ARG &optional END OBEG OEND)" t nil) + +(autoload 'calc-embedded-activate "calc" "\ +Scan the current editing buffer for all embedded := and => formulas. +Also looks for the equivalent TeX words, \\gets and \\evalto. + +\(fn &optional ARG CBUF)" t nil) + +(autoload 'defmath "calc" "\ +Define Calc function. + +Like `defun' except that code in the body of the definition can +make use of the full range of Calc data types and the usual +arithmetic operations are converted to their Calc equivalents. + +The prefix `calcFunc-' is added to the specified name to get the +actual Lisp function name. + +See Info node `(calc)Defining Functions'. + +\(fn FUNC ARGS &rest BODY)" nil t) + +(function-put 'defmath 'doc-string-elt '3) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc" '("math-" "calc" "var-" "inexact-result" "defcalcmodevar"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "calc-aent" "calc/calc-aent.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from calc/calc-aent.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-aent" '("math-" "calc"))) + +;;;*** + +;;;### (autoloads nil "calc-alg" "calc/calc-alg.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-alg.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-alg" '("math-" "calc"))) + +;;;*** + +;;;### (autoloads nil "calc-arith" "calc/calc-arith.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-arith.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-arith" '("math-" "calc"))) + +;;;*** + +;;;### (autoloads nil "calc-bin" "calc/calc-bin.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-bin.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-bin" '("math-" "calc"))) + +;;;*** + +;;;### (autoloads nil "calc-comb" "calc/calc-comb.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-comb.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-comb" '("math-" "calc"))) + +;;;*** + +;;;### (autoloads nil "calc-cplx" "calc/calc-cplx.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-cplx.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-cplx" '("calc" "math-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "calc-embed" "calc/calc-embed.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from calc/calc-embed.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-embed" '("calc-"))) + +;;;*** + +;;;### (autoloads nil "calc-ext" "calc/calc-ext.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-ext.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-ext" '("calc" "math-" "var-"))) + +;;;*** + +;;;### (autoloads nil "calc-fin" "calc/calc-fin.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-fin.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-fin" '("calc" "math-c"))) + +;;;*** + +;;;### (autoloads nil "calc-forms" "calc/calc-forms.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-forms.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-forms" '("math-" "calc" "var-TimeZone"))) + +;;;*** + +;;;### (autoloads nil "calc-frac" "calc/calc-frac.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-frac.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-frac" '("calc" "math-"))) + +;;;*** + +;;;### (autoloads nil "calc-funcs" "calc/calc-funcs.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-funcs.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-funcs" '("calc" "math-"))) + +;;;*** + +;;;### (autoloads nil "calc-graph" "calc/calc-graph.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-graph.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-graph" '("calc-"))) + +;;;*** + +;;;### (autoloads nil "calc-help" "calc/calc-help.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-help.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-help" '("calc-"))) + +;;;*** + +;;;### (autoloads nil "calc-incom" "calc/calc-incom.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-incom.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-incom" '("calc-"))) + +;;;*** + +;;;### (autoloads nil "calc-keypd" "calc/calc-keypd.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-keypd.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-keypd" '("calc-"))) + +;;;*** + +;;;### (autoloads nil "calc-lang" "calc/calc-lang.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-lang.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-lang" '("math-" "calc-"))) + +;;;*** + +;;;### (autoloads nil "calc-macs" "calc/calc-macs.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-macs.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-macs" '("Math-" "calc-" "math-"))) + +;;;*** + +;;;### (autoloads nil "calc-map" "calc/calc-map.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-map.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-map" '("math-" "calc"))) + +;;;*** + +;;;### (autoloads nil "calc-math" "calc/calc-math.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-math.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-math" '("calc" "math-"))) + +;;;*** + +;;;### (autoloads nil "calc-menu" "calc/calc-menu.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-menu.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-menu" '("calc-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "calc-misc" "calc/calc-misc.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from calc/calc-misc.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-misc" '("math-iipow"))) + +;;;*** + +;;;### (autoloads nil "calc-mode" "calc/calc-mode.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-mode.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-mode" '("calc-" "math-get-modes-vec"))) + +;;;*** + +;;;### (autoloads nil "calc-mtx" "calc/calc-mtx.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-mtx.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-mtx" '("calc" "math-"))) + +;;;*** + +;;;### (autoloads nil "calc-nlfit" "calc/calc-nlfit.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-nlfit.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-nlfit" '("calc-fit-" "math-nlfit-"))) + +;;;*** + +;;;### (autoloads nil "calc-poly" "calc/calc-poly.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-poly.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-poly" '("calcFunc-" "math-"))) + +;;;*** + +;;;### (autoloads nil "calc-prog" "calc/calc-prog.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-prog.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-prog" '("math-" "calc" "var-q"))) + +;;;*** + +;;;### (autoloads nil "calc-rewr" "calc/calc-rewr.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-rewr.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-rewr" '("math-" "calc"))) + +;;;*** + +;;;### (autoloads nil "calc-rules" "calc/calc-rules.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-rules.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-rules" '("calc-"))) + +;;;*** + +;;;### (autoloads nil "calc-sel" "calc/calc-sel.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-sel.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-sel" '("calc-"))) + +;;;*** + +;;;### (autoloads nil "calc-stat" "calc/calc-stat.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-stat.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-stat" '("math-" "calc"))) + +;;;*** + +;;;### (autoloads nil "calc-store" "calc/calc-store.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-store.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-store" '("calc"))) + +;;;*** + +;;;### (autoloads nil "calc-stuff" "calc/calc-stuff.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-stuff.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-stuff" '("math-" "calc"))) + +;;;*** + +;;;### (autoloads nil "calc-trail" "calc/calc-trail.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-trail.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-trail" '("calc-trail-"))) + +;;;*** + +;;;### (autoloads nil "calc-undo" "calc/calc-undo.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-undo.el + +(autoload 'calc-undo "calc-undo" "\ + + +\(fn N)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-undo" '("calc-"))) + +;;;*** + +;;;### (autoloads nil "calc-units" "calc/calc-units.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-units.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-units" '("calc" "math-"))) + +;;;*** + +;;;### (autoloads nil "calc-vec" "calc/calc-vec.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-vec.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-vec" '("math-" "calc"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "calc-yank" "calc/calc-yank.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from calc/calc-yank.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calc-yank" '("calc-" "math-number-regexp"))) + +;;;*** + +;;;### (autoloads nil "calcalg2" "calc/calcalg2.el" (0 0 0 0)) +;;; Generated autoloads from calc/calcalg2.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calcalg2" '("calc" "math-" "var-IntegLimit"))) + +;;;*** + +;;;### (autoloads nil "calcalg3" "calc/calcalg3.el" (0 0 0 0)) +;;; Generated autoloads from calc/calcalg3.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calcalg3" '("math-" "calc"))) + +;;;*** + +;;;### (autoloads nil "calccomp" "calc/calccomp.el" (0 0 0 0)) +;;; Generated autoloads from calc/calccomp.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calccomp" '("math-" "calcFunc-c"))) + +;;;*** + +;;;### (autoloads nil "calcsel2" "calc/calcsel2.el" (0 0 0 0)) +;;; Generated autoloads from calc/calcsel2.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calcsel2" '("calc-"))) + +;;;*** + +;;;### (autoloads nil "calculator" "calculator.el" (0 0 0 0)) +;;; Generated autoloads from calculator.el + +(autoload 'calculator "calculator" "\ +Run the Emacs calculator. +See the documentation for `calculator-mode' for more information. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calculator" '("calculator-"))) + +;;;*** + +;;;### (autoloads nil "calendar" "calendar/calendar.el" (0 0 0 0)) +;;; Generated autoloads from calendar/calendar.el + +(autoload 'calendar "calendar" "\ +Display a three-month Gregorian calendar. +The three months appear side by side, with the current month in +the middle surrounded by the previous and next months. The +cursor is put on today's date. If optional prefix argument ARG +is non-nil, prompts for the central month and year. + +Once in the calendar window, future or past months can be moved +into view. Arbitrary months can be displayed, or the calendar +can be scrolled forward or backward. The cursor can be moved +forward or backward by one day, one week, one month, or one year. +All of these commands take prefix arguments which, when negative, +cause movement in the opposite direction. For convenience, the +digit keys and the minus sign are automatically prefixes. Use +\\[describe-mode] for details of the key bindings in the calendar +window. + +Displays the calendar in a separate window, or optionally in a +separate frame, depending on the value of `calendar-setup'. + +If `calendar-view-diary-initially-flag' is non-nil, also displays the +diary entries for the current date (or however many days +`diary-number-of-entries' specifies). This variable can be +overridden by `calendar-setup'. As well as being displayed, +diary entries can also be marked on the calendar (see +`calendar-mark-diary-entries-flag'). + +Runs the following hooks: + +`calendar-today-visible-hook', `calendar-today-invisible-hook' - after + generating a calendar, if today's date is visible or not, respectively +`calendar-initial-window-hook' - after first creating a calendar + +This function is suitable for execution in an init file. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "calendar" '("calendar-" "solar-sunrises-buffer" "lunar-phases-buffer" "diary-" "holiday-buffer"))) + +;;;*** + +;;;### (autoloads nil "canlock" "gnus/canlock.el" (0 0 0 0)) +;;; Generated autoloads from gnus/canlock.el + +(autoload 'canlock-insert-header "canlock" "\ +Insert a Cancel-Key and/or a Cancel-Lock header if possible. + +\(fn &optional ID-FOR-KEY ID-FOR-LOCK PASSWORD)" nil nil) + +(autoload 'canlock-verify "canlock" "\ +Verify Cancel-Lock or Cancel-Key in BUFFER. +If BUFFER is nil, the current buffer is assumed. Signal an error if +it fails. + +\(fn &optional BUFFER)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "canlock" '("canlock-"))) + +;;;*** + +;;;### (autoloads nil "cc-align" "progmodes/cc-align.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/cc-align.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cc-align" '("c-"))) + +;;;*** + +;;;### (autoloads nil "cc-awk" "progmodes/cc-awk.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/cc-awk.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cc-awk" '("c-awk-" "awk-"))) + +;;;*** + +;;;### (autoloads nil "cc-bytecomp" "progmodes/cc-bytecomp.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from progmodes/cc-bytecomp.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cc-bytecomp" '("cc-"))) + +;;;*** + +;;;### (autoloads nil "cc-cmds" "progmodes/cc-cmds.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/cc-cmds.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cc-cmds" '("c-"))) + +;;;*** + +;;;### (autoloads nil "cc-defs" "progmodes/cc-defs.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/cc-defs.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cc-defs" '("cc-bytecomp-compiling-or-loading" "c-"))) + +;;;*** + +;;;### (autoloads nil "cc-engine" "progmodes/cc-engine.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from progmodes/cc-engine.el + +(autoload 'c-guess-basic-syntax "cc-engine" "\ +Return the syntactic context of the current line. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cc-engine" '("c-"))) + +;;;*** + +;;;### (autoloads nil "cc-fonts" "progmodes/cc-fonts.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/cc-fonts.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cc-fonts" '("autodoc-" "java" "gtkdoc-font-lock-" "c++-font-lock-keywords" "c-" "pike-font-lock-keywords" "idl-font-lock-keywords" "objc-font-lock-keywords"))) + +;;;*** + +;;;### (autoloads nil "cc-guess" "progmodes/cc-guess.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/cc-guess.el + +(defvar c-guess-guessed-offsets-alist nil "\ +Currently guessed offsets-alist.") + +(defvar c-guess-guessed-basic-offset nil "\ +Currently guessed basic-offset.") + +(autoload 'c-guess "cc-guess" "\ +Guess the style in the region up to `c-guess-region-max', and install it. + +The style is given a name based on the file's absolute file name. + +If given a prefix argument (or if the optional argument ACCUMULATE is +non-nil) then the previous guess is extended, otherwise a new guess is +made from scratch. + +\(fn &optional ACCUMULATE)" t nil) + +(autoload 'c-guess-no-install "cc-guess" "\ +Guess the style in the region up to `c-guess-region-max'; don't install it. + +If given a prefix argument (or if the optional argument ACCUMULATE is +non-nil) then the previous guess is extended, otherwise a new guess is +made from scratch. + +\(fn &optional ACCUMULATE)" t nil) + +(autoload 'c-guess-buffer "cc-guess" "\ +Guess the style on the whole current buffer, and install it. + +The style is given a name based on the file's absolute file name. + +If given a prefix argument (or if the optional argument ACCUMULATE is +non-nil) then the previous guess is extended, otherwise a new guess is +made from scratch. + +\(fn &optional ACCUMULATE)" t nil) + +(autoload 'c-guess-buffer-no-install "cc-guess" "\ +Guess the style on the whole current buffer; don't install it. + +If given a prefix argument (or if the optional argument ACCUMULATE is +non-nil) then the previous guess is extended, otherwise a new guess is +made from scratch. + +\(fn &optional ACCUMULATE)" t nil) + +(autoload 'c-guess-region "cc-guess" "\ +Guess the style on the region and install it. + +The style is given a name based on the file's absolute file name. + +If given a prefix argument (or if the optional argument ACCUMULATE is +non-nil) then the previous guess is extended, otherwise a new guess is +made from scratch. + +\(fn START END &optional ACCUMULATE)" t nil) + +(autoload 'c-guess-region-no-install "cc-guess" "\ +Guess the style on the region; don't install it. + +Every line of code in the region is examined and values for the following two +variables are guessed: + +* `c-basic-offset', and +* the indentation values of the various syntactic symbols in + `c-offsets-alist'. + +The guessed values are put into `c-guess-guessed-basic-offset' and +`c-guess-guessed-offsets-alist'. + +Frequencies of use are taken into account when guessing, so minor +inconsistencies in the indentation style shouldn't produce wrong guesses. + +If given a prefix argument (or if the optional argument ACCUMULATE is +non-nil) then the previous examination is extended, otherwise a new +guess is made from scratch. + +Note that the larger the region to guess in, the slower the guessing. +So you can limit the region with `c-guess-region-max'. + +\(fn START END &optional ACCUMULATE)" t nil) + +(autoload 'c-guess-install "cc-guess" "\ +Install the latest guessed style into the current buffer. +\(This guessed style is a combination of `c-guess-guessed-basic-offset', +`c-guess-guessed-offsets-alist' and `c-offsets-alist'.) + +The style is entered into CC Mode's style system by +`c-add-style'. Its name is either STYLE-NAME, or a name based on +the absolute file name of the file if STYLE-NAME is nil. + +\(fn &optional STYLE-NAME)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cc-guess" '("c-guess-"))) + +;;;*** + +;;;### (autoloads nil "cc-langs" "progmodes/cc-langs.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/cc-langs.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cc-langs" '("c-"))) + +;;;*** + +;;;### (autoloads nil "cc-menus" "progmodes/cc-menus.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/cc-menus.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cc-menus" '("cc-imenu-"))) + +;;;*** + +;;;### (autoloads nil "cc-mode" "progmodes/cc-mode.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/cc-mode.el + +(autoload 'c-initialize-cc-mode "cc-mode" "\ +Initialize CC Mode for use in the current buffer. +If the optional NEW-STYLE-INIT is nil or left out then all necessary +initialization to run CC Mode for the C language is done. Otherwise +only some basic setup is done, and a call to `c-init-language-vars' or +`c-init-language-vars-for' is necessary too (which gives more +control). See \"cc-mode.el\" for more info. + +\(fn &optional NEW-STYLE-INIT)" nil nil) + (add-to-list 'auto-mode-alist '("\\.\\(cc\\|hh\\)\\'" . c++-mode)) + (add-to-list 'auto-mode-alist '("\\.[ch]\\(pp\\|xx\\|\\+\\+\\)\\'" . c++-mode)) + (add-to-list 'auto-mode-alist '("\\.\\(CC?\\|HH?\\)\\'" . c++-mode)) + (add-to-list 'auto-mode-alist '("\\.c\\'" . c-mode)) + (add-to-list 'auto-mode-alist '("\\.h\\'" . c-or-c++-mode)) + (add-to-list 'auto-mode-alist '("\\.y\\(acc\\)?\\'" . c-mode)) + (add-to-list 'auto-mode-alist '("\\.lex\\'" . c-mode)) + (add-to-list 'auto-mode-alist '("\\.i\\'" . c-mode)) + (add-to-list 'auto-mode-alist '("\\.ii\\'" . c++-mode)) + +(autoload 'c-mode "cc-mode" "\ +Major mode for editing C code. + +To submit a problem report, enter `\\[c-submit-bug-report]' from a +c-mode buffer. This automatically sets up a mail buffer with version +information already added. You just need to add a description of the +problem, including a reproducible test case, and send the message. + +To see what version of CC Mode you are running, enter `\\[c-version]'. + +The hook `c-mode-common-hook' is run with no args at mode +initialization, then `c-mode-hook'. + +Key bindings: +\\{c-mode-map} + +\(fn)" t nil) + +(autoload 'c-or-c++-mode "cc-mode" "\ +Analyse buffer and enable either C or C++ mode. + +Some people and projects use .h extension for C++ header files +which is also the one used for C header files. This makes +matching on file name insufficient for detecting major mode that +should be used. + +This function attempts to use file contents to determine whether +the code is C or C++ and based on that chooses whether to enable +`c-mode' or `c++-mode'. + +\(fn)" nil nil) + +(autoload 'c++-mode "cc-mode" "\ +Major mode for editing C++ code. +To submit a problem report, enter `\\[c-submit-bug-report]' from a +c++-mode buffer. This automatically sets up a mail buffer with +version information already added. You just need to add a description +of the problem, including a reproducible test case, and send the +message. + +To see what version of CC Mode you are running, enter `\\[c-version]'. + +The hook `c-mode-common-hook' is run with no args at mode +initialization, then `c++-mode-hook'. + +Key bindings: +\\{c++-mode-map} + +\(fn)" t nil) + (add-to-list 'auto-mode-alist '("\\.m\\'" . objc-mode)) + +(autoload 'objc-mode "cc-mode" "\ +Major mode for editing Objective C code. +To submit a problem report, enter `\\[c-submit-bug-report]' from an +objc-mode buffer. This automatically sets up a mail buffer with +version information already added. You just need to add a description +of the problem, including a reproducible test case, and send the +message. + +To see what version of CC Mode you are running, enter `\\[c-version]'. + +The hook `c-mode-common-hook' is run with no args at mode +initialization, then `objc-mode-hook'. + +Key bindings: +\\{objc-mode-map} + +\(fn)" t nil) + (add-to-list 'auto-mode-alist '("\\.java\\'" . java-mode)) + +(autoload 'java-mode "cc-mode" "\ +Major mode for editing Java code. +To submit a problem report, enter `\\[c-submit-bug-report]' from a +java-mode buffer. This automatically sets up a mail buffer with +version information already added. You just need to add a description +of the problem, including a reproducible test case, and send the +message. + +To see what version of CC Mode you are running, enter `\\[c-version]'. + +The hook `c-mode-common-hook' is run with no args at mode +initialization, then `java-mode-hook'. + +Key bindings: +\\{java-mode-map} + +\(fn)" t nil) + (add-to-list 'auto-mode-alist '("\\.idl\\'" . idl-mode)) + +(autoload 'idl-mode "cc-mode" "\ +Major mode for editing CORBA's IDL, PSDL and CIDL code. +To submit a problem report, enter `\\[c-submit-bug-report]' from an +idl-mode buffer. This automatically sets up a mail buffer with +version information already added. You just need to add a description +of the problem, including a reproducible test case, and send the +message. + +To see what version of CC Mode you are running, enter `\\[c-version]'. + +The hook `c-mode-common-hook' is run with no args at mode +initialization, then `idl-mode-hook'. + +Key bindings: +\\{idl-mode-map} + +\(fn)" t nil) + (add-to-list 'auto-mode-alist '("\\.\\(u?lpc\\|pike\\|pmod\\(\\.in\\)?\\)\\'" . pike-mode)) + (add-to-list 'interpreter-mode-alist '("pike" . pike-mode)) + +(autoload 'pike-mode "cc-mode" "\ +Major mode for editing Pike code. +To submit a problem report, enter `\\[c-submit-bug-report]' from a +pike-mode buffer. This automatically sets up a mail buffer with +version information already added. You just need to add a description +of the problem, including a reproducible test case, and send the +message. + +To see what version of CC Mode you are running, enter `\\[c-version]'. + +The hook `c-mode-common-hook' is run with no args at mode +initialization, then `pike-mode-hook'. + +Key bindings: +\\{pike-mode-map} + +\(fn)" t nil) + (add-to-list 'auto-mode-alist '("\\.awk\\'" . awk-mode)) + (add-to-list 'interpreter-mode-alist '("awk" . awk-mode)) + (add-to-list 'interpreter-mode-alist '("mawk" . awk-mode)) + (add-to-list 'interpreter-mode-alist '("nawk" . awk-mode)) + (add-to-list 'interpreter-mode-alist '("gawk" . awk-mode)) + +(autoload 'awk-mode "cc-mode" "\ +Major mode for editing AWK code. +To submit a problem report, enter `\\[c-submit-bug-report]' from an +awk-mode buffer. This automatically sets up a mail buffer with version +information already added. You just need to add a description of the +problem, including a reproducible test case, and send the message. + +To see what version of CC Mode you are running, enter `\\[c-version]'. + +The hook `c-mode-common-hook' is run with no args at mode +initialization, then `awk-mode-hook'. + +Key bindings: +\\{awk-mode-map} + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cc-mode" '("c++-mode-" "c-" "awk-mode-map" "pike-mode-" "idl-mode-" "java-mode-" "objc-mode-"))) + +;;;*** + +;;;### (autoloads nil "cc-styles" "progmodes/cc-styles.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from progmodes/cc-styles.el + +(autoload 'c-set-style "cc-styles" "\ +Set the current buffer to use the style STYLENAME. +STYLENAME, a string, must be an existing CC Mode style - These are contained +in the variable `c-style-alist'. + +The variable `c-indentation-style' will get set to STYLENAME. + +\"Setting the style\" is done by setting CC Mode's \"style variables\" to the +values indicated by the pertinent entry in `c-style-alist'. Other variables +might get set too. + +If DONT-OVERRIDE is neither nil nor t, style variables whose default values +have been set (more precisely, whose default values are not the symbol +`set-from-style') will not be changed. This avoids overriding global settings +done in your init file. It is useful to call c-set-style from a mode hook +in this way. + +If DONT-OVERRIDE is t, style variables that already have values (i.e., whose +values are not the symbol `set-from-style') will not be overridden. CC Mode +calls c-set-style internally in this way whilst initializing a buffer; if +cc-set-style is called like this from anywhere else, it will usually behave as +a null operation. + +\(fn STYLENAME &optional DONT-OVERRIDE)" t nil) + +(autoload 'c-add-style "cc-styles" "\ +Adds a style to `c-style-alist', or updates an existing one. +STYLE is a string identifying the style to add or update. DESCRIPTION +is an association list describing the style and must be of the form: + + ([BASESTYLE] (VARIABLE . VALUE) [(VARIABLE . VALUE) ...]) + +See the variable `c-style-alist' for the semantics of BASESTYLE, +VARIABLE and VALUE. This function also sets the current style to +STYLE using `c-set-style' if the optional SET-P flag is non-nil. + +\(fn STYLE DESCRIPTION &optional SET-P)" t nil) + +(autoload 'c-set-offset "cc-styles" "\ +Change the value of a syntactic element symbol in `c-offsets-alist'. +SYMBOL is the syntactic element symbol to change and OFFSET is the new +offset for that syntactic element. The optional argument is not used +and exists only for compatibility reasons. + +\(fn SYMBOL OFFSET &optional IGNORED)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cc-styles" '("c-" "cc-choose-style-for-mode"))) + +;;;*** + +;;;### (autoloads nil "cc-vars" "progmodes/cc-vars.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/cc-vars.el +(put 'c-basic-offset 'safe-local-variable 'integerp) +(put 'c-backslash-column 'safe-local-variable 'integerp) +(put 'c-file-style 'safe-local-variable 'string-or-null-p) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cc-vars" '("c++-" "c-" "pike-" "idl-" "java-" "objc-" "awk-mode-hook" "defcustom-c-stylevar"))) + +;;;*** + +;;;### (autoloads nil "ccl" "international/ccl.el" (0 0 0 0)) +;;; Generated autoloads from international/ccl.el + +(autoload 'ccl-compile "ccl" "\ +Return the compiled code of CCL-PROGRAM as a vector of integers. + +\(fn CCL-PROGRAM)" nil nil) + +(autoload 'ccl-dump "ccl" "\ +Disassemble compiled CCL-code CODE. + +\(fn CODE)" nil nil) + +(autoload 'declare-ccl-program "ccl" "\ +Declare NAME as a name of CCL program. + +This macro exists for backward compatibility. In the old version of +Emacs, to compile a CCL program which calls another CCL program not +yet defined, it must be declared as a CCL program in advance. But, +now CCL program names are resolved not at compile time but before +execution. + +Optional arg VECTOR is a compiled CCL code of the CCL program. + +\(fn NAME &optional VECTOR)" nil t) + +(autoload 'define-ccl-program "ccl" "\ +Set NAME the compiled code of CCL-PROGRAM. + +CCL-PROGRAM has this form: + (BUFFER_MAGNIFICATION + CCL_MAIN_CODE + [ CCL_EOF_CODE ]) + +BUFFER_MAGNIFICATION is an integer value specifying the approximate +output buffer magnification size compared with the bytes of input data +text. It is assured that the actual output buffer has 256 bytes +more than the size calculated by BUFFER_MAGNIFICATION. +If the value is zero, the CCL program can't execute `read' and +`write' commands. + +CCL_MAIN_CODE and CCL_EOF_CODE are CCL program codes. CCL_MAIN_CODE +executed at first. If there's no more input data when `read' command +is executed in CCL_MAIN_CODE, CCL_EOF_CODE is executed. If +CCL_MAIN_CODE is terminated, CCL_EOF_CODE is not executed. + +Here's the syntax of CCL program code in BNF notation. The lines +starting by two semicolons (and optional leading spaces) describe the +semantics. + +CCL_MAIN_CODE := CCL_BLOCK + +CCL_EOF_CODE := CCL_BLOCK + +CCL_BLOCK := STATEMENT | (STATEMENT [STATEMENT ...]) + +STATEMENT := + SET | IF | BRANCH | LOOP | REPEAT | BREAK | READ | WRITE | CALL + | TRANSLATE | MAP | LOOKUP | END + +SET := (REG = EXPRESSION) + | (REG ASSIGNMENT_OPERATOR EXPRESSION) + ;; The following form is the same as (r0 = integer). + | integer + +EXPRESSION := ARG | (EXPRESSION OPERATOR ARG) + +;; Evaluate EXPRESSION. If the result is nonzero, execute +;; CCL_BLOCK_0. Otherwise, execute CCL_BLOCK_1. +IF := (if EXPRESSION CCL_BLOCK_0 CCL_BLOCK_1) + +;; Evaluate EXPRESSION. Provided that the result is N, execute +;; CCL_BLOCK_N. +BRANCH := (branch EXPRESSION CCL_BLOCK_0 [CCL_BLOCK_1 ...]) + +;; Execute STATEMENTs until (break) or (end) is executed. + +;; Create a block of STATEMENTs for repeating. The STATEMENTs +;; are executed sequentially until REPEAT or BREAK is executed. +;; If REPEAT statement is executed, STATEMENTs are executed from the +;; start again. If BREAK statements is executed, the execution +;; exits from the block. If neither REPEAT nor BREAK is +;; executed, the execution exits from the block after executing the +;; last STATEMENT. +LOOP := (loop STATEMENT [STATEMENT ...]) + +;; Terminate the most inner loop. +BREAK := (break) + +REPEAT := + ;; Jump to the head of the most inner loop. + (repeat) + ;; Same as: ((write [REG | integer | string]) + ;; (repeat)) + | (write-repeat [REG | integer | string]) + ;; Same as: ((write REG [ARRAY]) + ;; (read REG) + ;; (repeat)) + | (write-read-repeat REG [ARRAY]) + ;; Same as: ((write integer) + ;; (read REG) + ;; (repeat)) + | (write-read-repeat REG integer) + +READ := ;; Set REG_0 to a byte read from the input text, set REG_1 + ;; to the next byte read, and so on. + (read REG_0 [REG_1 ...]) + ;; Same as: ((read REG) + ;; (if (REG OPERATOR ARG) CCL_BLOCK_0 CCL_BLOCK_1)) + | (read-if (REG OPERATOR ARG) CCL_BLOCK_0 CCL_BLOCK_1) + ;; Same as: ((read REG) + ;; (branch REG CCL_BLOCK_0 [CCL_BLOCK_1 ...])) + | (read-branch REG CCL_BLOCK_0 [CCL_BLOCK_1 ...]) + ;; Read a character from the input text while parsing + ;; multibyte representation, set REG_0 to the charset ID of + ;; the character, set REG_1 to the code point of the + ;; character. If the dimension of charset is two, set REG_1 + ;; to ((CODE0 << 7) | CODE1), where CODE0 is the first code + ;; point and CODE1 is the second code point. + | (read-multibyte-character REG_0 REG_1) + +WRITE := + ;; Write REG_0, REG_1, ... to the output buffer. If REG_N is + ;; a multibyte character, write the corresponding multibyte + ;; representation. + (write REG_0 [REG_1 ...]) + ;; Same as: ((r7 = EXPRESSION) + ;; (write r7)) + | (write EXPRESSION) + ;; Write the value of `integer' to the output buffer. If it + ;; is a multibyte character, write the corresponding multibyte + ;; representation. + | (write integer) + ;; Write the byte sequence of `string' as is to the output + ;; buffer. + | (write string) + ;; Same as: (write string) + | string + ;; Provided that the value of REG is N, write Nth element of + ;; ARRAY to the output buffer. If it is a multibyte + ;; character, write the corresponding multibyte + ;; representation. + | (write REG ARRAY) + ;; Write a multibyte representation of a character whose + ;; charset ID is REG_0 and code point is REG_1. If the + ;; dimension of the charset is two, REG_1 should be ((CODE0 << + ;; 7) | CODE1), where CODE0 is the first code point and CODE1 + ;; is the second code point of the character. + | (write-multibyte-character REG_0 REG_1) + +;; Call CCL program whose name is ccl-program-name. +CALL := (call ccl-program-name) + +;; Terminate the CCL program. +END := (end) + +;; CCL registers that can contain any integer value. As r7 is also +;; used by CCL interpreter, its value is changed unexpectedly. +REG := r0 | r1 | r2 | r3 | r4 | r5 | r6 | r7 + +ARG := REG | integer + +OPERATOR := + ;; Normal arithmetic operators (same meaning as C code). + + | - | * | / | % + + ;; Bitwise operators (same meaning as C code) + | & | `|' | ^ + + ;; Shifting operators (same meaning as C code) + | << | >> + + ;; (REG = ARG_0 <8 ARG_1) means: + ;; (REG = ((ARG_0 << 8) | ARG_1)) + | <8 + + ;; (REG = ARG_0 >8 ARG_1) means: + ;; ((REG = (ARG_0 >> 8)) + ;; (r7 = (ARG_0 & 255))) + | >8 + + ;; (REG = ARG_0 // ARG_1) means: + ;; ((REG = (ARG_0 / ARG_1)) + ;; (r7 = (ARG_0 % ARG_1))) + | // + + ;; Normal comparing operators (same meaning as C code) + | < | > | == | <= | >= | != + + ;; If ARG_0 and ARG_1 are higher and lower byte of Shift-JIS + ;; code, and CHAR is the corresponding JISX0208 character, + ;; (REG = ARG_0 de-sjis ARG_1) means: + ;; ((REG = CODE0) + ;; (r7 = CODE1)) + ;; where CODE0 is the first code point of CHAR, CODE1 is the + ;; second code point of CHAR. + | de-sjis + + ;; If ARG_0 and ARG_1 are the first and second code point of + ;; JISX0208 character CHAR, and SJIS is the corresponding + ;; Shift-JIS code, + ;; (REG = ARG_0 en-sjis ARG_1) means: + ;; ((REG = HIGH) + ;; (r7 = LOW)) + ;; where HIGH is the higher byte of SJIS, LOW is the lower + ;; byte of SJIS. + | en-sjis + +ASSIGNMENT_OPERATOR := + ;; Same meaning as C code + += | -= | *= | /= | %= | &= | `|=' | ^= | <<= | >>= + + ;; (REG <8= ARG) is the same as: + ;; ((REG <<= 8) + ;; (REG |= ARG)) + | <8= + + ;; (REG >8= ARG) is the same as: + ;; ((r7 = (REG & 255)) + ;; (REG >>= 8)) + + ;; (REG //= ARG) is the same as: + ;; ((r7 = (REG % ARG)) + ;; (REG /= ARG)) + | //= + +ARRAY := `[' integer ... `]' + + +TRANSLATE := + ;; Decode character SRC, translate it by translate table + ;; TABLE, and encode it back to DST. TABLE is specified + ;; by its id number in REG_0, SRC is specified by its + ;; charset id number and codepoint in REG_1 and REG_2 + ;; respectively. + ;; On encoding, the charset of highest priority is selected. + ;; After the execution, DST is specified by its charset + ;; id number and codepoint in REG_1 and REG_2 respectively. + (translate-character REG_0 REG_1 REG_2) + + ;; Same as above except for SYMBOL specifying the name of + ;; the translate table defined by `define-translation-table'. + | (translate-character SYMBOL REG_1 REG_2) + +LOOKUP := + ;; Look up character SRC in hash table TABLE. TABLE is + ;; specified by its name in SYMBOL, and SRC is specified by + ;; its charset id number and codepoint in REG_1 and REG_2 + ;; respectively. + ;; If its associated value is an integer, set REG_1 to that + ;; value, and set r7 to 1. Otherwise, set r7 to 0. + (lookup-character SYMBOL REG_1 REG_2) + + ;; Look up integer value N in hash table TABLE. TABLE is + ;; specified by its name in SYMBOL and N is specified in + ;; REG. + ;; If its associated value is a character, set REG to that + ;; value, and set r7 to 1. Otherwise, set r7 to 0. + | (lookup-integer SYMBOL REG(integer)) + +MAP := + ;; The following statements are for internal use only. + (iterate-multiple-map REG REG MAP-IDs) + | (map-multiple REG REG (MAP-SET)) + | (map-single REG REG MAP-ID) + +MAP-IDs := MAP-ID ... +MAP-SET := MAP-IDs | (MAP-IDs) MAP-SET +MAP-ID := integer + +\(fn NAME CCL-PROGRAM &optional DOC)" nil t) + +(function-put 'define-ccl-program 'doc-string-elt '3) + +(autoload 'check-ccl-program "ccl" "\ +Check validity of CCL-PROGRAM. +If CCL-PROGRAM is a symbol denoting a CCL program, return +CCL-PROGRAM, else return nil. +If CCL-PROGRAM is a vector and optional arg NAME (symbol) is supplied, +register CCL-PROGRAM by name NAME, and return NAME. + +\(fn CCL-PROGRAM &optional NAME)" nil t) + +(autoload 'ccl-execute-with-args "ccl" "\ +Execute CCL-PROGRAM with registers initialized by the remaining args. +The return value is a vector of resulting CCL registers. + +See the documentation of `define-ccl-program' for the detail of CCL program. + +\(fn CCL-PROG &rest ARGS)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ccl" '("ccl-"))) + +;;;*** + +;;;### (autoloads nil "cconv" "emacs-lisp/cconv.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/cconv.el + +(autoload 'cconv-closure-convert "cconv" "\ +Main entry point for closure conversion. +-- FORM is a piece of Elisp code after macroexpansion. +-- TOPLEVEL(optional) is a boolean variable, true if we are at the root of AST + +Returns a form where all lambdas don't have any free variables. + +\(fn FORM)" nil nil) + +(autoload 'cconv-warnings-only "cconv" "\ +Add the warnings that closure conversion would encounter. + +\(fn FORM)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cconv" '("cconv-"))) + +;;;*** + +;;;### (autoloads nil "cdl" "cdl.el" (0 0 0 0)) +;;; Generated autoloads from cdl.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cdl" '("cdl-"))) + +;;;*** + +;;;### (autoloads nil "cedet" "cedet/cedet.el" (0 0 0 0)) +;;; Generated autoloads from cedet/cedet.el +(push (purecopy '(cedet 2 0)) package--builtin-versions) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cedet" '("cedet-"))) + +;;;*** + +;;;### (autoloads nil "cedet-cscope" "cedet/cedet-cscope.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from cedet/cedet-cscope.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cedet-cscope" '("cedet-cscope-"))) + +;;;*** + +;;;### (autoloads nil "cedet-files" "cedet/cedet-files.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from cedet/cedet-files.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cedet-files" '("cedet-"))) + +;;;*** + +;;;### (autoloads nil "cedet-global" "cedet/cedet-global.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from cedet/cedet-global.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cedet-global" '("cedet-g"))) + +;;;*** + +;;;### (autoloads nil "cedet-idutils" "cedet/cedet-idutils.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from cedet/cedet-idutils.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cedet-idutils" '("cedet-idutils-"))) + +;;;*** + +;;;### (autoloads nil "cfengine" "progmodes/cfengine.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/cfengine.el +(push (purecopy '(cfengine 1 4)) package--builtin-versions) + +(autoload 'cfengine3-mode "cfengine" "\ +Major mode for editing CFEngine3 input. +There are no special keybindings by default. + +Action blocks are treated as defuns, i.e. \\[beginning-of-defun] moves +to the action header. + +\(fn)" t nil) + +(autoload 'cfengine2-mode "cfengine" "\ +Major mode for editing CFEngine2 input. +There are no special keybindings by default. + +Action blocks are treated as defuns, i.e. \\[beginning-of-defun] moves +to the action header. + +\(fn)" t nil) + +(autoload 'cfengine-auto-mode "cfengine" "\ +Choose `cfengine2-mode' or `cfengine3-mode' by buffer contents. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cfengine" '("cfengine"))) + +;;;*** + +;;;### (autoloads nil "char-fold" "char-fold.el" (0 0 0 0)) +;;; Generated autoloads from char-fold.el + +(autoload 'char-fold-to-regexp "char-fold" "\ +Return a regexp matching anything that char-folds into STRING. +Any character in STRING that has an entry in +`char-fold-table' is replaced with that entry (which is a +regexp) and other characters are `regexp-quote'd. + +If the resulting regexp would be too long for Emacs to handle, +just return the result of calling `regexp-quote' on STRING. + +FROM is for internal use. It specifies an index in the STRING +from which to start. + +\(fn STRING &optional LAX FROM)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "char-fold" '("char-fold-"))) + +;;;*** + +;;;### (autoloads nil "chart" "emacs-lisp/chart.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/chart.el +(push (purecopy '(chart 0 2)) package--builtin-versions) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "chart" '("chart"))) + +;;;*** + +;;;### (autoloads nil "check-declare" "emacs-lisp/check-declare.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/check-declare.el + +(autoload 'check-declare-file "check-declare" "\ +Check veracity of all `declare-function' statements in FILE. +See `check-declare-directory' for more information. + +\(fn FILE)" t nil) + +(autoload 'check-declare-directory "check-declare" "\ +Check veracity of all `declare-function' statements under directory ROOT. +Returns non-nil if any false statements are found. + +\(fn ROOT)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "check-declare" '("check-declare-"))) + +;;;*** + +;;;### (autoloads nil "checkdoc" "emacs-lisp/checkdoc.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from emacs-lisp/checkdoc.el +(push (purecopy '(checkdoc 0 6 2)) package--builtin-versions) +(put 'checkdoc-force-docstrings-flag 'safe-local-variable #'booleanp) +(put 'checkdoc-force-history-flag 'safe-local-variable #'booleanp) +(put 'checkdoc-permit-comma-termination-flag 'safe-local-variable #'booleanp) +(put 'checkdoc-spellcheck-documentation-flag 'safe-local-variable #'booleanp) +(put 'checkdoc-ispell-list-words 'safe-local-variable #'checkdoc-list-of-strings-p) +(put 'checkdoc-arguments-in-order-flag 'safe-local-variable #'booleanp) +(put 'checkdoc-verb-check-experimental-flag 'safe-local-variable #'booleanp) +(put 'checkdoc-symbol-words 'safe-local-variable #'checkdoc-list-of-strings-p) + +(autoload 'checkdoc-list-of-strings-p "checkdoc" "\ +Return t when OBJ is a list of strings. + +\(fn OBJ)" nil nil) +(put 'checkdoc-proper-noun-regexp 'safe-local-variable 'stringp) +(put 'checkdoc-common-verbs-regexp 'safe-local-variable 'stringp) + +(autoload 'checkdoc "checkdoc" "\ +Interactively check the entire buffer for style errors. +The current status of the check will be displayed in a buffer which +the users will view as each check is completed. + +\(fn)" t nil) + +(autoload 'checkdoc-interactive "checkdoc" "\ +Interactively check the current buffer for doc string errors. +Prefix argument START-HERE will start the checking from the current +point, otherwise the check starts at the beginning of the current +buffer. Allows navigation forward and backwards through document +errors. Does not check for comment or space warnings. +Optional argument SHOWSTATUS indicates that we should update the +checkdoc status window instead of the usual behavior. + +\(fn &optional START-HERE SHOWSTATUS)" t nil) + +(autoload 'checkdoc-message-interactive "checkdoc" "\ +Interactively check the current buffer for message string errors. +Prefix argument START-HERE will start the checking from the current +point, otherwise the check starts at the beginning of the current +buffer. Allows navigation forward and backwards through document +errors. Does not check for comment or space warnings. +Optional argument SHOWSTATUS indicates that we should update the +checkdoc status window instead of the usual behavior. + +\(fn &optional START-HERE SHOWSTATUS)" t nil) + +(autoload 'checkdoc-eval-current-buffer "checkdoc" "\ +Evaluate and check documentation for the current buffer. +Evaluation is done first because good documentation for something that +doesn't work is just not useful. Comments, doc strings, and rogue +spacing are all verified. + +\(fn)" t nil) + +(autoload 'checkdoc-current-buffer "checkdoc" "\ +Check current buffer for document, comment, error style, and rogue spaces. +With a prefix argument (in Lisp, the argument TAKE-NOTES), +store all errors found in a warnings buffer, +otherwise stop after the first error. + +\(fn &optional TAKE-NOTES)" t nil) + +(autoload 'checkdoc-file "checkdoc" "\ +Check FILE for document, comment, error style, and rogue spaces. + +\(fn FILE)" nil nil) + +(autoload 'checkdoc-start "checkdoc" "\ +Start scanning the current buffer for documentation string style errors. +Only documentation strings are checked. +Use `checkdoc-continue' to continue checking if an error cannot be fixed. +Prefix argument TAKE-NOTES means to collect all the warning messages into +a separate buffer. + +\(fn &optional TAKE-NOTES)" t nil) + +(autoload 'checkdoc-continue "checkdoc" "\ +Find the next doc string in the current buffer which has a style error. +Prefix argument TAKE-NOTES means to continue through the whole buffer and +save warnings in a separate buffer. Second optional argument START-POINT +is the starting location. If this is nil, `point-min' is used instead. + +\(fn &optional TAKE-NOTES)" t nil) + +(autoload 'checkdoc-comments "checkdoc" "\ +Find missing comment sections in the current Emacs Lisp file. +Prefix argument TAKE-NOTES non-nil means to save warnings in a +separate buffer. Otherwise print a message. This returns the error +if there is one. + +\(fn &optional TAKE-NOTES)" t nil) + +(autoload 'checkdoc-rogue-spaces "checkdoc" "\ +Find extra spaces at the end of lines in the current file. +Prefix argument TAKE-NOTES non-nil means to save warnings in a +separate buffer. Otherwise print a message. This returns the error +if there is one. +Optional argument INTERACT permits more interactive fixing. + +\(fn &optional TAKE-NOTES INTERACT)" t nil) + +(autoload 'checkdoc-message-text "checkdoc" "\ +Scan the buffer for occurrences of the error function, and verify text. +Optional argument TAKE-NOTES causes all errors to be logged. + +\(fn &optional TAKE-NOTES)" t nil) + +(autoload 'checkdoc-eval-defun "checkdoc" "\ +Evaluate the current form with `eval-defun' and check its documentation. +Evaluation is done first so the form will be read before the +documentation is checked. If there is a documentation error, then the display +of what was evaluated will be overwritten by the diagnostic message. + +\(fn)" t nil) + +(autoload 'checkdoc-defun "checkdoc" "\ +Examine the doc string of the function or variable under point. +Call `error' if the doc string has problems. If NO-ERROR is +non-nil, then do not call error, but call `message' instead. +If the doc string passes the test, then check the function for rogue white +space at the end of each line. + +\(fn &optional NO-ERROR)" t nil) + +(autoload 'checkdoc-ispell "checkdoc" "\ +Check the style and spelling of everything interactively. +Calls `checkdoc' with spell-checking turned on. +Prefix argument is the same as for `checkdoc' + +\(fn)" t nil) + +(autoload 'checkdoc-ispell-current-buffer "checkdoc" "\ +Check the style and spelling of the current buffer. +Calls `checkdoc-current-buffer' with spell-checking turned on. +Prefix argument is the same as for `checkdoc-current-buffer' + +\(fn)" t nil) + +(autoload 'checkdoc-ispell-interactive "checkdoc" "\ +Check the style and spelling of the current buffer interactively. +Calls `checkdoc-interactive' with spell-checking turned on. +Prefix argument is the same as for `checkdoc-interactive' + +\(fn)" t nil) + +(autoload 'checkdoc-ispell-message-interactive "checkdoc" "\ +Check the style and spelling of message text interactively. +Calls `checkdoc-message-interactive' with spell-checking turned on. +Prefix argument is the same as for `checkdoc-message-interactive' + +\(fn)" t nil) + +(autoload 'checkdoc-ispell-message-text "checkdoc" "\ +Check the style and spelling of message text interactively. +Calls `checkdoc-message-text' with spell-checking turned on. +Prefix argument is the same as for `checkdoc-message-text' + +\(fn)" t nil) + +(autoload 'checkdoc-ispell-start "checkdoc" "\ +Check the style and spelling of the current buffer. +Calls `checkdoc-start' with spell-checking turned on. +Prefix argument is the same as for `checkdoc-start' + +\(fn)" t nil) + +(autoload 'checkdoc-ispell-continue "checkdoc" "\ +Check the style and spelling of the current buffer after point. +Calls `checkdoc-continue' with spell-checking turned on. +Prefix argument is the same as for `checkdoc-continue' + +\(fn)" t nil) + +(autoload 'checkdoc-ispell-comments "checkdoc" "\ +Check the style and spelling of the current buffer's comments. +Calls `checkdoc-comments' with spell-checking turned on. +Prefix argument is the same as for `checkdoc-comments' + +\(fn)" t nil) + +(autoload 'checkdoc-ispell-defun "checkdoc" "\ +Check the style and spelling of the current defun with Ispell. +Calls `checkdoc-defun' with spell-checking turned on. +Prefix argument is the same as for `checkdoc-defun' + +\(fn)" t nil) + +(autoload 'checkdoc-minor-mode "checkdoc" "\ +Toggle automatic docstring checking (Checkdoc minor mode). +With a prefix argument ARG, enable Checkdoc minor mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +In Checkdoc minor mode, the usual bindings for `eval-defun' which is +bound to \\<checkdoc-minor-mode-map>\\[checkdoc-eval-defun] and `checkdoc-eval-current-buffer' are overridden to include +checking of documentation strings. + +\\{checkdoc-minor-mode-map} + +\(fn &optional ARG)" t nil) + +(autoload 'checkdoc-package-keywords "checkdoc" "\ +Find package keywords that aren't in `finder-known-keywords'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "checkdoc" '("checkdoc-"))) + +;;;*** + +;;;### (autoloads nil "china-util" "language/china-util.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from language/china-util.el + +(autoload 'decode-hz-region "china-util" "\ +Decode HZ/ZW encoded text in the current region. +Return the length of resulting text. + +\(fn BEG END)" t nil) + +(autoload 'decode-hz-buffer "china-util" "\ +Decode HZ/ZW encoded text in the current buffer. + +\(fn)" t nil) + +(autoload 'encode-hz-region "china-util" "\ +Encode the text in the current region to HZ. +Return the length of resulting text. + +\(fn BEG END)" t nil) + +(autoload 'encode-hz-buffer "china-util" "\ +Encode the text in the current buffer to HZ. + +\(fn)" t nil) + +(autoload 'post-read-decode-hz "china-util" "\ + + +\(fn LEN)" nil nil) + +(autoload 'pre-write-encode-hz "china-util" "\ + + +\(fn FROM TO)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "china-util" '("hz/zw-start-gb" "hz-" "decode-hz-line-continuation" "zw-start-gb" "iso2022-"))) + +;;;*** + +;;;### (autoloads nil "chistory" "chistory.el" (0 0 0 0)) +;;; Generated autoloads from chistory.el + +(autoload 'repeat-matching-complex-command "chistory" "\ +Edit and re-evaluate complex command with name matching PATTERN. +Matching occurrences are displayed, most recent first, until you select +a form for evaluation. If PATTERN is empty (or nil), every form in the +command history is offered. The form is placed in the minibuffer for +editing and the result is evaluated. + +\(fn &optional PATTERN)" t nil) + +(autoload 'list-command-history "chistory" "\ +List history of commands that used the minibuffer. +The number of commands listed is controlled by `list-command-history-max'. +Calls value of `list-command-history-filter' (if non-nil) on each history +element to judge if that element should be excluded from the list. + +The buffer is left in Command History mode. + +\(fn)" t nil) + +(autoload 'command-history "chistory" "\ +Examine commands from `command-history' in a buffer. +The number of commands listed is controlled by `list-command-history-max'. +The command history is filtered by `list-command-history-filter' if non-nil. +Use \\<command-history-map>\\[command-history-repeat] to repeat the command on the current line. + +Otherwise much like Emacs-Lisp Mode except that there is no self-insertion +and digits provide prefix arguments. Tab does not indent. +\\{command-history-map} + +This command always recompiles the Command History listing +and runs the normal hook `command-history-hook'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "chistory" '("command-history-" "list-command-history-" "default-command-history-filter"))) + +;;;*** + +;;;### (autoloads nil "cl" "emacs-lisp/cl.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/cl.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cl" '("cl-" "defsetf" "define-" "lexical-let" "labels" "flet"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "cl-extra" "emacs-lisp/cl-extra.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/cl-extra.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cl-extra" '("cl-"))) + +;;;*** + +;;;### (autoloads nil "cl-generic" "emacs-lisp/cl-generic.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from emacs-lisp/cl-generic.el +(push (purecopy '(cl-generic 1 0)) package--builtin-versions) + +;;;*** + +;;;### (autoloads nil "cl-indent" "emacs-lisp/cl-indent.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from emacs-lisp/cl-indent.el + +(autoload 'common-lisp-indent-function "cl-indent" "\ +Function to indent the arguments of a Lisp function call. +This is suitable for use as the value of the variable +`lisp-indent-function'. INDENT-POINT is the point at which the +indentation function is called, and STATE is the +`parse-partial-sexp' state at that position. Browse the +`lisp-indent' customize group for options affecting the behavior +of this function. + +If the indentation point is in a call to a Lisp function, that +function's `common-lisp-indent-function' property specifies how +this function should indent it. Possible values for this +property are: + +* defun, meaning indent according to `lisp-indent-defun-method'; + i.e., like (4 &lambda &body), as explained below. + +* any other symbol, meaning a function to call. The function should + take the arguments: PATH STATE INDENT-POINT SEXP-COLUMN NORMAL-INDENT. + PATH is a list of integers describing the position of point in terms of + list-structure with respect to the containing lists. For example, in + ((a b c (d foo) f) g), foo has a path of (0 3 1). In other words, + to reach foo take the 0th element of the outermost list, then + the 3rd element of the next list, and finally the 1st element. + STATE and INDENT-POINT are as in the arguments to + `common-lisp-indent-function'. SEXP-COLUMN is the column of + the open parenthesis of the innermost containing list. + NORMAL-INDENT is the column the indentation point was + originally in. This function should behave like `lisp-indent-259'. + +* an integer N, meaning indent the first N arguments like + function arguments, and any further arguments like a body. + This is equivalent to (4 4 ... &body). + +* a list. The list element in position M specifies how to indent the Mth + function argument. If there are fewer elements than function arguments, + the last list element applies to all remaining arguments. The accepted + list elements are: + + * nil, meaning the default indentation. + + * an integer, specifying an explicit indentation. + + * &lambda. Indent the argument (which may be a list) by 4. + + * &rest. When used, this must be the penultimate element. The + element after this one applies to all remaining arguments. + + * &body. This is equivalent to &rest lisp-body-indent, i.e., indent + all remaining elements by `lisp-body-indent'. + + * &whole. This must be followed by nil, an integer, or a + function symbol. This indentation is applied to the + associated argument, and as a base indent for all remaining + arguments. For example, an integer P means indent this + argument by P, and all remaining arguments by P, plus the + value specified by their associated list element. + + * a symbol. A function to call, with the 6 arguments specified above. + + * a list, with elements as described above. This applies when the + associated function argument is itself a list. Each element of the list + specifies how to indent the associated argument. + +For example, the function `case' has an indent property +\(4 &rest (&whole 2 &rest 1)), meaning: + * indent the first argument by 4. + * arguments after the first should be lists, and there may be any number + of them. The first list element has an offset of 2, all the rest + have an offset of 2+1=3. + +If the current mode is actually `emacs-lisp-mode', look for a +`common-lisp-indent-function-for-elisp' property before looking +at `common-lisp-indent-function' and, if set, use its value +instead. + +\(fn INDENT-POINT STATE)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cl-indent" '("lisp-" "common-lisp-"))) + +;;;*** + +;;;### (autoloads nil "cl-lib" "emacs-lisp/cl-lib.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/cl-lib.el +(push (purecopy '(cl-lib 1 0)) package--builtin-versions) + +(define-obsolete-variable-alias 'custom-print-functions 'cl-custom-print-functions "24.3") + +(defvar cl-custom-print-functions nil "\ +This is a list of functions that format user objects for printing. +Each function is called in turn with three arguments: the object, the +stream, and the print level (currently ignored). If it is able to +print the object it returns true; otherwise it returns nil and the +printer proceeds to the next function on the list. + +This variable is not used at present, but it is defined in hopes that +a future Emacs interpreter will be able to use it.") + +(defvar cl-old-struct-compat-mode nil "\ +Non-nil if Cl-Old-Struct-Compat mode is enabled. +See the `cl-old-struct-compat-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `cl-old-struct-compat-mode'.") + +(custom-autoload 'cl-old-struct-compat-mode "cl-lib" nil) + +(autoload 'cl-old-struct-compat-mode "cl-lib" "\ +Enable backward compatibility with old-style structs. +This can be needed when using code byte-compiled using the old +macro-expansion of `cl-defstruct' that used vectors objects instead +of record objects. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cl-lib" '("cl-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "cl-macs" "emacs-lisp/cl-macs.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/cl-macs.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cl-macs" '("cl-"))) + +;;;*** + +;;;### (autoloads nil "cl-print" "emacs-lisp/cl-print.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from emacs-lisp/cl-print.el +(push (purecopy '(cl-print 1 0)) package--builtin-versions) + +(autoload 'cl-print-object "cl-print" "\ +Dispatcher to print OBJECT on STREAM according to its type. +You can add methods to it to customize the output. +But if you just want to print something, don't call this directly: +call other entry points instead, such as `cl-prin1'. + +\(fn OBJECT STREAM)" nil nil) + +(autoload 'cl-prin1 "cl-print" "\ + + +\(fn OBJECT &optional STREAM)" nil nil) + +(autoload 'cl-prin1-to-string "cl-print" "\ + + +\(fn OBJECT)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cl-print" '("cl-print-" "help-byte-code"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "cl-seq" "emacs-lisp/cl-seq.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/cl-seq.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cl-seq" '("cl--"))) + +;;;*** + +;;;### (autoloads nil "cmacexp" "progmodes/cmacexp.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/cmacexp.el + +(autoload 'c-macro-expand "cmacexp" "\ +Expand C macros in the region, using the C preprocessor. +Normally display output in temp buffer, but +prefix arg means replace the region with it. + +`c-macro-preprocessor' specifies the preprocessor to use. +Tf the user option `c-macro-prompt-flag' is non-nil +prompt for arguments to the preprocessor (e.g. `-DDEBUG -I ./include'), +otherwise use `c-macro-cppflags'. + +Noninteractive args are START, END, SUBST. +For use inside Lisp programs, see also `c-macro-expansion'. + +\(fn START END SUBST)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cmacexp" '("c-macro-"))) + +;;;*** + +;;;### (autoloads nil "cmuscheme" "cmuscheme.el" (0 0 0 0)) +;;; Generated autoloads from cmuscheme.el + +(autoload 'run-scheme "cmuscheme" "\ +Run an inferior Scheme process, input and output via buffer `*scheme*'. +If there is a process already running in `*scheme*', switch to that buffer. +With argument, allows you to edit the command line (default is value +of `scheme-program-name'). +If the file `~/.emacs_SCHEMENAME' or `~/.emacs.d/init_SCHEMENAME.scm' exists, +it is given as initial input. +Note that this may lose due to a timing error if the Scheme processor +discards input when it starts up. +Runs the hook `inferior-scheme-mode-hook' (after the `comint-mode-hook' +is run). +\(Type \\[describe-mode] in the process buffer for a list of commands.) + +\(fn CMD)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cmuscheme" '("cmuscheme-load-hook" "switch-to-scheme" "scheme-" "inferior-scheme-"))) + +;;;*** + +;;;### (autoloads nil "color" "color.el" (0 0 0 0)) +;;; Generated autoloads from color.el + +(autoload 'color-name-to-rgb "color" "\ +Convert COLOR string to a list of normalized RGB components. +COLOR should be a color name (e.g. \"white\") or an RGB triplet +string (e.g. \"#ff12ec\"). + +Normally the return value is a list of three floating-point +numbers, (RED GREEN BLUE), each between 0.0 and 1.0 inclusive. + +Optional argument FRAME specifies the frame where the color is to be +displayed. If FRAME is omitted or nil, use the selected frame. +If FRAME cannot display COLOR, return nil. + +\(fn COLOR &optional FRAME)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "color" '("color-"))) + +;;;*** + +;;;### (autoloads nil "comint" "comint.el" (0 0 0 0)) +;;; Generated autoloads from comint.el + +(defvar comint-output-filter-functions '(ansi-color-process-output comint-postoutput-scroll-to-bottom comint-watch-for-password-prompt) "\ +Functions to call after output is inserted into the buffer. +One possible function is `comint-postoutput-scroll-to-bottom'. +These functions get one argument, a string containing the text as originally +inserted. Note that this might not be the same as the buffer contents between +`comint-last-output-start' and the buffer's `process-mark', if other filter +functions have already modified the buffer. + +See also `comint-preoutput-filter-functions'. + +You can use `add-hook' to add functions to this list +either globally or locally.") + +(autoload 'make-comint-in-buffer "comint" "\ +Make a Comint process NAME in BUFFER, running PROGRAM. +If BUFFER is nil, it defaults to NAME surrounded by `*'s. +If there is a running process in BUFFER, it is not restarted. + +PROGRAM should be one of the following: +- a string, denoting an executable program to create via + `start-file-process' +- a cons pair of the form (HOST . SERVICE), denoting a TCP + connection to be opened via `open-network-stream' +- nil, denoting a newly-allocated pty. + +Optional fourth arg STARTFILE is the name of a file, whose +contents are sent to the process as its initial input. + +If PROGRAM is a string, any more args are arguments to PROGRAM. + +Return the (possibly newly created) process buffer. + +\(fn NAME BUFFER PROGRAM &optional STARTFILE &rest SWITCHES)" nil nil) + +(autoload 'make-comint "comint" "\ +Make a Comint process NAME in a buffer, running PROGRAM. +The name of the buffer is made by surrounding NAME with `*'s. +PROGRAM should be either a string denoting an executable program to create +via `start-file-process', or a cons pair of the form (HOST . SERVICE) denoting +a TCP connection to be opened via `open-network-stream'. If there is already +a running process in that buffer, it is not restarted. Optional third arg +STARTFILE is the name of a file, whose contents are sent to the +process as its initial input. + +If PROGRAM is a string, any more args are arguments to PROGRAM. + +Returns the (possibly newly created) process buffer. + +\(fn NAME PROGRAM &optional STARTFILE &rest SWITCHES)" nil nil) + +(autoload 'comint-run "comint" "\ +Run PROGRAM in a Comint buffer and switch to it. +The buffer name is made by surrounding the file name of PROGRAM with `*'s. +The file name is used to make a symbol name, such as `comint-sh-hook', and any +hooks on this symbol are run in the buffer. +See `make-comint' and `comint-exec'. + +\(fn PROGRAM)" t nil) + +(function-put 'comint-run 'interactive-only 'make-comint) + +(defvar comint-file-name-prefix (purecopy "") "\ +Prefix prepended to absolute file names taken from process input. +This is used by Comint's and shell's completion functions, and by shell's +directory tracking functions.") + +(autoload 'comint-redirect-send-command "comint" "\ +Send COMMAND to process in current buffer, with output to OUTPUT-BUFFER. +With prefix arg ECHO, echo output in process buffer. + +If NO-DISPLAY is non-nil, do not show the output buffer. + +\(fn COMMAND OUTPUT-BUFFER ECHO &optional NO-DISPLAY)" t nil) + +(autoload 'comint-redirect-send-command-to-process "comint" "\ +Send COMMAND to PROCESS, with output to OUTPUT-BUFFER. +With prefix arg, echo output in process buffer. + +If NO-DISPLAY is non-nil, do not show the output buffer. + +\(fn COMMAND OUTPUT-BUFFER PROCESS ECHO &optional NO-DISPLAY)" t nil) + +(autoload 'comint-redirect-results-list "comint" "\ +Send COMMAND to current process. +Return a list of expressions in the output which match REGEXP. +REGEXP-GROUP is the regular expression group in REGEXP to use. + +\(fn COMMAND REGEXP REGEXP-GROUP)" nil nil) + +(autoload 'comint-redirect-results-list-from-process "comint" "\ +Send COMMAND to PROCESS. +Return a list of expressions in the output which match REGEXP. +REGEXP-GROUP is the regular expression group in REGEXP to use. + +\(fn PROCESS COMMAND REGEXP REGEXP-GROUP)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "comint" '("comint-" "shell-strip-ctrl-m" "send-invisible"))) + +;;;*** + +;;;### (autoloads nil "compare-w" "vc/compare-w.el" (0 0 0 0)) +;;; Generated autoloads from vc/compare-w.el + +(autoload 'compare-windows "compare-w" "\ +Compare text in current window with text in another window. +The option `compare-windows-get-window-function' defines how +to get another window. + +Compares the text starting at point in each window, +moving over text in each one as far as they match. + +This command pushes the mark in each window +at the prior location of point in that window. +If both windows display the same buffer, +the mark is pushed twice in that buffer: +first in the other window, then in the selected window. + +A prefix arg means reverse the value of variable +`compare-ignore-whitespace'. If `compare-ignore-whitespace' is +nil, then a prefix arg means ignore changes in whitespace. If +`compare-ignore-whitespace' is non-nil, then a prefix arg means +don't ignore changes in whitespace. The variable +`compare-windows-whitespace' controls how whitespace is skipped. +If `compare-ignore-case' is non-nil, changes in case are also +ignored. + +If `compare-windows-sync' is non-nil, then successive calls of +this command work in interlaced mode: +on first call it advances points to the next difference, +on second call it synchronizes points by skipping the difference, +on third call it again advances points to the next difference and so on. + +\(fn IGNORE-WHITESPACE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "compare-w" '("compare-"))) + +;;;*** + +;;;### (autoloads nil "compface" "image/compface.el" (0 0 0 0)) +;;; Generated autoloads from image/compface.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "compface" '("uncompface"))) + +;;;*** + +;;;### (autoloads nil "compile" "progmodes/compile.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/compile.el + +(defvar compilation-mode-hook nil "\ +List of hook functions run by `compilation-mode'.") + +(custom-autoload 'compilation-mode-hook "compile" t) + +(defvar compilation-start-hook nil "\ +Hook run after starting a new compilation process. +The hook is run with one argument, the new process.") + +(custom-autoload 'compilation-start-hook "compile" t) + +(defvar compilation-window-height nil "\ +Number of lines in a compilation window. +If nil, use Emacs default.") + +(custom-autoload 'compilation-window-height "compile" t) + +(defvar compilation-process-setup-function nil "\ +Function to call to customize the compilation process. +This function is called immediately before the compilation process is +started. It can be used to set any variables or functions that are used +while processing the output of the compilation process.") + +(defvar compilation-buffer-name-function nil "\ +Function to compute the name of a compilation buffer. +The function receives one argument, the name of the major mode of the +compilation buffer. It should return a string. +If nil, compute the name with `(concat \"*\" (downcase major-mode) \"*\")'.") + +(defvar compilation-finish-function nil "\ +Function to call when a compilation process finishes. +It is called with two arguments: the compilation buffer, and a string +describing how the process finished.") + +(defvar compilation-finish-functions nil "\ +Functions to call when a compilation process finishes. +Each function is called with two arguments: the compilation buffer, +and a string describing how the process finished.") +(put 'compilation-directory 'safe-local-variable 'stringp) + +(defvar compilation-ask-about-save t "\ +Non-nil means \\[compile] asks which buffers to save before compiling. +Otherwise, it saves all modified buffers without asking.") + +(custom-autoload 'compilation-ask-about-save "compile" t) + +(defvar compilation-search-path '(nil) "\ +List of directories to search for source files named in error messages. +Elements should be directory names, not file names of directories. +The value nil as an element means to try the default directory.") + +(custom-autoload 'compilation-search-path "compile" t) + +(defvar compile-command (purecopy "make -k ") "\ +Last shell command used to do a compilation; default for next compilation. + +Sometimes it is useful for files to supply local values for this variable. +You might also use mode hooks to specify it in certain modes, like this: + + (add-hook \\='c-mode-hook + (lambda () + (unless (or (file-exists-p \"makefile\") + (file-exists-p \"Makefile\")) + (set (make-local-variable \\='compile-command) + (concat \"make -k \" + (if buffer-file-name + (shell-quote-argument + (file-name-sans-extension buffer-file-name)))))))) + +It's often useful to leave a space at the end of the value.") + +(custom-autoload 'compile-command "compile" t) +(put 'compile-command 'safe-local-variable (lambda (a) (and (stringp a) (or (not (boundp 'compilation-read-command)) compilation-read-command)))) + +(defvar compilation-disable-input nil "\ +If non-nil, send end-of-file as compilation process input. +This only affects platforms that support asynchronous processes (see +`start-process'); synchronous compilation processes never accept input.") + +(custom-autoload 'compilation-disable-input "compile" t) + +(autoload 'compile "compile" "\ +Compile the program including the current buffer. Default: run `make'. +Runs COMMAND, a shell command, in a separate process asynchronously +with output going to the buffer `*compilation*'. + +You can then use the command \\[next-error] to find the next error message +and move to the source code that caused it. + +If optional second arg COMINT is t the buffer will be in Comint mode with +`compilation-shell-minor-mode'. + +Interactively, prompts for the command if the variable +`compilation-read-command' is non-nil; otherwise uses `compile-command'. +With prefix arg, always prompts. +Additionally, with universal prefix arg, compilation buffer will be in +comint mode, i.e. interactive. + +To run more than one compilation at once, start one then rename +the `*compilation*' buffer to some other name with +\\[rename-buffer]. Then _switch buffers_ and start the new compilation. +It will create a new `*compilation*' buffer. + +On most systems, termination of the main compilation process +kills its subprocesses. + +The name used for the buffer is actually whatever is returned by +the function in `compilation-buffer-name-function', so you can set that +to a function that generates a unique name. + +\(fn COMMAND &optional COMINT)" t nil) + +(autoload 'compilation-start "compile" "\ +Run compilation command COMMAND (low level interface). +If COMMAND starts with a cd command, that becomes the `default-directory'. +The rest of the arguments are optional; for them, nil means use the default. + +MODE is the major mode to set in the compilation buffer. Mode +may also be t meaning use `compilation-shell-minor-mode' under `comint-mode'. + +If NAME-FUNCTION is non-nil, call it with one argument (the mode name) +to determine the buffer name. Otherwise, the default is to +reuses the current buffer if it has the proper major mode, +else use or create a buffer with name based on the major mode. + +If HIGHLIGHT-REGEXP is non-nil, `next-error' will temporarily highlight +the matching section of the visited source line; the default is to use the +global value of `compilation-highlight-regexp'. + +Returns the compilation buffer created. + +\(fn COMMAND &optional MODE NAME-FUNCTION HIGHLIGHT-REGEXP)" nil nil) + +(autoload 'compilation-mode "compile" "\ +Major mode for compilation log buffers. +\\<compilation-mode-map>To visit the source for a line-numbered error, +move point to the error message line and type \\[compile-goto-error]. +To kill the compilation, type \\[kill-compilation]. + +Runs `compilation-mode-hook' with `run-mode-hooks' (which see). + +\\{compilation-mode-map} + +\(fn &optional NAME-OF-MODE)" t nil) + +(put 'define-compilation-mode 'doc-string-elt 3) + +(autoload 'compilation-shell-minor-mode "compile" "\ +Toggle Compilation Shell minor mode. +With a prefix argument ARG, enable Compilation Shell minor mode +if ARG is positive, and disable it otherwise. If called from +Lisp, enable the mode if ARG is omitted or nil. + +When Compilation Shell minor mode is enabled, all the +error-parsing commands of the Compilation major mode are +available but bound to keys that don't collide with Shell mode. +See `compilation-mode'. + +\(fn &optional ARG)" t nil) + +(autoload 'compilation-minor-mode "compile" "\ +Toggle Compilation minor mode. +With a prefix argument ARG, enable Compilation minor mode if ARG +is positive, and disable it otherwise. If called from Lisp, +enable the mode if ARG is omitted or nil. + +When Compilation minor mode is enabled, all the error-parsing +commands of Compilation major mode are available. See +`compilation-mode'. + +\(fn &optional ARG)" t nil) + +(autoload 'compilation-next-error-function "compile" "\ +Advance to the next error message and visit the file where the error was. +This is the value of `next-error-function' in Compilation buffers. + +\(fn N &optional RESET)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "compile" '("compil" "kill-compilation" "define-compilation-mode" "recompile"))) + +;;;*** + +;;;### (autoloads nil "completion" "completion.el" (0 0 0 0)) +;;; Generated autoloads from completion.el + +(defvar dynamic-completion-mode nil "\ +Non-nil if Dynamic-Completion mode is enabled. +See the `dynamic-completion-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `dynamic-completion-mode'.") + +(custom-autoload 'dynamic-completion-mode "completion" nil) + +(autoload 'dynamic-completion-mode "completion" "\ +Toggle dynamic word-completion on or off. +With a prefix argument ARG, enable the mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode +if ARG is omitted or nil. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "completion" '("inside-locate-completion-entry" "interactive-completion-string-reader" "initialize-completions" "current-completion-source" "cdabbrev-" "clear-all-completions" "check-completion-length" "complet" "cmpl-" "use-completion-" "list-all-completions" "symbol-" "set-c" "save" "kill-" "accept-completion" "add-" "*lisp-def-regexp*" "*c-def-regexp*" "delete-completion" "find-" "make-c" "num-cmpl-sources" "next-cdabbrev" "reset-cdabbrev" "enable-completion"))) + +;;;*** + +;;;### (autoloads nil "conf-mode" "textmodes/conf-mode.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from textmodes/conf-mode.el + +(autoload 'conf-mode "conf-mode" "\ +Mode for Unix and Windows Conf files and Java properties. +Most conf files know only three kinds of constructs: parameter +assignments optionally grouped into sections and comments. Yet +there is a great range of variation in the exact syntax of conf +files. See below for various wrapper commands that set up the +details for some of the most widespread variants. + +This mode sets up font locking, outline, imenu and it provides +alignment support through `conf-align-assignments'. If strings +come out wrong, try `conf-quote-normal'. + +Some files allow continuation lines, either with a backslash at +the end of line, or by indenting the next line (further). These +constructs cannot currently be recognized. + +Because of this great variety of nuances, which are often not +even clearly specified, please don't expect it to get every file +quite right. Patches that clearly identify some special case, +without breaking the general ones, are welcome. + +If instead you start this mode with the generic `conf-mode' +command, it will parse the buffer. It will generally well +identify the first four cases listed below. If the buffer +doesn't have enough contents to decide, this is identical to +`conf-windows-mode' on Windows, elsewhere to `conf-unix-mode'. +See also `conf-space-mode', `conf-colon-mode', `conf-javaprop-mode', +`conf-ppd-mode' and `conf-xdefaults-mode'. + +\\{conf-mode-map} + +\(fn)" t nil) + +(autoload 'conf-unix-mode "conf-mode" "\ +Conf Mode starter for Unix style Conf files. +Comments start with `#'. +For details see `conf-mode'. Example: + +# Conf mode font-locks this right on Unix and with \\[conf-unix-mode] + +\[Desktop Entry] + Encoding=UTF-8 + Name=The GIMP + Name[ca]=El GIMP + Name[cs]=GIMP + +\(fn)" t nil) + +(autoload 'conf-windows-mode "conf-mode" "\ +Conf Mode starter for Windows style Conf files. +Comments start with `;'. +For details see `conf-mode'. Example: + +; Conf mode font-locks this right on Windows and with \\[conf-windows-mode] + +\[ExtShellFolderViews] +Default={5984FFE0-28D4-11CF-AE66-08002B2E1262} +{5984FFE0-28D4-11CF-AE66-08002B2E1262}={5984FFE0-28D4-11CF-AE66-08002B2E1262} + +\[{5984FFE0-28D4-11CF-AE66-08002B2E1262}] +PersistMoniker=file://Folder.htt + +\(fn)" t nil) + +(autoload 'conf-javaprop-mode "conf-mode" "\ +Conf Mode starter for Java properties files. +Comments start with `#' but are also recognized with `//' or +between `/*' and `*/'. +For details see `conf-mode'. Example: + +# Conf mode font-locks this right with \\[conf-javaprop-mode] (Java properties) +// another kind of comment +/* yet another */ + +name:value +name=value +name value +x.1 = +x.2.y.1.z.1 = +x.2.y.1.z.2.zz = + +\(fn)" t nil) + +(autoload 'conf-space-mode "conf-mode" "\ +Conf Mode starter for space separated conf files. +\"Assignments\" are with ` '. Keywords before the parameters are +recognized according to the variable `conf-space-keywords-alist'. +Alternatively, you can specify a value for the file local variable +`conf-space-keywords'. +Use the function `conf-space-keywords' if you want to specify keywords +in an interactive fashion instead. + +For details see `conf-mode'. Example: + +# Conf mode font-locks this right with \\[conf-space-mode] (space separated) + +image/jpeg jpeg jpg jpe +image/png png +image/tiff tiff tif + +# Or with keywords (from a recognized file name): +class desktop +# Standard multimedia devices +add /dev/audio desktop +add /dev/mixer desktop + +\(fn)" t nil) + +(autoload 'conf-space-keywords "conf-mode" "\ +Enter Conf Space mode using regexp KEYWORDS to match the keywords. +See `conf-space-mode'. + +\(fn KEYWORDS)" t nil) + +(autoload 'conf-colon-mode "conf-mode" "\ +Conf Mode starter for Colon files. +\"Assignments\" are with `:'. +For details see `conf-mode'. Example: + +# Conf mode font-locks this right with \\[conf-colon-mode] (colon) + +<Multi_key> <exclam> <exclam> : \"\\241\" exclamdown +<Multi_key> <c> <slash> : \"\\242\" cent + +\(fn)" t nil) + +(autoload 'conf-ppd-mode "conf-mode" "\ +Conf Mode starter for Adobe/CUPS PPD files. +Comments start with `*%' and \"assignments\" are with `:'. +For details see `conf-mode'. Example: + +*% Conf mode font-locks this right with \\[conf-ppd-mode] (PPD) + +*DefaultTransfer: Null +*Transfer Null.Inverse: \"{ 1 exch sub }\" + +\(fn)" t nil) + +(autoload 'conf-xdefaults-mode "conf-mode" "\ +Conf Mode starter for Xdefaults files. +Comments start with `!' and \"assignments\" are with `:'. +For details see `conf-mode'. Example: + +! Conf mode font-locks this right with \\[conf-xdefaults-mode] (.Xdefaults) + +*background: gray99 +*foreground: black + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "conf-mode" '("conf-"))) + +;;;*** + +;;;### (autoloads nil "cookie1" "play/cookie1.el" (0 0 0 0)) +;;; Generated autoloads from play/cookie1.el + +(autoload 'cookie "cookie1" "\ +Return a random phrase from PHRASE-FILE. +When the phrase file is read in, display STARTMSG at the beginning +of load, ENDMSG at the end. +Interactively, PHRASE-FILE defaults to `cookie-file', unless that +is nil or a prefix argument is used. + +\(fn PHRASE-FILE &optional STARTMSG ENDMSG)" t nil) + +(autoload 'cookie-insert "cookie1" "\ +Insert random phrases from PHRASE-FILE; COUNT of them. +When the phrase file is read in, display STARTMSG at the beginning +of load, ENDMSG at the end. + +\(fn PHRASE-FILE &optional COUNT STARTMSG ENDMSG)" nil nil) + +(autoload 'cookie-snarf "cookie1" "\ +Reads in the PHRASE-FILE, returns it as a vector of strings. +Emit STARTMSG and ENDMSG before and after. Caches the result; second +and subsequent calls on the same file won't go to disk. + +\(fn PHRASE-FILE &optional STARTMSG ENDMSG)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cookie1" '("cookie"))) + +;;;*** + +;;;### (autoloads nil "copyright" "emacs-lisp/copyright.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from emacs-lisp/copyright.el +(put 'copyright-at-end-flag 'safe-local-variable 'booleanp) +(put 'copyright-names-regexp 'safe-local-variable 'stringp) +(put 'copyright-year-ranges 'safe-local-variable 'booleanp) + +(autoload 'copyright-update "copyright" "\ +Update copyright notice to indicate the current year. +With prefix ARG, replace the years in the notice rather than adding +the current year after them. If necessary, and +`copyright-current-gpl-version' is set, any copying permissions +following the copyright are updated as well. +If non-nil, INTERACTIVEP tells the function to behave as when it's called +interactively. + +\(fn &optional ARG INTERACTIVEP)" t nil) + +(autoload 'copyright-fix-years "copyright" "\ +Convert 2 digit years to 4 digit years. +Uses heuristic: year >= 50 means 19xx, < 50 means 20xx. +If `copyright-year-ranges' (which see) is non-nil, also +independently replaces consecutive years with a range. + +\(fn)" t nil) + +(autoload 'copyright "copyright" "\ +Insert a copyright by $ORGANIZATION notice at cursor. + +\(fn &optional STR ARG)" t nil) + +(autoload 'copyright-update-directory "copyright" "\ +Update copyright notice for all files in DIRECTORY matching MATCH. +If FIX is non-nil, run `copyright-fix-years' instead. + +\(fn DIRECTORY MATCH &optional FIX)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "copyright" '("copyright-"))) + +;;;*** + +;;;### (autoloads nil "cperl-mode" "progmodes/cperl-mode.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from progmodes/cperl-mode.el +(put 'cperl-indent-level 'safe-local-variable 'integerp) +(put 'cperl-brace-offset 'safe-local-variable 'integerp) +(put 'cperl-continued-brace-offset 'safe-local-variable 'integerp) +(put 'cperl-label-offset 'safe-local-variable 'integerp) +(put 'cperl-continued-statement-offset 'safe-local-variable 'integerp) +(put 'cperl-extra-newline-before-brace 'safe-local-variable 'booleanp) +(put 'cperl-merge-trailing-else 'safe-local-variable 'booleanp) + +(autoload 'cperl-mode "cperl-mode" "\ +Major mode for editing Perl code. +Expression and list commands understand all C brackets. +Tab indents for Perl code. +Paragraphs are separated by blank lines only. +Delete converts tabs to spaces as it moves back. + +Various characters in Perl almost always come in pairs: {}, (), [], +sometimes <>. When the user types the first, she gets the second as +well, with optional special formatting done on {}. (Disabled by +default.) You can always quote (with \\[quoted-insert]) the left +\"paren\" to avoid the expansion. The processing of < is special, +since most the time you mean \"less\". CPerl mode tries to guess +whether you want to type pair <>, and inserts is if it +appropriate. You can set `cperl-electric-parens-string' to the string that +contains the parens from the above list you want to be electrical. +Electricity of parens is controlled by `cperl-electric-parens'. +You may also set `cperl-electric-parens-mark' to have electric parens +look for active mark and \"embrace\" a region if possible.' + +CPerl mode provides expansion of the Perl control constructs: + + if, else, elsif, unless, while, until, continue, do, + for, foreach, formy and foreachmy. + +and POD directives (Disabled by default, see `cperl-electric-keywords'.) + +The user types the keyword immediately followed by a space, which +causes the construct to be expanded, and the point is positioned where +she is most likely to want to be. E.g., when the user types a space +following \"if\" the following appears in the buffer: if () { or if () +} { } and the cursor is between the parentheses. The user can then +type some boolean expression within the parens. Having done that, +typing \\[cperl-linefeed] places you - appropriately indented - on a +new line between the braces (if you typed \\[cperl-linefeed] in a POD +directive line, then appropriate number of new lines is inserted). + +If CPerl decides that you want to insert \"English\" style construct like + + bite if angry; + +it will not do any expansion. See also help on variable +`cperl-extra-newline-before-brace'. (Note that one can switch the +help message on expansion by setting `cperl-message-electric-keyword' +to nil.) + +\\[cperl-linefeed] is a convenience replacement for typing carriage +return. It places you in the next line with proper indentation, or if +you type it inside the inline block of control construct, like + + foreach (@lines) {print; print} + +and you are on a boundary of a statement inside braces, it will +transform the construct into a multiline and will place you into an +appropriately indented blank line. If you need a usual +`newline-and-indent' behavior, it is on \\[newline-and-indent], +see documentation on `cperl-electric-linefeed'. + +Use \\[cperl-invert-if-unless] to change a construction of the form + + if (A) { B } + +into + + B if A; + +\\{cperl-mode-map} + +Setting the variable `cperl-font-lock' to t switches on font-lock-mode +\(even with older Emacsen), `cperl-electric-lbrace-space' to t switches +on electric space between $ and {, `cperl-electric-parens-string' is +the string that contains parentheses that should be electric in CPerl +\(see also `cperl-electric-parens-mark' and `cperl-electric-parens'), +setting `cperl-electric-keywords' enables electric expansion of +control structures in CPerl. `cperl-electric-linefeed' governs which +one of two linefeed behavior is preferable. You can enable all these +options simultaneously (recommended mode of use) by setting +`cperl-hairy' to t. In this case you can switch separate options off +by setting them to `null'. Note that one may undo the extra +whitespace inserted by semis and braces in `auto-newline'-mode by +consequent \\[cperl-electric-backspace]. + +If your site has perl5 documentation in info format, you can use commands +\\[cperl-info-on-current-command] and \\[cperl-info-on-command] to access it. +These keys run commands `cperl-info-on-current-command' and +`cperl-info-on-command', which one is which is controlled by variable +`cperl-info-on-command-no-prompt' and `cperl-clobber-lisp-bindings' +\(in turn affected by `cperl-hairy'). + +Even if you have no info-format documentation, short one-liner-style +help is available on \\[cperl-get-help], and one can run perldoc or +man via menu. + +It is possible to show this help automatically after some idle time. +This is regulated by variable `cperl-lazy-help-time'. Default with +`cperl-hairy' (if the value of `cperl-lazy-help-time' is nil) is 5 +secs idle time . It is also possible to switch this on/off from the +menu, or via \\[cperl-toggle-autohelp]. Requires `run-with-idle-timer'. + +Use \\[cperl-lineup] to vertically lineup some construction - put the +beginning of the region at the start of construction, and make region +span the needed amount of lines. + +Variables `cperl-pod-here-scan', `cperl-pod-here-fontify', +`cperl-pod-face', `cperl-pod-head-face' control processing of POD and +here-docs sections. With capable Emaxen results of scan are used +for indentation too, otherwise they are used for highlighting only. + +Variables controlling indentation style: + `cperl-tab-always-indent' + Non-nil means TAB in CPerl mode should always reindent the current line, + regardless of where in the line point is when the TAB command is used. + `cperl-indent-left-aligned-comments' + Non-nil means that the comment starting in leftmost column should indent. + `cperl-auto-newline' + Non-nil means automatically newline before and after braces, + and after colons and semicolons, inserted in Perl code. The following + \\[cperl-electric-backspace] will remove the inserted whitespace. + Insertion after colons requires both this variable and + `cperl-auto-newline-after-colon' set. + `cperl-auto-newline-after-colon' + Non-nil means automatically newline even after colons. + Subject to `cperl-auto-newline' setting. + `cperl-indent-level' + Indentation of Perl statements within surrounding block. + The surrounding block's indentation is the indentation + of the line on which the open-brace appears. + `cperl-continued-statement-offset' + Extra indentation given to a substatement, such as the + then-clause of an if, or body of a while, or just a statement continuation. + `cperl-continued-brace-offset' + Extra indentation given to a brace that starts a substatement. + This is in addition to `cperl-continued-statement-offset'. + `cperl-brace-offset' + Extra indentation for line if it starts with an open brace. + `cperl-brace-imaginary-offset' + An open brace following other text is treated as if it the line started + this far to the right of the actual line indentation. + `cperl-label-offset' + Extra indentation for line that is a label. + `cperl-min-label-indent' + Minimal indentation for line that is a label. + +Settings for classic indent-styles: K&R BSD=C++ GNU PerlStyle=Whitesmith + `cperl-indent-level' 5 4 2 4 + `cperl-brace-offset' 0 0 0 0 + `cperl-continued-brace-offset' -5 -4 0 0 + `cperl-label-offset' -5 -4 -2 -4 + `cperl-continued-statement-offset' 5 4 2 4 + +CPerl knows several indentation styles, and may bulk set the +corresponding variables. Use \\[cperl-set-style] to do this. Use +\\[cperl-set-style-back] to restore the memorized preexisting values +\(both available from menu). See examples in `cperl-style-examples'. + +Part of the indentation style is how different parts of if/elsif/else +statements are broken into lines; in CPerl, this is reflected on how +templates for these constructs are created (controlled by +`cperl-extra-newline-before-brace'), and how reflow-logic should treat +\"continuation\" blocks of else/elsif/continue, controlled by the same +variable, and by `cperl-extra-newline-before-brace-multiline', +`cperl-merge-trailing-else', `cperl-indent-region-fix-constructs'. + +If `cperl-indent-level' is 0, the statement after opening brace in +column 0 is indented on +`cperl-brace-offset'+`cperl-continued-statement-offset'. + +Turning on CPerl mode calls the hooks in the variable `cperl-mode-hook' +with no args. + +DO NOT FORGET to read micro-docs (available from `Perl' menu) +or as help on variables `cperl-tips', `cperl-problems', +`cperl-praise', `cperl-speed'. + +\(fn)" t nil) + +(autoload 'cperl-perldoc "cperl-mode" "\ +Run `perldoc' on WORD. + +\(fn WORD)" t nil) + +(autoload 'cperl-perldoc-at-point "cperl-mode" "\ +Run a `perldoc' on the word around point. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cperl-mode" '("cperl-" "pod2man-program"))) + +;;;*** + +;;;### (autoloads nil "cpp" "progmodes/cpp.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/cpp.el + +(autoload 'cpp-highlight-buffer "cpp" "\ +Highlight C code according to preprocessor conditionals. +This command pops up a buffer which you should edit to specify +what kind of highlighting to use, and the criteria for highlighting. +A prefix arg suppresses display of that buffer. + +\(fn ARG)" t nil) + +(autoload 'cpp-parse-edit "cpp" "\ +Edit display information for cpp conditionals. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cpp" '("cpp-"))) + +;;;*** + +;;;### (autoloads nil "crm" "emacs-lisp/crm.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/crm.el + +(autoload 'completing-read-multiple "crm" "\ +Read multiple strings in the minibuffer, with completion. +The arguments are the same as those of `completing-read'. +\\<crm-local-completion-map> +Input multiple strings by separating each one with a string that +matches the regexp `crm-separator'. For example, if the separator +regexp is \",\", entering \"alice,bob,eve\" specifies the strings +\"alice\", \"bob\", and \"eve\". + +We refer to contiguous strings of non-separator-characters as +\"elements\". In this example there are three elements. + +Completion is available on a per-element basis. For example, if the +contents of the minibuffer are \"alice,bob,eve\" and point is between +\"l\" and \"i\", pressing \\[minibuffer-complete] operates on the element \"alice\". + +This function returns a list of the strings that were read, +with empty strings removed. + +\(fn PROMPT TABLE &optional PREDICATE REQUIRE-MATCH INITIAL-INPUT HIST DEF INHERIT-INPUT-METHOD)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "crm" '("crm-"))) + +;;;*** + +;;;### (autoloads nil "css-mode" "textmodes/css-mode.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/css-mode.el + +(autoload 'css-mode "css-mode" "\ +Major mode to edit Cascading Style Sheets (CSS). +\\<css-mode-map> +This mode provides syntax highlighting, indentation, completion, +and documentation lookup for CSS. + +Use `\\[complete-symbol]' to complete CSS properties, property values, +pseudo-elements, pseudo-classes, at-rules, bang-rules, and HTML +tags, classes and IDs. Completion candidates for HTML class +names and IDs are found by looking through open HTML mode +buffers. + +Use `\\[info-lookup-symbol]' to look up documentation of CSS properties, at-rules, +pseudo-classes, and pseudo-elements on the Mozilla Developer +Network (MDN). + +\\{css-mode-map} + +\(fn)" t nil) + (add-to-list 'auto-mode-alist '("\\.scss\\'" . scss-mode)) + +(autoload 'scss-mode "css-mode" "\ +Major mode to edit \"Sassy CSS\" files. + +\(fn)" t nil) + +(autoload 'css-lookup-symbol "css-mode" "\ +Display the CSS documentation for SYMBOL, as found on MDN. +When this command is used interactively, it picks a default +symbol based on the CSS text before point -- either an @-keyword, +a property name, a pseudo-class, or a pseudo-element, depending +on what is seen near point. + +\(fn SYMBOL)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "css-mode" '("css-" "scss-"))) + +;;;*** + +;;;### (autoloads nil "cua-base" "emulation/cua-base.el" (0 0 0 0)) +;;; Generated autoloads from emulation/cua-base.el + +(defvar cua-mode nil "\ +Non-nil if Cua mode is enabled. +See the `cua-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `cua-mode'.") + +(custom-autoload 'cua-mode "cua-base" nil) + +(autoload 'cua-mode "cua-base" "\ +Toggle Common User Access style editing (CUA mode). +With a prefix argument ARG, enable CUA mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode +if ARG is omitted or nil. + +CUA mode is a global minor mode. When enabled, typed text +replaces the active selection, and you can use C-z, C-x, C-c, and +C-v to undo, cut, copy, and paste in addition to the normal Emacs +bindings. The C-x and C-c keys only do cut and copy when the +region is active, so in most cases, they do not conflict with the +normal function of these prefix keys. + +If you really need to perform a command which starts with one of +the prefix keys even when the region is active, you have three +options: +- press the prefix key twice very quickly (within 0.2 seconds), +- press the prefix key and the following key within 0.2 seconds, or +- use the SHIFT key with the prefix key, i.e. C-S-x or C-S-c. + +You can customize `cua-enable-cua-keys' to completely disable the +CUA bindings, or `cua-prefix-override-inhibit-delay' to change +the prefix fallback behavior. + +\(fn &optional ARG)" t nil) + +(autoload 'cua-selection-mode "cua-base" "\ +Enable CUA selection mode without the C-z/C-x/C-c/C-v bindings. + +\(fn ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cua-base" '("cua-"))) + +;;;*** + +;;;### (autoloads nil "cua-gmrk" "emulation/cua-gmrk.el" (0 0 0 0)) +;;; Generated autoloads from emulation/cua-gmrk.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cua-gmrk" '("cua-"))) + +;;;*** + +;;;### (autoloads nil "cua-rect" "emulation/cua-rect.el" (0 0 0 0)) +;;; Generated autoloads from emulation/cua-rect.el + +(autoload 'cua-rectangle-mark-mode "cua-rect" "\ +Toggle the region as rectangular. +Activates the region if needed. Only lasts until the region is deactivated. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cua-rect" '("cua-"))) + +;;;*** + +;;;### (autoloads nil "cursor-sensor" "emacs-lisp/cursor-sensor.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/cursor-sensor.el + +(defvar cursor-sensor-inhibit nil) + +(autoload 'cursor-intangible-mode "cursor-sensor" "\ +Keep cursor outside of any `cursor-intangible' text property. + +\(fn &optional ARG)" t nil) + +(autoload 'cursor-sensor-mode "cursor-sensor" "\ +Handle the `cursor-sensor-functions' text property. +This property should hold a list of functions which react to the motion +of the cursor. They're called with three arguments (WINDOW OLDPOS DIR) +where WINDOW is the affected window, OLDPOS is the last known position of +the cursor and DIR can be `entered' or `left' depending on whether the cursor +is entering the area covered by the text-property property or leaving it. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cursor-sensor" '("cursor-sensor-"))) + +;;;*** + +;;;### (autoloads nil "cus-dep" "cus-dep.el" (0 0 0 0)) +;;; Generated autoloads from cus-dep.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cus-dep" '("custom-" "generated-custom-dependencies-file"))) + +;;;*** + +;;;### (autoloads nil "cus-edit" "cus-edit.el" (0 0 0 0)) +;;; Generated autoloads from cus-edit.el + +(defvar custom-browse-sort-alphabetically nil "\ +If non-nil, sort customization group alphabetically in `custom-browse'.") + +(custom-autoload 'custom-browse-sort-alphabetically "cus-edit" t) + +(defvar custom-buffer-sort-alphabetically t "\ +Whether to sort customization groups alphabetically in Custom buffer.") + +(custom-autoload 'custom-buffer-sort-alphabetically "cus-edit" t) + +(defvar custom-menu-sort-alphabetically nil "\ +If non-nil, sort each customization group alphabetically in menus.") + +(custom-autoload 'custom-menu-sort-alphabetically "cus-edit" t) + +(autoload 'customize-set-value "cus-edit" "\ +Set VARIABLE to VALUE, and return VALUE. VALUE is a Lisp object. + +If VARIABLE has a `variable-interactive' property, that is used as if +it were the arg to `interactive' (which see) to interactively read the value. + +If VARIABLE has a `custom-type' property, it must be a widget and the +`:prompt-value' property of that widget will be used for reading the value. + +If given a prefix (or a COMMENT argument), also prompt for a comment. + +\(fn VARIABLE VALUE &optional COMMENT)" t nil) + +(autoload 'customize-set-variable "cus-edit" "\ +Set the default for VARIABLE to VALUE, and return VALUE. +VALUE is a Lisp object. + +If VARIABLE has a `custom-set' property, that is used for setting +VARIABLE, otherwise `set-default' is used. + +If VARIABLE has a `variable-interactive' property, that is used as if +it were the arg to `interactive' (which see) to interactively read the value. + +If VARIABLE has a `custom-type' property, it must be a widget and the +`:prompt-value' property of that widget will be used for reading the value. + +If given a prefix (or a COMMENT argument), also prompt for a comment. + +\(fn VARIABLE VALUE &optional COMMENT)" t nil) + +(autoload 'customize-save-variable "cus-edit" "\ +Set the default for VARIABLE to VALUE, and save it for future sessions. +Return VALUE. + +If VARIABLE has a `custom-set' property, that is used for setting +VARIABLE, otherwise `set-default' is used. + +If VARIABLE has a `variable-interactive' property, that is used as if +it were the arg to `interactive' (which see) to interactively read the value. + +If VARIABLE has a `custom-type' property, it must be a widget and the +`:prompt-value' property of that widget will be used for reading the value. + +If given a prefix (or a COMMENT argument), also prompt for a comment. + +\(fn VARIABLE VALUE &optional COMMENT)" t nil) + +(autoload 'customize-push-and-save "cus-edit" "\ +Add ELTS to LIST-VAR and save for future sessions, safely. +ELTS should be a list. This function adds each entry to the +value of LIST-VAR using `add-to-list'. + +If Emacs is initialized, call `customize-save-variable' to save +the resulting list value now. Otherwise, add an entry to +`after-init-hook' to save it after initialization. + +\(fn LIST-VAR ELTS)" nil nil) + +(autoload 'customize "cus-edit" "\ +Select a customization buffer which you can use to set user options. +User options are structured into \"groups\". +Initially the top-level group `Emacs' and its immediate subgroups +are shown; the contents of those subgroups are initially hidden. + +\(fn)" t nil) + +(autoload 'customize-mode "cus-edit" "\ +Customize options related to a major or minor mode. +By default the current major mode is used. With a prefix +argument or if the current major mode has no known group, prompt +for the MODE to customize. + +\(fn MODE)" t nil) + +(autoload 'customize-group "cus-edit" "\ +Customize GROUP, which must be a customization group. +If OTHER-WINDOW is non-nil, display in another window. + +\(fn &optional GROUP OTHER-WINDOW)" t nil) + +(autoload 'customize-group-other-window "cus-edit" "\ +Customize GROUP, which must be a customization group, in another window. + +\(fn &optional GROUP)" t nil) + +(defalias 'customize-variable 'customize-option) + +(autoload 'customize-option "cus-edit" "\ +Customize SYMBOL, which must be a user option. + +\(fn SYMBOL)" t nil) + +(defalias 'customize-variable-other-window 'customize-option-other-window) + +(autoload 'customize-option-other-window "cus-edit" "\ +Customize SYMBOL, which must be a user option. +Show the buffer in another window, but don't select it. + +\(fn SYMBOL)" t nil) + +(defvar customize-package-emacs-version-alist nil "\ +Alist mapping versions of a package to Emacs versions. +We use this for packages that have their own names, but are released +as part of Emacs itself. + +Each elements looks like this: + + (PACKAGE (PVERSION . EVERSION)...) + +Here PACKAGE is the name of a package, as a symbol. After +PACKAGE come one or more elements, each associating a +package version PVERSION with the first Emacs version +EVERSION in which it (or a subsequent version of PACKAGE) +was first released. Both PVERSION and EVERSION are strings. +PVERSION should be a string that this package used in +the :package-version keyword for `defcustom', `defgroup', +and `defface'. + +For example, the MH-E package updates this alist as follows: + + (add-to-list \\='customize-package-emacs-version-alist + \\='(MH-E (\"6.0\" . \"22.1\") (\"6.1\" . \"22.1\") + (\"7.0\" . \"22.1\") (\"7.1\" . \"22.1\") + (\"7.2\" . \"22.1\") (\"7.3\" . \"22.1\") + (\"7.4\" . \"22.1\") (\"8.0\" . \"22.1\"))) + +The value of PACKAGE needs to be unique and it needs to match the +PACKAGE value appearing in the :package-version keyword. Since +the user might see the value in a error message, a good choice is +the official name of the package, such as MH-E or Gnus.") + +(defalias 'customize-changed 'customize-changed-options) + +(autoload 'customize-changed-options "cus-edit" "\ +Customize all settings whose meanings have changed in Emacs itself. +This includes new user options and faces, and new customization +groups, as well as older options and faces whose meanings or +default values have changed since the previous major Emacs +release. + +With argument SINCE-VERSION (a string), customize all settings +that were added or redefined since that version. + +\(fn &optional SINCE-VERSION)" t nil) + +(autoload 'customize-face "cus-edit" "\ +Customize FACE, which should be a face name or nil. +If FACE is nil, customize all faces. If FACE is actually a +face-alias, customize the face it is aliased to. + +If OTHER-WINDOW is non-nil, display in another window. + +Interactively, when point is on text which has a face specified, +suggest to customize that face, if it's customizable. + +\(fn &optional FACE OTHER-WINDOW)" t nil) + +(autoload 'customize-face-other-window "cus-edit" "\ +Show customization buffer for face FACE in other window. +If FACE is actually a face-alias, customize the face it is aliased to. + +Interactively, when point is on text which has a face specified, +suggest to customize that face, if it's customizable. + +\(fn &optional FACE)" t nil) + +(autoload 'customize-unsaved "cus-edit" "\ +Customize all options and faces set in this session but not saved. + +\(fn)" t nil) + +(autoload 'customize-rogue "cus-edit" "\ +Customize all user variables modified outside customize. + +\(fn)" t nil) + +(autoload 'customize-saved "cus-edit" "\ +Customize all saved options and faces. + +\(fn)" t nil) + +(autoload 'customize-apropos "cus-edit" "\ +Customize loaded options, faces and groups matching PATTERN. +PATTERN can be a word, a list of words (separated by spaces), +or a regexp (using some regexp special characters). If it is a word, +search for matches for that word as a substring. If it is a list of +words, search for matches for any two (or more) of those words. + +If TYPE is `options', include only options. +If TYPE is `faces', include only faces. +If TYPE is `groups', include only groups. + +\(fn PATTERN &optional TYPE)" t nil) + +(autoload 'customize-apropos-options "cus-edit" "\ +Customize all loaded customizable options matching REGEXP. + +\(fn REGEXP &optional IGNORED)" t nil) + +(autoload 'customize-apropos-faces "cus-edit" "\ +Customize all loaded faces matching REGEXP. + +\(fn REGEXP)" t nil) + +(autoload 'customize-apropos-groups "cus-edit" "\ +Customize all loaded groups matching REGEXP. + +\(fn REGEXP)" t nil) + +(autoload 'custom-prompt-customize-unsaved-options "cus-edit" "\ +Prompt user to customize any unsaved customization options. +Return non-nil if user chooses to customize, for use in +`kill-emacs-query-functions'. + +\(fn)" nil nil) + +(autoload 'custom-buffer-create "cus-edit" "\ +Create a buffer containing OPTIONS. +Optional NAME is the name of the buffer. +OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where +SYMBOL is a customization option, and WIDGET is a widget for editing +that option. +DESCRIPTION is unused. + +\(fn OPTIONS &optional NAME DESCRIPTION)" nil nil) + +(autoload 'custom-buffer-create-other-window "cus-edit" "\ +Create a buffer containing OPTIONS, and display it in another window. +The result includes selecting that window. +Optional NAME is the name of the buffer. +OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where +SYMBOL is a customization option, and WIDGET is a widget for editing +that option. +DESCRIPTION is unused. + +\(fn OPTIONS &optional NAME DESCRIPTION)" nil nil) + +(autoload 'customize-browse "cus-edit" "\ +Create a tree browser for the customize hierarchy. + +\(fn &optional GROUP)" t nil) + +(defvar custom-file nil "\ +File used for storing customization information. +The default is nil, which means to use your init file +as specified by `user-init-file'. If the value is not nil, +it should be an absolute file name. + +You can set this option through Custom, if you carefully read the +last paragraph below. However, usually it is simpler to write +something like the following in your init file: + +\(setq custom-file \"~/.emacs-custom.el\") +\(load custom-file) + +Note that both lines are necessary: the first line tells Custom to +save all customizations in this file, but does not load it. + +When you change this variable outside Custom, look in the +previous custom file (usually your init file) for the +forms `(custom-set-variables ...)' and `(custom-set-faces ...)', +and copy them (whichever ones you find) to the new custom file. +This will preserve your existing customizations. + +If you save this option using Custom, Custom will write all +currently saved customizations, including the new one for this +option itself, into the file you specify, overwriting any +`custom-set-variables' and `custom-set-faces' forms already +present in that file. It will not delete any customizations from +the old custom file. You should do that manually if that is what you +want. You also have to put something like (load \"CUSTOM-FILE\") +in your init file, where CUSTOM-FILE is the actual name of the +file. Otherwise, Emacs will not load the file when it starts up, +and hence will not set `custom-file' to that file either.") + +(custom-autoload 'custom-file "cus-edit" t) + +(autoload 'custom-save-all "cus-edit" "\ +Save all customizations in `custom-file'. + +\(fn)" nil nil) + +(autoload 'customize-save-customized "cus-edit" "\ +Save all user options which have been set in this session. + +\(fn)" t nil) + +(autoload 'custom-menu-create "cus-edit" "\ +Create menu for customization group SYMBOL. +The menu is in a format applicable to `easy-menu-define'. + +\(fn SYMBOL)" nil nil) + +(autoload 'customize-menu-create "cus-edit" "\ +Return a customize menu for customization group SYMBOL. +If optional NAME is given, use that as the name of the menu. +Otherwise the menu will be named `Customize'. +The format is suitable for use with `easy-menu-define'. + +\(fn SYMBOL &optional NAME)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cus-edit" '("Custom-" "custom" "widget-"))) + +;;;*** + +;;;### (autoloads nil "cus-theme" "cus-theme.el" (0 0 0 0)) +;;; Generated autoloads from cus-theme.el + +(autoload 'customize-create-theme "cus-theme" "\ +Create or edit a custom theme. +THEME, if non-nil, should be an existing theme to edit. If THEME +is `user', the resulting *Custom Theme* buffer also contains a +checkbox for removing the theme settings specified in the buffer +from the Custom save file. +BUFFER, if non-nil, should be a buffer to use; the default is +named *Custom Theme*. + +\(fn &optional THEME BUFFER)" t nil) + +(autoload 'custom-theme-visit-theme "cus-theme" "\ +Set up a Custom buffer to edit custom theme THEME. + +\(fn THEME)" t nil) + +(autoload 'describe-theme "cus-theme" "\ +Display a description of the Custom theme THEME (a symbol). + +\(fn THEME)" t nil) + +(autoload 'customize-themes "cus-theme" "\ +Display a selectable list of Custom themes. +When called from Lisp, BUFFER should be the buffer to use; if +omitted, a buffer named *Custom Themes* is used. + +\(fn &optional BUFFER)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cus-theme" '("custom-" "describe-theme-1"))) + +;;;*** + +;;;### (autoloads nil "cvs-status" "vc/cvs-status.el" (0 0 0 0)) +;;; Generated autoloads from vc/cvs-status.el + +(autoload 'cvs-status-mode "cvs-status" "\ +Mode used for cvs status output. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cvs-status" '("cvs-"))) + +;;;*** + +;;;### (autoloads nil "cwarn" "progmodes/cwarn.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/cwarn.el +(push (purecopy '(cwarn 1 3 1)) package--builtin-versions) + +(autoload 'cwarn-mode "cwarn" "\ +Minor mode that highlights suspicious C and C++ constructions. + +Suspicious constructs are highlighted using `font-lock-warning-face'. + +Note, in addition to enabling this minor mode, the major mode must +be included in the variable `cwarn-configuration'. By default C and +C++ modes are included. + +With a prefix argument ARG, enable the mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode +if ARG is omitted or nil. + +\(fn &optional ARG)" t nil) + +(define-obsolete-function-alias 'turn-on-cwarn-mode 'cwarn-mode "24.1") + +(defvar global-cwarn-mode nil "\ +Non-nil if Global Cwarn mode is enabled. +See the `global-cwarn-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `global-cwarn-mode'.") + +(custom-autoload 'global-cwarn-mode "cwarn" nil) + +(autoload 'global-cwarn-mode "cwarn" "\ +Toggle Cwarn mode in all buffers. +With prefix ARG, enable Global Cwarn mode if ARG is positive; +otherwise, disable it. If called from Lisp, enable the mode if +ARG is omitted or nil. + +Cwarn mode is enabled in all buffers where +`turn-on-cwarn-mode-if-enabled' would do it. +See `cwarn-mode' for more information on Cwarn mode. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cwarn" '("turn-on-cwarn-mode-if-enabled" "cwarn-"))) + +;;;*** + +;;;### (autoloads nil "cyril-util" "language/cyril-util.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from language/cyril-util.el + +(autoload 'cyrillic-encode-koi8-r-char "cyril-util" "\ +Return KOI8-R external character code of CHAR if appropriate. + +\(fn CHAR)" nil nil) + +(autoload 'cyrillic-encode-alternativnyj-char "cyril-util" "\ +Return ALTERNATIVNYJ external character code of CHAR if appropriate. + +\(fn CHAR)" nil nil) + +(autoload 'standard-display-cyrillic-translit "cyril-util" "\ +Display a cyrillic buffer using a transliteration. +For readability, the table is slightly +different from the one used for the input method `cyrillic-translit'. + +The argument is a string which specifies which language you are using; +that affects the choice of transliterations slightly. +Possible values are listed in `cyrillic-language-alist'. +If the argument is t, we use the default cyrillic transliteration. +If the argument is nil, we return the display table to its standard state. + +\(fn &optional CYRILLIC-LANGUAGE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cyril-util" '("cyrillic-language-alist"))) + +;;;*** + +;;;### (autoloads nil "dabbrev" "dabbrev.el" (0 0 0 0)) +;;; Generated autoloads from dabbrev.el +(put 'dabbrev-case-fold-search 'risky-local-variable t) +(put 'dabbrev-case-replace 'risky-local-variable t) + (define-key esc-map "/" 'dabbrev-expand) + (define-key esc-map [?\C-/] 'dabbrev-completion) + +(autoload 'dabbrev-completion "dabbrev" "\ +Completion on current word. +Like \\[dabbrev-expand] but finds all expansions in the current buffer +and presents suggestions for completion. + +With a prefix argument ARG, it searches all buffers accepted by the +function pointed out by `dabbrev-friend-buffer-function' to find the +completions. + +If the prefix argument is 16 (which comes from \\[universal-argument] \\[universal-argument]), +then it searches *all* buffers. + +\(fn &optional ARG)" t nil) + +(autoload 'dabbrev-expand "dabbrev" "\ +Expand previous word \"dynamically\". + +Expands to the most recent, preceding word for which this is a prefix. +If no suitable preceding word is found, words following point are +considered. If still no suitable word is found, then look in the +buffers accepted by the function pointed out by variable +`dabbrev-friend-buffer-function', if `dabbrev-check-other-buffers' +says so. Then, if `dabbrev-check-all-buffers' is non-nil, look in +all the other buffers, subject to constraints specified +by `dabbrev-ignored-buffer-names' and `dabbrev-ignored-regexps'. + +A positive prefix argument, N, says to take the Nth backward *distinct* +possibility. A negative argument says search forward. + +If the cursor has not moved from the end of the previous expansion and +no argument is given, replace the previously-made expansion +with the next possible expansion not yet tried. + +The variable `dabbrev-backward-only' may be used to limit the +direction of search to backward if set non-nil. + +See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]. + +\(fn ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dabbrev" '("dabbrev-"))) + +;;;*** + +;;;### (autoloads nil "data-debug" "cedet/data-debug.el" (0 0 0 0)) +;;; Generated autoloads from cedet/data-debug.el + +(autoload 'data-debug-new-buffer "data-debug" "\ +Create a new data-debug buffer with NAME. + +\(fn NAME)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "data-debug" '("data-debug-"))) + +;;;*** + +;;;### (autoloads nil "dbus" "net/dbus.el" (0 0 0 0)) +;;; Generated autoloads from net/dbus.el + +(autoload 'dbus-handle-event "dbus" "\ +Handle events from the D-Bus. +EVENT is a D-Bus event, see `dbus-check-event'. HANDLER, being +part of the event, is called with arguments ARGS. +If the HANDLER returns a `dbus-error', it is propagated as return message. + +\(fn EVENT)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dbus" '("dbus-"))) + +;;;*** + +;;;### (autoloads nil "dcl-mode" "progmodes/dcl-mode.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/dcl-mode.el + +(autoload 'dcl-mode "dcl-mode" "\ +Major mode for editing DCL-files. + +This mode indents command lines in blocks. (A block is commands between +THEN-ELSE-ENDIF and between lines matching dcl-block-begin-regexp and +dcl-block-end-regexp.) + +Labels are indented to a fixed position unless they begin or end a block. +Whole-line comments (matching dcl-comment-line-regexp) are not indented. +Data lines are not indented. + +Key bindings: + +\\{dcl-mode-map} +Commands not usually bound to keys: + +\\[dcl-save-nondefault-options] Save changed options +\\[dcl-save-all-options] Save all options +\\[dcl-save-option] Save any option +\\[dcl-save-mode] Save buffer mode + +Variables controlling indentation style and extra features: + + dcl-basic-offset + Extra indentation within blocks. + + dcl-continuation-offset + Extra indentation for continued lines. + + dcl-margin-offset + Indentation for the first command line in a file or SUBROUTINE. + + dcl-margin-label-offset + Indentation for a label. + + dcl-comment-line-regexp + Lines matching this regexp will not be indented. + + dcl-block-begin-regexp + dcl-block-end-regexp + Regexps that match command lines that begin and end, respectively, + a block of command lines that will be given extra indentation. + Command lines between THEN-ELSE-ENDIF are always indented; these variables + make it possible to define other places to indent. + Set to nil to disable this feature. + + dcl-calc-command-indent-function + Can be set to a function that customizes indentation for command lines. + Two such functions are included in the package: + dcl-calc-command-indent-multiple + dcl-calc-command-indent-hang + + dcl-calc-cont-indent-function + Can be set to a function that customizes indentation for continued lines. + One such function is included in the package: + dcl-calc-cont-indent-relative (set by default) + + dcl-tab-always-indent + If t, pressing TAB always indents the current line. + If nil, pressing TAB indents the current line if point is at the left + margin. + + dcl-electric-characters + Non-nil causes lines to be indented at once when a label, ELSE or ENDIF is + typed. + + dcl-electric-reindent-regexps + Use this variable and function dcl-electric-character to customize + which words trigger electric indentation. + + dcl-tempo-comma + dcl-tempo-left-paren + dcl-tempo-right-paren + These variables control the look of expanded templates. + + dcl-imenu-generic-expression + Default value for imenu-generic-expression. The default includes + SUBROUTINE labels in the main listing and sub-listings for + other labels, CALL, GOTO and GOSUB statements. + + dcl-imenu-label-labels + dcl-imenu-label-goto + dcl-imenu-label-gosub + dcl-imenu-label-call + Change the text that is used as sub-listing labels in imenu. + +Loading this package calls the value of the variable +`dcl-mode-load-hook' with no args, if that value is non-nil. +Turning on DCL mode calls the value of the variable `dcl-mode-hook' +with no args, if that value is non-nil. + + +The following example uses the default values for all variables: + +$! This is a comment line that is not indented (it matches +$! dcl-comment-line-regexp) +$! Next follows the first command line. It is indented dcl-margin-offset. +$ i = 1 +$ ! Other comments are indented like command lines. +$ ! A margin label indented dcl-margin-label-offset: +$ label: +$ if i.eq.1 +$ then +$ ! Lines between THEN-ELSE and ELSE-ENDIF are +$ ! indented dcl-basic-offset +$ loop1: ! This matches dcl-block-begin-regexp... +$ ! ...so this line is indented dcl-basic-offset +$ text = \"This \" + - ! is a continued line + \"lined up with the command line\" +$ type sys$input +Data lines are not indented at all. +$ endloop1: ! This matches dcl-block-end-regexp +$ endif +$ + + +There is some minimal font-lock support (see vars +`dcl-font-lock-defaults' and `dcl-font-lock-keywords'). + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dcl-mode" '("dcl-"))) + +;;;*** + +;;;### (autoloads nil "debug" "emacs-lisp/debug.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/debug.el + +(setq debugger 'debug) + +(autoload 'debug "debug" "\ +Enter debugger. \\<debugger-mode-map>`\\[debugger-continue]' returns from the debugger. +Arguments are mainly for use when this is called from the internals +of the evaluator. + +You may call with no args, or you may pass nil as the first arg and +any other args you like. In that case, the list of args after the +first will be printed into the backtrace buffer. + +\(fn &rest ARGS)" t nil) + +(autoload 'debug-on-entry "debug" "\ +Request FUNCTION to invoke debugger each time it is called. + +When called interactively, prompt for FUNCTION in the minibuffer. + +This works by modifying the definition of FUNCTION. If you tell the +debugger to continue, FUNCTION's execution proceeds. If FUNCTION is a +normal function or a macro written in Lisp, you can also step through +its execution. FUNCTION can also be a primitive that is not a special +form, in which case stepping is not possible. Break-on-entry for +primitive functions only works when that function is called from Lisp. + +Use \\[cancel-debug-on-entry] to cancel the effect of this command. +Redefining FUNCTION also cancels it. + +\(fn FUNCTION)" t nil) + +(autoload 'cancel-debug-on-entry "debug" "\ +Undo effect of \\[debug-on-entry] on FUNCTION. +If FUNCTION is nil, cancel debug-on-entry for all functions. +When called interactively, prompt for FUNCTION in the minibuffer. +To specify a nil argument interactively, exit with an empty minibuffer. + +\(fn &optional FUNCTION)" t nil) + +(autoload 'debug-on-variable-change "debug" "\ +Trigger a debugger invocation when VARIABLE is changed. + +When called interactively, prompt for VARIABLE in the minibuffer. + +This works by calling `add-variable-watch' on VARIABLE. If you +quit from the debugger, this will abort the change (unless the +change is caused by the termination of a let-binding). + +The watchpoint may be circumvented by C code that changes the +variable directly (i.e., not via `set'). Changing the value of +the variable (e.g., `setcar' on a list variable) will not trigger +watchpoint. + +Use \\[cancel-debug-on-variable-change] to cancel the effect of +this command. Uninterning VARIABLE or making it an alias of +another symbol also cancels it. + +\(fn VARIABLE)" t nil) + +(defalias 'debug-watch #'debug-on-variable-change) + +(autoload 'cancel-debug-on-variable-change "debug" "\ +Undo effect of \\[debug-on-variable-change] on VARIABLE. +If VARIABLE is nil, cancel debug-on-variable-change for all variables. +When called interactively, prompt for VARIABLE in the minibuffer. +To specify a nil argument interactively, exit with an empty minibuffer. + +\(fn &optional VARIABLE)" t nil) + +(defalias 'cancel-debug-watch #'cancel-debug-on-variable-change) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "debug" '("debug" "inhibit-debug-on-entry"))) + +;;;*** + +;;;### (autoloads nil "decipher" "play/decipher.el" (0 0 0 0)) +;;; Generated autoloads from play/decipher.el + +(autoload 'decipher "decipher" "\ +Format a buffer of ciphertext for cryptanalysis and enter Decipher mode. + +\(fn)" t nil) + +(autoload 'decipher-mode "decipher" "\ +Major mode for decrypting monoalphabetic substitution ciphers. +Lower-case letters enter plaintext. +Upper-case letters are commands. + +The buffer is made read-only so that normal Emacs commands cannot +modify it. + +The most useful commands are: +\\<decipher-mode-map> +\\[decipher-digram-list] Display a list of all digrams & their frequency +\\[decipher-frequency-count] Display the frequency of each ciphertext letter +\\[decipher-adjacency-list] Show adjacency list for current letter (lists letters appearing next to it) +\\[decipher-make-checkpoint] Save the current cipher alphabet (checkpoint) +\\[decipher-restore-checkpoint] Restore a saved cipher alphabet (checkpoint) + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "decipher" '("decipher-"))) + +;;;*** + +;;;### (autoloads nil "delim-col" "delim-col.el" (0 0 0 0)) +;;; Generated autoloads from delim-col.el +(push (purecopy '(delim-col 2 1)) package--builtin-versions) + +(autoload 'delimit-columns-customize "delim-col" "\ +Customization of `columns' group. + +\(fn)" t nil) + +(autoload 'delimit-columns-region "delim-col" "\ +Prettify all columns in a text region. + +START and END delimits the text region. + +\(fn START END)" t nil) + +(autoload 'delimit-columns-rectangle "delim-col" "\ +Prettify all columns in a text rectangle. + +START and END delimits the corners of text rectangle. + +\(fn START END)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "delim-col" '("delimit-columns-"))) + +;;;*** + +;;;### (autoloads nil "delsel" "delsel.el" (0 0 0 0)) +;;; Generated autoloads from delsel.el + +(defalias 'pending-delete-mode 'delete-selection-mode) + +(defvar delete-selection-mode nil "\ +Non-nil if Delete-Selection mode is enabled. +See the `delete-selection-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `delete-selection-mode'.") + +(custom-autoload 'delete-selection-mode "delsel" nil) + +(autoload 'delete-selection-mode "delsel" "\ +Toggle Delete Selection mode. +With a prefix argument ARG, enable Delete Selection mode if ARG +is positive, and disable it otherwise. If called from Lisp, +enable the mode if ARG is omitted or nil. + +When Delete Selection mode is enabled, typed text replaces the selection +if the selection is active. Otherwise, typed text is just inserted at +point regardless of any selection. Also, commands that normally delete +just one character will delete the entire selection instead. + +See `delete-selection-helper' and `delete-selection-pre-hook' for +information on adapting behavior of commands in Delete Selection mode. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "delsel" '("del" "minibuffer-keyboard-quit"))) + +;;;*** + +;;;### (autoloads nil "derived" "emacs-lisp/derived.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/derived.el + +(autoload 'define-derived-mode "derived" "\ +Create a new mode as a variant of an existing mode. + +The arguments to this command are as follow: + +CHILD: the name of the command for the derived mode. +PARENT: the name of the command for the parent mode (e.g. `text-mode') + or nil if there is no parent. +NAME: a string which will appear in the status line (e.g. \"Hypertext\") +DOCSTRING: an optional documentation string--if you do not supply one, + the function will attempt to invent something useful. +BODY: forms to execute just before running the + hooks for the new mode. Do not use `interactive' here. + +BODY can start with a bunch of keyword arguments. The following keyword + arguments are currently understood: +:group GROUP + Declare the customization group that corresponds to this mode. + The command `customize-mode' uses this. +:syntax-table TABLE + Use TABLE instead of the default (CHILD-syntax-table). + A nil value means to simply use the same syntax-table as the parent. +:abbrev-table TABLE + Use TABLE instead of the default (CHILD-abbrev-table). + A nil value means to simply use the same abbrev-table as the parent. +:after-hook FORM + A single lisp form which is evaluated after the mode hooks have been + run. It should not be quoted. + +Here is how you could define LaTeX-Thesis mode as a variant of LaTeX mode: + + (define-derived-mode LaTeX-thesis-mode LaTeX-mode \"LaTeX-Thesis\") + +You could then make new key bindings for `LaTeX-thesis-mode-map' +without changing regular LaTeX mode. In this example, BODY is empty, +and DOCSTRING is generated by default. + +On a more complicated level, the following command uses `sgml-mode' as +the parent, and then sets the variable `case-fold-search' to nil: + + (define-derived-mode article-mode sgml-mode \"Article\" + \"Major mode for editing technical articles.\" + (setq case-fold-search nil)) + +Note that if the documentation string had been left out, it would have +been generated automatically, with a reference to the keymap. + +The new mode runs the hook constructed by the function +`derived-mode-hook-name'. + +See Info node `(elisp)Derived Modes' for more details. + +\(fn CHILD PARENT NAME &optional DOCSTRING &rest BODY)" nil t) + +(function-put 'define-derived-mode 'doc-string-elt '4) + +(autoload 'derived-mode-init-mode-variables "derived" "\ +Initialize variables for a new MODE. +Right now, if they don't already exist, set up a blank keymap, an +empty syntax table, and an empty abbrev table -- these will be merged +the first time the mode is used. + +\(fn MODE)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "derived" '("derived-mode-"))) + +;;;*** + +;;;### (autoloads nil "descr-text" "descr-text.el" (0 0 0 0)) +;;; Generated autoloads from descr-text.el + +(autoload 'describe-text-properties "descr-text" "\ +Describe widgets, buttons, overlays, and text properties at POS. +POS is taken to be in BUFFER or in current buffer if nil. +Interactively, describe them for the character after point. +If optional second argument OUTPUT-BUFFER is non-nil, +insert the output into that buffer, and don't initialize or clear it +otherwise. + +\(fn POS &optional OUTPUT-BUFFER BUFFER)" t nil) + +(autoload 'describe-char "descr-text" "\ +Describe position POS (interactively, point) and the char after POS. +POS is taken to be in BUFFER, or the current buffer if BUFFER is nil. +The information is displayed in buffer `*Help*'. + +The position information includes POS; the total size of BUFFER; the +region limits, if narrowed; the column number; and the horizontal +scroll amount, if the buffer is horizontally scrolled. + +The character information includes the character code; charset and +code points in it; syntax; category; how the character is encoded in +BUFFER and in BUFFER's file; character composition information (if +relevant); the font and font glyphs used to display the character; +the character's canonical name and other properties defined by the +Unicode Data Base; and widgets, buttons, overlays, and text properties +relevant to POS. + +\(fn POS &optional BUFFER)" t nil) + +(autoload 'describe-char-eldoc "descr-text" "\ +Return a description of character at point for use by ElDoc mode. + +Return nil if character at point is a printable ASCII +character (i.e. codepoint between 32 and 127 inclusively). +Otherwise return a description formatted by +`describe-char-eldoc--format' function taking into account value +of `eldoc-echo-area-use-multiline-p' variable and width of +minibuffer window for width limit. + +This function is meant to be used as a value of +`eldoc-documentation-function' variable. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "descr-text" '("describe-"))) + +;;;*** + +;;;### (autoloads nil "desktop" "desktop.el" (0 0 0 0)) +;;; Generated autoloads from desktop.el + +(defvar desktop-save-mode nil "\ +Non-nil if Desktop-Save mode is enabled. +See the `desktop-save-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `desktop-save-mode'.") + +(custom-autoload 'desktop-save-mode "desktop" nil) + +(autoload 'desktop-save-mode "desktop" "\ +Toggle desktop saving (Desktop Save mode). +With a prefix argument ARG, enable Desktop Save mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode if ARG +is omitted or nil. + +When Desktop Save mode is enabled, the state of Emacs is saved from +one session to another. In particular, Emacs will save the desktop when +it exits (this may prompt you; see the option `desktop-save'). The next +time Emacs starts, if this mode is active it will restore the desktop. + +To manually save the desktop at any time, use the command `\\[desktop-save]'. +To load it, use `\\[desktop-read]'. + +Once a desktop file exists, Emacs will auto-save it according to the +option `desktop-auto-save-timeout'. + +To see all the options you can set, browse the `desktop' customization group. + +For further details, see info node `(emacs)Saving Emacs Sessions'. + +\(fn &optional ARG)" t nil) + +(defvar desktop-locals-to-save '(desktop-locals-to-save truncate-lines case-fold-search case-replace fill-column overwrite-mode change-log-default-name line-number-mode column-number-mode size-indication-mode buffer-file-coding-system buffer-display-time indent-tabs-mode tab-width indicate-buffer-boundaries indicate-empty-lines show-trailing-whitespace) "\ +List of local variables to save for each buffer. +The variables are saved only when they really are local. Conventional minor +modes are restored automatically; they should not be listed here.") + +(custom-autoload 'desktop-locals-to-save "desktop" t) + +(defvar-local desktop-save-buffer nil "\ +When non-nil, save buffer status in desktop file. + +If the value is a function, it is called by `desktop-save' with argument +DESKTOP-DIRNAME to obtain auxiliary information to save in the desktop +file along with the state of the buffer for which it was called. + +When file names are returned, they should be formatted using the call +\"(desktop-file-name FILE-NAME DESKTOP-DIRNAME)\". + +Later, when `desktop-read' evaluates the desktop file, auxiliary information +is passed as the argument DESKTOP-BUFFER-MISC to functions in +`desktop-buffer-mode-handlers'.") + +(defvar desktop-buffer-mode-handlers nil "\ +Alist of major mode specific functions to restore a desktop buffer. +Functions listed are called by `desktop-create-buffer' when `desktop-read' +evaluates the desktop file. List elements must have the form + + (MAJOR-MODE . RESTORE-BUFFER-FUNCTION). + +Buffers with a major mode not specified here, are restored by the default +handler `desktop-restore-file-buffer'. + +Handlers are called with argument list + + (DESKTOP-BUFFER-FILE-NAME DESKTOP-BUFFER-NAME DESKTOP-BUFFER-MISC) + +Furthermore, they may use the following variables: + + `desktop-file-version' + `desktop-buffer-major-mode' + `desktop-buffer-minor-modes' + `desktop-buffer-point' + `desktop-buffer-mark' + `desktop-buffer-read-only' + `desktop-buffer-locals' + +If a handler returns a buffer, then the saved mode settings +and variable values for that buffer are copied into it. + +Modules that define a major mode that needs a special handler should contain +code like + + (defun foo-restore-desktop-buffer + ... + (add-to-list \\='desktop-buffer-mode-handlers + \\='(foo-mode . foo-restore-desktop-buffer)) + +The major mode function must either be autoloaded, or of the form +\"foobar-mode\" and defined in library \"foobar\", so that desktop +can guess how to load the mode's definition.") + +(put 'desktop-buffer-mode-handlers 'risky-local-variable t) + +(defvar desktop-minor-mode-handlers nil "\ +Alist of functions to restore non-standard minor modes. +Functions are called by `desktop-create-buffer' to restore minor modes. +List elements must have the form + + (MINOR-MODE . RESTORE-FUNCTION). + +Minor modes not specified here, are restored by the standard minor mode +function. + +Handlers are called with argument list + + (DESKTOP-BUFFER-LOCALS) + +Furthermore, they may use the following variables: + + `desktop-file-version' + `desktop-buffer-file-name' + `desktop-buffer-name' + `desktop-buffer-major-mode' + `desktop-buffer-minor-modes' + `desktop-buffer-point' + `desktop-buffer-mark' + `desktop-buffer-read-only' + `desktop-buffer-misc' + +When a handler is called, the buffer has been created and the major mode has +been set, but local variables listed in desktop-buffer-locals has not yet been +created and set. + +Modules that define a minor mode that needs a special handler should contain +code like + + (defun foo-desktop-restore + ... + (add-to-list \\='desktop-minor-mode-handlers + \\='(foo-mode . foo-desktop-restore)) + +The minor mode function must either be autoloaded, or of the form +\"foobar-mode\" and defined in library \"foobar\", so that desktop +can guess how to load the mode's definition. + +See also `desktop-minor-mode-table'.") + +(put 'desktop-minor-mode-handlers 'risky-local-variable t) + +(autoload 'desktop-clear "desktop" "\ +Empty the Desktop. +This kills all buffers except for internal ones and those with names matched by +a regular expression in the list `desktop-clear-preserve-buffers'. +Furthermore, it clears the variables listed in `desktop-globals-to-clear'. +When called interactively and `desktop-restore-frames' is non-nil, it also +deletes all frames except the selected one (and its minibuffer frame, +if different). + +\(fn)" t nil) + +(autoload 'desktop-save "desktop" "\ +Save the desktop in a desktop file. +Parameter DIRNAME specifies where to save the desktop file. +Optional parameter RELEASE says whether we're done with this +desktop. If ONLY-IF-CHANGED is non-nil, compare the current +desktop information to that in the desktop file, and if the +desktop information has not changed since it was last saved then +do not rewrite the file. + +This function can save the desktop in either format version +208 (which only Emacs 25.1 and later can read) or version +206 (which is readable by any Emacs from version 22.1 onwards). +By default, it will use the same format the desktop file had when +it was last saved, or version 208 when writing a fresh desktop +file. + +To upgrade a version 206 file to version 208, call this command +explicitly with a bare prefix argument: C-u M-x desktop-save. +You are recommended to do this once you have firmly upgraded to +Emacs 25.1 (or later). To downgrade a version 208 file to version +206, use a double command prefix: C-u C-u M-x desktop-save. +Confirmation will be requested in either case. In a non-interactive +call, VERSION can be given as an integer, either 206 or 208, which +will be accepted as the format version in which to save the file +without further confirmation. + +\(fn DIRNAME &optional RELEASE ONLY-IF-CHANGED VERSION)" t nil) + +(autoload 'desktop-remove "desktop" "\ +Delete desktop file in `desktop-dirname'. +This function also sets `desktop-dirname' to nil. + +\(fn)" t nil) + +(autoload 'desktop-read "desktop" "\ +Read and process the desktop file in directory DIRNAME. +Look for a desktop file in DIRNAME, or if DIRNAME is omitted, look in +directories listed in `desktop-path'. If a desktop file is found, it +is processed and `desktop-after-read-hook' is run. If no desktop file +is found, clear the desktop and run `desktop-no-desktop-file-hook'. +This function is a no-op when Emacs is running in batch mode. +It returns t if a desktop file was loaded, nil otherwise. + +\(fn &optional DIRNAME)" t nil) + +(autoload 'desktop-load-default "desktop" "\ +Load the `default' start-up library manually. +Also inhibit further loading of it. + +\(fn)" nil nil) + +(make-obsolete 'desktop-load-default 'desktop-save-mode '"22.1") + +(autoload 'desktop-change-dir "desktop" "\ +Change to desktop saved in DIRNAME. +Kill the desktop as specified by variables `desktop-save-mode' and +`desktop-save', then clear the desktop and load the desktop file in +directory DIRNAME. + +\(fn DIRNAME)" t nil) + +(autoload 'desktop-save-in-desktop-dir "desktop" "\ +Save the desktop in directory `desktop-dirname'. + +\(fn)" t nil) + +(autoload 'desktop-revert "desktop" "\ +Revert to the last loaded desktop. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "desktop" '("desktop-"))) + +;;;*** + +;;;### (autoloads nil "deuglify" "gnus/deuglify.el" (0 0 0 0)) +;;; Generated autoloads from gnus/deuglify.el + +(autoload 'gnus-article-outlook-unwrap-lines "deuglify" "\ +Unwrap lines that appear to be wrapped citation lines. +You can control what lines will be unwrapped by frobbing +`gnus-outlook-deuglify-unwrap-min' and `gnus-outlook-deuglify-unwrap-max', +indicating the minimum and maximum length of an unwrapped citation line. If +NODISPLAY is non-nil, don't redisplay the article buffer. + +\(fn &optional NODISPLAY)" t nil) + +(autoload 'gnus-article-outlook-repair-attribution "deuglify" "\ +Repair a broken attribution line. +If NODISPLAY is non-nil, don't redisplay the article buffer. + +\(fn &optional NODISPLAY)" t nil) + +(autoload 'gnus-outlook-deuglify-article "deuglify" "\ +Full deuglify of broken Outlook (Express) articles. +Treat dumbquotes, unwrap lines, repair attribution and rearrange citation. If +NODISPLAY is non-nil, don't redisplay the article buffer. + +\(fn &optional NODISPLAY)" t nil) + +(autoload 'gnus-article-outlook-deuglify-article "deuglify" "\ +Deuglify broken Outlook (Express) articles and redisplay. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "deuglify" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "dframe" "dframe.el" (0 0 0 0)) +;;; Generated autoloads from dframe.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dframe" '("dframe-"))) + +;;;*** + +;;;### (autoloads nil "diary-lib" "calendar/diary-lib.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from calendar/diary-lib.el + +(autoload 'diary "diary-lib" "\ +Generate the diary window for ARG days starting with the current date. +If no argument is provided, the number of days of diary entries is governed +by the variable `diary-number-of-entries'. A value of ARG less than 1 +does nothing. This function is suitable for execution in an init file. + +\(fn &optional ARG)" t nil) + +(autoload 'diary-mail-entries "diary-lib" "\ +Send a mail message showing diary entries for next NDAYS days. +If no prefix argument is given, NDAYS is set to `diary-mail-days'. +Mail is sent to the address specified by `diary-mail-addr'. + +Here is an example of a script to call `diary-mail-entries', +suitable for regular scheduling using cron (or at). Note that +since `emacs -script' does not load your init file, you should +ensure that all relevant variables are set. + +#!/usr/bin/emacs -script +;; diary-rem.el - run the Emacs diary-reminder + +\(setq diary-mail-days 3 + diary-file \"/path/to/diary.file\" + calendar-date-style \\='european + diary-mail-addr \"user@host.name\") + +\(diary-mail-entries) + +# diary-rem.el ends here + +\(fn &optional NDAYS)" t nil) + +(autoload 'diary-mode "diary-lib" "\ +Major mode for editing the diary file. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "diary-lib" '("diary-" "calendar-mark-"))) + +;;;*** + +;;;### (autoloads nil "diff" "vc/diff.el" (0 0 0 0)) +;;; Generated autoloads from vc/diff.el + +(defvar diff-switches (purecopy "-u") "\ +A string or list of strings specifying switches to be passed to diff.") + +(custom-autoload 'diff-switches "diff" t) + +(defvar diff-command (purecopy "diff") "\ +The command to use to run diff.") + +(custom-autoload 'diff-command "diff" t) + +(autoload 'diff "diff" "\ +Find and display the differences between OLD and NEW files. +When called interactively, read NEW, then OLD, using the +minibuffer. The default for NEW is the current buffer's file +name, and the default for OLD is a backup file for NEW, if one +exists. If NO-ASYNC is non-nil, call diff synchronously. + +When called interactively with a prefix argument, prompt +interactively for diff switches. Otherwise, the switches +specified in the variable `diff-switches' are passed to the diff command. + +\(fn OLD NEW &optional SWITCHES NO-ASYNC)" t nil) + +(autoload 'diff-backup "diff" "\ +Diff this file with its backup file or vice versa. +Uses the latest backup, if there are several numerical backups. +If this file is a backup, diff it with its original. +The backup file is the first file given to `diff'. +With prefix arg, prompt for diff switches. + +\(fn FILE &optional SWITCHES)" t nil) + +(autoload 'diff-latest-backup-file "diff" "\ +Return the latest existing backup of FILE, or nil. + +\(fn FN)" nil nil) + +(autoload 'diff-buffer-with-file "diff" "\ +View the differences between BUFFER and its associated file. +This requires the external program `diff' to be in your `exec-path'. + +\(fn &optional BUFFER)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "diff" '("diff-"))) + +;;;*** + +;;;### (autoloads nil "diff-mode" "vc/diff-mode.el" (0 0 0 0)) +;;; Generated autoloads from vc/diff-mode.el + +(autoload 'diff-mode "diff-mode" "\ +Major mode for viewing/editing context diffs. +Supports unified and context diffs as well as (to a lesser extent) +normal diffs. + +When the buffer is read-only, the ESC prefix is not necessary. +If you edit the buffer manually, diff-mode will try to update the hunk +headers for you on-the-fly. + +You can also switch between context diff and unified diff with \\[diff-context->unified], +or vice versa with \\[diff-unified->context] and you can also reverse the direction of +a diff with \\[diff-reverse-direction]. + + \\{diff-mode-map} + +\(fn)" t nil) + +(autoload 'diff-minor-mode "diff-mode" "\ +Toggle Diff minor mode. +With a prefix argument ARG, enable Diff minor mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +\\{diff-minor-mode-map} + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "diff-mode" '("diff-"))) + +;;;*** + +;;;### (autoloads nil "dig" "net/dig.el" (0 0 0 0)) +;;; Generated autoloads from net/dig.el + +(autoload 'dig "dig" "\ +Query addresses of a DOMAIN using dig, by calling `dig-invoke'. +Optional arguments are passed to `dig-invoke'. + +\(fn DOMAIN &optional QUERY-TYPE QUERY-CLASS QUERY-OPTION DIG-OPTION SERVER)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dig" '("query-dig" "dig-"))) + +;;;*** + +;;;### (autoloads nil "dired" "dired.el" (0 0 0 0)) +;;; Generated autoloads from dired.el + +(defvar dired-listing-switches (purecopy "-al") "\ +Switches passed to `ls' for Dired. MUST contain the `l' option. +May contain all other options that don't contradict `-l'; +may contain even `F', `b', `i' and `s'. See also the variable +`dired-ls-F-marks-symlinks' concerning the `F' switch. +Options that include embedded whitespace must be quoted +like this: \\\"--option=value with spaces\\\"; you can use +`combine-and-quote-strings' to produce the correct quoting of +each option. +On systems such as MS-DOS and MS-Windows, which use `ls' emulation in Lisp, +some of the `ls' switches are not supported; see the doc string of +`insert-directory' in `ls-lisp.el' for more details.") + +(custom-autoload 'dired-listing-switches "dired" t) + +(defvar dired-directory nil "\ +The directory name or wildcard spec that this Dired directory lists. +Local to each Dired buffer. May be a list, in which case the car is the +directory name and the cdr is the list of files to mention. +The directory name must be absolute, but need not be fully expanded.") + (define-key ctl-x-map "d" 'dired) + +(autoload 'dired "dired" "\ +\"Edit\" directory DIRNAME--delete, rename, print, etc. some files in it. +Optional second argument SWITCHES specifies the `ls' options used. +\(Interactively, use a prefix argument to be able to specify SWITCHES.) + +If DIRNAME is a string, Dired displays a list of files in DIRNAME (which +may also have shell wildcards appended to select certain files). + +If DIRNAME is a cons, its first element is taken as the directory name +and the rest as an explicit list of files to make directory entries for. +In this case, SWITCHES are applied to each of the files separately, and +therefore switches that control the order of the files in the produced +listing have no effect. + +\\<dired-mode-map>You can flag files for deletion with \\[dired-flag-file-deletion] and then +delete them by typing \\[dired-do-flagged-delete]. +Type \\[describe-mode] after entering Dired for more info. + +If DIRNAME is already in a Dired buffer, that buffer is used without refresh. + +\(fn DIRNAME &optional SWITCHES)" t nil) + (define-key ctl-x-4-map "d" 'dired-other-window) + +(autoload 'dired-other-window "dired" "\ +\"Edit\" directory DIRNAME. Like `dired' but selects in another window. + +\(fn DIRNAME &optional SWITCHES)" t nil) + (define-key ctl-x-5-map "d" 'dired-other-frame) + +(autoload 'dired-other-frame "dired" "\ +\"Edit\" directory DIRNAME. Like `dired' but makes a new frame. + +\(fn DIRNAME &optional SWITCHES)" t nil) + +(autoload 'dired-noselect "dired" "\ +Like `dired' but returns the Dired buffer as value, does not select it. + +\(fn DIR-OR-LIST &optional SWITCHES)" nil nil) + +(autoload 'dired-mode "dired" "\ +Mode for \"editing\" directory listings. +In Dired, you are \"editing\" a list of the files in a directory and + (optionally) its subdirectories, in the format of `ls -lR'. + Each directory is a page: use \\[backward-page] and \\[forward-page] to move pagewise. +\"Editing\" means that you can run shell commands on files, visit, + compress, load or byte-compile them, change their file attributes + and insert subdirectories into the same buffer. You can \"mark\" + files for later commands or \"flag\" them for deletion, either file + by file or all files matching certain criteria. +You can move using the usual cursor motion commands.\\<dired-mode-map> +The buffer is read-only. Digits are prefix arguments. +Type \\[dired-flag-file-deletion] to flag a file `D' for deletion. +Type \\[dired-mark] to Mark a file or subdirectory for later commands. + Most commands operate on the marked files and use the current file + if no files are marked. Use a numeric prefix argument to operate on + the next ARG (or previous -ARG if ARG<0) files, or just `1' + to operate on the current file only. Prefix arguments override marks. + Mark-using commands display a list of failures afterwards. Type \\[dired-summary] + to see why something went wrong. +Type \\[dired-unmark] to Unmark a file or all files of an inserted subdirectory. +Type \\[dired-unmark-backward] to back up one line and unmark or unflag. +Type \\[dired-do-flagged-delete] to delete (eXpunge) the files flagged `D'. +Type \\[dired-find-file] to Find the current line's file + (or dired it in another buffer, if it is a directory). +Type \\[dired-find-file-other-window] to find file or Dired directory in Other window. +Type \\[dired-maybe-insert-subdir] to Insert a subdirectory in this buffer. +Type \\[dired-do-rename] to Rename a file or move the marked files to another directory. +Type \\[dired-do-copy] to Copy files. +Type \\[dired-sort-toggle-or-edit] to toggle Sorting by name/date or change the `ls' switches. +Type \\[revert-buffer] to read all currently expanded directories aGain. + This retains all marks and hides subdirs again that were hidden before. +Use `SPC' and `DEL' to move down and up by lines. + +If Dired ever gets confused, you can either type \\[revert-buffer] to read the +directories again, type \\[dired-do-redisplay] to relist the file at point or the marked files or a +subdirectory, or type \\[dired-build-subdir-alist] to parse the buffer +again for the directory tree. + +Customization variables (rename this buffer and type \\[describe-variable] on each line +for more info): + + `dired-listing-switches' + `dired-trivial-filenames' + `dired-marker-char' + `dired-del-marker' + `dired-keep-marker-rename' + `dired-keep-marker-copy' + `dired-keep-marker-hardlink' + `dired-keep-marker-symlink' + +Hooks (use \\[describe-variable] to see their documentation): + + `dired-before-readin-hook' + `dired-after-readin-hook' + `dired-mode-hook' + `dired-load-hook' + +Keybindings: +\\{dired-mode-map} + +\(fn &optional DIRNAME SWITCHES)" nil nil) + (put 'dired-find-alternate-file 'disabled t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dired" '("dired-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "dired-aux" "dired-aux.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from dired-aux.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dired-aux" '("dired-" "minibuffer-default-add-dired-shell-commands"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "dired-x" "dired-x.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from dired-x.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dired-x" '("dired-" "virtual-dired"))) + +;;;*** + +;;;### (autoloads nil "dirtrack" "dirtrack.el" (0 0 0 0)) +;;; Generated autoloads from dirtrack.el + +(autoload 'dirtrack-mode "dirtrack" "\ +Toggle directory tracking in shell buffers (Dirtrack mode). +With a prefix argument ARG, enable Dirtrack mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +This method requires that your shell prompt contain the current +working directory at all times, and that you set the variable +`dirtrack-list' to match the prompt. + +This is an alternative to `shell-dirtrack-mode', which works by +tracking `cd' and similar commands which change the shell working +directory. + +\(fn &optional ARG)" t nil) + +(autoload 'dirtrack "dirtrack" "\ +Determine the current directory from the process output for a prompt. +This filter function is used by `dirtrack-mode'. It looks for +the prompt specified by `dirtrack-list', and calls +`shell-process-cd' if the directory seems to have changed away +from `default-directory'. + +\(fn INPUT)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dirtrack" '("dirtrack-"))) + +;;;*** + +;;;### (autoloads nil "disass" "emacs-lisp/disass.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/disass.el + +(autoload 'disassemble "disass" "\ +Print disassembled code for OBJECT in (optional) BUFFER. +OBJECT can be a symbol defined as a function, or a function itself +\(a lambda expression or a compiled-function object). +If OBJECT is not already compiled, we compile it, but do not +redefine OBJECT if it is a symbol. + +\(fn OBJECT &optional BUFFER INDENT INTERACTIVE-P)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "disass" '("disassemble-"))) + +;;;*** + +;;;### (autoloads nil "disp-table" "disp-table.el" (0 0 0 0)) +;;; Generated autoloads from disp-table.el + +(autoload 'make-display-table "disp-table" "\ +Return a new, empty display table. + +\(fn)" nil nil) + +(autoload 'display-table-slot "disp-table" "\ +Return the value of the extra slot in DISPLAY-TABLE named SLOT. +SLOT may be a number from 0 to 5 inclusive, or a slot name (symbol). +Valid symbols are `truncation', `wrap', `escape', `control', +`selective-display', and `vertical-border'. + +\(fn DISPLAY-TABLE SLOT)" nil nil) + +(autoload 'set-display-table-slot "disp-table" "\ +Set the value of the extra slot in DISPLAY-TABLE named SLOT to VALUE. +SLOT may be a number from 0 to 5 inclusive, or a name (symbol). +Valid symbols are `truncation', `wrap', `escape', `control', +`selective-display', and `vertical-border'. + +\(fn DISPLAY-TABLE SLOT VALUE)" nil nil) + +(autoload 'describe-display-table "disp-table" "\ +Describe the display table DT in a help buffer. + +\(fn DT)" nil nil) + +(autoload 'describe-current-display-table "disp-table" "\ +Describe the display table in use in the selected window and buffer. + +\(fn)" t nil) + +(autoload 'standard-display-8bit "disp-table" "\ +Display characters representing raw bytes in the range L to H literally. + +On a terminal display, each character in the range is displayed +by sending the corresponding byte directly to the terminal. + +On a graphic display, each character in the range is displayed +using the default font by a glyph whose code is the corresponding +byte. + +Note that ASCII printable characters (SPC to TILDA) are displayed +in the default way after this call. + +\(fn L H)" nil nil) + +(autoload 'standard-display-default "disp-table" "\ +Display characters in the range L to H using the default notation. + +\(fn L H)" nil nil) + +(autoload 'standard-display-ascii "disp-table" "\ +Display character C using printable string S. + +\(fn C S)" nil nil) + +(autoload 'standard-display-g1 "disp-table" "\ +Display character C as character SC in the g1 character set. +This function assumes that your terminal uses the SO/SI characters; +it is meaningless for an X frame. + +\(fn C SC)" nil nil) + +(autoload 'standard-display-graphic "disp-table" "\ +Display character C as character GC in graphics character set. +This function assumes VT100-compatible escapes; it is meaningless for an +X frame. + +\(fn C GC)" nil nil) + +(autoload 'standard-display-underline "disp-table" "\ +Display character C as character UC plus underlining. + +\(fn C UC)" nil nil) + +(autoload 'create-glyph "disp-table" "\ +Allocate a glyph code to display by sending STRING to the terminal. + +\(fn STRING)" nil nil) + +(autoload 'make-glyph-code "disp-table" "\ +Return a glyph code representing char CHAR with face FACE. + +\(fn CHAR &optional FACE)" nil nil) + +(autoload 'glyph-char "disp-table" "\ +Return the character of glyph code GLYPH. + +\(fn GLYPH)" nil nil) + +(autoload 'glyph-face "disp-table" "\ +Return the face of glyph code GLYPH, or nil if glyph has default face. + +\(fn GLYPH)" nil nil) + +(autoload 'standard-display-european "disp-table" "\ +Semi-obsolete way to toggle display of ISO 8859 European characters. + +This function is semi-obsolete; you probably don't need it, or else you +probably should use `set-language-environment' or `set-locale-environment'. + +This function enables European character display if ARG is positive, +disables it if negative. Otherwise, it toggles European character display. + +When this mode is enabled, characters in the range of 160 to 255 +display not as octal escapes, but as accented characters. Codes 146 +and 160 display as apostrophe and space, even though they are not the +ASCII codes for apostrophe and space. + +Enabling European character display with this command noninteractively +from Lisp code also selects Latin-1 as the language environment. +This provides increased compatibility for users who call this function +in `.emacs'. + +\(fn ARG)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "disp-table" '("display-table-print-array"))) + +;;;*** + +;;;### (autoloads nil "dissociate" "play/dissociate.el" (0 0 0 0)) +;;; Generated autoloads from play/dissociate.el + +(autoload 'dissociated-press "dissociate" "\ +Dissociate the text of the current buffer. +Output goes in buffer named *Dissociation*, +which is redisplayed each time text is added to it. +Every so often the user must say whether to continue. +If ARG is positive, require ARG chars of continuity. +If ARG is negative, require -ARG words of continuity. +Default is 2. + +\(fn &optional ARG)" t nil) + +;;;*** + +;;;### (autoloads nil "dnd" "dnd.el" (0 0 0 0)) +;;; Generated autoloads from dnd.el + +(defvar dnd-protocol-alist `((,(purecopy "^file:///") . dnd-open-local-file) (,(purecopy "^file://") . dnd-open-file) (,(purecopy "^file:") . dnd-open-local-file) (,(purecopy "^\\(https?\\|ftp\\|file\\|nfs\\)://") . dnd-open-file)) "\ +The functions to call for different protocols when a drop is made. +This variable is used by `dnd-handle-one-url' and `dnd-handle-file-name'. +The list contains of (REGEXP . FUNCTION) pairs. +The functions shall take two arguments, URL, which is the URL dropped and +ACTION which is the action to be performed for the drop (move, copy, link, +private or ask). +If no match is found here, and the value of `browse-url-browser-function' +is a pair of (REGEXP . FUNCTION), those regexps are tried for a match. +If no match is found, the URL is inserted as text by calling `dnd-insert-text'. +The function shall return the action done (move, copy, link or private) +if some action was made, or nil if the URL is ignored.") + +(custom-autoload 'dnd-protocol-alist "dnd" t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dnd" '("dnd-"))) + +;;;*** + +;;;### (autoloads nil "dns" "net/dns.el" (0 0 0 0)) +;;; Generated autoloads from net/dns.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dns" '("dns-"))) + +;;;*** + +;;;### (autoloads nil "dns-mode" "textmodes/dns-mode.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/dns-mode.el + +(autoload 'dns-mode "dns-mode" "\ +Major mode for viewing and editing DNS master files. +This mode is inherited from text mode. It add syntax +highlighting, and some commands for handling DNS master files. +Its keymap inherits from `text-mode' and it has the same +variables for customizing indentation. It has its own abbrev +table and its own syntax table. + +Turning on DNS mode runs `dns-mode-hook'. + +\(fn)" t nil) + (defalias 'zone-mode 'dns-mode) + +(autoload 'dns-mode-soa-increment-serial "dns-mode" "\ +Locate SOA record and increment the serial field. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dns-mode" '("dns-mode-"))) + +;;;*** + +;;;### (autoloads nil "doc-view" "doc-view.el" (0 0 0 0)) +;;; Generated autoloads from doc-view.el + +(autoload 'doc-view-mode-p "doc-view" "\ +Return non-nil if document type TYPE is available for `doc-view'. +Document types are symbols like `dvi', `ps', `pdf', or `odf' (any +OpenDocument format). + +\(fn TYPE)" nil nil) + +(autoload 'doc-view-mode "doc-view" "\ +Major mode in DocView buffers. + +DocView Mode is an Emacs document viewer. It displays PDF, PS +and DVI files (as PNG images) in Emacs buffers. + +You can use \\<doc-view-mode-map>\\[doc-view-toggle-display] to +toggle between displaying the document or editing it as text. +\\{doc-view-mode-map} + +\(fn)" t nil) + +(autoload 'doc-view-mode-maybe "doc-view" "\ +Switch to `doc-view-mode' if possible. +If the required external tools are not available, then fallback +to the next best mode. + +\(fn)" nil nil) + +(autoload 'doc-view-minor-mode "doc-view" "\ +Toggle displaying buffer via Doc View (Doc View minor mode). +With a prefix argument ARG, enable Doc View minor mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +See the command `doc-view-mode' for more information on this mode. + +\(fn &optional ARG)" t nil) + +(autoload 'doc-view-bookmark-jump "doc-view" "\ + + +\(fn BMK)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "doc-view" '("doc-view-"))) + +;;;*** + +;;;### (autoloads nil "doctor" "play/doctor.el" (0 0 0 0)) +;;; Generated autoloads from play/doctor.el + +(autoload 'doctor "doctor" "\ +Switch to *doctor* buffer and start giving psychotherapy. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "doctor" '("doc" "make-doctor-variables"))) + +;;;*** + +;;;### (autoloads nil "dom" "dom.el" (0 0 0 0)) +;;; Generated autoloads from dom.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dom" '("dom-"))) + +;;;*** + +;;;### (autoloads nil "dos-fns" "dos-fns.el" (0 0 0 0)) +;;; Generated autoloads from dos-fns.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dos-fns" '("dos"))) + +;;;*** + +;;;### (autoloads nil "dos-vars" "dos-vars.el" (0 0 0 0)) +;;; Generated autoloads from dos-vars.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dos-vars" '("dos-codepage-setup-hook" "msdos-shells"))) + +;;;*** + +;;;### (autoloads nil "dos-w32" "dos-w32.el" (0 0 0 0)) +;;; Generated autoloads from dos-w32.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dos-w32" '("w32-" "file-name-buffer-file-type-alist" "find-"))) + +;;;*** + +;;;### (autoloads nil "double" "double.el" (0 0 0 0)) +;;; Generated autoloads from double.el + +(autoload 'double-mode "double" "\ +Toggle special insertion on double keypresses (Double mode). +With a prefix argument ARG, enable Double mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +When Double mode is enabled, some keys will insert different +strings when pressed twice. See `double-map' for details. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "double" '("double-"))) + +;;;*** + +;;;### (autoloads nil "dunnet" "play/dunnet.el" (0 0 0 0)) +;;; Generated autoloads from play/dunnet.el +(push (purecopy '(dunnet 2 2)) package--builtin-versions) + +(autoload 'dunnet "dunnet" "\ +Switch to *dungeon* buffer and start game. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dunnet" '("dun" "obj-special"))) + +;;;*** + +;;;### (autoloads nil "dynamic-setting" "dynamic-setting.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from dynamic-setting.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dynamic-setting" '("dynamic-setting-handle-config-changed-event" "font-setting-change-default-font"))) + +;;;*** + +;;;### (autoloads nil "easy-mmode" "emacs-lisp/easy-mmode.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from emacs-lisp/easy-mmode.el + +(defalias 'easy-mmode-define-minor-mode 'define-minor-mode) + +(autoload 'define-minor-mode "easy-mmode" "\ +Define a new minor mode MODE. +This defines the toggle command MODE and (by default) a control variable +MODE (you can override this with the :variable keyword, see below). +DOC is the documentation for the mode toggle command. + +The defined mode command takes one optional (prefix) argument. +Interactively with no prefix argument, it toggles the mode. +A prefix argument enables the mode if the argument is positive, +and disables it otherwise. + +When called from Lisp, the mode command toggles the mode if the +argument is `toggle', disables the mode if the argument is a +non-positive integer, and enables the mode otherwise (including +if the argument is omitted or nil or a positive integer). + +If DOC is nil, give the mode command a basic doc-string +documenting what its argument does. + +Optional INIT-VALUE is the initial value of the mode's variable. +Optional LIGHTER is displayed in the mode line when the mode is on. +Optional KEYMAP is the default keymap bound to the mode keymap. + If non-nil, it should be a variable name (whose value is a keymap), + or an expression that returns either a keymap or a list of + (KEY . BINDING) pairs where KEY and BINDING are suitable for + `define-key'. If you supply a KEYMAP argument that is not a + symbol, this macro defines the variable MODE-map and gives it + the value that KEYMAP specifies. + +BODY contains code to execute each time the mode is enabled or disabled. + It is executed after toggling the mode, and before running MODE-hook. + Before the actual body code, you can write keyword arguments, i.e. + alternating keywords and values. If you provide BODY, then you must + provide (even if just nil) INIT-VALUE, LIGHTER, and KEYMAP, or provide + at least one keyword argument, or both; otherwise, BODY would be + misinterpreted as the first omitted argument. The following special + keywords are supported (other keywords are passed to `defcustom' if + the minor mode is global): + +:group GROUP Custom group name to use in all generated `defcustom' forms. + Defaults to MODE without the possible trailing \"-mode\". + Don't use this default group name unless you have written a + `defgroup' to define that group properly. +:global GLOBAL If non-nil specifies that the minor mode is not meant to be + buffer-local, so don't make the variable MODE buffer-local. + By default, the mode is buffer-local. +:init-value VAL Same as the INIT-VALUE argument. + Not used if you also specify :variable. +:lighter SPEC Same as the LIGHTER argument. +:keymap MAP Same as the KEYMAP argument. +:require SYM Same as in `defcustom'. +:variable PLACE The location to use instead of the variable MODE to store + the state of the mode. This can be simply a different + named variable, or a generalized variable. + PLACE can also be of the form (GET . SET), where GET is + an expression that returns the current state, and SET is + a function that takes one argument, the new state, and + sets it. If you specify a :variable, this function does + not define a MODE variable (nor any of the terms used + in :variable). + +:after-hook A single lisp form which is evaluated after the mode hooks + have been run. It should not be quoted. + +For example, you could write + (define-minor-mode foo-mode \"If enabled, foo on you!\" + :lighter \" Foo\" :require \\='foo :global t :group \\='hassle :version \"27.5\" + ...BODY CODE...) + +\(fn MODE DOC &optional INIT-VALUE LIGHTER KEYMAP &rest BODY)" nil t) + +(function-put 'define-minor-mode 'doc-string-elt '2) + +(defalias 'easy-mmode-define-global-mode 'define-globalized-minor-mode) + +(defalias 'define-global-minor-mode 'define-globalized-minor-mode) + +(autoload 'define-globalized-minor-mode "easy-mmode" "\ +Make a global mode GLOBAL-MODE corresponding to buffer-local minor MODE. +TURN-ON is a function that will be called with no args in every buffer + and that should try to turn MODE on if applicable for that buffer. +KEYS is a list of CL-style keyword arguments. As the minor mode + defined by this function is always global, any :global keyword is + ignored. Other keywords have the same meaning as in `define-minor-mode', + which see. In particular, :group specifies the custom group. + The most useful keywords are those that are passed on to the + `defcustom'. It normally makes no sense to pass the :lighter + or :keymap keywords to `define-globalized-minor-mode', since these + are usually passed to the buffer-local version of the minor mode. + +If MODE's set-up depends on the major mode in effect when it was +enabled, then disabling and reenabling MODE should make MODE work +correctly with the current major mode. This is important to +prevent problems with derived modes, that is, major modes that +call another major mode in their body. + +When a major mode is initialized, MODE is actually turned on just +after running the major mode's hook. However, MODE is not turned +on if the hook has explicitly disabled it. + +\(fn GLOBAL-MODE MODE TURN-ON &rest KEYS)" nil t) + +(function-put 'define-globalized-minor-mode 'doc-string-elt '2) + +(autoload 'easy-mmode-define-keymap "easy-mmode" "\ +Return a keymap built from bindings BS. +BS must be a list of (KEY . BINDING) where +KEY and BINDINGS are suitable for `define-key'. +Optional NAME is passed to `make-sparse-keymap'. +Optional map M can be used to modify an existing map. +ARGS is a list of additional keyword arguments. + +Valid keywords and arguments are: + + :name Name of the keymap; overrides NAME argument. + :dense Non-nil for a dense keymap. + :inherit Parent keymap. + :group Ignored. + :suppress Non-nil to call `suppress-keymap' on keymap, + `nodigits' to suppress digits as prefix arguments. + +\(fn BS &optional NAME M ARGS)" nil nil) + +(autoload 'easy-mmode-defmap "easy-mmode" "\ +Define a constant M whose value is the result of `easy-mmode-define-keymap'. +The M, BS, and ARGS arguments are as per that function. DOC is +the constant's documentation. + +\(fn M BS DOC &rest ARGS)" nil t) + +(autoload 'easy-mmode-defsyntax "easy-mmode" "\ +Define variable ST as a syntax-table. +CSS contains a list of syntax specifications of the form (CHAR . SYNTAX). + +\(fn ST CSS DOC &rest ARGS)" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "easy-mmode" '("easy-mmode-"))) + +;;;*** + +;;;### (autoloads nil "easymenu" "emacs-lisp/easymenu.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from emacs-lisp/easymenu.el + +(autoload 'easy-menu-define "easymenu" "\ +Define a pop-up menu and/or menu bar menu specified by MENU. +If SYMBOL is non-nil, define SYMBOL as a function to pop up the +submenu defined by MENU, with DOC as its doc string. + +MAPS, if non-nil, should be a keymap or a list of keymaps; add +the submenu defined by MENU to the keymap or each of the keymaps, +as a top-level menu bar item. + +The first element of MENU must be a string. It is the menu bar +item name. It may be followed by the following keyword argument +pairs: + + :filter FUNCTION + FUNCTION must be a function which, if called with one + argument---the list of the other menu items---returns the + items to actually display. + + :visible INCLUDE + INCLUDE is an expression. The menu is visible if the + expression evaluates to a non-nil value. `:included' is an + alias for `:visible'. + + :active ENABLE + ENABLE is an expression. The menu is enabled for selection + if the expression evaluates to a non-nil value. `:enable' is + an alias for `:active'. + +The rest of the elements in MENU are menu items. +A menu item can be a vector of three elements: + + [NAME CALLBACK ENABLE] + +NAME is a string--the menu item name. + +CALLBACK is a command to run when the item is chosen, or an +expression to evaluate when the item is chosen. + +ENABLE is an expression; the item is enabled for selection if the +expression evaluates to a non-nil value. + +Alternatively, a menu item may have the form: + + [ NAME CALLBACK [ KEYWORD ARG ]... ] + +where NAME and CALLBACK have the same meanings as above, and each +optional KEYWORD and ARG pair should be one of the following: + + :keys KEYS + KEYS is a string; a keyboard equivalent to the menu item. + This is normally not needed because keyboard equivalents are + usually computed automatically. KEYS is expanded with + `substitute-command-keys' before it is used. + + :key-sequence KEYS + KEYS is a hint for speeding up Emacs's first display of the + menu. It should be nil if you know that the menu item has no + keyboard equivalent; otherwise it should be a string or + vector specifying a keyboard equivalent for the menu item. + + :active ENABLE + ENABLE is an expression; the item is enabled for selection + whenever this expression's value is non-nil. `:enable' is an + alias for `:active'. + + :visible INCLUDE + INCLUDE is an expression; this item is only visible if this + expression has a non-nil value. `:included' is an alias for + `:visible'. + + :label FORM + FORM is an expression that is dynamically evaluated and whose + value serves as the menu item's label (the default is NAME). + + :suffix FORM + FORM is an expression that is dynamically evaluated and whose + value is concatenated with the menu entry's label. + + :style STYLE + STYLE is a symbol describing the type of menu item; it should + be `toggle' (a checkbox), or `radio' (a radio button), or any + other value (meaning an ordinary menu item). + + :selected SELECTED + SELECTED is an expression; the checkbox or radio button is + selected whenever the expression's value is non-nil. + + :help HELP + HELP is a string, the help to display for the menu item. + +Alternatively, a menu item can be a string. Then that string +appears in the menu as unselectable text. A string consisting +solely of dashes is displayed as a menu separator. + +Alternatively, a menu item can be a list with the same format as +MENU. This is a submenu. + +\(fn SYMBOL MAPS DOC MENU)" nil t) + +(function-put 'easy-menu-define 'lisp-indent-function 'defun) + +(autoload 'easy-menu-do-define "easymenu" "\ + + +\(fn SYMBOL MAPS DOC MENU)" nil nil) + +(autoload 'easy-menu-create-menu "easymenu" "\ +Create a menu called MENU-NAME with items described in MENU-ITEMS. +MENU-NAME is a string, the name of the menu. MENU-ITEMS is a list of items +possibly preceded by keyword pairs as described in `easy-menu-define'. + +\(fn MENU-NAME MENU-ITEMS)" nil nil) + +(autoload 'easy-menu-change "easymenu" "\ +Change menu found at PATH as item NAME to contain ITEMS. +PATH is a list of strings for locating the menu that +should contain a submenu named NAME. +ITEMS is a list of menu items, as in `easy-menu-define'. +These items entirely replace the previous items in that submenu. + +If MAP is specified, it should normally be a keymap; nil stands for the local +menu-bar keymap. It can also be a symbol, which has earlier been used as the +first argument in a call to `easy-menu-define', or the value of such a symbol. + +If the menu located by PATH has no submenu named NAME, add one. +If the optional argument BEFORE is present, add it just before +the submenu named BEFORE, otherwise add it at the end of the menu. + +To implement dynamic menus, either call this from +`menu-bar-update-hook' or use a menu filter. + +\(fn PATH NAME ITEMS &optional BEFORE MAP)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "easymenu" '("easy-menu-" "add-submenu"))) + +;;;*** + +;;;### (autoloads nil "ebnf-abn" "progmodes/ebnf-abn.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/ebnf-abn.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ebnf-abn" '("ebnf-abn-"))) + +;;;*** + +;;;### (autoloads nil "ebnf-bnf" "progmodes/ebnf-bnf.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/ebnf-bnf.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ebnf-bnf" '("ebnf-"))) + +;;;*** + +;;;### (autoloads nil "ebnf-dtd" "progmodes/ebnf-dtd.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/ebnf-dtd.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ebnf-dtd" '("ebnf-dtd-"))) + +;;;*** + +;;;### (autoloads nil "ebnf-ebx" "progmodes/ebnf-ebx.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/ebnf-ebx.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ebnf-ebx" '("ebnf-ebx-"))) + +;;;*** + +;;;### (autoloads nil "ebnf-iso" "progmodes/ebnf-iso.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/ebnf-iso.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ebnf-iso" '("ebnf-"))) + +;;;*** + +;;;### (autoloads nil "ebnf-otz" "progmodes/ebnf-otz.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/ebnf-otz.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ebnf-otz" '("ebnf-"))) + +;;;*** + +;;;### (autoloads nil "ebnf-yac" "progmodes/ebnf-yac.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/ebnf-yac.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ebnf-yac" '("ebnf-yac-"))) + +;;;*** + +;;;### (autoloads nil "ebnf2ps" "progmodes/ebnf2ps.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/ebnf2ps.el +(push (purecopy '(ebnf2ps 4 4)) package--builtin-versions) + +(autoload 'ebnf-customize "ebnf2ps" "\ +Customization for ebnf group. + +\(fn)" t nil) + +(autoload 'ebnf-print-directory "ebnf2ps" "\ +Generate and print a PostScript syntactic chart image of DIRECTORY. + +If DIRECTORY is nil, it's used `default-directory'. + +The files in DIRECTORY that matches `ebnf-file-suffix-regexp' (which see) are +processed. + +See also `ebnf-print-buffer'. + +\(fn &optional DIRECTORY)" t nil) + +(autoload 'ebnf-print-file "ebnf2ps" "\ +Generate and print a PostScript syntactic chart image of the file FILE. + +If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't +killed after process termination. + +See also `ebnf-print-buffer'. + +\(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil) + +(autoload 'ebnf-print-buffer "ebnf2ps" "\ +Generate and print a PostScript syntactic chart image of the buffer. + +When called with a numeric prefix argument (C-u), prompts the user for +the name of a file to save the PostScript image in, instead of sending +it to the printer. + +More specifically, the FILENAME argument is treated as follows: if it +is nil, send the image to the printer. If FILENAME is a string, save +the PostScript image in a file with that name. If FILENAME is a +number, prompt the user for the name of the file to save in. + +\(fn &optional FILENAME)" t nil) + +(autoload 'ebnf-print-region "ebnf2ps" "\ +Generate and print a PostScript syntactic chart image of the region. +Like `ebnf-print-buffer', but prints just the current region. + +\(fn FROM TO &optional FILENAME)" t nil) + +(autoload 'ebnf-spool-directory "ebnf2ps" "\ +Generate and spool a PostScript syntactic chart image of DIRECTORY. + +If DIRECTORY is nil, it's used `default-directory'. + +The files in DIRECTORY that matches `ebnf-file-suffix-regexp' (which see) are +processed. + +See also `ebnf-spool-buffer'. + +\(fn &optional DIRECTORY)" t nil) + +(autoload 'ebnf-spool-file "ebnf2ps" "\ +Generate and spool a PostScript syntactic chart image of the file FILE. + +If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't +killed after process termination. + +See also `ebnf-spool-buffer'. + +\(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil) + +(autoload 'ebnf-spool-buffer "ebnf2ps" "\ +Generate and spool a PostScript syntactic chart image of the buffer. +Like `ebnf-print-buffer' except that the PostScript image is saved in a +local buffer to be sent to the printer later. + +Use the command `ebnf-despool' to send the spooled images to the printer. + +\(fn)" t nil) + +(autoload 'ebnf-spool-region "ebnf2ps" "\ +Generate a PostScript syntactic chart image of the region and spool locally. +Like `ebnf-spool-buffer', but spools just the current region. + +Use the command `ebnf-despool' to send the spooled images to the printer. + +\(fn FROM TO)" t nil) + +(autoload 'ebnf-eps-directory "ebnf2ps" "\ +Generate EPS files from EBNF files in DIRECTORY. + +If DIRECTORY is nil, it's used `default-directory'. + +The files in DIRECTORY that matches `ebnf-file-suffix-regexp' (which see) are +processed. + +See also `ebnf-eps-buffer'. + +\(fn &optional DIRECTORY)" t nil) + +(autoload 'ebnf-eps-file "ebnf2ps" "\ +Generate an EPS file from EBNF file FILE. + +If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't +killed after EPS generation. + +See also `ebnf-eps-buffer'. + +\(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil) + +(autoload 'ebnf-eps-buffer "ebnf2ps" "\ +Generate a PostScript syntactic chart image of the buffer in an EPS file. + +Generate an EPS file for each production in the buffer. +The EPS file name has the following form: + + <PREFIX><PRODUCTION>.eps + +<PREFIX> is given by variable `ebnf-eps-prefix'. + The default value is \"ebnf--\". + +<PRODUCTION> is the production name. + Some characters in the production file name are replaced to + produce a valid file name. For example, the production name + \"A/B + C\" is modified to produce \"A_B_+_C\", and the EPS + file name used in this case will be \"ebnf--A_B_+_C.eps\". + +WARNING: This function does *NOT* ask any confirmation to override existing + files. + +\(fn)" t nil) + +(autoload 'ebnf-eps-region "ebnf2ps" "\ +Generate a PostScript syntactic chart image of the region in an EPS file. + +Generate an EPS file for each production in the region. +The EPS file name has the following form: + + <PREFIX><PRODUCTION>.eps + +<PREFIX> is given by variable `ebnf-eps-prefix'. + The default value is \"ebnf--\". + +<PRODUCTION> is the production name. + Some characters in the production file name are replaced to + produce a valid file name. For example, the production name + \"A/B + C\" is modified to produce \"A_B_+_C\", and the EPS + file name used in this case will be \"ebnf--A_B_+_C.eps\". + +WARNING: This function does *NOT* ask any confirmation to override existing + files. + +\(fn FROM TO)" t nil) + +(defalias 'ebnf-despool 'ps-despool) + +(autoload 'ebnf-syntax-directory "ebnf2ps" "\ +Do a syntactic analysis of the files in DIRECTORY. + +If DIRECTORY is nil, use `default-directory'. + +Only the files in DIRECTORY that match `ebnf-file-suffix-regexp' (which see) +are processed. + +See also `ebnf-syntax-buffer'. + +\(fn &optional DIRECTORY)" t nil) + +(autoload 'ebnf-syntax-file "ebnf2ps" "\ +Do a syntactic analysis of the named FILE. + +If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't +killed after syntax checking. + +See also `ebnf-syntax-buffer'. + +\(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil) + +(autoload 'ebnf-syntax-buffer "ebnf2ps" "\ +Do a syntactic analysis of the current buffer. + +\(fn)" t nil) + +(autoload 'ebnf-syntax-region "ebnf2ps" "\ +Do a syntactic analysis of a region. + +\(fn FROM TO)" t nil) + +(autoload 'ebnf-setup "ebnf2ps" "\ +Return the current ebnf2ps setup. + +\(fn)" nil nil) + +(autoload 'ebnf-find-style "ebnf2ps" "\ +Return style definition if NAME is already defined; otherwise, return nil. + +See `ebnf-style-database' documentation. + +\(fn NAME)" t nil) + +(autoload 'ebnf-insert-style "ebnf2ps" "\ +Insert a new style NAME with inheritance INHERITS and values VALUES. + +See `ebnf-style-database' documentation. + +\(fn NAME INHERITS &rest VALUES)" t nil) + +(autoload 'ebnf-delete-style "ebnf2ps" "\ +Delete style NAME. + +See `ebnf-style-database' documentation. + +\(fn NAME)" t nil) + +(autoload 'ebnf-merge-style "ebnf2ps" "\ +Merge values of style NAME with style VALUES. + +See `ebnf-style-database' documentation. + +\(fn NAME &rest VALUES)" t nil) + +(autoload 'ebnf-apply-style "ebnf2ps" "\ +Set STYLE as the current style. + +Returns the old style symbol. + +See `ebnf-style-database' documentation. + +\(fn STYLE)" t nil) + +(autoload 'ebnf-reset-style "ebnf2ps" "\ +Reset current style. + +Returns the old style symbol. + +See `ebnf-style-database' documentation. + +\(fn &optional STYLE)" t nil) + +(autoload 'ebnf-push-style "ebnf2ps" "\ +Push the current style onto a stack and set STYLE as the current style. + +Returns the old style symbol. + +See also `ebnf-pop-style'. + +See `ebnf-style-database' documentation. + +\(fn &optional STYLE)" t nil) + +(autoload 'ebnf-pop-style "ebnf2ps" "\ +Pop a style from the stack of pushed styles and set it as the current style. + +Returns the old style symbol. + +See also `ebnf-push-style'. + +See `ebnf-style-database' documentation. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ebnf2ps" '("ebnf-"))) + +;;;*** + +;;;### (autoloads nil "ebrowse" "progmodes/ebrowse.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/ebrowse.el + +(autoload 'ebrowse-tree-mode "ebrowse" "\ +Major mode for Ebrowse class tree buffers. +Each line corresponds to a class in a class tree. +Letters do not insert themselves, they are commands. +File operations in the tree buffer work on class tree data structures. +E.g.\\[save-buffer] writes the tree to the file it was loaded from. + +Tree mode key bindings: +\\{ebrowse-tree-mode-map} + +\(fn)" t nil) + +(autoload 'ebrowse-electric-choose-tree "ebrowse" "\ +Return a buffer containing a tree or nil if no tree found or canceled. + +\(fn)" t nil) + +(autoload 'ebrowse-member-mode "ebrowse" "\ +Major mode for Ebrowse member buffers. + +\(fn)" t nil) + +(autoload 'ebrowse-tags-view-declaration "ebrowse" "\ +View declaration of member at point. + +\(fn)" t nil) + +(autoload 'ebrowse-tags-find-declaration "ebrowse" "\ +Find declaration of member at point. + +\(fn)" t nil) + +(autoload 'ebrowse-tags-view-definition "ebrowse" "\ +View definition of member at point. + +\(fn)" t nil) + +(autoload 'ebrowse-tags-find-definition "ebrowse" "\ +Find definition of member at point. + +\(fn)" t nil) + +(autoload 'ebrowse-tags-find-declaration-other-window "ebrowse" "\ +Find declaration of member at point in other window. + +\(fn)" t nil) + +(autoload 'ebrowse-tags-view-definition-other-window "ebrowse" "\ +View definition of member at point in other window. + +\(fn)" t nil) + +(autoload 'ebrowse-tags-find-definition-other-window "ebrowse" "\ +Find definition of member at point in other window. + +\(fn)" t nil) + +(autoload 'ebrowse-tags-find-declaration-other-frame "ebrowse" "\ +Find definition of member at point in other frame. + +\(fn)" t nil) + +(autoload 'ebrowse-tags-view-definition-other-frame "ebrowse" "\ +View definition of member at point in other frame. + +\(fn)" t nil) + +(autoload 'ebrowse-tags-find-definition-other-frame "ebrowse" "\ +Find definition of member at point in other frame. + +\(fn)" t nil) + +(autoload 'ebrowse-tags-complete-symbol "ebrowse" "\ +Perform completion on the C++ symbol preceding point. +A second call of this function without changing point inserts the next match. +A call with prefix PREFIX reads the symbol to insert from the minibuffer with +completion. + +\(fn PREFIX)" t nil) + +(autoload 'ebrowse-tags-loop-continue "ebrowse" "\ +Repeat last operation on files in tree. +FIRST-TIME non-nil means this is not a repetition, but the first time. +TREE-BUFFER if indirectly specifies which files to loop over. + +\(fn &optional FIRST-TIME TREE-BUFFER)" t nil) + +(autoload 'ebrowse-tags-search "ebrowse" "\ +Search for REGEXP in all files in a tree. +If marked classes exist, process marked classes, only. +If regular expression is nil, repeat last search. + +\(fn REGEXP)" t nil) + +(autoload 'ebrowse-tags-query-replace "ebrowse" "\ +Query replace FROM with TO in all files of a class tree. +With prefix arg, process files of marked classes only. + +\(fn FROM TO)" t nil) + +(autoload 'ebrowse-tags-search-member-use "ebrowse" "\ +Search for call sites of a member. +If FIX-NAME is specified, search uses of that member. +Otherwise, read a member name from the minibuffer. +Searches in all files mentioned in a class tree for something that +looks like a function call to the member. + +\(fn &optional FIX-NAME)" t nil) + +(autoload 'ebrowse-back-in-position-stack "ebrowse" "\ +Move backward in the position stack. +Prefix arg ARG says how much. + +\(fn ARG)" t nil) + +(autoload 'ebrowse-forward-in-position-stack "ebrowse" "\ +Move forward in the position stack. +Prefix arg ARG says how much. + +\(fn ARG)" t nil) + +(autoload 'ebrowse-electric-position-menu "ebrowse" "\ +List positions in the position stack in an electric buffer. + +\(fn)" t nil) + +(autoload 'ebrowse-save-tree "ebrowse" "\ +Save current tree in same file it was loaded from. + +\(fn)" t nil) + +(autoload 'ebrowse-save-tree-as "ebrowse" "\ +Write the current tree data structure to a file. +Read the file name from the minibuffer if interactive. +Otherwise, FILE-NAME specifies the file to save the tree in. + +\(fn &optional FILE-NAME)" t nil) + +(autoload 'ebrowse-statistics "ebrowse" "\ +Display statistics for a class tree. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ebrowse" '("electric-buffer-menu-mode-hook" "ebrowse-"))) + +;;;*** + +;;;### (autoloads nil "ebuff-menu" "ebuff-menu.el" (0 0 0 0)) +;;; Generated autoloads from ebuff-menu.el + +(autoload 'electric-buffer-list "ebuff-menu" "\ +Pop up the Buffer Menu in an \"electric\" window. +If you type SPC or RET (`Electric-buffer-menu-select'), that +selects the buffer at point and quits the \"electric\" window. +Otherwise, you can move around in the Buffer Menu, marking +buffers to be selected, saved or deleted; these other commands +are much like those of `Buffer-menu-mode'. + +Run hooks in `electric-buffer-menu-mode-hook' on entry. + +\\<electric-buffer-menu-mode-map> +\\[keyboard-quit] or \\[Electric-buffer-menu-quit] -- exit buffer menu, returning to previous window and buffer + configuration. If the very first character typed is a space, it + also has this effect. +\\[Electric-buffer-menu-select] -- select buffer of line point is on. + Also show buffers marked with m in other windows, + deletes buffers marked with \"D\", and saves those marked with \"S\". +\\[Buffer-menu-mark] -- mark buffer to be displayed. +\\[Buffer-menu-not-modified] -- clear modified-flag on that buffer. +\\[Buffer-menu-save] -- mark that buffer to be saved. +\\[Buffer-menu-delete] or \\[Buffer-menu-delete-backwards] -- mark that buffer to be deleted. +\\[Buffer-menu-unmark] -- remove all kinds of marks from current line. +\\[Buffer-menu-unmark-all] -- remove all kinds of marks from all lines. +\\[Electric-buffer-menu-mode-view-buffer] -- view buffer, returning when done. +\\[Buffer-menu-backup-unmark] -- back up a line and remove marks. + +\(fn ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ebuff-menu" '("electric-buffer-" "Electric-buffer-menu-"))) + +;;;*** + +;;;### (autoloads nil "echistory" "echistory.el" (0 0 0 0)) +;;; Generated autoloads from echistory.el + +(autoload 'Electric-command-history-redo-expression "echistory" "\ +Edit current history line in minibuffer and execute result. +With prefix arg NOCONFIRM, execute current line as-is without editing. + +\(fn &optional NOCONFIRM)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "echistory" '("Electric-history-" "electric-"))) + +;;;*** + +;;;### (autoloads nil "ecomplete" "ecomplete.el" (0 0 0 0)) +;;; Generated autoloads from ecomplete.el + +(autoload 'ecomplete-setup "ecomplete" "\ + + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ecomplete" '("ecomplete-"))) + +;;;*** + +;;;### (autoloads nil "ede" "cedet/ede.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede.el +(push (purecopy '(ede 1 2)) package--builtin-versions) + +(defvar global-ede-mode nil "\ +Non-nil if Global Ede mode is enabled. +See the `global-ede-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `global-ede-mode'.") + +(custom-autoload 'global-ede-mode "ede" nil) + +(autoload 'global-ede-mode "ede" "\ +Toggle global EDE (Emacs Development Environment) mode. +With a prefix argument ARG, enable global EDE mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +This global minor mode enables `ede-minor-mode' in all buffers in +an EDE controlled project. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede" '("project-try-ede" "ede" "global-ede-mode-map"))) + +;;;*** + +;;;### (autoloads nil "ede/auto" "cedet/ede/auto.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/auto.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/auto" '("ede-"))) + +;;;*** + +;;;### (autoloads nil "ede/autoconf-edit" "cedet/ede/autoconf-edit.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/autoconf-edit.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/autoconf-edit" '("autoconf-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ede/base" "cedet/ede/base.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/base.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/base" '("ede-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ede/config" "cedet/ede/config.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/config.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/config" '("ede-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ede/cpp-root" +;;;;;; "cedet/ede/cpp-root.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/cpp-root.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/cpp-root" '("ede-c"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ede/custom" "cedet/ede/custom.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/custom.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/custom" '("eieio-ede-old-variables" "ede-"))) + +;;;*** + +;;;### (autoloads nil "ede/detect" "cedet/ede/detect.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/detect.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/detect" '("ede-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ede/dired" "cedet/ede/dired.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/dired.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/dired" '("ede-dired-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ede/emacs" "cedet/ede/emacs.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/emacs.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/emacs" '("ede-emacs-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ede/files" "cedet/ede/files.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/files.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/files" '("ede-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ede/generic" +;;;;;; "cedet/ede/generic.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/generic.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/generic" '("ede-generic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ede/linux" "cedet/ede/linux.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/linux.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/linux" '("ede-linux-" "project-linux-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ede/locate" "cedet/ede/locate.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/locate.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/locate" '("ede-locate-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ede/make" "cedet/ede/make.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/make.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/make" '("ede-make-"))) + +;;;*** + +;;;### (autoloads nil "ede/makefile-edit" "cedet/ede/makefile-edit.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/makefile-edit.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/makefile-edit" '("makefile-"))) + +;;;*** + +;;;### (autoloads nil "ede/pconf" "cedet/ede/pconf.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/pconf.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/pconf" '("ede-pconf-create-file-query"))) + +;;;*** + +;;;### (autoloads nil "ede/pmake" "cedet/ede/pmake.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/pmake.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/pmake" '("ede-pmake-"))) + +;;;*** + +;;;### (autoloads nil "ede/proj" "cedet/ede/proj.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/proj.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/proj" '("ede-proj-"))) + +;;;*** + +;;;### (autoloads nil "ede/proj-archive" "cedet/ede/proj-archive.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/proj-archive.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/proj-archive" '("ede-"))) + +;;;*** + +;;;### (autoloads nil "ede/proj-aux" "cedet/ede/proj-aux.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from cedet/ede/proj-aux.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/proj-aux" '("ede-"))) + +;;;*** + +;;;### (autoloads nil "ede/proj-comp" "cedet/ede/proj-comp.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from cedet/ede/proj-comp.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/proj-comp" '("proj-comp-insert-variable-once" "ede-"))) + +;;;*** + +;;;### (autoloads nil "ede/proj-elisp" "cedet/ede/proj-elisp.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/proj-elisp.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/proj-elisp" '("ede-"))) + +;;;*** + +;;;### (autoloads nil "ede/proj-info" "cedet/ede/proj-info.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from cedet/ede/proj-info.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/proj-info" '("ede-"))) + +;;;*** + +;;;### (autoloads nil "ede/proj-misc" "cedet/ede/proj-misc.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from cedet/ede/proj-misc.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/proj-misc" '("ede-"))) + +;;;*** + +;;;### (autoloads nil "ede/proj-obj" "cedet/ede/proj-obj.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from cedet/ede/proj-obj.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/proj-obj" '("ede-"))) + +;;;*** + +;;;### (autoloads nil "ede/proj-prog" "cedet/ede/proj-prog.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from cedet/ede/proj-prog.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/proj-prog" '("ede-proj-target-makefile-program"))) + +;;;*** + +;;;### (autoloads nil "ede/proj-scheme" "cedet/ede/proj-scheme.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/proj-scheme.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/proj-scheme" '("ede-proj-target-scheme"))) + +;;;*** + +;;;### (autoloads nil "ede/proj-shared" "cedet/ede/proj-shared.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/proj-shared.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/proj-shared" '("ede-"))) + +;;;*** + +;;;### (autoloads nil "ede/project-am" "cedet/ede/project-am.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/project-am.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/project-am" '("project-am-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ede/shell" "cedet/ede/shell.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/shell.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/shell" '("ede-shell-run-command"))) + +;;;*** + +;;;### (autoloads nil "ede/simple" "cedet/ede/simple.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/simple.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/simple" '("ede-simple-"))) + +;;;*** + +;;;### (autoloads nil "ede/source" "cedet/ede/source.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/source.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/source" '("ede-source"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ede/speedbar" +;;;;;; "cedet/ede/speedbar.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/speedbar.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/speedbar" '("ede-"))) + +;;;*** + +;;;### (autoloads nil "ede/srecode" "cedet/ede/srecode.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from cedet/ede/srecode.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/srecode" '("ede-srecode-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ede/util" "cedet/ede/util.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/ede/util.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ede/util" '("ede-make-buffer-writable"))) + +;;;*** + +;;;### (autoloads nil "edebug" "emacs-lisp/edebug.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/edebug.el + +(defvar edebug-all-defs nil "\ +If non-nil, evaluating defining forms instruments for Edebug. +This applies to `eval-defun', `eval-region', `eval-buffer', and +`eval-current-buffer'. `eval-region' is also called by +`eval-last-sexp', and `eval-print-last-sexp'. + +You can use the command `edebug-all-defs' to toggle the value of this +variable. You may wish to make it local to each buffer with +\(make-local-variable \\='edebug-all-defs) in your +`emacs-lisp-mode-hook'.") + +(custom-autoload 'edebug-all-defs "edebug" t) + +(defvar edebug-all-forms nil "\ +Non-nil means evaluation of all forms will instrument for Edebug. +This doesn't apply to loading or evaluations in the minibuffer. +Use the command `edebug-all-forms' to toggle the value of this option.") + +(custom-autoload 'edebug-all-forms "edebug" t) + +(autoload 'edebug-basic-spec "edebug" "\ +Return t if SPEC uses only extant spec symbols. +An extant spec symbol is a symbol that is not a function and has a +`edebug-form-spec' property. + +\(fn SPEC)" nil nil) + +(defalias 'edebug-defun 'edebug-eval-top-level-form) + +(autoload 'edebug-eval-top-level-form "edebug" "\ +Evaluate the top level form point is in, stepping through with Edebug. +This is like `eval-defun' except that it steps the code for Edebug +before evaluating it. It displays the value in the echo area +using `eval-expression' (which see). + +If you do this on a function definition such as a defun or defmacro, +it defines the function and instruments its definition for Edebug, +so it will do Edebug stepping when called later. It displays +`Edebug: FUNCTION' in the echo area to indicate that FUNCTION is now +instrumented for Edebug. + +If the current defun is actually a call to `defvar' or `defcustom', +evaluating it this way resets the variable using its initial value +expression even if the variable already has some other value. +\(Normally `defvar' and `defcustom' do not alter the value if there +already is one.) + +\(fn)" t nil) + +(autoload 'edebug-all-defs "edebug" "\ +Toggle edebugging of all definitions. + +\(fn)" t nil) + +(autoload 'edebug-all-forms "edebug" "\ +Toggle edebugging of all forms. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "edebug" '("edebug" "get-edebug-spec" "global-edebug-" "cancel-edebug-on-entry"))) + +;;;*** + +;;;### (autoloads nil "ediff" "vc/ediff.el" (0 0 0 0)) +;;; Generated autoloads from vc/ediff.el +(push (purecopy '(ediff 2 81 4)) package--builtin-versions) + +(autoload 'ediff-files "ediff" "\ +Run Ediff on a pair of files, FILE-A and FILE-B. + +\(fn FILE-A FILE-B &optional STARTUP-HOOKS)" t nil) + +(autoload 'ediff-files3 "ediff" "\ +Run Ediff on three files, FILE-A, FILE-B, and FILE-C. + +\(fn FILE-A FILE-B FILE-C &optional STARTUP-HOOKS)" t nil) + +(defalias 'ediff3 'ediff-files3) + +(defalias 'ediff 'ediff-files) + +(autoload 'ediff-current-file "ediff" "\ +Start ediff between current buffer and its file on disk. +This command can be used instead of `revert-buffer'. If there is +nothing to revert then this command fails. + +\(fn)" t nil) + +(autoload 'ediff-backup "ediff" "\ +Run Ediff on FILE and its backup file. +Uses the latest backup, if there are several numerical backups. +If this file is a backup, `ediff' it with its original. + +\(fn FILE)" t nil) + +(autoload 'ediff-buffers "ediff" "\ +Run Ediff on a pair of buffers, BUFFER-A and BUFFER-B. + +\(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS JOB-NAME)" t nil) + +(defalias 'ebuffers 'ediff-buffers) + +(autoload 'ediff-buffers3 "ediff" "\ +Run Ediff on three buffers, BUFFER-A, BUFFER-B, and BUFFER-C. + +\(fn BUFFER-A BUFFER-B BUFFER-C &optional STARTUP-HOOKS JOB-NAME)" t nil) + +(defalias 'ebuffers3 'ediff-buffers3) + +(autoload 'ediff-directories "ediff" "\ +Run Ediff on a pair of directories, DIR1 and DIR2, comparing files that have +the same name in both. The third argument, REGEXP, is nil or a regular +expression; only file names that match the regexp are considered. + +\(fn DIR1 DIR2 REGEXP)" t nil) + +(defalias 'edirs 'ediff-directories) + +(autoload 'ediff-directory-revisions "ediff" "\ +Run Ediff on a directory, DIR1, comparing its files with their revisions. +The second argument, REGEXP, is a regular expression that filters the file +names. Only the files that are under revision control are taken into account. + +\(fn DIR1 REGEXP)" t nil) + +(defalias 'edir-revisions 'ediff-directory-revisions) + +(autoload 'ediff-directories3 "ediff" "\ +Run Ediff on three directories, DIR1, DIR2, and DIR3, comparing files that +have the same name in all three. The last argument, REGEXP, is nil or a +regular expression; only file names that match the regexp are considered. + +\(fn DIR1 DIR2 DIR3 REGEXP)" t nil) + +(defalias 'edirs3 'ediff-directories3) + +(autoload 'ediff-merge-directories "ediff" "\ +Run Ediff on a pair of directories, DIR1 and DIR2, merging files that have +the same name in both. The third argument, REGEXP, is nil or a regular +expression; only file names that match the regexp are considered. + +\(fn DIR1 DIR2 REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil) + +(defalias 'edirs-merge 'ediff-merge-directories) + +(autoload 'ediff-merge-directories-with-ancestor "ediff" "\ +Merge files in directories DIR1 and DIR2 using files in ANCESTOR-DIR as ancestors. +Ediff merges files that have identical names in DIR1, DIR2. If a pair of files +in DIR1 and DIR2 doesn't have an ancestor in ANCESTOR-DIR, Ediff will merge +without ancestor. The fourth argument, REGEXP, is nil or a regular expression; +only file names that match the regexp are considered. + +\(fn DIR1 DIR2 ANCESTOR-DIR REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil) + +(autoload 'ediff-merge-directory-revisions "ediff" "\ +Run Ediff on a directory, DIR1, merging its files with their revisions. +The second argument, REGEXP, is a regular expression that filters the file +names. Only the files that are under revision control are taken into account. + +\(fn DIR1 REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil) + +(defalias 'edir-merge-revisions 'ediff-merge-directory-revisions) + +(autoload 'ediff-merge-directory-revisions-with-ancestor "ediff" "\ +Run Ediff on a directory, DIR1, merging its files with their revisions and ancestors. +The second argument, REGEXP, is a regular expression that filters the file +names. Only the files that are under revision control are taken into account. + +\(fn DIR1 REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil) + +(defalias 'edir-merge-revisions-with-ancestor 'ediff-merge-directory-revisions-with-ancestor) + +(defalias 'edirs-merge-with-ancestor 'ediff-merge-directories-with-ancestor) + +(autoload 'ediff-windows-wordwise "ediff" "\ +Compare WIND-A and WIND-B, which are selected by clicking, wordwise. +With prefix argument, DUMB-MODE, or on a non-windowing display, works as +follows: +If WIND-A is nil, use selected window. +If WIND-B is nil, use window next to WIND-A. + +\(fn DUMB-MODE &optional WIND-A WIND-B STARTUP-HOOKS)" t nil) + +(autoload 'ediff-windows-linewise "ediff" "\ +Compare WIND-A and WIND-B, which are selected by clicking, linewise. +With prefix argument, DUMB-MODE, or on a non-windowing display, works as +follows: +If WIND-A is nil, use selected window. +If WIND-B is nil, use window next to WIND-A. + +\(fn DUMB-MODE &optional WIND-A WIND-B STARTUP-HOOKS)" t nil) + +(autoload 'ediff-regions-wordwise "ediff" "\ +Run Ediff on a pair of regions in specified buffers. +Regions (i.e., point and mark) can be set in advance or marked interactively. +This function is effective only for relatively small regions, up to 200 +lines. For large regions, use `ediff-regions-linewise'. + +\(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS)" t nil) + +(autoload 'ediff-regions-linewise "ediff" "\ +Run Ediff on a pair of regions in specified buffers. +Regions (i.e., point and mark) can be set in advance or marked interactively. +Each region is enlarged to contain full lines. +This function is effective for large regions, over 100-200 +lines. For small regions, use `ediff-regions-wordwise'. + +\(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS)" t nil) + +(defalias 'ediff-merge 'ediff-merge-files) + +(autoload 'ediff-merge-files "ediff" "\ +Merge two files without ancestor. + +\(fn FILE-A FILE-B &optional STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil) + +(autoload 'ediff-merge-files-with-ancestor "ediff" "\ +Merge two files with ancestor. + +\(fn FILE-A FILE-B FILE-ANCESTOR &optional STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil) + +(defalias 'ediff-merge-with-ancestor 'ediff-merge-files-with-ancestor) + +(autoload 'ediff-merge-buffers "ediff" "\ +Merge buffers without ancestor. + +\(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS JOB-NAME MERGE-BUFFER-FILE)" t nil) + +(autoload 'ediff-merge-buffers-with-ancestor "ediff" "\ +Merge buffers with ancestor. + +\(fn BUFFER-A BUFFER-B BUFFER-ANCESTOR &optional STARTUP-HOOKS JOB-NAME MERGE-BUFFER-FILE)" t nil) + +(autoload 'ediff-merge-revisions "ediff" "\ +Run Ediff by merging two revisions of a file. +The file is the optional FILE argument or the file visited by the current +buffer. + +\(fn &optional FILE STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil) + +(autoload 'ediff-merge-revisions-with-ancestor "ediff" "\ +Run Ediff by merging two revisions of a file with a common ancestor. +The file is the optional FILE argument or the file visited by the current +buffer. + +\(fn &optional FILE STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil) + +(autoload 'ediff-patch-file "ediff" "\ +Query for a file name, and then run Ediff by patching that file. +If optional PATCH-BUF is given, use the patch in that buffer +and don't ask the user. +If prefix argument, then: if even argument, assume that the patch is in a +buffer. If odd -- assume it is in a file. + +\(fn &optional ARG PATCH-BUF)" t nil) + +(autoload 'ediff-patch-buffer "ediff" "\ +Run Ediff by patching the buffer specified at prompt. +Without the optional prefix ARG, asks if the patch is in some buffer and +prompts for the buffer or a file, depending on the answer. +With ARG=1, assumes the patch is in a file and prompts for the file. +With ARG=2, assumes the patch is in a buffer and prompts for the buffer. +PATCH-BUF is an optional argument, which specifies the buffer that contains the +patch. If not given, the user is prompted according to the prefix argument. + +\(fn &optional ARG PATCH-BUF)" t nil) + +(defalias 'epatch 'ediff-patch-file) + +(defalias 'epatch-buffer 'ediff-patch-buffer) + +(autoload 'ediff-revision "ediff" "\ +Run Ediff by comparing versions of a file. +The file is an optional FILE argument or the file entered at the prompt. +Default: the file visited by the current buffer. +Uses `vc.el' or `rcs.el' depending on `ediff-version-control-package'. + +\(fn &optional FILE STARTUP-HOOKS)" t nil) + +(defalias 'erevision 'ediff-revision) + +(autoload 'ediff-version "ediff" "\ +Return string describing the version of Ediff. +When called interactively, displays the version. + +\(fn)" t nil) + +(autoload 'ediff-documentation "ediff" "\ +Display Ediff's manual. +With optional NODE, goes to that node. + +\(fn &optional NODE)" t nil) + +(autoload 'ediff-files-command "ediff" "\ + + +\(fn)" nil nil) + +(autoload 'ediff3-files-command "ediff" "\ + + +\(fn)" nil nil) + +(autoload 'ediff-merge-command "ediff" "\ + + +\(fn)" nil nil) + +(autoload 'ediff-merge-with-ancestor-command "ediff" "\ + + +\(fn)" nil nil) + +(autoload 'ediff-directories-command "ediff" "\ + + +\(fn)" nil nil) + +(autoload 'ediff-directories3-command "ediff" "\ + + +\(fn)" nil nil) + +(autoload 'ediff-merge-directories-command "ediff" "\ + + +\(fn)" nil nil) + +(autoload 'ediff-merge-directories-with-ancestor-command "ediff" "\ + + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ediff" '("ediff-"))) + +;;;*** + +;;;### (autoloads nil "ediff-diff" "vc/ediff-diff.el" (0 0 0 0)) +;;; Generated autoloads from vc/ediff-diff.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ediff-diff" '("ediff-"))) + +;;;*** + +;;;### (autoloads nil "ediff-help" "vc/ediff-help.el" (0 0 0 0)) +;;; Generated autoloads from vc/ediff-help.el + +(autoload 'ediff-customize "ediff-help" "\ + + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ediff-help" '("ediff-"))) + +;;;*** + +;;;### (autoloads nil "ediff-init" "vc/ediff-init.el" (0 0 0 0)) +;;; Generated autoloads from vc/ediff-init.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ediff-init" '("ediff-" "stipple-pixmap"))) + +;;;*** + +;;;### (autoloads nil "ediff-merg" "vc/ediff-merg.el" (0 0 0 0)) +;;; Generated autoloads from vc/ediff-merg.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ediff-merg" '("ediff-"))) + +;;;*** + +;;;### (autoloads nil "ediff-mult" "vc/ediff-mult.el" (0 0 0 0)) +;;; Generated autoloads from vc/ediff-mult.el + +(autoload 'ediff-show-registry "ediff-mult" "\ +Display Ediff's registry. + +\(fn)" t nil) + +(defalias 'eregistry 'ediff-show-registry) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ediff-mult" '("ediff-"))) + +;;;*** + +;;;### (autoloads nil "ediff-ptch" "vc/ediff-ptch.el" (0 0 0 0)) +;;; Generated autoloads from vc/ediff-ptch.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ediff-ptch" '("ediff-"))) + +;;;*** + +;;;### (autoloads nil "ediff-util" "vc/ediff-util.el" (0 0 0 0)) +;;; Generated autoloads from vc/ediff-util.el + +(autoload 'ediff-toggle-multiframe "ediff-util" "\ +Switch from multiframe display to single-frame display and back. +To change the default, set the variable `ediff-window-setup-function', +which see. + +\(fn)" t nil) + +(autoload 'ediff-toggle-use-toolbar "ediff-util" "\ +Enable or disable Ediff toolbar. +Works only in versions of Emacs that support toolbars. +To change the default, set the variable `ediff-use-toolbar-p', which see. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ediff-util" '("ediff-"))) + +;;;*** + +;;;### (autoloads nil "ediff-vers" "vc/ediff-vers.el" (0 0 0 0)) +;;; Generated autoloads from vc/ediff-vers.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ediff-vers" '("ediff-" "rcs-ediff-view-revision"))) + +;;;*** + +;;;### (autoloads nil "ediff-wind" "vc/ediff-wind.el" (0 0 0 0)) +;;; Generated autoloads from vc/ediff-wind.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ediff-wind" '("ediff-"))) + +;;;*** + +;;;### (autoloads nil "edmacro" "edmacro.el" (0 0 0 0)) +;;; Generated autoloads from edmacro.el +(push (purecopy '(edmacro 2 1)) package--builtin-versions) + +(autoload 'edit-kbd-macro "edmacro" "\ +Edit a keyboard macro. +At the prompt, type any key sequence which is bound to a keyboard macro. +Or, type `C-x e' or RET to edit the last keyboard macro, `C-h l' to edit +the last 300 keystrokes as a keyboard macro, or `\\[execute-extended-command]' to edit a macro by +its command name. +With a prefix argument, format the macro in a more concise way. + +\(fn KEYS &optional PREFIX FINISH-HOOK STORE-HOOK)" t nil) + +(autoload 'edit-last-kbd-macro "edmacro" "\ +Edit the most recently defined keyboard macro. + +\(fn &optional PREFIX)" t nil) + +(autoload 'edit-named-kbd-macro "edmacro" "\ +Edit a keyboard macro which has been given a name by `name-last-kbd-macro'. + +\(fn &optional PREFIX)" t nil) + +(autoload 'read-kbd-macro "edmacro" "\ +Read the region as a keyboard macro definition. +The region is interpreted as spelled-out keystrokes, e.g., \"M-x abc RET\". +See documentation for `edmacro-mode' for details. +Leading/trailing \"C-x (\" and \"C-x )\" in the text are allowed and ignored. +The resulting macro is installed as the \"current\" keyboard macro. + +In Lisp, may also be called with a single STRING argument in which case +the result is returned rather than being installed as the current macro. +The result will be a string if possible, otherwise an event vector. +Second argument NEED-VECTOR means to return an event vector always. + +\(fn START &optional END)" t nil) + +(autoload 'format-kbd-macro "edmacro" "\ +Return the keyboard macro MACRO as a human-readable string. +This string is suitable for passing to `read-kbd-macro'. +Second argument VERBOSE means to put one command per line with comments. +If VERBOSE is `1', put everything on one line. If VERBOSE is omitted +or nil, use a compact 80-column format. + +\(fn &optional MACRO VERBOSE)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "edmacro" '("edmacro-"))) + +;;;*** + +;;;### (autoloads nil "edt" "emulation/edt.el" (0 0 0 0)) +;;; Generated autoloads from emulation/edt.el + +(autoload 'edt-set-scroll-margins "edt" "\ +Set scroll margins. +Argument TOP is the top margin in number of lines or percent of window. +Argument BOTTOM is the bottom margin in number of lines or percent of window. + +\(fn TOP BOTTOM)" t nil) + +(autoload 'edt-emulation-on "edt" "\ +Turn on EDT Emulation. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "edt" '("edt-"))) + +;;;*** + +;;;### (autoloads nil "edt-lk201" "emulation/edt-lk201.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from emulation/edt-lk201.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "edt-lk201" '("*EDT-keys*"))) + +;;;*** + +;;;### (autoloads nil "edt-mapper" "emulation/edt-mapper.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from emulation/edt-mapper.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "edt-mapper" '("edt-"))) + +;;;*** + +;;;### (autoloads nil "edt-pc" "emulation/edt-pc.el" (0 0 0 0)) +;;; Generated autoloads from emulation/edt-pc.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "edt-pc" '("*EDT-keys*"))) + +;;;*** + +;;;### (autoloads nil "edt-vt100" "emulation/edt-vt100.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from emulation/edt-vt100.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "edt-vt100" '("edt-set-term-width-"))) + +;;;*** + +;;;### (autoloads nil "ehelp" "ehelp.el" (0 0 0 0)) +;;; Generated autoloads from ehelp.el + +(autoload 'with-electric-help "ehelp" "\ +Pop up an \"electric\" help buffer. +THUNK is a function of no arguments which is called to initialize the +contents of BUFFER. BUFFER defaults to `*Help*'. BUFFER will be +erased before THUNK is called unless NOERASE is non-nil. THUNK will +be called while BUFFER is current and with `standard-output' bound to +the buffer specified by BUFFER. + +If THUNK returns nil, we display BUFFER starting at the top, and shrink +the window to fit. If THUNK returns non-nil, we don't do those things. + +After THUNK has been called, this function \"electrically\" pops up a +window in which BUFFER is displayed and allows the user to scroll +through that buffer in `electric-help-mode'. The window's height will +be at least MINHEIGHT if this value is non-nil. + +If THUNK returns nil, we display BUFFER starting at the top, and +shrink the window to fit if `electric-help-shrink-window' is non-nil. +If THUNK returns non-nil, we don't do those things. + +When the user exits (with `electric-help-exit', or otherwise), the help +buffer's window disappears (i.e., we use `save-window-excursion'), and +BUFFER is put back into its original major mode. + +\(fn THUNK &optional BUFFER NOERASE MINHEIGHT)" nil nil) + +(autoload 'electric-helpify "ehelp" "\ + + +\(fn FUN &optional NAME)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ehelp" '("electric-" "ehelp-"))) + +;;;*** + +;;;### (autoloads nil "eieio" "emacs-lisp/eieio.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/eieio.el +(push (purecopy '(eieio 1 4)) package--builtin-versions) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eieio" '("eieio-" "oref" "oset" "obj" "find-class" "set-slot-value" "same-class-p" "slot-" "child-of-class-p" "with-slots" "defclass"))) + +;;;*** + +;;;### (autoloads nil "eieio-base" "emacs-lisp/eieio-base.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from emacs-lisp/eieio-base.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eieio-base" '("eieio-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "eieio-compat" +;;;;;; "emacs-lisp/eieio-compat.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/eieio-compat.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eieio-compat" '("no-" "next-method-p" "generic-p" "eieio--generic-static-symbol-specializers"))) + +;;;*** + +;;;### (autoloads nil "eieio-core" "emacs-lisp/eieio-core.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from emacs-lisp/eieio-core.el +(push (purecopy '(eieio-core 1 4)) package--builtin-versions) + +(autoload 'eieio-defclass-autoload "eieio-core" "\ +Create autoload symbols for the EIEIO class CNAME. +SUPERCLASSES are the superclasses that CNAME inherits from. +DOC is the docstring for CNAME. +This function creates a mock-class for CNAME and adds it into +SUPERCLASSES as children. +It creates an autoload function for CNAME's constructor. + +\(fn CNAME SUPERCLASSES FILENAME DOC)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eieio-core" '("eieio-" "invalid-slot-" "inconsistent-class-hierarchy" "unbound-slot" "class-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "eieio-custom" +;;;;;; "emacs-lisp/eieio-custom.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/eieio-custom.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eieio-custom" '("eieio-"))) + +;;;*** + +;;;### (autoloads nil "eieio-datadebug" "emacs-lisp/eieio-datadebug.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/eieio-datadebug.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eieio-datadebug" '("data-debug-insert-object-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "eieio-opt" "emacs-lisp/eieio-opt.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/eieio-opt.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eieio-opt" '("eieio-"))) + +;;;*** + +;;;### (autoloads nil "eieio-speedbar" "emacs-lisp/eieio-speedbar.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/eieio-speedbar.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eieio-speedbar" '("eieio-speedbar"))) + +;;;*** + +;;;### (autoloads nil "elec-pair" "elec-pair.el" (0 0 0 0)) +;;; Generated autoloads from elec-pair.el + +(defvar electric-pair-text-pairs '((34 . 34) ((nth 0 electric-quote-chars) nth 1 electric-quote-chars) ((nth 2 electric-quote-chars) nth 3 electric-quote-chars)) "\ +Alist of pairs that should always be used in comments and strings. + +Pairs of delimiters in this list are a fallback in case they have +no syntax relevant to `electric-pair-mode' in the syntax table +defined in `electric-pair-text-syntax-table'") + +(custom-autoload 'electric-pair-text-pairs "elec-pair" t) + +(defvar electric-pair-mode nil "\ +Non-nil if Electric-Pair mode is enabled. +See the `electric-pair-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `electric-pair-mode'.") + +(custom-autoload 'electric-pair-mode "elec-pair" nil) + +(autoload 'electric-pair-mode "elec-pair" "\ +Toggle automatic parens pairing (Electric Pair mode). +With a prefix argument ARG, enable Electric Pair mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Electric Pair mode is a global minor mode. When enabled, typing +an open parenthesis automatically inserts the corresponding +closing parenthesis. (Likewise for brackets, etc.). To toggle +the mode in a single buffer, use `electric-pair-local-mode'. + +\(fn &optional ARG)" t nil) + +(autoload 'electric-pair-local-mode "elec-pair" "\ +Toggle `electric-pair-mode' only in this buffer. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "elec-pair" '("electric-pair-"))) + +;;;*** + +;;;### (autoloads nil "elide-head" "elide-head.el" (0 0 0 0)) +;;; Generated autoloads from elide-head.el + +(autoload 'elide-head "elide-head" "\ +Hide header material in buffer according to `elide-head-headers-to-hide'. + +The header is made invisible with an overlay. With a prefix arg, show +an elided material again. + +This is suitable as an entry on `find-file-hook' or appropriate mode hooks. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "elide-head" '("elide-head-"))) + +;;;*** + +;;;### (autoloads nil "elint" "emacs-lisp/elint.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/elint.el + +(autoload 'elint-file "elint" "\ +Lint the file FILE. + +\(fn FILE)" t nil) + +(autoload 'elint-directory "elint" "\ +Lint all the .el files in DIRECTORY. +A complicated directory may require a lot of memory. + +\(fn DIRECTORY)" t nil) + +(autoload 'elint-current-buffer "elint" "\ +Lint the current buffer. +If necessary, this first calls `elint-initialize'. + +\(fn)" t nil) + +(autoload 'elint-defun "elint" "\ +Lint the function at point. +If necessary, this first calls `elint-initialize'. + +\(fn)" t nil) + +(autoload 'elint-initialize "elint" "\ +Initialize elint. +If elint is already initialized, this does nothing, unless +optional prefix argument REINIT is non-nil. + +\(fn &optional REINIT)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "elint" '("elint-"))) + +;;;*** + +;;;### (autoloads nil "elp" "emacs-lisp/elp.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/elp.el + +(autoload 'elp-instrument-function "elp" "\ +Instrument FUNSYM for profiling. +FUNSYM must be a symbol of a defined function. + +\(fn FUNSYM)" t nil) + +(autoload 'elp-instrument-list "elp" "\ +Instrument, for profiling, all functions in `elp-function-list'. +Use optional LIST if provided instead. +If called interactively, read LIST using the minibuffer. + +\(fn &optional LIST)" t nil) + +(autoload 'elp-instrument-package "elp" "\ +Instrument for profiling, all functions which start with PREFIX. +For example, to instrument all ELP functions, do the following: + + \\[elp-instrument-package] RET elp- RET + +\(fn PREFIX)" t nil) + +(autoload 'elp-results "elp" "\ +Display current profiling results. +If `elp-reset-after-results' is non-nil, then current profiling +information for all instrumented functions is reset after results are +displayed. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "elp" '("elp-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "em-alias" "eshell/em-alias.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from eshell/em-alias.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "em-alias" '("eshell" "pcomplete/eshell-mode/alias"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "em-banner" "eshell/em-banner.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from eshell/em-banner.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "em-banner" '("eshell-banner-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "em-basic" "eshell/em-basic.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from eshell/em-basic.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "em-basic" '("eshell"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "em-cmpl" "eshell/em-cmpl.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from eshell/em-cmpl.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "em-cmpl" '("eshell-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "em-dirs" "eshell/em-dirs.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from eshell/em-dirs.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "em-dirs" '("eshell"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "em-glob" "eshell/em-glob.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from eshell/em-glob.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "em-glob" '("eshell-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "em-hist" "eshell/em-hist.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from eshell/em-hist.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "em-hist" '("eshell"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "em-ls" "eshell/em-ls.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from eshell/em-ls.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "em-ls" '("eshell"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "em-pred" "eshell/em-pred.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from eshell/em-pred.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "em-pred" '("eshell-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "em-prompt" "eshell/em-prompt.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from eshell/em-prompt.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "em-prompt" '("eshell-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "em-rebind" "eshell/em-rebind.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from eshell/em-rebind.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "em-rebind" '("eshell-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "em-script" "eshell/em-script.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from eshell/em-script.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "em-script" '("eshell"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "em-smart" "eshell/em-smart.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from eshell/em-smart.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "em-smart" '("eshell-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "em-term" "eshell/em-term.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from eshell/em-term.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "em-term" '("eshell-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "em-tramp" "eshell/em-tramp.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from eshell/em-tramp.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "em-tramp" '("eshell"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "em-unix" "eshell/em-unix.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from eshell/em-unix.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "em-unix" '("eshell" "nil-blank-string" "pcomplete/"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "em-xtra" "eshell/em-xtra.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from eshell/em-xtra.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "em-xtra" '("pcomplete/bcc" "eshell/"))) + +;;;*** + +;;;### (autoloads nil "emacs-lock" "emacs-lock.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lock.el + +(autoload 'emacs-lock-mode "emacs-lock" "\ +Toggle Emacs Lock mode in the current buffer. +If called with a plain prefix argument, ask for the locking mode +to be used. With any other prefix ARG, turn mode on if ARG is +positive, off otherwise. If called from Lisp, enable the mode if +ARG is omitted or nil. + +Initially, if the user does not pass an explicit locking mode, it +defaults to `emacs-lock-default-locking-mode' (which see); +afterwards, the locking mode most recently set on the buffer is +used instead. + +When called from Elisp code, ARG can be any locking mode: + + exit -- Emacs cannot exit while the buffer is locked + kill -- the buffer cannot be killed, but Emacs can exit as usual + all -- the buffer is locked against both actions + +Other values are interpreted as usual. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emacs-lock" '("toggle-emacs-lock" "emacs-lock-"))) + +;;;*** + +;;;### (autoloads nil "emacsbug" "mail/emacsbug.el" (0 0 0 0)) +;;; Generated autoloads from mail/emacsbug.el + +(autoload 'report-emacs-bug "emacsbug" "\ +Report a bug in GNU Emacs. +Prompts for bug subject. Leaves you in a mail buffer. + +\(fn TOPIC &optional UNUSED)" t nil) + +(set-advertised-calling-convention 'report-emacs-bug '(topic) '"24.5") + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emacsbug" '("report-emacs-bug-"))) + +;;;*** + +;;;### (autoloads nil "emerge" "vc/emerge.el" (0 0 0 0)) +;;; Generated autoloads from vc/emerge.el + +(autoload 'emerge-files "emerge" "\ +Run Emerge on two files. + +\(fn ARG FILE-A FILE-B FILE-OUT &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) + +(autoload 'emerge-files-with-ancestor "emerge" "\ +Run Emerge on two files, giving another file as the ancestor. + +\(fn ARG FILE-A FILE-B FILE-ANCESTOR FILE-OUT &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) + +(autoload 'emerge-buffers "emerge" "\ +Run Emerge on two buffers. + +\(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) + +(autoload 'emerge-buffers-with-ancestor "emerge" "\ +Run Emerge on two buffers, giving another buffer as the ancestor. + +\(fn BUFFER-A BUFFER-B BUFFER-ANCESTOR &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) + +(autoload 'emerge-files-command "emerge" "\ + + +\(fn)" nil nil) + +(autoload 'emerge-files-with-ancestor-command "emerge" "\ + + +\(fn)" nil nil) + +(autoload 'emerge-files-remote "emerge" "\ + + +\(fn FILE-A FILE-B FILE-OUT)" nil nil) + +(autoload 'emerge-files-with-ancestor-remote "emerge" "\ + + +\(fn FILE-A FILE-B FILE-ANC FILE-OUT)" nil nil) + +(autoload 'emerge-revisions "emerge" "\ +Emerge two RCS revisions of a file. + +\(fn ARG FILE REVISION-A REVISION-B &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) + +(autoload 'emerge-revisions-with-ancestor "emerge" "\ +Emerge two RCS revisions of a file, with another revision as ancestor. + +\(fn ARG FILE REVISION-A REVISION-B ANCESTOR &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) + +(autoload 'emerge-merge-directories "emerge" "\ + + +\(fn A-DIR B-DIR ANCESTOR-DIR OUTPUT-DIR)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emerge" '("emerge-"))) + +;;;*** + +;;;### (autoloads nil "enriched" "textmodes/enriched.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/enriched.el + +(autoload 'enriched-mode "enriched" "\ +Minor mode for editing text/enriched files. +These are files with embedded formatting information in the MIME standard +text/enriched format. + +With a prefix argument ARG, enable the mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode +if ARG is omitted or nil. + +Turning the mode on or off runs `enriched-mode-hook'. + +More information about Enriched mode is available in the file +\"enriched.txt\" in `data-directory'. + +Commands: + +\\{enriched-mode-map} + +\(fn &optional ARG)" t nil) + +(autoload 'enriched-encode "enriched" "\ + + +\(fn FROM TO ORIG-BUF)" nil nil) + +(autoload 'enriched-decode "enriched" "\ + + +\(fn FROM TO)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "enriched" '("enriched-"))) + +;;;*** + +;;;### (autoloads nil "epa" "epa.el" (0 0 0 0)) +;;; Generated autoloads from epa.el + +(autoload 'epa-list-keys "epa" "\ +List all keys matched with NAME from the public keyring. + +\(fn &optional NAME)" t nil) + +(autoload 'epa-list-secret-keys "epa" "\ +List all keys matched with NAME from the private keyring. + +\(fn &optional NAME)" t nil) + +(autoload 'epa-select-keys "epa" "\ +Display a user's keyring and ask him to select keys. +CONTEXT is an epg-context. +PROMPT is a string to prompt with. +NAMES is a list of strings to be matched with keys. If it is nil, all +the keys are listed. +If SECRET is non-nil, list secret keys instead of public keys. + +\(fn CONTEXT PROMPT &optional NAMES SECRET)" nil nil) + +(autoload 'epa-decrypt-file "epa" "\ +Decrypt DECRYPT-FILE into PLAIN-FILE. +If you do not specify PLAIN-FILE, this functions prompts for the value to use. + +\(fn DECRYPT-FILE &optional PLAIN-FILE)" t nil) + +(autoload 'epa-verify-file "epa" "\ +Verify FILE. + +\(fn FILE)" t nil) + +(autoload 'epa-sign-file "epa" "\ +Sign FILE by SIGNERS keys selected. + +\(fn FILE SIGNERS MODE)" t nil) + +(autoload 'epa-encrypt-file "epa" "\ +Encrypt FILE for RECIPIENTS. + +\(fn FILE RECIPIENTS)" t nil) + +(autoload 'epa-decrypt-region "epa" "\ +Decrypt the current region between START and END. + +If MAKE-BUFFER-FUNCTION is non-nil, call it to prepare an output buffer. +It should return that buffer. If it copies the input, it should +delete the text now being decrypted. It should leave point at the +proper place to insert the plaintext. + +Be careful about using this command in Lisp programs! +Since this function operates on regions, it does some tricks such +as coding-system detection and unibyte/multibyte conversion. If +you are sure how the data in the region should be treated, you +should consider using the string based counterpart +`epg-decrypt-string', or the file based counterpart +`epg-decrypt-file' instead. + +For example: + +\(let ((context (epg-make-context \\='OpenPGP))) + (decode-coding-string + (epg-decrypt-string context (buffer-substring start end)) + \\='utf-8)) + +\(fn START END &optional MAKE-BUFFER-FUNCTION)" t nil) + +(autoload 'epa-decrypt-armor-in-region "epa" "\ +Decrypt OpenPGP armors in the current region between START and END. + +Don't use this command in Lisp programs! +See the reason described in the `epa-decrypt-region' documentation. + +\(fn START END)" t nil) + +(function-put 'epa-decrypt-armor-in-region 'interactive-only 't) + +(autoload 'epa-verify-region "epa" "\ +Verify the current region between START and END. + +Don't use this command in Lisp programs! +Since this function operates on regions, it does some tricks such +as coding-system detection and unibyte/multibyte conversion. If +you are sure how the data in the region should be treated, you +should consider using the string based counterpart +`epg-verify-string', or the file based counterpart +`epg-verify-file' instead. + +For example: + +\(let ((context (epg-make-context \\='OpenPGP))) + (decode-coding-string + (epg-verify-string context (buffer-substring start end)) + \\='utf-8)) + +\(fn START END)" t nil) + +(function-put 'epa-verify-region 'interactive-only 't) + +(autoload 'epa-verify-cleartext-in-region "epa" "\ +Verify OpenPGP cleartext signed messages in the current region +between START and END. + +Don't use this command in Lisp programs! +See the reason described in the `epa-verify-region' documentation. + +\(fn START END)" t nil) + +(function-put 'epa-verify-cleartext-in-region 'interactive-only 't) + +(autoload 'epa-sign-region "epa" "\ +Sign the current region between START and END by SIGNERS keys selected. + +Don't use this command in Lisp programs! +Since this function operates on regions, it does some tricks such +as coding-system detection and unibyte/multibyte conversion. If +you are sure how the data should be treated, you should consider +using the string based counterpart `epg-sign-string', or the file +based counterpart `epg-sign-file' instead. + +For example: + +\(let ((context (epg-make-context \\='OpenPGP))) + (epg-sign-string + context + (encode-coding-string (buffer-substring start end) \\='utf-8))) + +\(fn START END SIGNERS MODE)" t nil) + +(function-put 'epa-sign-region 'interactive-only 't) + +(autoload 'epa-encrypt-region "epa" "\ +Encrypt the current region between START and END for RECIPIENTS. + +Don't use this command in Lisp programs! +Since this function operates on regions, it does some tricks such +as coding-system detection and unibyte/multibyte conversion. If +you are sure how the data should be treated, you should consider +using the string based counterpart `epg-encrypt-string', or the +file based counterpart `epg-encrypt-file' instead. + +For example: + +\(let ((context (epg-make-context \\='OpenPGP))) + (epg-encrypt-string + context + (encode-coding-string (buffer-substring start end) \\='utf-8) + nil)) + +\(fn START END RECIPIENTS SIGN SIGNERS)" t nil) + +(function-put 'epa-encrypt-region 'interactive-only 't) + +(autoload 'epa-delete-keys "epa" "\ +Delete selected KEYS. + +\(fn KEYS &optional ALLOW-SECRET)" t nil) + +(autoload 'epa-import-keys "epa" "\ +Import keys from FILE. + +\(fn FILE)" t nil) + +(autoload 'epa-import-keys-region "epa" "\ +Import keys from the region. + +\(fn START END)" t nil) + +(autoload 'epa-import-armor-in-region "epa" "\ +Import keys in the OpenPGP armor format in the current region +between START and END. + +\(fn START END)" t nil) + +(autoload 'epa-export-keys "epa" "\ +Export selected KEYS to FILE. + +\(fn KEYS FILE)" t nil) + +(autoload 'epa-insert-keys "epa" "\ +Insert selected KEYS after the point. + +\(fn KEYS)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "epa" '("epa-"))) + +;;;*** + +;;;### (autoloads nil "epa-dired" "epa-dired.el" (0 0 0 0)) +;;; Generated autoloads from epa-dired.el + +(autoload 'epa-dired-do-decrypt "epa-dired" "\ +Decrypt marked files. + +\(fn)" t nil) + +(autoload 'epa-dired-do-verify "epa-dired" "\ +Verify marked files. + +\(fn)" t nil) + +(autoload 'epa-dired-do-sign "epa-dired" "\ +Sign marked files. + +\(fn)" t nil) + +(autoload 'epa-dired-do-encrypt "epa-dired" "\ +Encrypt marked files. + +\(fn)" t nil) + +;;;*** + +;;;### (autoloads nil "epa-file" "epa-file.el" (0 0 0 0)) +;;; Generated autoloads from epa-file.el + +(autoload 'epa-file-handler "epa-file" "\ + + +\(fn OPERATION &rest ARGS)" nil nil) + +(autoload 'epa-file-enable "epa-file" "\ + + +\(fn)" t nil) + +(autoload 'epa-file-disable "epa-file" "\ + + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "epa-file" '("epa-"))) + +;;;*** + +;;;### (autoloads nil "epa-mail" "epa-mail.el" (0 0 0 0)) +;;; Generated autoloads from epa-mail.el + +(autoload 'epa-mail-mode "epa-mail" "\ +A minor-mode for composing encrypted/clearsigned mails. +With a prefix argument ARG, enable the mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode +if ARG is omitted or nil. + +\(fn &optional ARG)" t nil) + +(autoload 'epa-mail-decrypt "epa-mail" "\ +Decrypt OpenPGP armors in the current buffer. +The buffer is expected to contain a mail message. + +\(fn)" t nil) + +(function-put 'epa-mail-decrypt 'interactive-only 't) + +(autoload 'epa-mail-verify "epa-mail" "\ +Verify OpenPGP cleartext signed messages in the current buffer. +The buffer is expected to contain a mail message. + +\(fn)" t nil) + +(function-put 'epa-mail-verify 'interactive-only 't) + +(autoload 'epa-mail-sign "epa-mail" "\ +Sign the current buffer. +The buffer is expected to contain a mail message. + +\(fn START END SIGNERS MODE)" t nil) + +(function-put 'epa-mail-sign 'interactive-only 't) + +(autoload 'epa-mail-encrypt "epa-mail" "\ +Encrypt the outgoing mail message in the current buffer. +Takes the recipients from the text in the header in the buffer +and translates them through `epa-mail-aliases'. +With prefix argument, asks you to select among them interactively +and also whether and how to sign. + +Called from Lisp, the optional argument RECIPIENTS is a list +of recipient addresses, t to perform symmetric encryption, +or nil meaning use the defaults. + +SIGNERS is a list of keys to sign the message with. + +\(fn &optional RECIPIENTS SIGNERS)" t nil) + +(autoload 'epa-mail-import-keys "epa-mail" "\ +Import keys in the OpenPGP armor format in the current buffer. +The buffer is expected to contain a mail message. + +\(fn)" t nil) + +(function-put 'epa-mail-import-keys 'interactive-only 't) + +(defvar epa-global-mail-mode nil "\ +Non-nil if Epa-Global-Mail mode is enabled. +See the `epa-global-mail-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `epa-global-mail-mode'.") + +(custom-autoload 'epa-global-mail-mode "epa-mail" nil) + +(autoload 'epa-global-mail-mode "epa-mail" "\ +Minor mode to hook EasyPG into Mail mode. +With a prefix argument ARG, enable the mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode +if ARG is omitted or nil. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "epa-mail" '("epa-mail-"))) + +;;;*** + +;;;### (autoloads nil "epg" "epg.el" (0 0 0 0)) +;;; Generated autoloads from epg.el +(push (purecopy '(epg 1 0 0)) package--builtin-versions) + +(autoload 'epg-make-context "epg" "\ +Return a context object. + +\(fn &optional PROTOCOL ARMOR TEXTMODE INCLUDE-CERTS CIPHER-ALGORITHM DIGEST-ALGORITHM COMPRESS-ALGORITHM)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "epg" '("epg-"))) + +;;;*** + +;;;### (autoloads nil "epg-config" "epg-config.el" (0 0 0 0)) +;;; Generated autoloads from epg-config.el + +(autoload 'epg-find-configuration "epg-config" "\ +Find or create a usable configuration to handle PROTOCOL. +This function first looks at the existing configuration found by +the previous invocation of this function, unless NO-CACHE is non-nil. + +Then it walks through PROGRAM-ALIST or +`epg-config--program-alist'. If `epg-gpg-program' or +`epg-gpgsm-program' is already set with custom, use it. +Otherwise, it tries the programs listed in the entry until the +version requirement is met. + +\(fn PROTOCOL &optional NO-CACHE PROGRAM-ALIST)" nil nil) + +(autoload 'epg-configuration "epg-config" "\ +Return a list of internal configuration parameters of `epg-gpg-program'. + +\(fn)" nil nil) + +(make-obsolete 'epg-configuration 'epg-find-configuration '"25.1") + +(autoload 'epg-check-configuration "epg-config" "\ +Verify that a sufficient version of GnuPG is installed. + +\(fn CONFIG &optional MINIMUM-VERSION)" nil nil) + +(autoload 'epg-expand-group "epg-config" "\ +Look at CONFIG and try to expand GROUP. + +\(fn CONFIG GROUP)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "epg-config" '("epg-"))) + +;;;*** + +;;;### (autoloads nil "erc" "erc/erc.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc.el +(push (purecopy '(erc 5 3)) package--builtin-versions) + +(autoload 'erc-select-read-args "erc" "\ +Prompt the user for values of nick, server, port, and password. + +\(fn)" nil nil) + +(autoload 'erc "erc" "\ +ERC is a powerful, modular, and extensible IRC client. +This function is the main entry point for ERC. + +It permits you to select connection parameters, and then starts ERC. + +Non-interactively, it takes the keyword arguments + (server (erc-compute-server)) + (port (erc-compute-port)) + (nick (erc-compute-nick)) + password + (full-name (erc-compute-full-name))) + +That is, if called with + + (erc :server \"irc.freenode.net\" :full-name \"Harry S Truman\") + +then the server and full-name will be set to those values, whereas +`erc-compute-port', `erc-compute-nick' and `erc-compute-full-name' will +be invoked for the values of the other parameters. + +\(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK (erc-compute-nick)) PASSWORD (FULL-NAME (erc-compute-full-name)))" t nil) + +(defalias 'erc-select 'erc) + +(autoload 'erc-tls "erc" "\ +Interactively select TLS connection parameters and run ERC. +Arguments are the same as for `erc'. + +\(fn &rest R)" t nil) + +(autoload 'erc-handle-irc-url "erc" "\ +Use ERC to IRC on HOST:PORT in CHANNEL as USER with PASSWORD. +If ERC is already connected to HOST:PORT, simply /join CHANNEL. +Otherwise, connect to HOST:PORT as USER and /join CHANNEL. + +\(fn HOST PORT CHANNEL USER PASSWORD)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc" '("erc-" "define-erc-module"))) + +;;;*** + +;;;### (autoloads nil "erc-autoaway" "erc/erc-autoaway.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from erc/erc-autoaway.el + (autoload 'erc-autoaway-mode "erc-autoaway") + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-autoaway" '("erc-auto" "autoaway"))) + +;;;*** + +;;;### (autoloads nil "erc-backend" "erc/erc-backend.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-backend.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-backend" '("erc-"))) + +;;;*** + +;;;### (autoloads nil "erc-button" "erc/erc-button.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-button.el + (autoload 'erc-button-mode "erc-button" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-button" '("erc-" "button"))) + +;;;*** + +;;;### (autoloads nil "erc-capab" "erc/erc-capab.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-capab.el + (autoload 'erc-capab-identify-mode "erc-capab" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-capab" '("erc-capab-identify-" "capab-identify"))) + +;;;*** + +;;;### (autoloads nil "erc-compat" "erc/erc-compat.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-compat.el + (autoload 'erc-define-minor-mode "erc-compat") + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-compat" '("erc-"))) + +;;;*** + +;;;### (autoloads nil "erc-dcc" "erc/erc-dcc.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-dcc.el + (autoload 'erc-dcc-mode "erc-dcc") + +(autoload 'erc-cmd-DCC "erc-dcc" "\ +Parser for /dcc command. +This figures out the dcc subcommand and calls the appropriate routine to +handle it. The function dispatched should be named \"erc-dcc-do-FOO-command\", +where FOO is one of CLOSE, GET, SEND, LIST, CHAT, etc. + +\(fn CMD &rest ARGS)" nil nil) + +(autoload 'pcomplete/erc-mode/DCC "erc-dcc" "\ +Provides completion for the /DCC command. + +\(fn)" nil nil) + +(defvar erc-ctcp-query-DCC-hook '(erc-ctcp-query-DCC) "\ +Hook variable for CTCP DCC queries.") + +(autoload 'erc-ctcp-query-DCC "erc-dcc" "\ +The function called when a CTCP DCC request is detected by the client. +It examines the DCC subcommand, and calls the appropriate routine for +that subcommand. + +\(fn PROC NICK LOGIN HOST TO QUERY)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-dcc" '("erc-" "pcomplete/erc-mode/" "dcc"))) + +;;;*** + +;;;### (autoloads nil "erc-desktop-notifications" "erc/erc-desktop-notifications.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from erc/erc-desktop-notifications.el +(autoload 'erc-notifications-mode "erc-desktop-notifications" "" t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-desktop-notifications" '("notifications" "erc-notifications-"))) + +;;;*** + +;;;### (autoloads nil "erc-ezbounce" "erc/erc-ezbounce.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from erc/erc-ezbounce.el + +(autoload 'erc-cmd-ezb "erc-ezbounce" "\ +Send EZB commands to the EZBouncer verbatim. + +\(fn LINE &optional FORCE)" nil nil) + +(autoload 'erc-ezb-get-login "erc-ezbounce" "\ +Return an appropriate EZBounce login for SERVER and PORT. +Look up entries in `erc-ezb-login-alist'. If the username or password +in the alist is nil, prompt for the appropriate values. + +\(fn SERVER PORT)" nil nil) + +(autoload 'erc-ezb-lookup-action "erc-ezbounce" "\ + + +\(fn MESSAGE)" nil nil) + +(autoload 'erc-ezb-notice-autodetect "erc-ezbounce" "\ +React on an EZBounce NOTICE request. + +\(fn PROC PARSED)" nil nil) + +(autoload 'erc-ezb-identify "erc-ezbounce" "\ +Identify to the EZBouncer server. + +\(fn MESSAGE)" nil nil) + +(autoload 'erc-ezb-init-session-list "erc-ezbounce" "\ +Reset the EZBounce session list to nil. + +\(fn MESSAGE)" nil nil) + +(autoload 'erc-ezb-end-of-session-list "erc-ezbounce" "\ +Indicate the end of the EZBounce session listing. + +\(fn MESSAGE)" nil nil) + +(autoload 'erc-ezb-add-session "erc-ezbounce" "\ +Add an EZBounce session to the session list. + +\(fn MESSAGE)" nil nil) + +(autoload 'erc-ezb-select "erc-ezbounce" "\ +Select an IRC server to use by EZBounce, in ERC style. + +\(fn MESSAGE)" nil nil) + +(autoload 'erc-ezb-select-session "erc-ezbounce" "\ +Select a detached EZBounce session. + +\(fn)" nil nil) + +(autoload 'erc-ezb-initialize "erc-ezbounce" "\ +Add EZBouncer convenience functions to ERC. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-ezbounce" '("erc-ezb-"))) + +;;;*** + +;;;### (autoloads nil "erc-fill" "erc/erc-fill.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-fill.el + (autoload 'erc-fill-mode "erc-fill" nil t) + +(autoload 'erc-fill "erc-fill" "\ +Fill a region using the function referenced in `erc-fill-function'. +You can put this on `erc-insert-modify-hook' and/or `erc-send-modify-hook'. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-fill" '("erc-"))) + +;;;*** + +;;;### (autoloads nil "erc-goodies" "erc/erc-goodies.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-goodies.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-goodies" '("erc-" "unmorse" "scrolltobottom" "smiley" "irccontrols" "noncommands" "keep-place" "move-to-prompt" "readonly"))) + +;;;*** + +;;;### (autoloads nil "erc-ibuffer" "erc/erc-ibuffer.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-ibuffer.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-ibuffer" '("erc-"))) + +;;;*** + +;;;### (autoloads nil "erc-identd" "erc/erc-identd.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-identd.el + (autoload 'erc-identd-mode "erc-identd") + +(autoload 'erc-identd-start "erc-identd" "\ +Start an identd server listening to port 8113. +Port 113 (auth) will need to be redirected to port 8113 on your +machine -- using iptables, or a program like redir which can be +run from inetd. The idea is to provide a simple identd server +when you need one, without having to install one globally on your +system. + +\(fn &optional PORT)" t nil) + +(autoload 'erc-identd-stop "erc-identd" "\ + + +\(fn &rest IGNORE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-identd" '("erc-identd-" "identd"))) + +;;;*** + +;;;### (autoloads nil "erc-imenu" "erc/erc-imenu.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-imenu.el + +(autoload 'erc-create-imenu-index "erc-imenu" "\ + + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-imenu" '("erc-unfill-notice"))) + +;;;*** + +;;;### (autoloads nil "erc-join" "erc/erc-join.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-join.el + (autoload 'erc-autojoin-mode "erc-join" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-join" '("erc-" "autojoin"))) + +;;;*** + +;;;### (autoloads nil "erc-lang" "erc/erc-lang.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-lang.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-lang" '("erc-cmd-LANG" "language" "iso-638-languages"))) + +;;;*** + +;;;### (autoloads nil "erc-list" "erc/erc-list.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-list.el + (autoload 'erc-list-mode "erc-list") + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-list" '("erc-" "list"))) + +;;;*** + +;;;### (autoloads nil "erc-log" "erc/erc-log.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-log.el + (autoload 'erc-log-mode "erc-log" nil t) + +(autoload 'erc-logging-enabled "erc-log" "\ +Return non-nil if logging is enabled for BUFFER. +If BUFFER is nil, the value of `current-buffer' is used. +Logging is enabled if `erc-log-channels-directory' is non-nil, the directory +is writable (it will be created as necessary) and +`erc-enable-logging' returns a non-nil value. + +\(fn &optional BUFFER)" nil nil) + +(autoload 'erc-save-buffer-in-logs "erc-log" "\ +Append BUFFER contents to the log file, if logging is enabled. +If BUFFER is not provided, current buffer is used. +Logging is enabled if `erc-logging-enabled' returns non-nil. + +This is normally done on exit, to save the unsaved portion of the +buffer, since only the text that runs off the buffer limit is logged +automatically. + +You can save every individual message by putting this function on +`erc-insert-post-hook'. + +\(fn &optional BUFFER)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-log" '("erc-" "log"))) + +;;;*** + +;;;### (autoloads nil "erc-match" "erc/erc-match.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-match.el + (autoload 'erc-match-mode "erc-match") + +(autoload 'erc-add-pal "erc-match" "\ +Add pal interactively to `erc-pals'. + +\(fn)" t nil) + +(autoload 'erc-delete-pal "erc-match" "\ +Delete pal interactively to `erc-pals'. + +\(fn)" t nil) + +(autoload 'erc-add-fool "erc-match" "\ +Add fool interactively to `erc-fools'. + +\(fn)" t nil) + +(autoload 'erc-delete-fool "erc-match" "\ +Delete fool interactively to `erc-fools'. + +\(fn)" t nil) + +(autoload 'erc-add-keyword "erc-match" "\ +Add keyword interactively to `erc-keywords'. + +\(fn)" t nil) + +(autoload 'erc-delete-keyword "erc-match" "\ +Delete keyword interactively to `erc-keywords'. + +\(fn)" t nil) + +(autoload 'erc-add-dangerous-host "erc-match" "\ +Add dangerous-host interactively to `erc-dangerous-hosts'. + +\(fn)" t nil) + +(autoload 'erc-delete-dangerous-host "erc-match" "\ +Delete dangerous-host interactively to `erc-dangerous-hosts'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-match" '("erc-" "match"))) + +;;;*** + +;;;### (autoloads nil "erc-menu" "erc/erc-menu.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-menu.el + (autoload 'erc-menu-mode "erc-menu" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-menu" '("erc-menu-" "menu"))) + +;;;*** + +;;;### (autoloads nil "erc-netsplit" "erc/erc-netsplit.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from erc/erc-netsplit.el + (autoload 'erc-netsplit-mode "erc-netsplit") + +(autoload 'erc-cmd-WHOLEFT "erc-netsplit" "\ +Show who's gone. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-netsplit" '("erc-" "netsplit"))) + +;;;*** + +;;;### (autoloads nil "erc-networks" "erc/erc-networks.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from erc/erc-networks.el + +(autoload 'erc-determine-network "erc-networks" "\ +Return the name of the network or \"Unknown\" as a symbol. Use the +server parameter NETWORK if provided, otherwise parse the server name and +search for a match in `erc-networks-alist'. + +\(fn)" nil nil) + +(autoload 'erc-server-select "erc-networks" "\ +Interactively select a server to connect to using `erc-server-alist'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-networks" '("erc-" "networks"))) + +;;;*** + +;;;### (autoloads nil "erc-notify" "erc/erc-notify.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-notify.el + (autoload 'erc-notify-mode "erc-notify" nil t) + +(autoload 'erc-cmd-NOTIFY "erc-notify" "\ +Change `erc-notify-list' or list current notify-list members online. +Without args, list the current list of notified people online, +with args, toggle notify status of people. + +\(fn &rest ARGS)" nil nil) + +(autoload 'pcomplete/erc-mode/NOTIFY "erc-notify" "\ + + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-notify" '("erc-" "notify"))) + +;;;*** + +;;;### (autoloads nil "erc-page" "erc/erc-page.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-page.el + (autoload 'erc-page-mode "erc-page") + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-page" '("erc-" "page"))) + +;;;*** + +;;;### (autoloads nil "erc-pcomplete" "erc/erc-pcomplete.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from erc/erc-pcomplete.el + (autoload 'erc-completion-mode "erc-pcomplete" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-pcomplete" '("pcomplete" "erc-pcomplet"))) + +;;;*** + +;;;### (autoloads nil "erc-replace" "erc/erc-replace.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-replace.el + (autoload 'erc-replace-mode "erc-replace") + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-replace" '("replace" "erc-replace-"))) + +;;;*** + +;;;### (autoloads nil "erc-ring" "erc/erc-ring.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-ring.el + (autoload 'erc-ring-mode "erc-ring" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-ring" '("erc-" "ring"))) + +;;;*** + +;;;### (autoloads nil "erc-services" "erc/erc-services.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from erc/erc-services.el + (autoload 'erc-services-mode "erc-services" nil t) + +(autoload 'erc-nickserv-identify-mode "erc-services" "\ +Set up hooks according to which MODE the user has chosen. + +\(fn MODE)" t nil) + +(autoload 'erc-nickserv-identify "erc-services" "\ +Send an \"identify <PASSWORD>\" message to NickServ. +When called interactively, read the password using `read-passwd'. + +\(fn PASSWORD)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-services" '("erc-" "services"))) + +;;;*** + +;;;### (autoloads nil "erc-sound" "erc/erc-sound.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-sound.el + (autoload 'erc-sound-mode "erc-sound") + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-sound" '("erc-" "sound"))) + +;;;*** + +;;;### (autoloads nil "erc-speedbar" "erc/erc-speedbar.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from erc/erc-speedbar.el + +(autoload 'erc-speedbar-browser "erc-speedbar" "\ +Initialize speedbar to display an ERC browser. +This will add a speedbar major display mode. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-speedbar" '("erc-"))) + +;;;*** + +;;;### (autoloads nil "erc-spelling" "erc/erc-spelling.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from erc/erc-spelling.el + (autoload 'erc-spelling-mode "erc-spelling" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-spelling" '("erc-spelling-" "spelling"))) + +;;;*** + +;;;### (autoloads nil "erc-stamp" "erc/erc-stamp.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-stamp.el + (autoload 'erc-timestamp-mode "erc-stamp" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-stamp" '("erc-" "stamp"))) + +;;;*** + +;;;### (autoloads nil "erc-track" "erc/erc-track.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-track.el + +(defvar erc-track-minor-mode nil "\ +Non-nil if Erc-Track minor mode is enabled. +See the `erc-track-minor-mode' command +for a description of this minor mode.") + +(custom-autoload 'erc-track-minor-mode "erc-track" nil) + +(autoload 'erc-track-minor-mode "erc-track" "\ +Toggle mode line display of ERC activity (ERC Track minor mode). +With a prefix argument ARG, enable ERC Track minor mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +ERC Track minor mode is a global minor mode. It exists for the +sole purpose of providing the C-c C-SPC and C-c C-@ keybindings. +Make sure that you have enabled the track module, otherwise the +keybindings will not do anything useful. + +\(fn &optional ARG)" t nil) + (autoload 'erc-track-mode "erc-track" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-track" '("erc-" "track"))) + +;;;*** + +;;;### (autoloads nil "erc-truncate" "erc/erc-truncate.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from erc/erc-truncate.el + (autoload 'erc-truncate-mode "erc-truncate" nil t) + +(autoload 'erc-truncate-buffer-to-size "erc-truncate" "\ +Truncates the buffer to the size SIZE. +If BUFFER is not provided, the current buffer is assumed. The deleted +region is logged if `erc-logging-enabled' returns non-nil. + +\(fn SIZE &optional BUFFER)" nil nil) + +(autoload 'erc-truncate-buffer "erc-truncate" "\ +Truncates the current buffer to `erc-max-buffer-size'. +Meant to be used in hooks, like `erc-insert-post-hook'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-truncate" '("truncate" "erc-max-buffer-size"))) + +;;;*** + +;;;### (autoloads nil "erc-xdcc" "erc/erc-xdcc.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-xdcc.el + (autoload 'erc-xdcc-mode "erc-xdcc") + +(autoload 'erc-xdcc-add-file "erc-xdcc" "\ +Add a file to `erc-xdcc-files'. + +\(fn FILE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "erc-xdcc" '("erc-" "xdcc"))) + +;;;*** + +;;;### (autoloads nil "ert" "emacs-lisp/ert.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/ert.el + +(autoload 'ert-deftest "ert" "\ +Define NAME (a symbol) as a test. + +BODY is evaluated as a `progn' when the test is run. It should +signal a condition on failure or just return if the test passes. + +`should', `should-not', `should-error' and `skip-unless' are +useful for assertions in BODY. + +Use `ert' to run tests interactively. + +Tests that are expected to fail can be marked as such +using :expected-result. See `ert-test-result-type-p' for a +description of valid values for RESULT-TYPE. + +\(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] [:tags \\='(TAG...)] BODY...)" nil t) + +(function-put 'ert-deftest 'doc-string-elt '3) + +(function-put 'ert-deftest 'lisp-indent-function '2) + +(put 'ert-deftest 'lisp-indent-function 2) + +(put 'ert-info 'lisp-indent-function 1) + +(autoload 'ert-run-tests-batch "ert" "\ +Run the tests specified by SELECTOR, printing results to the terminal. + +SELECTOR works as described in `ert-select-tests', except if +SELECTOR is nil, in which case all tests rather than none will be +run; this makes the command line \"emacs -batch -l my-tests.el -f +ert-run-tests-batch-and-exit\" useful. + +Returns the stats object. + +\(fn &optional SELECTOR)" nil nil) + +(autoload 'ert-run-tests-batch-and-exit "ert" "\ +Like `ert-run-tests-batch', but exits Emacs when done. + +The exit status will be 0 if all test results were as expected, 1 +on unexpected results, or 2 if the tool detected an error outside +of the tests (e.g. invalid SELECTOR or bug in the code that runs +the tests). + +\(fn &optional SELECTOR)" nil nil) + +(autoload 'ert-run-tests-interactively "ert" "\ +Run the tests specified by SELECTOR and display the results in a buffer. + +SELECTOR works as described in `ert-select-tests'. +OUTPUT-BUFFER-NAME and MESSAGE-FN should normally be nil; they +are used for automated self-tests and specify which buffer to use +and how to display message. + +\(fn SELECTOR &optional OUTPUT-BUFFER-NAME MESSAGE-FN)" t nil) + +(defalias 'ert 'ert-run-tests-interactively) + +(autoload 'ert-describe-test "ert" "\ +Display the documentation for TEST-OR-TEST-NAME (a symbol or ert-test). + +\(fn TEST-OR-TEST-NAME)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ert" '("ert-"))) + +;;;*** + +;;;### (autoloads nil "ert-x" "emacs-lisp/ert-x.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/ert-x.el + +(put 'ert-with-test-buffer 'lisp-indent-function 1) + +(autoload 'ert-kill-all-test-buffers "ert-x" "\ +Kill all test buffers that are still live. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ert-x" '("ert-"))) + +;;;*** + +;;;### (autoloads nil "esh-arg" "eshell/esh-arg.el" (0 0 0 0)) +;;; Generated autoloads from eshell/esh-arg.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "esh-arg" '("eshell-"))) + +;;;*** + +;;;### (autoloads nil "esh-cmd" "eshell/esh-cmd.el" (0 0 0 0)) +;;; Generated autoloads from eshell/esh-cmd.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "esh-cmd" '("eshell" "pcomplete/eshell-mode/eshell-debug"))) + +;;;*** + +;;;### (autoloads nil "esh-ext" "eshell/esh-ext.el" (0 0 0 0)) +;;; Generated autoloads from eshell/esh-ext.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "esh-ext" '("eshell"))) + +;;;*** + +;;;### (autoloads nil "esh-io" "eshell/esh-io.el" (0 0 0 0)) +;;; Generated autoloads from eshell/esh-io.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "esh-io" '("eshell-"))) + +;;;*** + +;;;### (autoloads nil "esh-mode" "eshell/esh-mode.el" (0 0 0 0)) +;;; Generated autoloads from eshell/esh-mode.el + +(autoload 'eshell-mode "esh-mode" "\ +Emacs shell interactive mode. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "esh-mode" '("eshell"))) + +;;;*** + +;;;### (autoloads nil "esh-module" "eshell/esh-module.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from eshell/esh-module.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "esh-module" '("eshell-"))) + +;;;*** + +;;;### (autoloads nil "esh-opt" "eshell/esh-opt.el" (0 0 0 0)) +;;; Generated autoloads from eshell/esh-opt.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "esh-opt" '("eshell-"))) + +;;;*** + +;;;### (autoloads nil "esh-proc" "eshell/esh-proc.el" (0 0 0 0)) +;;; Generated autoloads from eshell/esh-proc.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "esh-proc" '("eshell"))) + +;;;*** + +;;;### (autoloads nil "esh-util" "eshell/esh-util.el" (0 0 0 0)) +;;; Generated autoloads from eshell/esh-util.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "esh-util" '("eshell-"))) + +;;;*** + +;;;### (autoloads nil "esh-var" "eshell/esh-var.el" (0 0 0 0)) +;;; Generated autoloads from eshell/esh-var.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "esh-var" '("eshell" "pcomplete/eshell-mode/"))) + +;;;*** + +;;;### (autoloads nil "eshell" "eshell/eshell.el" (0 0 0 0)) +;;; Generated autoloads from eshell/eshell.el +(push (purecopy '(eshell 2 4 2)) package--builtin-versions) + +(autoload 'eshell "eshell" "\ +Create an interactive Eshell buffer. +The buffer used for Eshell sessions is determined by the value of +`eshell-buffer-name'. If there is already an Eshell session active in +that buffer, Emacs will simply switch to it. Otherwise, a new session +will begin. A numeric prefix arg (as in `C-u 42 M-x eshell RET') +switches to the session with that number, creating it if necessary. A +nonnumeric prefix arg means to create a new session. Returns the +buffer selected (or created). + +\(fn &optional ARG)" t nil) + +(autoload 'eshell-command "eshell" "\ +Execute the Eshell command string COMMAND. +With prefix ARG, insert output into the current buffer at point. + +\(fn &optional COMMAND ARG)" t nil) + +(autoload 'eshell-command-result "eshell" "\ +Execute the given Eshell COMMAND, and return the result. +The result might be any Lisp object. +If STATUS-VAR is a symbol, it will be set to the exit status of the +command. This is the only way to determine whether the value returned +corresponding to a successful execution. + +\(fn COMMAND &optional STATUS-VAR)" nil nil) + +(define-obsolete-function-alias 'eshell-report-bug 'report-emacs-bug "23.1") + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eshell" '("eshell-"))) + +;;;*** + +;;;### (autoloads nil "etags" "progmodes/etags.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/etags.el + +(defvar tags-file-name nil "\ +File name of tags table. +To switch to a new tags table, do not set this variable; instead, +invoke `visit-tags-table', which is the only reliable way of +setting the value of this variable, whether buffer-local or global. +Use the `etags' program to make a tags table file.") + (put 'tags-file-name 'variable-interactive (purecopy "fVisit tags table: ")) + (put 'tags-file-name 'safe-local-variable 'stringp) + +(defvar tags-case-fold-search 'default "\ +Whether tags operations should be case-sensitive. +A value of t means case-insensitive, a value of nil means case-sensitive. +Any other value means use the setting of `case-fold-search'.") + +(custom-autoload 'tags-case-fold-search "etags" t) + +(defvar tags-table-list nil "\ +List of file names of tags tables to search. +An element that is a directory means the file \"TAGS\" in that directory. +To switch to a new list of tags tables, setting this variable is sufficient. +If you set this variable, do not also set `tags-file-name'. +Use the `etags' program to make a tags table file.") + +(custom-autoload 'tags-table-list "etags" t) + +(defvar tags-compression-info-list (purecopy '("" ".Z" ".bz2" ".gz" ".xz" ".tgz")) "\ +List of extensions tried by etags when `auto-compression-mode' is on. +An empty string means search the non-compressed file.") + +(custom-autoload 'tags-compression-info-list "etags" t) + +(defvar tags-add-tables 'ask-user "\ +Control whether to add a new tags table to the current list. +t means do; nil means don't (always start a new list). +Any other value means ask the user whether to add a new tags table +to the current list (as opposed to starting a new list).") + +(custom-autoload 'tags-add-tables "etags" t) + +(defvar find-tag-hook nil "\ +Hook to be run by \\[find-tag] after finding a tag. See `run-hooks'. +The value in the buffer in which \\[find-tag] is done is used, +not the value in the buffer \\[find-tag] goes to.") + +(custom-autoload 'find-tag-hook "etags" t) + +(defvar find-tag-default-function nil "\ +A function of no arguments used by \\[find-tag] to pick a default tag. +If nil, and the symbol that is the value of `major-mode' +has a `find-tag-default-function' property (see `put'), that is used. +Otherwise, `find-tag-default' is used.") + +(custom-autoload 'find-tag-default-function "etags" t) + +(autoload 'tags-table-mode "etags" "\ +Major mode for tags table file buffers. + +\(fn)" t nil) + +(autoload 'visit-tags-table "etags" "\ +Tell tags commands to use tags table file FILE. +FILE should be the name of a file created with the `etags' program. +A directory name is ok too; it means file TAGS in that directory. + +Normally \\[visit-tags-table] sets the global value of `tags-file-name'. +With a prefix arg, set the buffer-local value instead. When called +from Lisp, if the optional arg LOCAL is non-nil, set the local value. +When you find a tag with \\[find-tag], the buffer it finds the tag +in is given a local value of this variable which is the name of the tags +file the tag was in. + +\(fn FILE &optional LOCAL)" t nil) + +(autoload 'visit-tags-table-buffer "etags" "\ +Select the buffer containing the current tags table. +Optional arg CONT specifies which tags table to visit. +If CONT is a string, visit that file as a tags table. +If CONT is t, visit the next table in `tags-table-list'. +If CONT is the atom `same', don't look for a new table; + just select the buffer visiting `tags-file-name'. +If CONT is nil or absent, choose a first buffer from information in + `tags-file-name', `tags-table-list', `tags-table-list-pointer'. +Optional second arg CBUF, if non-nil, specifies the initial buffer, +which is important if that buffer has a local value of `tags-file-name'. +Returns t if it visits a tags table, or nil if there are no more in the list. + +\(fn &optional CONT CBUF)" nil nil) + +(autoload 'tags-table-files "etags" "\ +Return a list of files in the current tags table. +Assumes the tags table is the current buffer. The file names are returned +as they appeared in the `etags' command that created the table, usually +without directory names. + +\(fn)" nil nil) + +(autoload 'tags-lazy-completion-table "etags" "\ + + +\(fn)" nil nil) + (defun tags-completion-at-point-function () + (if (or tags-table-list tags-file-name) + (progn + (load "etags") + (tags-completion-at-point-function)))) + +(autoload 'find-tag-noselect "etags" "\ +Find tag (in current tags table) whose name contains TAGNAME. +Returns the buffer containing the tag's definition and moves its point there, +but does not select the buffer. +The default for TAGNAME is the expression in the buffer near point. + +If second arg NEXT-P is t (interactively, with prefix arg), search for +another tag that matches the last tagname or regexp used. When there are +multiple matches for a tag, more exact matches are found first. If NEXT-P +is the atom `-' (interactively, with prefix arg that is a negative number +or just \\[negative-argument]), pop back to the previous tag gone to. + +If third arg REGEXP-P is non-nil, treat TAGNAME as a regexp. + +A marker representing the point when this command is invoked is pushed +onto a ring and may be popped back to with \\[pop-tag-mark]. +Contrast this with the ring of marks gone to by the command. + +See documentation of variable `tags-file-name'. + +\(fn TAGNAME &optional NEXT-P REGEXP-P)" t nil) + +(autoload 'find-tag "etags" "\ +Find tag (in current tags table) whose name contains TAGNAME. +Select the buffer containing the tag's definition, and move point there. +The default for TAGNAME is the expression in the buffer around or before point. + +If second arg NEXT-P is t (interactively, with prefix arg), search for +another tag that matches the last tagname or regexp used. When there are +multiple matches for a tag, more exact matches are found first. If NEXT-P +is the atom `-' (interactively, with prefix arg that is a negative number +or just \\[negative-argument]), pop back to the previous tag gone to. + +If third arg REGEXP-P is non-nil, treat TAGNAME as a regexp. + +A marker representing the point when this command is invoked is pushed +onto a ring and may be popped back to with \\[pop-tag-mark]. +Contrast this with the ring of marks gone to by the command. + +See documentation of variable `tags-file-name'. + +\(fn TAGNAME &optional NEXT-P REGEXP-P)" t nil) + +(make-obsolete 'find-tag 'xref-find-definitions '"25.1") + +(autoload 'find-tag-other-window "etags" "\ +Find tag (in current tags table) whose name contains TAGNAME. +Select the buffer containing the tag's definition in another window, and +move point there. The default for TAGNAME is the expression in the buffer +around or before point. + +If second arg NEXT-P is t (interactively, with prefix arg), search for +another tag that matches the last tagname or regexp used. When there are +multiple matches for a tag, more exact matches are found first. If NEXT-P +is negative (interactively, with prefix arg that is a negative number or +just \\[negative-argument]), pop back to the previous tag gone to. + +If third arg REGEXP-P is non-nil, treat TAGNAME as a regexp. + +A marker representing the point when this command is invoked is pushed +onto a ring and may be popped back to with \\[pop-tag-mark]. +Contrast this with the ring of marks gone to by the command. + +See documentation of variable `tags-file-name'. + +\(fn TAGNAME &optional NEXT-P REGEXP-P)" t nil) + +(make-obsolete 'find-tag-other-window 'xref-find-definitions-other-window '"25.1") + +(autoload 'find-tag-other-frame "etags" "\ +Find tag (in current tags table) whose name contains TAGNAME. +Select the buffer containing the tag's definition in another frame, and +move point there. The default for TAGNAME is the expression in the buffer +around or before point. + +If second arg NEXT-P is t (interactively, with prefix arg), search for +another tag that matches the last tagname or regexp used. When there are +multiple matches for a tag, more exact matches are found first. If NEXT-P +is negative (interactively, with prefix arg that is a negative number or +just \\[negative-argument]), pop back to the previous tag gone to. + +If third arg REGEXP-P is non-nil, treat TAGNAME as a regexp. + +A marker representing the point when this command is invoked is pushed +onto a ring and may be popped back to with \\[pop-tag-mark]. +Contrast this with the ring of marks gone to by the command. + +See documentation of variable `tags-file-name'. + +\(fn TAGNAME &optional NEXT-P)" t nil) + +(make-obsolete 'find-tag-other-frame 'xref-find-definitions-other-frame '"25.1") + +(autoload 'find-tag-regexp "etags" "\ +Find tag (in current tags table) whose name matches REGEXP. +Select the buffer containing the tag's definition and move point there. + +If second arg NEXT-P is t (interactively, with prefix arg), search for +another tag that matches the last tagname or regexp used. When there are +multiple matches for a tag, more exact matches are found first. If NEXT-P +is negative (interactively, with prefix arg that is a negative number or +just \\[negative-argument]), pop back to the previous tag gone to. + +If third arg OTHER-WINDOW is non-nil, select the buffer in another window. + +A marker representing the point when this command is invoked is pushed +onto a ring and may be popped back to with \\[pop-tag-mark]. +Contrast this with the ring of marks gone to by the command. + +See documentation of variable `tags-file-name'. + +\(fn REGEXP &optional NEXT-P OTHER-WINDOW)" t nil) + +(make-obsolete 'find-tag-regexp 'xref-find-apropos '"25.1") + +(defalias 'pop-tag-mark 'xref-pop-marker-stack) + +(autoload 'next-file "etags" "\ +Select next file among files in current tags table. + +A first argument of t (prefix arg, if interactive) initializes to the +beginning of the list of files in the tags table. If the argument is +neither nil nor t, it is evalled to initialize the list of files. + +Non-nil second argument NOVISIT means use a temporary buffer + to save time and avoid uninteresting warnings. + +Value is nil if the file was already visited; +if the file was newly read in, the value is the filename. + +\(fn &optional INITIALIZE NOVISIT)" t nil) + +(autoload 'tags-loop-continue "etags" "\ +Continue last \\[tags-search] or \\[tags-query-replace] command. +Used noninteractively with non-nil argument to begin such a command (the +argument is passed to `next-file', which see). + +Two variables control the processing we do on each file: the value of +`tags-loop-scan' is a form to be executed on each file to see if it is +interesting (it returns non-nil if so) and `tags-loop-operate' is a form to +evaluate to operate on an interesting file. If the latter evaluates to +nil, we exit; otherwise we scan the next file. + +\(fn &optional FIRST-TIME)" t nil) + +(autoload 'tags-search "etags" "\ +Search through all files listed in tags table for match for REGEXP. +Stops when a match is found. +To continue searching for next match, use command \\[tags-loop-continue]. + +If FILE-LIST-FORM is non-nil, it should be a form that, when +evaluated, will return a list of file names. The search will be +restricted to these files. + +Also see the documentation of the `tags-file-name' variable. + +\(fn REGEXP &optional FILE-LIST-FORM)" t nil) + +(autoload 'tags-query-replace "etags" "\ +Do `query-replace-regexp' of FROM with TO on all files listed in tags table. +Third arg DELIMITED (prefix arg) means replace only word-delimited matches. +If you exit (\\[keyboard-quit], RET or q), you can resume the query replace +with the command \\[tags-loop-continue]. +Fourth arg FILE-LIST-FORM non-nil means initialize the replacement loop. + +If FILE-LIST-FORM is non-nil, it is a form to evaluate to +produce the list of files to search. + +See also the documentation of the variable `tags-file-name'. + +\(fn FROM TO &optional DELIMITED FILE-LIST-FORM)" t nil) + +(autoload 'list-tags "etags" "\ +Display list of tags in file FILE. +This searches only the first table in the list, and no included tables. +FILE should be as it appeared in the `etags' command, usually without a +directory specification. + +\(fn FILE &optional NEXT-MATCH)" t nil) + +(autoload 'tags-apropos "etags" "\ +Display list of all tags in tags table REGEXP matches. + +\(fn REGEXP)" t nil) + +(make-obsolete 'tags-apropos 'xref-find-apropos '"25.1") + +(autoload 'select-tags-table "etags" "\ +Select a tags table file from a menu of those you have already used. +The list of tags tables to select from is stored in `tags-table-set-list'; +see the doc of that variable if you want to add names to the list. + +\(fn)" t nil) + +(autoload 'complete-tag "etags" "\ +Perform tags completion on the text around point. +Completes to the set of names listed in the current tags table. +The string to complete is chosen in the same way as the default +for \\[find-tag] (which see). + +\(fn)" t nil) + +(autoload 'etags--xref-backend "etags" "\ + + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "etags" '("xref-" "etags-" "snarf-tag-function" "select-tags-table-" "tag" "file-of-tag" "find-tag-" "list-tags-function" "last-tag" "initialize-new-tags-table" "verify-tags-table-function" "goto-tag-location-function" "next-file-list" "default-tags-table-function"))) + +;;;*** + +;;;### (autoloads nil "ethio-util" "language/ethio-util.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from language/ethio-util.el + +(autoload 'setup-ethiopic-environment-internal "ethio-util" "\ + + +\(fn)" nil nil) + +(autoload 'ethio-sera-to-fidel-buffer "ethio-util" "\ +Convert the current buffer from SERA to FIDEL. + +The variable `ethio-primary-language' specifies the primary +language and `ethio-secondary-language' specifies the secondary. + +If the 1st optional argument SECONDARY is non-nil, assume the +buffer begins with the secondary language; otherwise with the +primary language. + +If the 2nd optional argument FORCE is non-nil, perform conversion +even if the buffer is read-only. + +See also the descriptions of the variables +`ethio-use-colon-for-colon' and `ethio-use-three-dot-question'. + +\(fn &optional SECONDARY FORCE)" t nil) + +(autoload 'ethio-sera-to-fidel-region "ethio-util" "\ +Convert the characters in region from SERA to FIDEL. + +The variable `ethio-primary-language' specifies the primary +language and `ethio-secondary-language' specifies the secondary. + +If the 3rd argument SECONDARY is given and non-nil, assume the +region begins with the secondary language; otherwise with the +primary language. + +If the 4th argument FORCE is given and non-nil, perform +conversion even if the buffer is read-only. + +See also the descriptions of the variables +`ethio-use-colon-for-colon' and `ethio-use-three-dot-question'. + +\(fn BEGIN END &optional SECONDARY FORCE)" t nil) + +(autoload 'ethio-sera-to-fidel-marker "ethio-util" "\ +Convert the regions surrounded by \"<sera>\" and \"</sera>\" from SERA to FIDEL. +Assume that each region begins with `ethio-primary-language'. +The markers \"<sera>\" and \"</sera>\" themselves are not deleted. + +\(fn &optional FORCE)" t nil) + +(autoload 'ethio-fidel-to-sera-buffer "ethio-util" "\ +Replace all the FIDEL characters in the current buffer to the SERA format. +The variable `ethio-primary-language' specifies the primary +language and `ethio-secondary-language' specifies the secondary. + +If the 1st optional argument SECONDARY is non-nil, try to convert the +region so that it begins with the secondary language; otherwise with the +primary language. + +If the 2nd optional argument FORCE is non-nil, convert even if the +buffer is read-only. + +See also the descriptions of the variables +`ethio-use-colon-for-colon', `ethio-use-three-dot-question', +`ethio-quote-vowel-always' and `ethio-numeric-reduction'. + +\(fn &optional SECONDARY FORCE)" t nil) + +(autoload 'ethio-fidel-to-sera-region "ethio-util" "\ +Replace all the FIDEL characters in the region to the SERA format. + +The variable `ethio-primary-language' specifies the primary +language and `ethio-secondary-language' specifies the secondary. + +If the 3rd argument SECONDARY is given and non-nil, convert +the region so that it begins with the secondary language; otherwise with +the primary language. + +If the 4th argument FORCE is given and non-nil, convert even if the +buffer is read-only. + +See also the descriptions of the variables +`ethio-use-colon-for-colon', `ethio-use-three-dot-question', +`ethio-quote-vowel-always' and `ethio-numeric-reduction'. + +\(fn BEGIN END &optional SECONDARY FORCE)" t nil) + +(autoload 'ethio-fidel-to-sera-marker "ethio-util" "\ +Convert the regions surrounded by \"<sera>\" and \"</sera>\" from FIDEL to SERA. +The markers \"<sera>\" and \"</sera>\" themselves are not deleted. + +\(fn &optional FORCE)" t nil) + +(autoload 'ethio-modify-vowel "ethio-util" "\ +Modify the vowel of the FIDEL that is under the cursor. + +\(fn)" t nil) + +(autoload 'ethio-replace-space "ethio-util" "\ +Replace ASCII spaces with Ethiopic word separators in the region. + +In the specified region, replace word separators surrounded by two +Ethiopic characters, depending on the first argument CH, which should +be 1, 2, or 3. + +If CH = 1, word separator will be replaced with an ASCII space. +If CH = 2, with two ASCII spaces. +If CH = 3, with the Ethiopic colon-like word separator. + +The 2nd and 3rd arguments BEGIN and END specify the region. + +\(fn CH BEGIN END)" t nil) + +(autoload 'ethio-input-special-character "ethio-util" "\ +This function is deprecated. + +\(fn ARG)" t nil) + +(autoload 'ethio-fidel-to-tex-buffer "ethio-util" "\ +Convert each fidel characters in the current buffer into a fidel-tex command. + +\(fn)" t nil) + +(autoload 'ethio-tex-to-fidel-buffer "ethio-util" "\ +Convert fidel-tex commands in the current buffer into fidel chars. + +\(fn)" t nil) + +(autoload 'ethio-fidel-to-java-buffer "ethio-util" "\ +Convert Ethiopic characters into the Java escape sequences. + +Each escape sequence is of the form \\uXXXX, where XXXX is the +character's codepoint (in hex) in Unicode. + +If `ethio-java-save-lowercase' is non-nil, use [0-9a-f]. +Otherwise, [0-9A-F]. + +\(fn)" nil nil) + +(autoload 'ethio-java-to-fidel-buffer "ethio-util" "\ +Convert the Java escape sequences into corresponding Ethiopic characters. + +\(fn)" nil nil) + +(autoload 'ethio-find-file "ethio-util" "\ +Transliterate file content into Ethiopic depending on filename suffix. + +\(fn)" nil nil) + +(autoload 'ethio-write-file "ethio-util" "\ +Transliterate Ethiopic characters in ASCII depending on the file extension. + +\(fn)" nil nil) + +(autoload 'ethio-insert-ethio-space "ethio-util" "\ +Insert the Ethiopic word delimiter (the colon-like character). +With ARG, insert that many delimiters. + +\(fn ARG)" t nil) + +(autoload 'ethio-composition-function "ethio-util" "\ + + +\(fn POS TO FONT-OBJECT STRING)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ethio-util" '("exit-ethiopic-environment" "ethio-"))) + +;;;*** + +;;;### (autoloads nil "eudc" "net/eudc.el" (0 0 0 0)) +;;; Generated autoloads from net/eudc.el + +(autoload 'eudc-set-server "eudc" "\ +Set the directory server to SERVER using PROTOCOL. +Unless NO-SAVE is non-nil, the server is saved as the default +server for future sessions. + +\(fn SERVER PROTOCOL &optional NO-SAVE)" t nil) + +(autoload 'eudc-get-email "eudc" "\ +Get the email field of NAME from the directory server. +If ERROR is non-nil, report an error if there is none. + +\(fn NAME &optional ERROR)" t nil) + +(autoload 'eudc-get-phone "eudc" "\ +Get the phone field of NAME from the directory server. +If ERROR is non-nil, report an error if there is none. + +\(fn NAME &optional ERROR)" t nil) + +(autoload 'eudc-expand-inline "eudc" "\ +Query the directory server, and expand the query string before point. +The query string consists of the buffer substring from the point back to +the preceding comma, colon or beginning of line. +The variable `eudc-inline-query-format' controls how to associate the +individual inline query words with directory attribute names. +After querying the server for the given string, the expansion specified by +`eudc-inline-expansion-format' is inserted in the buffer at point. +If REPLACE is non-nil, then this expansion replaces the name in the buffer. +`eudc-expansion-overwrites-query' being non-nil inverts the meaning of REPLACE. +Multiple servers can be tried with the same query until one finds a match, +see `eudc-inline-expansion-servers' + +\(fn &optional REPLACE)" t nil) + +(autoload 'eudc-query-form "eudc" "\ +Display a form to query the directory server. +If given a non-nil argument GET-FIELDS-FROM-SERVER, the function first +queries the server for the existing fields and displays a corresponding form. + +\(fn &optional GET-FIELDS-FROM-SERVER)" t nil) + +(autoload 'eudc-load-eudc "eudc" "\ +Load the Emacs Unified Directory Client. +This does nothing except loading eudc by autoload side-effect. + +\(fn)" t nil) + +(cond ((not (featurep 'xemacs)) (defvar eudc-tools-menu (let ((map (make-sparse-keymap "Directory Servers"))) (define-key map [phone] `(menu-item ,(purecopy "Get Phone") eudc-get-phone :help ,(purecopy "Get the phone field of name from the directory server"))) (define-key map [email] `(menu-item ,(purecopy "Get Email") eudc-get-email :help ,(purecopy "Get the email field of NAME from the directory server"))) (define-key map [separator-eudc-email] menu-bar-separator) (define-key map [expand-inline] `(menu-item ,(purecopy "Expand Inline Query") eudc-expand-inline :help ,(purecopy "Query the directory server, and expand the query string before point"))) (define-key map [query] `(menu-item ,(purecopy "Query with Form") eudc-query-form :help ,(purecopy "Display a form to query the directory server"))) (define-key map [separator-eudc-query] menu-bar-separator) (define-key map [new] `(menu-item ,(purecopy "New Server") eudc-set-server :help ,(purecopy "Set the directory server to SERVER using PROTOCOL"))) (define-key map [load] `(menu-item ,(purecopy "Load Hotlist of Servers") eudc-load-eudc :help ,(purecopy "Load the Emacs Unified Directory Client"))) map)) (fset 'eudc-tools-menu (symbol-value 'eudc-tools-menu))) (t (let ((menu '("Directory Servers" ["Load Hotlist of Servers" eudc-load-eudc t] ["New Server" eudc-set-server t] ["---" nil nil] ["Query with Form" eudc-query-form t] ["Expand Inline Query" eudc-expand-inline t] ["---" nil nil] ["Get Email" eudc-get-email t] ["Get Phone" eudc-get-phone t]))) (if (not (featurep 'eudc-autoloads)) (if (featurep 'xemacs) (if (and (featurep 'menubar) (not (featurep 'infodock))) (add-submenu '("Tools") menu)) (require 'easymenu) (cond ((fboundp 'easy-menu-add-item) (easy-menu-add-item nil '("tools") (easy-menu-create-menu (car menu) (cdr menu)))) ((fboundp 'easy-menu-create-keymaps) (define-key global-map [menu-bar tools eudc] (cons "Directory Servers" (easy-menu-create-keymaps "Directory Servers" (cdr menu))))))))))) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eudc" '("eudc-"))) + +;;;*** + +;;;### (autoloads nil "eudc-bob" "net/eudc-bob.el" (0 0 0 0)) +;;; Generated autoloads from net/eudc-bob.el + +(autoload 'eudc-display-generic-binary "eudc-bob" "\ +Display a button for unidentified binary DATA. + +\(fn DATA)" nil nil) + +(autoload 'eudc-display-url "eudc-bob" "\ +Display URL and make it clickable. + +\(fn URL)" nil nil) + +(autoload 'eudc-display-mail "eudc-bob" "\ +Display e-mail address and make it clickable. + +\(fn MAIL)" nil nil) + +(autoload 'eudc-display-sound "eudc-bob" "\ +Display a button to play the sound DATA. + +\(fn DATA)" nil nil) + +(autoload 'eudc-display-jpeg-inline "eudc-bob" "\ +Display the JPEG DATA inline at point if possible. + +\(fn DATA)" nil nil) + +(autoload 'eudc-display-jpeg-as-button "eudc-bob" "\ +Display a button for the JPEG DATA. + +\(fn DATA)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eudc-bob" '("eudc-"))) + +;;;*** + +;;;### (autoloads nil "eudc-export" "net/eudc-export.el" (0 0 0 0)) +;;; Generated autoloads from net/eudc-export.el + +(autoload 'eudc-insert-record-at-point-into-bbdb "eudc-export" "\ +Insert record at point into the BBDB database. +This function can only be called from a directory query result buffer. + +\(fn)" t nil) + +(autoload 'eudc-try-bbdb-insert "eudc-export" "\ +Call `eudc-insert-record-at-point-into-bbdb' if on a record. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eudc-export" '("eudc-"))) + +;;;*** + +;;;### (autoloads nil "eudc-hotlist" "net/eudc-hotlist.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from net/eudc-hotlist.el + +(autoload 'eudc-edit-hotlist "eudc-hotlist" "\ +Edit the hotlist of directory servers in a specialized buffer. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eudc-hotlist" '("eudc-hotlist-"))) + +;;;*** + +;;;### (autoloads nil "eudc-vars" "net/eudc-vars.el" (0 0 0 0)) +;;; Generated autoloads from net/eudc-vars.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eudc-vars" '("eudc-"))) + +;;;*** + +;;;### (autoloads nil "eudcb-bbdb" "net/eudcb-bbdb.el" (0 0 0 0)) +;;; Generated autoloads from net/eudcb-bbdb.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eudcb-bbdb" '("eudc-bbdb-"))) + +;;;*** + +;;;### (autoloads nil "eudcb-ldap" "net/eudcb-ldap.el" (0 0 0 0)) +;;; Generated autoloads from net/eudcb-ldap.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eudcb-ldap" '("eudc-"))) + +;;;*** + +;;;### (autoloads nil "eudcb-mab" "net/eudcb-mab.el" (0 0 0 0)) +;;; Generated autoloads from net/eudcb-mab.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eudcb-mab" '("eudc-"))) + +;;;*** + +;;;### (autoloads nil "ewoc" "emacs-lisp/ewoc.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/ewoc.el + +(autoload 'ewoc-create "ewoc" "\ +Create an empty ewoc. + +The ewoc will be inserted in the current buffer at the current position. + +PRETTY-PRINTER should be a function that takes one argument, an +element, and inserts a string representing it in the buffer (at +point). The string PRETTY-PRINTER inserts may be empty or span +several lines. The PRETTY-PRINTER should use `insert', and not +`insert-before-markers'. + +Optional second and third arguments HEADER and FOOTER are strings, +possibly empty, that will always be present at the top and bottom, +respectively, of the ewoc. + +Normally, a newline is automatically inserted after the header, +the footer and every node's printed representation. Optional +fourth arg NOSEP non-nil inhibits this. + +\(fn PRETTY-PRINTER &optional HEADER FOOTER NOSEP)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ewoc" '("ewoc-"))) + +;;;*** + +;;;### (autoloads nil "eww" "net/eww.el" (0 0 0 0)) +;;; Generated autoloads from net/eww.el + +(defvar eww-suggest-uris '(eww-links-at-point url-get-url-at-point eww-current-url) "\ +List of functions called to form the list of default URIs for `eww'. +Each of the elements is a function returning either a string or a list +of strings. The results will be joined into a single list with +duplicate entries (if any) removed.") + +(custom-autoload 'eww-suggest-uris "eww" t) + +(autoload 'eww "eww" "\ +Fetch URL and render the page. +If the input doesn't look like an URL or a domain name, the +word(s) will be searched for via `eww-search-prefix'. + +\(fn URL)" t nil) + (defalias 'browse-web 'eww) + +(autoload 'eww-open-file "eww" "\ +Render FILE using EWW. + +\(fn FILE)" t nil) + +(autoload 'eww-search-words "eww" "\ +Search the web for the text between BEG and END. +See the `eww-search-prefix' variable for the search engine used. + +\(fn &optional BEG END)" t nil) + +(autoload 'eww-mode "eww" "\ +Mode for browsing the web. + +\(fn)" t nil) + +(autoload 'eww-browse-url "eww" "\ + + +\(fn URL &optional NEW-WINDOW)" nil nil) + +(autoload 'eww-list-bookmarks "eww" "\ +Display the bookmarks. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "eww" '("eww-"))) + +;;;*** + +;;;### (autoloads nil "executable" "progmodes/executable.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from progmodes/executable.el + +(autoload 'executable-command-find-posix-p "executable" "\ +Check if PROGRAM handles arguments Posix-style. +If PROGRAM is non-nil, use that instead of \"find\". + +\(fn &optional PROGRAM)" nil nil) + +(autoload 'executable-interpret "executable" "\ +Run script with user-specified args, and collect output in a buffer. +While script runs asynchronously, you can use the \\[next-error] +command to find the next error. The buffer is also in `comint-mode' and +`compilation-shell-minor-mode', so that you can answer any prompts. + +\(fn COMMAND)" t nil) + +(autoload 'executable-set-magic "executable" "\ +Set this buffer's interpreter to INTERPRETER with optional ARGUMENT. +The variables `executable-magicless-file-regexp', `executable-prefix', +`executable-insert', `executable-query' and `executable-chmod' control +when and how magic numbers are inserted or replaced and scripts made +executable. + +\(fn INTERPRETER &optional ARGUMENT NO-QUERY-FLAG INSERT-FLAG)" t nil) + +(autoload 'executable-make-buffer-file-executable-if-script-p "executable" "\ +Make file executable according to umask if not already executable. +If file already has any execute bits set at all, do not change existing +file modes. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "executable" '("executable-"))) + +;;;*** + +;;;### (autoloads nil "expand" "expand.el" (0 0 0 0)) +;;; Generated autoloads from expand.el + +(autoload 'expand-add-abbrevs "expand" "\ +Add a list of abbreviations to abbrev table TABLE. +ABBREVS is a list of abbrev definitions; each abbrev description entry +has the form (ABBREV EXPANSION ARG). + +ABBREV is the abbreviation to replace. + +EXPANSION is the replacement string or a function which will make the +expansion. For example, you could use the DMacros or skeleton packages +to generate such functions. + +ARG is an optional argument which can be a number or a list of +numbers. If ARG is a number, point is placed ARG chars from the +beginning of the expanded text. + +If ARG is a list of numbers, point is placed according to the first +member of the list, but you can visit the other specified positions +cyclically with the functions `expand-jump-to-previous-slot' and +`expand-jump-to-next-slot'. + +If ARG is omitted, point is placed at the end of the expanded text. + +\(fn TABLE ABBREVS)" nil nil) + +(autoload 'expand-abbrev-hook "expand" "\ +Abbrev hook used to do the expansion job of expand abbrevs. +See `expand-add-abbrevs'. Value is non-nil if expansion was done. + +\(fn)" nil nil) + +(autoload 'expand-jump-to-previous-slot "expand" "\ +Move the cursor to the previous slot in the last abbrev expansion. +This is used only in conjunction with `expand-add-abbrevs'. + +\(fn)" t nil) + +(autoload 'expand-jump-to-next-slot "expand" "\ +Move the cursor to the next slot in the last abbrev expansion. +This is used only in conjunction with `expand-add-abbrevs'. + +\(fn)" t nil) + (define-key abbrev-map "p" 'expand-jump-to-previous-slot) + (define-key abbrev-map "n" 'expand-jump-to-next-slot) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "expand" '("expand-"))) + +;;;*** + +;;;### (autoloads nil "ezimage" "ezimage.el" (0 0 0 0)) +;;; Generated autoloads from ezimage.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ezimage" '("ezimage-"))) + +;;;*** + +;;;### (autoloads nil "f90" "progmodes/f90.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/f90.el + +(autoload 'f90-mode "f90" "\ +Major mode for editing Fortran 90,95 code in free format. +For fixed format code, use `fortran-mode'. + +\\[f90-indent-line] indents the current line. +\\[f90-indent-new-line] indents current line and creates a new indented line. +\\[f90-indent-subprogram] indents the current subprogram. + +Type \\=`? or \\=`\\[help-command] to display a list of built-in abbrevs for F90 keywords. + +Key definitions: +\\{f90-mode-map} + +Variables controlling indentation style and extra features: + +`f90-do-indent' + Extra indentation within do blocks (default 3). +`f90-if-indent' + Extra indentation within if/select/where/forall blocks (default 3). +`f90-type-indent' + Extra indentation within type/enum/interface/block-data blocks (default 3). +`f90-program-indent' + Extra indentation within program/module/subroutine/function blocks + (default 2). +`f90-associate-indent' + Extra indentation within associate blocks (default 2). +`f90-critical-indent' + Extra indentation within critical/block blocks (default 2). +`f90-continuation-indent' + Extra indentation applied to continuation lines (default 5). +`f90-comment-region' + String inserted by function \\[f90-comment-region] at start of each + line in region (default \"!!!$\"). +`f90-indented-comment-re' + Regexp determining the type of comment to be intended like code + (default \"!\"). +`f90-directive-comment-re' + Regexp of comment-like directive like \"!HPF\\\\$\", not to be indented + (default \"!hpf\\\\$\"). +`f90-break-delimiters' + Regexp holding list of delimiters at which lines may be broken + (default \"[-+*/><=,% \\t]\"). +`f90-break-before-delimiters' + Non-nil causes `f90-do-auto-fill' to break lines before delimiters + (default t). +`f90-beginning-ampersand' + Automatic insertion of `&' at beginning of continuation lines (default t). +`f90-smart-end' + From an END statement, check and fill the end using matching block start. + Allowed values are `blink', `no-blink', and nil, which determine + whether to blink the matching beginning (default `blink'). +`f90-auto-keyword-case' + Automatic change of case of keywords (default nil). + The possibilities are `downcase-word', `upcase-word', `capitalize-word'. +`f90-leave-line-no' + Do not left-justify line numbers (default nil). + +Turning on F90 mode calls the value of the variable `f90-mode-hook' +with no args, if that value is non-nil. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "f90" '("f90-"))) + +;;;*** + +;;;### (autoloads nil "face-remap" "face-remap.el" (0 0 0 0)) +;;; Generated autoloads from face-remap.el + +(autoload 'face-remap-add-relative "face-remap" "\ +Add a face remapping entry of FACE to SPECS in the current buffer. +Return a cookie which can be used to delete this remapping with +`face-remap-remove-relative'. + +The remaining arguments, SPECS, should form a list of faces. +Each list element should be either a face name or a property list +of face attribute/value pairs. If more than one face is listed, +that specifies an aggregate face, in the same way as in a `face' +text property, except for possible priority changes noted below. + +The face remapping specified by SPECS takes effect alongside the +remappings from other calls to `face-remap-add-relative' for the +same FACE, as well as the normal definition of FACE (at lowest +priority). This function tries to sort multiple remappings for +the same face, so that remappings specifying relative face +attributes are applied after remappings specifying absolute face +attributes. + +The base (lowest priority) remapping may be set to something +other than the normal definition of FACE via `face-remap-set-base'. + +\(fn FACE &rest SPECS)" nil nil) + +(autoload 'face-remap-reset-base "face-remap" "\ +Set the base remapping of FACE to the normal definition of FACE. +This causes the remappings specified by `face-remap-add-relative' +to apply on top of the normal definition of FACE. + +\(fn FACE)" nil nil) + +(autoload 'face-remap-set-base "face-remap" "\ +Set the base remapping of FACE in the current buffer to SPECS. +This causes the remappings specified by `face-remap-add-relative' +to apply on top of the face specification given by SPECS. + +The remaining arguments, SPECS, should form a list of faces. +Each list element should be either a face name or a property list +of face attribute/value pairs, like in a `face' text property. + +If SPECS is empty, call `face-remap-reset-base' to use the normal +definition of FACE as the base remapping; note that this is +different from SPECS containing a single value nil, which means +not to inherit from the global definition of FACE at all. + +\(fn FACE &rest SPECS)" nil nil) + +(autoload 'text-scale-set "face-remap" "\ +Set the scale factor of the default face in the current buffer to LEVEL. +If LEVEL is non-zero, `text-scale-mode' is enabled, otherwise it is disabled. + +LEVEL is a number of steps, with 0 representing the default size. +Each step scales the height of the default face by the variable +`text-scale-mode-step' (a negative number decreases the height by +the same amount). + +\(fn LEVEL)" t nil) + +(autoload 'text-scale-increase "face-remap" "\ +Increase the height of the default face in the current buffer by INC steps. +If the new height is other than the default, `text-scale-mode' is enabled. + +Each step scales the height of the default face by the variable +`text-scale-mode-step' (a negative number of steps decreases the +height by the same amount). As a special case, an argument of 0 +will remove any scaling currently active. + +\(fn INC)" t nil) + +(autoload 'text-scale-decrease "face-remap" "\ +Decrease the height of the default face in the current buffer by DEC steps. +See `text-scale-increase' for more details. + +\(fn DEC)" t nil) + (define-key ctl-x-map [(control ?+)] 'text-scale-adjust) + (define-key ctl-x-map [(control ?-)] 'text-scale-adjust) + (define-key ctl-x-map [(control ?=)] 'text-scale-adjust) + (define-key ctl-x-map [(control ?0)] 'text-scale-adjust) + +(autoload 'text-scale-adjust "face-remap" "\ +Adjust the height of the default face by INC. + +INC may be passed as a numeric prefix argument. + +The actual adjustment made depends on the final component of the +key-binding used to invoke the command, with all modifiers removed: + + +, = Increase the default face height by one step + - Decrease the default face height by one step + 0 Reset the default face height to the global default + +After adjusting, continue to read input events and further adjust +the face height as long as the input event read +\(with all modifiers removed) is one of the above characters. + +Each step scales the height of the default face by the variable +`text-scale-mode-step' (a negative number of steps decreases the +height by the same amount). As a special case, an argument of 0 +will remove any scaling currently active. + +This command is a special-purpose wrapper around the +`text-scale-increase' command which makes repetition convenient +even when it is bound in a non-top-level keymap. For binding in +a top-level keymap, `text-scale-increase' or +`text-scale-decrease' may be more appropriate. + +\(fn INC)" t nil) + +(autoload 'buffer-face-mode "face-remap" "\ +Minor mode for a buffer-specific default face. +With a prefix argument ARG, enable the mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode +if ARG is omitted or nil. When enabled, the face specified by the +variable `buffer-face-mode-face' is used to display the buffer text. + +\(fn &optional ARG)" t nil) + +(autoload 'buffer-face-set "face-remap" "\ +Enable `buffer-face-mode', using face specs SPECS. +Each argument in SPECS should be a face, i.e. either a face name +or a property list of face attributes and values. If more than +one face is listed, that specifies an aggregate face, like in a +`face' text property. If SPECS is nil or omitted, disable +`buffer-face-mode'. + +This function makes the variable `buffer-face-mode-face' buffer +local, and sets it to FACE. + +\(fn &rest SPECS)" t nil) + +(autoload 'buffer-face-toggle "face-remap" "\ +Toggle `buffer-face-mode', using face specs SPECS. +Each argument in SPECS should be a face, i.e. either a face name +or a property list of face attributes and values. If more than +one face is listed, that specifies an aggregate face, like in a +`face' text property. + +If `buffer-face-mode' is already enabled, and is currently using +the face specs SPECS, then it is disabled; if `buffer-face-mode' +is disabled, or is enabled and currently displaying some other +face, then is left enabled, but the face changed to reflect SPECS. + +This function will make the variable `buffer-face-mode-face' +buffer local, and set it to SPECS. + +\(fn &rest SPECS)" t nil) + +(autoload 'variable-pitch-mode "face-remap" "\ +Variable-pitch default-face mode. +An interface to `buffer-face-mode' which uses the `variable-pitch' face. +Besides the choice of face, it is the same as `buffer-face-mode'. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "face-remap" '("buffer-face-mode-" "text-scale-m" "face-" "internal-lisp-face-attributes"))) + +;;;*** + +;;;### (autoloads nil "feedmail" "mail/feedmail.el" (0 0 0 0)) +;;; Generated autoloads from mail/feedmail.el +(push (purecopy '(feedmail 11)) package--builtin-versions) + +(autoload 'feedmail-send-it "feedmail" "\ +Send the current mail buffer using the Feedmail package. +This is a suitable value for `send-mail-function'. It can be used +with various lower-level mechanisms to provide features such as queueing. + +\(fn)" nil nil) + +(autoload 'feedmail-run-the-queue-no-prompts "feedmail" "\ +Like `feedmail-run-the-queue', but suppress confirmation prompts. + +\(fn &optional ARG)" t nil) + +(autoload 'feedmail-run-the-queue-global-prompt "feedmail" "\ +Like `feedmail-run-the-queue', but with a global confirmation prompt. +This is generally most useful if run non-interactively, since you can +bail out with an appropriate answer to the global confirmation prompt. + +\(fn &optional ARG)" t nil) + +(autoload 'feedmail-run-the-queue "feedmail" "\ +Visit each message in the feedmail queue directory and send it out. +Return value is a list of three things: number of messages sent, number of +messages skipped, and number of non-message things in the queue (commonly +backup file names and the like). + +\(fn &optional ARG)" t nil) + +(autoload 'feedmail-queue-reminder "feedmail" "\ +Perform some kind of reminder activity about queued and draft messages. +Called with an optional symbol argument which says what kind of event +is triggering the reminder activity. The default is `on-demand', which +is what you typically would use if you were putting this in your Emacs start-up +or mail hook code. Other recognized values for WHAT-EVENT (these are passed +internally by feedmail): + + after-immediate (a message has just been sent in immediate mode) + after-queue (a message has just been queued) + after-draft (a message has just been placed in the draft directory) + after-run (the queue has just been run, possibly sending messages) + +WHAT-EVENT is used as a key into the table `feedmail-queue-reminder-alist'. If +the associated value is a function, it is called without arguments and is expected +to perform the reminder activity. You can supply your own reminder functions +by redefining `feedmail-queue-reminder-alist'. If you don't want any reminders, +you can set `feedmail-queue-reminder-alist' to nil. + +\(fn &optional WHAT-EVENT)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "feedmail" '("feedmail-"))) + +;;;*** + +;;;### (autoloads nil "ffap" "ffap.el" (0 0 0 0)) +;;; Generated autoloads from ffap.el + +(autoload 'ffap-next "ffap" "\ +Search buffer for next file or URL, and run ffap. +Optional argument BACK says to search backwards. +Optional argument WRAP says to try wrapping around if necessary. +Interactively: use a single prefix \\[universal-argument] to search backwards, +double prefix to wrap forward, triple to wrap backwards. +Actual search is done by the function `ffap-next-guess'. + +\(fn &optional BACK WRAP)" t nil) + +(autoload 'find-file-at-point "ffap" "\ +Find FILENAME, guessing a default from text around point. +If `ffap-url-regexp' is not nil, the FILENAME may also be an URL. +With a prefix, this command behaves exactly like `ffap-file-finder'. +If `ffap-require-prefix' is set, the prefix meaning is reversed. +See also the variables `ffap-dired-wildcards', `ffap-newfile-prompt', +and the functions `ffap-file-at-point' and `ffap-url-at-point'. + +\(fn &optional FILENAME)" t nil) + +(defalias 'ffap 'find-file-at-point) + +(autoload 'ffap-menu "ffap" "\ +Put up a menu of files and URLs mentioned in this buffer. +Then set mark, jump to choice, and try to fetch it. The menu is +cached in `ffap-menu-alist', and rebuilt by `ffap-menu-rescan'. +The optional RESCAN argument (a prefix, interactively) forces +a rebuild. Searches with `ffap-menu-regexp'. + +\(fn &optional RESCAN)" t nil) + +(autoload 'ffap-at-mouse "ffap" "\ +Find file or URL guessed from text around mouse click. +Interactively, calls `ffap-at-mouse-fallback' if no guess is found. +Return value: + * if a guess string is found, return it (after finding it) + * if the fallback is called, return whatever it returns + * otherwise, nil + +\(fn E)" t nil) + +(autoload 'dired-at-point "ffap" "\ +Start Dired, defaulting to file at point. See `ffap'. +If `dired-at-point-require-prefix' is set, the prefix meaning is reversed. + +\(fn &optional FILENAME)" t nil) + +(autoload 'ffap-guess-file-name-at-point "ffap" "\ +Try to get a file name at point. +This hook is intended to be put in `file-name-at-point-functions'. + +\(fn)" nil nil) + +(autoload 'ffap-bindings "ffap" "\ +Evaluate the forms in variable `ffap-bindings'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ffap" '("find-file-literally-at-point" "ffap-" "dired-at-point-"))) + +;;;*** + +;;;### (autoloads nil "filecache" "filecache.el" (0 0 0 0)) +;;; Generated autoloads from filecache.el + +(autoload 'file-cache-add-directory "filecache" "\ +Add all files in DIRECTORY to the file cache. +If called from Lisp with a non-nil REGEXP argument is non-nil, +only add files whose names match REGEXP. + +\(fn DIRECTORY &optional REGEXP)" t nil) + +(autoload 'file-cache-add-directory-list "filecache" "\ +Add DIRECTORIES (a list of directory names) to the file cache. +If called interactively, read the directory names one by one. +If the optional REGEXP argument is non-nil, only files which match it +will be added to the cache. Note that the REGEXP is applied to the +files in each directory, not to the directory list itself. + +\(fn DIRECTORIES &optional REGEXP)" t nil) + +(autoload 'file-cache-add-file "filecache" "\ +Add FILE to the file cache. + +\(fn FILE)" t nil) + +(autoload 'file-cache-add-directory-using-find "filecache" "\ +Use the `find' command to add files to the file cache. +Find is run in DIRECTORY. + +\(fn DIRECTORY)" t nil) + +(autoload 'file-cache-add-directory-using-locate "filecache" "\ +Use the `locate' command to add files to the file cache. +STRING is passed as an argument to the locate command. + +\(fn STRING)" t nil) + +(autoload 'file-cache-add-directory-recursively "filecache" "\ +Adds DIR and any subdirectories to the file-cache. +This function does not use any external programs. +If the optional REGEXP argument is non-nil, only files which match it +will be added to the cache. Note that the REGEXP is applied to the +files in each directory, not to the directory list itself. + +\(fn DIR &optional REGEXP)" t nil) + +(autoload 'file-cache-minibuffer-complete "filecache" "\ +Complete a filename in the minibuffer using a preloaded cache. +Filecache does two kinds of substitution: it completes on names in +the cache, and, once it has found a unique name, it cycles through +the directories that the name is available in. With a prefix argument, +the name is considered already unique; only the second substitution +\(directories) is done. + +\(fn ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "filecache" '("file-cache-"))) + +;;;*** + +;;;### (autoloads nil "filenotify" "filenotify.el" (0 0 0 0)) +;;; Generated autoloads from filenotify.el + +(autoload 'file-notify-handle-event "filenotify" "\ +Handle file system monitoring event. +If EVENT is a filewatch event, call its callback. It has the format + + (file-notify (DESCRIPTOR ACTIONS FILE [FILE1-OR-COOKIE]) CALLBACK) + +Otherwise, signal a `file-notify-error'. + +\(fn EVENT)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "filenotify" '("file-notify-"))) + +;;;*** + +;;;### (autoloads nil "files-x" "files-x.el" (0 0 0 0)) +;;; Generated autoloads from files-x.el + +(autoload 'add-file-local-variable "files-x" "\ +Add file-local VARIABLE with its VALUE to the Local Variables list. + +This command deletes all existing settings of VARIABLE (except `mode' +and `eval') and adds a new file-local VARIABLE with VALUE to the +Local Variables list. + +If there is no Local Variables list in the current file buffer +then this function adds the first line containing the string +`Local Variables:' and the last line containing the string `End:'. + +\(fn VARIABLE VALUE &optional INTERACTIVE)" t nil) + +(autoload 'delete-file-local-variable "files-x" "\ +Delete all settings of file-local VARIABLE from the Local Variables list. + +\(fn VARIABLE &optional INTERACTIVE)" t nil) + +(autoload 'add-file-local-variable-prop-line "files-x" "\ +Add file-local VARIABLE with its VALUE to the -*- line. + +This command deletes all existing settings of VARIABLE (except `mode' +and `eval') and adds a new file-local VARIABLE with VALUE to +the -*- line. + +If there is no -*- line at the beginning of the current file buffer +then this function adds it. + +\(fn VARIABLE VALUE &optional INTERACTIVE)" t nil) + +(autoload 'delete-file-local-variable-prop-line "files-x" "\ +Delete all settings of file-local VARIABLE from the -*- line. + +\(fn VARIABLE &optional INTERACTIVE)" t nil) + +(autoload 'add-dir-local-variable "files-x" "\ +Add directory-local VARIABLE with its VALUE and MODE to .dir-locals.el. + +\(fn MODE VARIABLE VALUE)" t nil) + +(autoload 'delete-dir-local-variable "files-x" "\ +Delete all MODE settings of file-local VARIABLE from .dir-locals.el. + +\(fn MODE VARIABLE)" t nil) + +(autoload 'copy-file-locals-to-dir-locals "files-x" "\ +Copy file-local variables to .dir-locals.el. + +\(fn)" t nil) + +(autoload 'copy-dir-locals-to-file-locals "files-x" "\ +Copy directory-local variables to the Local Variables list. + +\(fn)" t nil) + +(autoload 'copy-dir-locals-to-file-locals-prop-line "files-x" "\ +Copy directory-local variables to the -*- line. + +\(fn)" t nil) + +(defvar enable-connection-local-variables t "\ +Non-nil means enable use of connection-local variables.") + +(autoload 'connection-local-set-profiles "files-x" "\ +Add PROFILES for CRITERIA. +CRITERIA is a plist identifying a connection and the application +using this connection, see `connection-local-criteria-alist'. +PROFILES are the names of connection profiles (a symbol). + +When a connection to a remote server is opened and CRITERIA +matches to that server, the connection-local variables from +PROFILES are applied to the corresponding process buffer. The +variables for a connection profile are defined using +`connection-local-set-profile-variables'. + +\(fn CRITERIA &rest PROFILES)" nil nil) + +(autoload 'connection-local-set-profile-variables "files-x" "\ +Map the symbol PROFILE to a list of variable settings. +VARIABLES is a list that declares connection-local variables for +the connection profile. An element in VARIABLES is an alist +whose elements are of the form (VAR . VALUE). + +When a connection to a remote server is opened, the server's +connection profiles are found. A server may be assigned a +connection profile using `connection-local-set-profile'. Then +variables are set in the server's process buffer according to the +VARIABLES list of the connection profile. The list is processed +in order. + +\(fn PROFILE VARIABLES)" nil nil) + +(autoload 'hack-connection-local-variables-apply "files-x" "\ +Apply connection-local variables identified by CRITERIA. +Other local variables, like file-local and dir-local variables, +will not be changed. + +\(fn CRITERIA)" nil nil) + +(autoload 'with-connection-local-profiles "files-x" "\ +Apply connection-local variables according to PROFILES in current buffer. +Execute BODY, and unwind connection-local variables. + +\(fn PROFILES &rest BODY)" nil t) + +(function-put 'with-connection-local-profiles 'lisp-indent-function '1) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "files-x" '("hack-connection-local-variables" "connection-local-" "modify-" "read-file-local-variable"))) + +;;;*** + +;;;### (autoloads nil "filesets" "filesets.el" (0 0 0 0)) +;;; Generated autoloads from filesets.el + +(autoload 'filesets-init "filesets" "\ +Filesets initialization. +Set up hooks, load the cache file -- if existing -- and build the menu. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "filesets" '("filesets-"))) + +;;;*** + +;;;### (autoloads nil "find-cmd" "find-cmd.el" (0 0 0 0)) +;;; Generated autoloads from find-cmd.el +(push (purecopy '(find-cmd 0 6)) package--builtin-versions) + +(autoload 'find-cmd "find-cmd" "\ +Initiate the building of a find command. +For example: + +\(find-cmd \\='(prune (name \".svn\" \".git\" \".CVS\")) + \\='(and (or (name \"*.pl\" \"*.pm\" \"*.t\") + (mtime \"+1\")) + (fstype \"nfs\" \"ufs\")))) + +`default-directory' is used as the initial search path. The +result is a string that should be ready for the command line. + +\(fn &rest SUBFINDS)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "find-cmd" '("find-"))) + +;;;*** + +;;;### (autoloads nil "find-dired" "find-dired.el" (0 0 0 0)) +;;; Generated autoloads from find-dired.el + +(autoload 'find-dired "find-dired" "\ +Run `find' and go into Dired mode on a buffer of the output. +The command run (after changing into DIR) is essentially + + find . \\( ARGS \\) -ls + +except that the car of the variable `find-ls-option' specifies what to +use in place of \"-ls\" as the final argument. + +\(fn DIR ARGS)" t nil) + +(autoload 'find-name-dired "find-dired" "\ +Search DIR recursively for files matching the globbing pattern PATTERN, +and run Dired on those files. +PATTERN is a shell wildcard (not an Emacs regexp) and need not be quoted. +The default command run (after changing into DIR) is + + find . -name \\='PATTERN\\=' -ls + +See `find-name-arg' to customize the arguments. + +\(fn DIR PATTERN)" t nil) + +(autoload 'find-grep-dired "find-dired" "\ +Find files in DIR matching a regexp REGEXP and start Dired on output. +The command run (after changing into DIR) is + + find . \\( -type f -exec `grep-program' `find-grep-options' \\ + -e REGEXP {} \\; \\) -ls + +where the car of the variable `find-ls-option' specifies what to +use in place of \"-ls\" as the final argument. + +\(fn DIR REGEXP)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "find-dired" '("find-" "lookfor-dired" "kill-find"))) + +;;;*** + +;;;### (autoloads nil "find-file" "find-file.el" (0 0 0 0)) +;;; Generated autoloads from find-file.el + +(defvar ff-special-constructs `((,(purecopy "^#\\s *\\(include\\|import\\)\\s +[<\"]\\(.*\\)[>\"]") lambda nil (buffer-substring (match-beginning 2) (match-end 2)))) "\ +List of special constructs recognized by `ff-treat-as-special'. +Each element, tried in order, has the form (REGEXP . EXTRACT). +If REGEXP matches the current line (from the beginning of the line), +`ff-treat-as-special' calls function EXTRACT with no args. +If EXTRACT returns nil, keep trying. Otherwise, return the +filename that EXTRACT returned.") + +(custom-autoload 'ff-special-constructs "find-file" t) + +(autoload 'ff-get-other-file "find-file" "\ +Find the header or source file corresponding to this file. +See also the documentation for `ff-find-other-file'. + +If optional IN-OTHER-WINDOW is non-nil, find the file in another window. + +\(fn &optional IN-OTHER-WINDOW)" t nil) + +(defalias 'ff-find-related-file 'ff-find-other-file) + +(autoload 'ff-find-other-file "find-file" "\ +Find the header or source file corresponding to this file. +Being on a `#include' line pulls in that file. + +If optional IN-OTHER-WINDOW is non-nil, find the file in the other window. +If optional IGNORE-INCLUDE is non-nil, ignore being on `#include' lines. + +Variables of interest include: + + - `ff-case-fold-search' + Non-nil means ignore cases in matches (see `case-fold-search'). + If you have extensions in different cases, you will want this to be nil. + + - `ff-always-in-other-window' + If non-nil, always open the other file in another window, unless an + argument is given to `ff-find-other-file'. + + - `ff-ignore-include' + If non-nil, ignores #include lines. + + - `ff-always-try-to-create' + If non-nil, always attempt to create the other file if it was not found. + + - `ff-quiet-mode' + If non-nil, traces which directories are being searched. + + - `ff-special-constructs' + A list of regular expressions specifying how to recognize special + constructs such as include files etc, and an associated method for + extracting the filename from that construct. + + - `ff-other-file-alist' + Alist of extensions to find given the current file's extension. + + - `ff-search-directories' + List of directories searched through with each extension specified in + `ff-other-file-alist' that matches this file's extension. + + - `ff-pre-find-hook' + List of functions to be called before the search for the file starts. + + - `ff-pre-load-hook' + List of functions to be called before the other file is loaded. + + - `ff-post-load-hook' + List of functions to be called after the other file is loaded. + + - `ff-not-found-hook' + List of functions to be called if the other file could not be found. + + - `ff-file-created-hook' + List of functions to be called if the other file has been created. + +\(fn &optional IN-OTHER-WINDOW IGNORE-INCLUDE)" t nil) + +(autoload 'ff-mouse-find-other-file "find-file" "\ +Visit the file you click on. + +\(fn EVENT)" t nil) + +(autoload 'ff-mouse-find-other-file-other-window "find-file" "\ +Visit the file you click on in another window. + +\(fn EVENT)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "find-file" '("ff-" "modula2-other-file-alist" "cc-"))) + +;;;*** + +;;;### (autoloads nil "find-func" "emacs-lisp/find-func.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from emacs-lisp/find-func.el + +(autoload 'find-library "find-func" "\ +Find the Emacs Lisp source of LIBRARY. + +Interactively, prompt for LIBRARY using the one at or near point. + +\(fn LIBRARY)" t nil) + +(autoload 'find-library-other-window "find-func" "\ +Find the Emacs Lisp source of LIBRARY in another window. + +See `find-library' for more details. + +\(fn LIBRARY)" t nil) + +(autoload 'find-library-other-frame "find-func" "\ +Find the Emacs Lisp source of LIBRARY in another frame. + +See `find-library' for more details. + +\(fn LIBRARY)" t nil) + +(autoload 'find-function-search-for-symbol "find-func" "\ +Search for SYMBOL's definition of type TYPE in LIBRARY. +Visit the library in a buffer, and return a cons cell (BUFFER . POSITION), +or just (BUFFER . nil) if the definition can't be found in the file. + +If TYPE is nil, look for a function definition. +Otherwise, TYPE specifies the kind of definition, +and it is interpreted via `find-function-regexp-alist'. +The search is done in the source for library LIBRARY. + +\(fn SYMBOL TYPE LIBRARY)" nil nil) + +(autoload 'find-function-noselect "find-func" "\ +Return a pair (BUFFER . POINT) pointing to the definition of FUNCTION. + +Finds the source file containing the definition of FUNCTION +in a buffer and the point of the definition. The buffer is +not selected. If the function definition can't be found in +the buffer, returns (BUFFER). + +If FUNCTION is a built-in function, this function normally +attempts to find it in the Emacs C sources; however, if LISP-ONLY +is non-nil, signal an error instead. + +If the file where FUNCTION is defined is not known, then it is +searched for in `find-function-source-path' if non-nil, otherwise +in `load-path'. + +\(fn FUNCTION &optional LISP-ONLY)" nil nil) + +(autoload 'find-function "find-func" "\ +Find the definition of the FUNCTION near point. + +Finds the source file containing the definition of the function +near point (selected by `function-called-at-point') in a buffer and +places point before the definition. +Set mark before moving, if the buffer already existed. + +The library where FUNCTION is defined is searched for in +`find-function-source-path', if non-nil, otherwise in `load-path'. +See also `find-function-recenter-line' and `find-function-after-hook'. + +\(fn FUNCTION)" t nil) + +(autoload 'find-function-other-window "find-func" "\ +Find, in another window, the definition of FUNCTION near point. + +See `find-function' for more details. + +\(fn FUNCTION)" t nil) + +(autoload 'find-function-other-frame "find-func" "\ +Find, in another frame, the definition of FUNCTION near point. + +See `find-function' for more details. + +\(fn FUNCTION)" t nil) + +(autoload 'find-variable-noselect "find-func" "\ +Return a pair `(BUFFER . POINT)' pointing to the definition of VARIABLE. + +Finds the library containing the definition of VARIABLE in a buffer and +the point of the definition. The buffer is not selected. +If the variable's definition can't be found in the buffer, return (BUFFER). + +The library where VARIABLE is defined is searched for in FILE or +`find-function-source-path', if non-nil, otherwise in `load-path'. + +\(fn VARIABLE &optional FILE)" nil nil) + +(autoload 'find-variable "find-func" "\ +Find the definition of the VARIABLE at or before point. + +Finds the library containing the definition of the variable +near point (selected by `variable-at-point') in a buffer and +places point before the definition. + +Set mark before moving, if the buffer already existed. + +The library where VARIABLE is defined is searched for in +`find-function-source-path', if non-nil, otherwise in `load-path'. +See also `find-function-recenter-line' and `find-function-after-hook'. + +\(fn VARIABLE)" t nil) + +(autoload 'find-variable-other-window "find-func" "\ +Find, in another window, the definition of VARIABLE near point. + +See `find-variable' for more details. + +\(fn VARIABLE)" t nil) + +(autoload 'find-variable-other-frame "find-func" "\ +Find, in another frame, the definition of VARIABLE near point. + +See `find-variable' for more details. + +\(fn VARIABLE)" t nil) + +(autoload 'find-definition-noselect "find-func" "\ +Return a pair `(BUFFER . POINT)' pointing to the definition of SYMBOL. +If the definition can't be found in the buffer, return (BUFFER). +TYPE says what type of definition: nil for a function, `defvar' for a +variable, `defface' for a face. This function does not switch to the +buffer nor display it. + +The library where SYMBOL is defined is searched for in FILE or +`find-function-source-path', if non-nil, otherwise in `load-path'. + +\(fn SYMBOL TYPE &optional FILE)" nil nil) + +(autoload 'find-face-definition "find-func" "\ +Find the definition of FACE. FACE defaults to the name near point. + +Finds the Emacs Lisp library containing the definition of the face +near point (selected by `variable-at-point') in a buffer and +places point before the definition. + +Set mark before moving, if the buffer already existed. + +The library where FACE is defined is searched for in +`find-function-source-path', if non-nil, otherwise in `load-path'. +See also `find-function-recenter-line' and `find-function-after-hook'. + +\(fn FACE)" t nil) + +(autoload 'find-function-on-key "find-func" "\ +Find the function that KEY invokes. KEY is a string. +Set mark before moving, if the buffer already existed. + +\(fn KEY)" t nil) + +(autoload 'find-function-on-key-other-window "find-func" "\ +Find, in the other window, the function that KEY invokes. +See `find-function-on-key'. + +\(fn KEY)" t nil) + +(autoload 'find-function-on-key-other-frame "find-func" "\ +Find, in the other frame, the function that KEY invokes. +See `find-function-on-key'. + +\(fn KEY)" t nil) + +(autoload 'find-function-at-point "find-func" "\ +Find directly the function at point in the other window. + +\(fn)" t nil) + +(autoload 'find-variable-at-point "find-func" "\ +Find directly the variable at point in the other window. + +\(fn)" t nil) + +(autoload 'find-function-setup-keys "find-func" "\ +Define some key bindings for the find-function family of functions. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "find-func" '("find-" "read-library-name"))) + +;;;*** + +;;;### (autoloads nil "find-lisp" "find-lisp.el" (0 0 0 0)) +;;; Generated autoloads from find-lisp.el + +(autoload 'find-lisp-find-dired "find-lisp" "\ +Find files in DIR, matching REGEXP. + +\(fn DIR REGEXP)" t nil) + +(autoload 'find-lisp-find-dired-subdirectories "find-lisp" "\ +Find all subdirectories of DIR. + +\(fn DIR)" t nil) + +(autoload 'find-lisp-find-dired-filter "find-lisp" "\ +Change the filter on a `find-lisp-find-dired' buffer to REGEXP. + +\(fn REGEXP)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "find-lisp" '("find-lisp-"))) + +;;;*** + +;;;### (autoloads nil "finder" "finder.el" (0 0 0 0)) +;;; Generated autoloads from finder.el +(push (purecopy '(finder 1 0)) package--builtin-versions) + +(autoload 'finder-list-keywords "finder" "\ +Display descriptions of the keywords in the Finder buffer. + +\(fn)" t nil) + +(autoload 'finder-commentary "finder" "\ +Display FILE's commentary section. +FILE should be in a form suitable for passing to `locate-library'. + +\(fn FILE)" t nil) + +(autoload 'finder-by-keyword "finder" "\ +Find packages matching a given keyword. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "finder" '("finder-" "generated-finder-keywords-file"))) + +;;;*** + +;;;### (autoloads nil "flow-ctrl" "flow-ctrl.el" (0 0 0 0)) +;;; Generated autoloads from flow-ctrl.el + +(autoload 'enable-flow-control "flow-ctrl" "\ +Toggle flow control handling. +When handling is enabled, user can type C-s as C-\\, and C-q as C-^. +With arg, enable flow control mode if arg is positive, otherwise disable. + +\(fn &optional ARGUMENT)" t nil) + +(autoload 'enable-flow-control-on "flow-ctrl" "\ +Enable flow control if using one of a specified set of terminal types. +Use `(enable-flow-control-on \"vt100\" \"h19\")' to enable flow control +on VT-100 and H19 terminals. When flow control is enabled, +you must type C-\\ to get the effect of a C-s, and type C-^ +to get the effect of a C-q. + +\(fn &rest LOSING-TERMINAL-TYPES)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "flow-ctrl" '("flow-control-c-"))) + +;;;*** + +;;;### (autoloads nil "flow-fill" "mail/flow-fill.el" (0 0 0 0)) +;;; Generated autoloads from mail/flow-fill.el + +(autoload 'fill-flowed-encode "flow-fill" "\ + + +\(fn &optional BUFFER)" nil nil) + +(autoload 'fill-flowed "flow-fill" "\ + + +\(fn &optional BUFFER DELETE-SPACE)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "flow-fill" '("fill-flowed-"))) + +;;;*** + +;;;### (autoloads nil "flymake" "progmodes/flymake.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/flymake.el +(push (purecopy '(flymake 0 3)) package--builtin-versions) + +(autoload 'flymake-mode "flymake" "\ +Toggle Flymake mode on or off. +With a prefix argument ARG, enable Flymake mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil, and toggle it if ARG is `toggle'. +\\{flymake-mode-map} + +\(fn &optional ARG)" t nil) + +(autoload 'flymake-mode-on "flymake" "\ +Turn flymake mode on. + +\(fn)" nil nil) + +(autoload 'flymake-mode-off "flymake" "\ +Turn flymake mode off. + +\(fn)" nil nil) + +(autoload 'flymake-find-file-hook "flymake" "\ + + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "flymake" '("flymake-"))) + +;;;*** + +;;;### (autoloads nil "flyspell" "textmodes/flyspell.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/flyspell.el + +(autoload 'flyspell-prog-mode "flyspell" "\ +Turn on `flyspell-mode' for comments and strings. + +\(fn)" t nil) +(defvar flyspell-mode nil "Non-nil if Flyspell mode is enabled.") + +(autoload 'flyspell-mode "flyspell" "\ +Toggle on-the-fly spell checking (Flyspell mode). +With a prefix argument ARG, enable Flyspell mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Flyspell mode is a buffer-local minor mode. When enabled, it +spawns a single Ispell process and checks each word. The default +flyspell behavior is to highlight incorrect words. + +Bindings: +\\[ispell-word]: correct words (using Ispell). +\\[flyspell-auto-correct-word]: automatically correct word. +\\[flyspell-auto-correct-previous-word]: automatically correct the last misspelled word. +\\[flyspell-correct-word] (or down-mouse-2): popup correct words. + +Hooks: +This runs `flyspell-mode-hook' after flyspell mode is entered or exit. + +Remark: +`flyspell-mode' uses `ispell-mode'. Thus all Ispell options are +valid. For instance, a different dictionary can be used by +invoking `ispell-change-dictionary'. + +Consider using the `ispell-parser' to check your text. For instance +consider adding: +\(add-hook \\='tex-mode-hook (function (lambda () (setq ispell-parser \\='tex)))) +in your init file. + +\\[flyspell-region] checks all words inside a region. +\\[flyspell-buffer] checks the whole buffer. + +\(fn &optional ARG)" t nil) + +(autoload 'turn-on-flyspell "flyspell" "\ +Unconditionally turn on Flyspell mode. + +\(fn)" nil nil) + +(autoload 'turn-off-flyspell "flyspell" "\ +Unconditionally turn off Flyspell mode. + +\(fn)" nil nil) + +(autoload 'flyspell-mode-off "flyspell" "\ +Turn Flyspell mode off. + +\(fn)" nil nil) + +(autoload 'flyspell-region "flyspell" "\ +Flyspell text between BEG and END. + +\(fn BEG END)" t nil) + +(autoload 'flyspell-buffer "flyspell" "\ +Flyspell whole buffer. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "flyspell" '("flyspell-" "mail-mode-flyspell-verify" "make-flyspell-overlay" "sgml-mode-flyspell-verify" "tex"))) + +;;;*** + +;;;### (autoloads nil "foldout" "foldout.el" (0 0 0 0)) +;;; Generated autoloads from foldout.el +(push (purecopy '(foldout 1 10)) package--builtin-versions) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "foldout" '("foldout-"))) + +;;;*** + +;;;### (autoloads nil "follow" "follow.el" (0 0 0 0)) +;;; Generated autoloads from follow.el + +(autoload 'turn-on-follow-mode "follow" "\ +Turn on Follow mode. Please see the function `follow-mode'. + +\(fn)" nil nil) + +(autoload 'turn-off-follow-mode "follow" "\ +Turn off Follow mode. Please see the function `follow-mode'. + +\(fn)" nil nil) + +(autoload 'follow-mode "follow" "\ +Toggle Follow mode. +With a prefix argument ARG, enable Follow mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Follow mode is a minor mode that combines windows into one tall +virtual window. This is accomplished by two main techniques: + +* The windows always displays adjacent sections of the buffer. + This means that whenever one window is moved, all the + others will follow. (Hence the name Follow mode.) + +* Should point (cursor) end up outside a window, another + window displaying that point is selected, if possible. This + makes it possible to walk between windows using normal cursor + movement commands. + +Follow mode comes to its prime when used on a large screen and two or +more side-by-side windows are used. The user can, with the help of +Follow mode, use these full-height windows as though they were one. +Imagine yourself editing a large function, or section of text, and +being able to use 144 or 216 lines instead of the normal 72... (your +mileage may vary). + +To split one large window into two side-by-side windows, the commands +`\\[split-window-right]' or `\\[follow-delete-other-windows-and-split]' can be used. + +Only windows displayed in the same frame follow each other. + +This command runs the normal hook `follow-mode-hook'. + +Keys specific to Follow mode: +\\{follow-mode-map} + +\(fn &optional ARG)" t nil) + +(autoload 'follow-scroll-up-window "follow" "\ +Scroll text in a Follow mode window up by that window's size. +The other windows in the window chain will scroll synchronously. + +If called with no ARG, the `next-screen-context-lines' last lines of +the window will be visible after the scroll. + +If called with an argument, scroll ARG lines up. +Negative ARG means scroll downward. + +Works like `scroll-up' when not in Follow mode. + +\(fn &optional ARG)" t nil) + +(autoload 'follow-scroll-down-window "follow" "\ +Scroll text in a Follow mode window down by that window's size. +The other windows in the window chain will scroll synchronously. + +If called with no ARG, the `next-screen-context-lines' top lines of +the window in the chain will be visible after the scroll. + +If called with an argument, scroll ARG lines down. +Negative ARG means scroll upward. + +Works like `scroll-down' when not in Follow mode. + +\(fn &optional ARG)" t nil) + +(autoload 'follow-scroll-up "follow" "\ +Scroll text in a Follow mode window chain up. + +If called with no ARG, the `next-screen-context-lines' last lines of +the bottom window in the chain will be visible in the top window. + +If called with an argument, scroll ARG lines up. +Negative ARG means scroll downward. + +Works like `scroll-up' when not in Follow mode. + +\(fn &optional ARG)" t nil) + +(autoload 'follow-scroll-down "follow" "\ +Scroll text in a Follow mode window chain down. + +If called with no ARG, the `next-screen-context-lines' top lines of +the top window in the chain will be visible in the bottom window. + +If called with an argument, scroll ARG lines down. +Negative ARG means scroll upward. + +Works like `scroll-down' when not in Follow mode. + +\(fn &optional ARG)" t nil) + +(autoload 'follow-delete-other-windows-and-split "follow" "\ +Create two side by side windows and enter Follow mode. + +Execute this command to display as much as possible of the text +in the selected window. All other windows, in the current +frame, are deleted and the selected window is split in two +side-by-side windows. Follow mode is activated, hence the +two windows always will display two successive pages. +\(If one window is moved, the other one will follow.) + +If ARG is positive, the leftmost window is selected. If negative, +the rightmost is selected. If ARG is nil, the leftmost window is +selected if the original window is the first one in the frame. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "follow" '("follow-"))) + +;;;*** + +;;;### (autoloads nil "fontset" "international/fontset.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from international/fontset.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "fontset" '("charset-script-alist" "create-" "set" "standard-fontset-spec" "fontset-" "generate-fontset-menu" "xlfd-" "x-"))) + +;;;*** + +;;;### (autoloads nil "footnote" "mail/footnote.el" (0 0 0 0)) +;;; Generated autoloads from mail/footnote.el +(push (purecopy '(footnote 0 19)) package--builtin-versions) + +(autoload 'footnote-mode "footnote" "\ +Toggle Footnote mode. +With a prefix argument ARG, enable Footnote mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Footnote mode is a buffer-local minor mode. If enabled, it +provides footnote support for `message-mode'. To get started, +play around with the following keys: +\\{footnote-minor-mode-map} + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "footnote" '("footnote-" "Footnote-"))) + +;;;*** + +;;;### (autoloads nil "format-spec" "format-spec.el" (0 0 0 0)) +;;; Generated autoloads from format-spec.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "format-spec" '("format-spec"))) + +;;;*** + +;;;### (autoloads nil "forms" "forms.el" (0 0 0 0)) +;;; Generated autoloads from forms.el + +(autoload 'forms-mode "forms" "\ +Major mode to visit files in a field-structured manner using a form. + +Commands: Equivalent keys in read-only mode: + TAB forms-next-field TAB + C-c TAB forms-next-field + C-c < forms-first-record < + C-c > forms-last-record > + C-c ? describe-mode ? + C-c C-k forms-delete-record + C-c C-q forms-toggle-read-only q + C-c C-o forms-insert-record + C-c C-l forms-jump-record l + C-c C-n forms-next-record n + C-c C-p forms-prev-record p + C-c C-r forms-search-reverse r + C-c C-s forms-search-forward s + C-c C-x forms-exit x + +\(fn &optional PRIMARY)" t nil) + +(autoload 'forms-find-file "forms" "\ +Visit a file in Forms mode. + +\(fn FN)" t nil) + +(autoload 'forms-find-file-other-window "forms" "\ +Visit a file in Forms mode in other window. + +\(fn FN)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "forms" '("forms-"))) + +;;;*** + +;;;### (autoloads nil "fortran" "progmodes/fortran.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/fortran.el + +(autoload 'fortran-mode "fortran" "\ +Major mode for editing Fortran code in fixed format. +For free format code, use `f90-mode'. + +\\[fortran-indent-line] indents the current Fortran line correctly. +Note that DO statements must not share a common CONTINUE. + +Type ;? or ;\\[help-command] to display a list of built-in abbrevs for Fortran keywords. + +Key definitions: +\\{fortran-mode-map} + +Variables controlling indentation style and extra features: + +`fortran-comment-line-start' + To use comments starting with `!', set this to the string \"!\". +`fortran-do-indent' + Extra indentation within DO blocks (default 3). +`fortran-if-indent' + Extra indentation within IF blocks (default 3). +`fortran-structure-indent' + Extra indentation within STRUCTURE, UNION, MAP and INTERFACE blocks. + (default 3) +`fortran-continuation-indent' + Extra indentation applied to continuation statements (default 5). +`fortran-comment-line-extra-indent' + Amount of extra indentation for text in full-line comments (default 0). +`fortran-comment-indent-style' + How to indent the text in full-line comments. Allowed values are: + nil don't change the indentation + `fixed' indent to `fortran-comment-line-extra-indent' beyond the + value of either + `fortran-minimum-statement-indent-fixed' (fixed format) or + `fortran-minimum-statement-indent-tab' (TAB format), + depending on the continuation format in use. + `relative' indent to `fortran-comment-line-extra-indent' beyond the + indentation for a line of code. + (default `fixed') +`fortran-comment-indent-char' + Single-character string to be inserted instead of space for + full-line comment indentation (default \" \"). +`fortran-minimum-statement-indent-fixed' + Minimum indentation for statements in fixed format mode (default 6). +`fortran-minimum-statement-indent-tab' + Minimum indentation for statements in TAB format mode (default 9). +`fortran-line-number-indent' + Maximum indentation for line numbers (default 1). A line number will + get less than this much indentation if necessary to avoid reaching + column 5. +`fortran-check-all-num-for-matching-do' + Non-nil causes all numbered lines to be treated as possible \"continue\" + statements (default nil). +`fortran-blink-matching-if' + Non-nil causes \\[fortran-indent-line] on an ENDIF (or ENDDO) statement + to blink on the matching IF (or DO [WHILE]). (default nil) +`fortran-continuation-string' + Single-character string to be inserted in column 5 of a continuation + line (default \"$\"). +`fortran-comment-region' + String inserted by \\[fortran-comment-region] at start of each line in + the region (default \"c$$$\"). +`fortran-electric-line-number' + Non-nil causes line number digits to be moved to the correct column + as typed (default t). +`fortran-break-before-delimiters' + Non-nil causes lines to be broken before delimiters (default t). + +Turning on Fortran mode calls the value of the variable `fortran-mode-hook' +with no args, if that value is non-nil. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "fortran" '("fortran-"))) + +;;;*** + +;;;### (autoloads nil "fortune" "play/fortune.el" (0 0 0 0)) +;;; Generated autoloads from play/fortune.el + +(autoload 'fortune-add-fortune "fortune" "\ +Add STRING to a fortune file FILE. + +Interactively, if called with a prefix argument, +read the file name to use. Otherwise use the value of `fortune-file'. + +\(fn STRING FILE)" t nil) + +(autoload 'fortune-from-region "fortune" "\ +Append the current region to a local fortune-like data file. + +Interactively, if called with a prefix argument, +read the file name to use. Otherwise use the value of `fortune-file'. + +\(fn BEG END FILE)" t nil) + +(autoload 'fortune-compile "fortune" "\ +Compile fortune file. + +If called with a prefix asks for the FILE to compile, otherwise uses +the value of `fortune-file'. This currently cannot handle directories. + +\(fn &optional FILE)" t nil) + +(autoload 'fortune-to-signature "fortune" "\ +Create signature from output of the fortune program. + +If called with a prefix asks for the FILE to choose the fortune from, +otherwise uses the value of `fortune-file'. If you want to have fortune +choose from a set of files in a directory, call interactively with prefix +and choose the directory as the fortune-file. + +\(fn &optional FILE)" t nil) + +(autoload 'fortune-message "fortune" "\ +Display a fortune cookie to the mini-buffer. +If called with a prefix, it has the same behavior as `fortune'. +Optional FILE is a fortune file from which a cookie will be selected. + +\(fn &optional FILE)" t nil) + +(autoload 'fortune "fortune" "\ +Display a fortune cookie. +If called with a prefix asks for the FILE to choose the fortune from, +otherwise uses the value of `fortune-file'. If you want to have fortune +choose from a set of files in a directory, call interactively with prefix +and choose the directory as the fortune-file. + +\(fn &optional FILE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "fortune" '("fortune-"))) + +;;;*** + +;;;### (autoloads nil "frameset" "frameset.el" (0 0 0 0)) +;;; Generated autoloads from frameset.el + +(defvar frameset-session-filter-alist '((name . :never) (left . frameset-filter-iconified) (minibuffer . frameset-filter-minibuffer) (top . frameset-filter-iconified)) "\ +Minimum set of parameters to filter for live (on-session) framesets. +DO NOT MODIFY. See `frameset-filter-alist' for a full description.") + +(defvar frameset-persistent-filter-alist (nconc '((background-color . frameset-filter-sanitize-color) (buffer-list . :never) (buffer-predicate . :never) (buried-buffer-list . :never) (delete-before . :never) (font . frameset-filter-shelve-param) (foreground-color . frameset-filter-sanitize-color) (fullscreen . frameset-filter-shelve-param) (GUI:font . frameset-filter-unshelve-param) (GUI:fullscreen . frameset-filter-unshelve-param) (GUI:height . frameset-filter-unshelve-param) (GUI:width . frameset-filter-unshelve-param) (height . frameset-filter-shelve-param) (outer-window-id . :never) (parent-frame . :never) (parent-id . :never) (mouse-wheel-frame . :never) (tty . frameset-filter-tty-to-GUI) (tty-type . frameset-filter-tty-to-GUI) (width . frameset-filter-shelve-param) (window-id . :never) (window-system . :never)) frameset-session-filter-alist) "\ +Parameters to filter for persistent framesets. +DO NOT MODIFY. See `frameset-filter-alist' for a full description.") + +(defvar frameset-filter-alist frameset-persistent-filter-alist "\ +Alist of frame parameters and filtering functions. + +This alist is the default value of the FILTERS argument of +`frameset-save' and `frameset-restore' (which see). + +Initially, `frameset-filter-alist' is set to, and shares the value of, +`frameset-persistent-filter-alist'. You can override any item in +this alist by `push'ing a new item onto it. If, for some reason, you +intend to modify existing values, do + + (setq frameset-filter-alist (copy-tree frameset-filter-alist)) + +before changing anything. + +On saving, PARAMETERS is the parameter alist of each frame processed, +and FILTERED is the parameter alist that gets saved to the frameset. + +On restoring, PARAMETERS is the parameter alist extracted from the +frameset, and FILTERED is the resulting frame parameter alist used +to restore the frame. + +Elements of `frameset-filter-alist' are conses (PARAM . ACTION), +where PARAM is a parameter name (a symbol identifying a frame +parameter), and ACTION can be: + + nil The parameter is copied to FILTERED. + :never The parameter is never copied to FILTERED. + :save The parameter is copied only when saving the frame. + :restore The parameter is copied only when restoring the frame. + FILTER A filter function. + +FILTER can be a symbol FILTER-FUN, or a list (FILTER-FUN ARGS...). +FILTER-FUN is invoked with + + (apply FILTER-FUN CURRENT FILTERED PARAMETERS SAVING ARGS) + +where + + CURRENT A cons (PARAM . VALUE), where PARAM is the one being + filtered and VALUE is its current value. + FILTERED The resulting alist (so far). + PARAMETERS The complete alist of parameters being filtered, + SAVING Non-nil if filtering before saving state, nil if filtering + before restoring it. + ARGS Any additional arguments specified in the ACTION. + +FILTER-FUN is allowed to modify items in FILTERED, but no other arguments. +It must return: + nil Skip CURRENT (do not add it to FILTERED). + t Add CURRENT to FILTERED as is. + (NEW-PARAM . NEW-VALUE) Add this to FILTERED instead of CURRENT. + +Frame parameters not on this alist are passed intact, as if they were +defined with ACTION = nil.") + +(autoload 'frameset-frame-id "frameset" "\ +Return the frame id of FRAME, if it has one; else, return nil. +A frame id is a string that uniquely identifies a frame. +It is persistent across `frameset-save' / `frameset-restore' +invocations, and once assigned is never changed unless the same +frame is duplicated (via `frameset-restore'), in which case the +newest frame keeps the id and the old frame's is set to nil. + +\(fn FRAME)" nil nil) + +(autoload 'frameset-frame-id-equal-p "frameset" "\ +Return non-nil if FRAME's id matches ID. + +\(fn FRAME ID)" nil nil) + +(autoload 'frameset-frame-with-id "frameset" "\ +Return the live frame with id ID, if exists; else nil. +If FRAME-LIST is a list of frames, check these frames only. +If nil, check all live frames. + +\(fn ID &optional FRAME-LIST)" nil nil) + +(autoload 'frameset-save "frameset" "\ +Return a frameset for FRAME-LIST, a list of frames. +Dead frames and non-frame objects are silently removed from the list. +If nil, FRAME-LIST defaults to the output of `frame-list' (all live frames). +APP, NAME and DESCRIPTION are optional data; see the docstring of the +`frameset' defstruct for details. +FILTERS is an alist of parameter filters; if nil, the value of the variable +`frameset-filter-alist' is used instead. +PREDICATE is a predicate function, which must return non-nil for frames that +should be saved; if PREDICATE is nil, all frames from FRAME-LIST are saved. +PROPERTIES is a user-defined property list to add to the frameset. + +\(fn FRAME-LIST &key APP NAME DESCRIPTION FILTERS PREDICATE PROPERTIES)" nil nil) + +(autoload 'frameset-restore "frameset" "\ +Restore a FRAMESET into the current display(s). + +PREDICATE is a function called with two arguments, the parameter alist +and the window-state of the frame being restored, in that order (see +the docstring of the `frameset' defstruct for additional details). +If PREDICATE returns nil, the frame described by that parameter alist +and window-state is not restored. + +FILTERS is an alist of parameter filters; if nil, the value of +`frameset-filter-alist' is used instead. + +REUSE-FRAMES selects the policy to reuse frames when restoring: + t All existing frames can be reused. + nil No existing frame can be reused. + match Only frames with matching frame ids can be reused. + PRED A predicate function; it receives as argument a live frame, + and must return non-nil to allow reusing it, nil otherwise. + +FORCE-DISPLAY can be: + t Frames are restored in the current display. + nil Frames are restored, if possible, in their original displays. + delete Frames in other displays are deleted instead of restored. + PRED A function called with two arguments, the parameter alist and + the window state (in that order). It must return t, nil or + `delete', as above but affecting only the frame that will + be created from that parameter alist. + +FORCE-ONSCREEN can be: + t Force onscreen only those frames that are fully offscreen. + nil Do not force any frame back onscreen. + all Force onscreen any frame fully or partially offscreen. + PRED A function called with three arguments, + - the live frame just restored, + - a list (LEFT TOP WIDTH HEIGHT), describing the frame, + - a list (LEFT TOP WIDTH HEIGHT), describing the workarea. + It must return non-nil to force the frame onscreen, nil otherwise. + +CLEANUP-FRAMES allows \"cleaning up\" the frame list after restoring a frameset: + t Delete all frames that were not created or restored upon. + nil Keep all frames. + FUNC A function called with two arguments: + - FRAME, a live frame. + - ACTION, which can be one of + :rejected Frame existed, but was not a candidate for reuse. + :ignored Frame existed, was a candidate, but wasn't reused. + :reused Frame existed, was a candidate, and restored upon. + :created Frame didn't exist, was created and restored upon. + Return value is ignored. + +Note the timing and scope of the operations described above: REUSE-FRAMES +affects existing frames; PREDICATE, FILTERS and FORCE-DISPLAY affect the frame +being restored before that happens; FORCE-ONSCREEN affects the frame once +it has been restored; and CLEANUP-FRAMES affects all frames alive after the +restoration, including those that have been reused or created anew. + +All keyword parameters default to nil. + +\(fn FRAMESET &key PREDICATE FILTERS REUSE-FRAMES FORCE-DISPLAY FORCE-ONSCREEN CLEANUP-FRAMES)" nil nil) + +(autoload 'frameset--jump-to-register "frameset" "\ +Restore frameset from DATA stored in register. +Called from `jump-to-register'. Internal use only. + +\(fn DATA)" nil nil) + +(autoload 'frameset--print-register "frameset" "\ +Print basic info about frameset stored in DATA. +Called from `list-registers' and `view-register'. Internal use only. + +\(fn DATA)" nil nil) + +(autoload 'frameset-to-register "frameset" "\ +Store the current frameset in register REGISTER. +Use \\[jump-to-register] to restore the frameset. +Argument is a character, naming the register. + +Interactively, reads the register using `register-read-with-preview'. + +\(fn REGISTER)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "frameset" '("frameset-"))) + +;;;*** + +;;;### (autoloads nil "fringe" "fringe.el" (0 0 0 0)) +;;; Generated autoloads from fringe.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "fringe" '("fringe-" "set-fringe-"))) + +;;;*** + +;;;### (autoloads nil "gamegrid" "play/gamegrid.el" (0 0 0 0)) +;;; Generated autoloads from play/gamegrid.el +(push (purecopy '(gamegrid 1 2)) package--builtin-versions) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gamegrid" '("gamegrid-"))) + +;;;*** + +;;;### (autoloads nil "gametree" "play/gametree.el" (0 0 0 0)) +;;; Generated autoloads from play/gametree.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gametree" '("gametree-"))) + +;;;*** + +;;;### (autoloads nil "gdb-mi" "progmodes/gdb-mi.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/gdb-mi.el + +(defvar gdb-enable-debug nil "\ +Non-nil if Gdb-Enable-Debug mode is enabled. +See the `gdb-enable-debug' command +for a description of this minor mode.") + +(custom-autoload 'gdb-enable-debug "gdb-mi" nil) + +(autoload 'gdb-enable-debug "gdb-mi" "\ +Toggle logging of transaction between Emacs and Gdb. +The log is stored in `gdb-debug-log' as an alist with elements +whose cons is send, send-item or recv and whose cdr is the string +being transferred. This list may grow up to a size of +`gdb-debug-log-max' after which the oldest element (at the end of +the list) is deleted every time a new one is added (at the front). + +\(fn &optional ARG)" t nil) + +(autoload 'gdb "gdb-mi" "\ +Run gdb passing it COMMAND-LINE as arguments. + +If COMMAND-LINE names a program FILE to debug, gdb will run in +a buffer named *gud-FILE*, and the directory containing FILE +becomes the initial working directory and source-file directory +for your debugger. +If COMMAND-LINE requests that gdb attaches to a process PID, gdb +will run in *gud-PID*, otherwise it will run in *gud*; in these +cases the initial working directory is the default-directory of +the buffer in which this command was invoked. + +COMMAND-LINE should include \"-i=mi\" to use gdb's MI text interface. +Note that the old \"--annotate\" option is no longer supported. + +If option `gdb-many-windows' is nil (the default value) then gdb just +pops up the GUD buffer unless `gdb-show-main' is t. In this case +it starts with two windows: one displaying the GUD buffer and the +other with the source file with the main routine of the inferior. + +If option `gdb-many-windows' is t, regardless of the value of +`gdb-show-main', the layout below will appear. Keybindings are +shown in some of the buffers. + +Watch expressions appear in the speedbar/slowbar. + +The following commands help control operation : + +`gdb-many-windows' - Toggle the number of windows gdb uses. +`gdb-restore-windows' - To restore the window layout. + +See Info node `(emacs)GDB Graphical Interface' for a more +detailed description of this mode. + + ++----------------------------------------------------------------------+ +| GDB Toolbar | ++-----------------------------------+----------------------------------+ +| GUD buffer (I/O of GDB) | Locals buffer | +| | | +| | | +| | | ++-----------------------------------+----------------------------------+ +| Source buffer | I/O buffer (of debugged program) | +| | (comint-mode) | +| | | +| | | +| | | +| | | +| | | +| | | ++-----------------------------------+----------------------------------+ +| Stack buffer | Breakpoints buffer | +| RET gdb-select-frame | SPC gdb-toggle-breakpoint | +| | RET gdb-goto-breakpoint | +| | D gdb-delete-breakpoint | ++-----------------------------------+----------------------------------+ + +\(fn COMMAND-LINE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gdb-mi" '("gdb" "gud-" "def-gdb-" "breakpoint-" "nil"))) + +;;;*** + +;;;### (autoloads nil "generator" "emacs-lisp/generator.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from emacs-lisp/generator.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "generator" '("cps-" "iter-"))) + +;;;*** + +;;;### (autoloads nil "generic" "emacs-lisp/generic.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/generic.el + +(defvar generic-mode-list nil "\ +A list of mode names for `generic-mode'. +Do not add entries to this list directly; use `define-generic-mode' +instead (which see).") + +(autoload 'define-generic-mode "generic" "\ +Create a new generic mode MODE. + +MODE is the name of the command for the generic mode; don't quote it. +The optional DOCSTRING is the documentation for the mode command. If +you do not supply it, `define-generic-mode' uses a default +documentation string instead. + +COMMENT-LIST is a list in which each element is either a character, a +string of one or two characters, or a cons cell. A character or a +string is set up in the mode's syntax table as a \"comment starter\". +If the entry is a cons cell, the `car' is set up as a \"comment +starter\" and the `cdr' as a \"comment ender\". (Use nil for the +latter if you want comments to end at the end of the line.) Note that +the syntax table has limitations about what comment starters and +enders are actually possible. + +KEYWORD-LIST is a list of keywords to highlight with +`font-lock-keyword-face'. Each keyword should be a string. + +FONT-LOCK-LIST is a list of additional expressions to highlight. Each +element of this list should have the same form as an element of +`font-lock-keywords'. + +AUTO-MODE-LIST is a list of regular expressions to add to +`auto-mode-alist'. These regular expressions are added when Emacs +runs the macro expansion. + +FUNCTION-LIST is a list of functions to call to do some additional +setup. The mode command calls these functions just before it runs the +mode hook `MODE-hook'. + +See the file generic-x.el for some examples of `define-generic-mode'. + +\(fn MODE COMMENT-LIST KEYWORD-LIST FONT-LOCK-LIST AUTO-MODE-LIST FUNCTION-LIST &optional DOCSTRING)" nil t) + +(function-put 'define-generic-mode 'lisp-indent-function '1) + +(function-put 'define-generic-mode 'doc-string-elt '7) + +(autoload 'generic-mode-internal "generic" "\ +Go into the generic mode MODE. + +\(fn MODE COMMENT-LIST KEYWORD-LIST FONT-LOCK-LIST FUNCTION-LIST)" nil nil) + +(autoload 'generic-mode "generic" "\ +Enter generic mode MODE. + +Generic modes provide basic comment and font-lock functionality +for \"generic\" files. (Files which are too small to warrant their +own mode, but have comment characters, keywords, and the like.) + +To define a generic-mode, use the function `define-generic-mode'. +Some generic modes are defined in `generic-x.el'. + +\(fn MODE)" t nil) + +(autoload 'generic-make-keywords-list "generic" "\ +Return a `font-lock-keywords' construct that highlights KEYWORD-LIST. +KEYWORD-LIST is a list of keyword strings that should be +highlighted with face FACE. This function calculates a regular +expression that matches these keywords and concatenates it with +PREFIX and SUFFIX. Then it returns a construct based on this +regular expression that can be used as an element of +`font-lock-keywords'. + +\(fn KEYWORD-LIST FACE &optional PREFIX SUFFIX)" nil nil) + +(make-obsolete 'generic-make-keywords-list 'regexp-opt '"24.4") + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "generic" '("generic-"))) + +;;;*** + +;;;### (autoloads nil "generic-x" "generic-x.el" (0 0 0 0)) +;;; Generated autoloads from generic-x.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "generic-x" '("generic-" "default-generic-mode"))) + +;;;*** + +;;;### (autoloads nil "glasses" "progmodes/glasses.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/glasses.el + +(autoload 'glasses-mode "glasses" "\ +Minor mode for making identifiers likeThis readable. +With a prefix argument ARG, enable the mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode +if ARG is omitted or nil. When this mode is active, it tries to +add virtual separators (like underscores) at places they belong to. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "glasses" '("glasses-"))) + +;;;*** + +;;;### (autoloads nil "gmm-utils" "gnus/gmm-utils.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gmm-utils.el + +(autoload 'gmm-regexp-concat "gmm-utils" "\ +Potentially concat a list of regexps into a single one. +The concatenation is done with logical ORs. + +\(fn REGEXP)" nil nil) + +(autoload 'gmm-message "gmm-utils" "\ +If LEVEL is lower than `gmm-verbose' print ARGS using `message'. + +Guideline for numbers: +1 - error messages +3 - non-serious error messages +5 - messages for things that take a long time +7 - not very important messages on stuff +9 - messages inside loops. + +\(fn LEVEL &rest ARGS)" nil nil) + +(autoload 'gmm-error "gmm-utils" "\ +Beep an error if LEVEL is equal to or less than `gmm-verbose'. +ARGS are passed to `message'. + +\(fn LEVEL &rest ARGS)" nil nil) + +(autoload 'gmm-widget-p "gmm-utils" "\ +Non-nil if SYMBOL is a widget. + +\(fn SYMBOL)" nil nil) + +(autoload 'gmm-tool-bar-from-list "gmm-utils" "\ +Make a tool bar from ICON-LIST. + +Within each entry of ICON-LIST, the first element is a menu +command, the second element is an icon file name and the third +element is a test function. You can use \\[describe-key] +<menu-entry> to find out the name of a menu command. The fourth +and all following elements are passed as the PROPS argument to the +function `tool-bar-local-item'. + +If ZAP-LIST is a list, remove those item from the default +`tool-bar-map'. If it is t, start with a new sparse map. You +can use \\[describe-key] <icon> to find out the name of an icon +item. When \\[describe-key] <icon> shows \"<tool-bar> <new-file> +runs the command find-file\", then use `new-file' in ZAP-LIST. + +DEFAULT-MAP specifies the default key map for ICON-LIST. + +\(fn ICON-LIST ZAP-LIST DEFAULT-MAP)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gmm-utils" '("gmm-" "defun-gmm"))) + +;;;*** + +;;;### (autoloads nil "gnus" "gnus/gnus.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus.el +(push (purecopy '(gnus 5 13)) package--builtin-versions) +(when (fboundp 'custom-autoload) + (custom-autoload 'gnus-select-method "gnus")) + +(autoload 'gnus-slave-no-server "gnus" "\ +Read network news as a slave, without connecting to the local server. + +\(fn &optional ARG)" t nil) + +(autoload 'gnus-no-server "gnus" "\ +Read network news. +If ARG is a positive number, Gnus will use that as the startup +level. If ARG is nil, Gnus will be started at level 2. If ARG is +non-nil and not a positive number, Gnus will prompt the user for the +name of an NNTP server to use. +As opposed to `gnus', this command will not connect to the local +server. + +\(fn &optional ARG SLAVE)" t nil) + +(autoload 'gnus-slave "gnus" "\ +Read news as a slave. + +\(fn &optional ARG)" t nil) + +(autoload 'gnus-other-frame "gnus" "\ +Pop up a frame to read news. +This will call one of the Gnus commands which is specified by the user +option `gnus-other-frame-function' (default `gnus') with the argument +ARG if Gnus is not running, otherwise pop up a Gnus frame and run the +command specified by `gnus-other-frame-resume-function'. +The optional second argument DISPLAY should be a standard display string +such as \"unix:0\" to specify where to pop up a frame. If DISPLAY is +omitted or the function `make-frame-on-display' is not available, the +current display is used. + +\(fn &optional ARG DISPLAY)" t nil) + +(autoload 'gnus "gnus" "\ +Read network news. +If ARG is non-nil and a positive number, Gnus will use that as the +startup level. If ARG is non-nil and not a positive number, Gnus will +prompt the user for the name of an NNTP server to use. + +\(fn &optional ARG DONT-CONNECT SLAVE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-agent" "gnus/gnus-agent.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-agent.el + +(autoload 'gnus-unplugged "gnus-agent" "\ +Start Gnus unplugged. + +\(fn)" t nil) + +(autoload 'gnus-plugged "gnus-agent" "\ +Start Gnus plugged. + +\(fn)" t nil) + +(autoload 'gnus-slave-unplugged "gnus-agent" "\ +Read news as a slave unplugged. + +\(fn &optional ARG)" t nil) + +(autoload 'gnus-agentize "gnus-agent" "\ +Allow Gnus to be an offline newsreader. + +The gnus-agentize function is now called internally by gnus when +gnus-agent is set. If you wish to avoid calling gnus-agentize, +customize gnus-agent to nil. + +This will modify the `gnus-setup-news-hook', and +`message-send-mail-real-function' variables, and install the Gnus agent +minor mode in all Gnus buffers. + +\(fn)" t nil) + +(autoload 'gnus-agent-possibly-save-gcc "gnus-agent" "\ +Save GCC if Gnus is unplugged. + +\(fn)" nil nil) + +(autoload 'gnus-agent-rename-group "gnus-agent" "\ +Rename fully-qualified OLD-GROUP as NEW-GROUP. +Always updates the agent, even when disabled, as the old agent +files would corrupt gnus when the agent was next enabled. +Depends upon the caller to determine whether group renaming is +supported. + +\(fn OLD-GROUP NEW-GROUP)" nil nil) + +(autoload 'gnus-agent-delete-group "gnus-agent" "\ +Delete fully-qualified GROUP. +Always updates the agent, even when disabled, as the old agent +files would corrupt gnus when the agent was next enabled. +Depends upon the caller to determine whether group deletion is +supported. + +\(fn GROUP)" nil nil) + +(autoload 'gnus-agent-get-undownloaded-list "gnus-agent" "\ +Construct list of articles that have not been downloaded. + +\(fn)" nil nil) + +(autoload 'gnus-agent-possibly-alter-active "gnus-agent" "\ +Possibly expand a group's active range to include articles +downloaded into the agent. + +\(fn GROUP ACTIVE &optional INFO)" nil nil) + +(autoload 'gnus-agent-find-parameter "gnus-agent" "\ +Search for GROUPs SYMBOL in the group's parameters, the group's +topic parameters, the group's category, or the customizable +variables. Returns the first non-nil value found. + +\(fn GROUP SYMBOL)" nil nil) + +(autoload 'gnus-agent-batch-fetch "gnus-agent" "\ +Start Gnus and fetch session. + +\(fn)" t nil) + +(autoload 'gnus-agent-batch "gnus-agent" "\ +Start Gnus, send queue and fetch session. + +\(fn)" t nil) + +(autoload 'gnus-agent-regenerate "gnus-agent" "\ +Regenerate all agent covered files. +CLEAN is obsolete and ignored. + +\(fn &optional CLEAN REREAD)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-agent" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-art" "gnus/gnus-art.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-art.el + +(autoload 'gnus-article-prepare-display "gnus-art" "\ +Make the current buffer look like a nice article. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-art" '("gnus-" "article-"))) + +;;;*** + +;;;### (autoloads nil "gnus-async" "gnus/gnus-async.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-async.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-async" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-bcklg" "gnus/gnus-bcklg.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-bcklg.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-bcklg" '("gnus-backlog-"))) + +;;;*** + +;;;### (autoloads nil "gnus-bookmark" "gnus/gnus-bookmark.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from gnus/gnus-bookmark.el + +(autoload 'gnus-bookmark-set "gnus-bookmark" "\ +Set a bookmark for this article. + +\(fn)" t nil) + +(autoload 'gnus-bookmark-jump "gnus-bookmark" "\ +Jump to a Gnus bookmark (BMK-NAME). + +\(fn &optional BMK-NAME)" t nil) + +(autoload 'gnus-bookmark-bmenu-list "gnus-bookmark" "\ +Display a list of existing Gnus bookmarks. +The list is displayed in a buffer named `*Gnus Bookmark List*'. +The leftmost column displays a D if the bookmark is flagged for +deletion, or > if it is flagged for displaying. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-bookmark" '("gnus-bookmark-"))) + +;;;*** + +;;;### (autoloads nil "gnus-cache" "gnus/gnus-cache.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-cache.el + +(autoload 'gnus-jog-cache "gnus-cache" "\ +Go through all groups and put the articles into the cache. + +Usage: +$ emacs -batch -l ~/.emacs -l gnus -f gnus-jog-cache + +\(fn)" t nil) + +(autoload 'gnus-cache-generate-active "gnus-cache" "\ +Generate the cache active file. + +\(fn &optional DIRECTORY)" t nil) + +(autoload 'gnus-cache-generate-nov-databases "gnus-cache" "\ +Generate NOV files recursively starting in DIR. + +\(fn DIR)" t nil) + +(autoload 'gnus-cache-rename-group "gnus-cache" "\ +Rename OLD-GROUP as NEW-GROUP. +Always updates the cache, even when disabled, as the old cache +files would corrupt Gnus when the cache was next enabled. It +depends on the caller to determine whether group renaming is +supported. + +\(fn OLD-GROUP NEW-GROUP)" nil nil) + +(autoload 'gnus-cache-delete-group "gnus-cache" "\ +Delete GROUP from the cache. +Always updates the cache, even when disabled, as the old cache +files would corrupt gnus when the cache was next enabled. +Depends upon the caller to determine whether group deletion is +supported. + +\(fn GROUP)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-cache" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-cite" "gnus/gnus-cite.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-cite.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-cite" '("turn-o" "gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-cloud" "gnus/gnus-cloud.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-cloud.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-cloud" '("gnus-cloud-"))) + +;;;*** + +;;;### (autoloads nil "gnus-cus" "gnus/gnus-cus.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-cus.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-cus" '("gnus-" "category-fields"))) + +;;;*** + +;;;### (autoloads nil "gnus-delay" "gnus/gnus-delay.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-delay.el + +(autoload 'gnus-delay-article "gnus-delay" "\ +Delay this article by some time. +DELAY is a string, giving the length of the time. Possible values are: + +* <digits><units> for <units> in minutes (`m'), hours (`h'), days (`d'), + weeks (`w'), months (`M'), or years (`Y'); + +* YYYY-MM-DD for a specific date. The time of day is given by the + variable `gnus-delay-default-hour', minute and second are zero. + +* hh:mm for a specific time. Use 24h format. If it is later than this + time, then the deadline is tomorrow, else today. + +\(fn DELAY)" t nil) + +(autoload 'gnus-delay-send-queue "gnus-delay" "\ +Send all the delayed messages that are due now. + +\(fn)" t nil) + +(autoload 'gnus-delay-initialize "gnus-delay" "\ +Initialize the gnus-delay package. +This sets up a key binding in `message-mode' to delay a message. +This tells Gnus to look for delayed messages after getting new news. + +The optional arg NO-KEYMAP is ignored. +Checking delayed messages is skipped if optional arg NO-CHECK is non-nil. + +\(fn &optional NO-KEYMAP NO-CHECK)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-delay" '("gnus-delay-"))) + +;;;*** + +;;;### (autoloads nil "gnus-demon" "gnus/gnus-demon.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-demon.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-demon" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-diary" "gnus/gnus-diary.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-diary.el + +(autoload 'gnus-user-format-function-d "gnus-diary" "\ + + +\(fn HEADER)" nil nil) + +(autoload 'gnus-user-format-function-D "gnus-diary" "\ + + +\(fn HEADER)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-diary" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-dired" "gnus/gnus-dired.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-dired.el + +(autoload 'turn-on-gnus-dired-mode "gnus-dired" "\ +Convenience method to turn on gnus-dired-mode. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-dired" '("gnus-dired-"))) + +;;;*** + +;;;### (autoloads nil "gnus-draft" "gnus/gnus-draft.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-draft.el + +(autoload 'gnus-draft-reminder "gnus-draft" "\ +Reminder user if there are unsent drafts. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-draft" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-dup" "gnus/gnus-dup.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-dup.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-dup" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-eform" "gnus/gnus-eform.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-eform.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-eform" '("gnus-edit-form"))) + +;;;*** + +;;;### (autoloads nil "gnus-fun" "gnus/gnus-fun.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-fun.el + +(autoload 'gnus--random-face-with-type "gnus-fun" "\ +Return file from DIR with extension EXT, omitting matches of OMIT, processed by FUN. + +\(fn DIR EXT OMIT FUN)" nil nil) + +(autoload 'message-goto-eoh "message" nil t) + +(autoload 'gnus-random-x-face "gnus-fun" "\ +Return X-Face header data chosen randomly from `gnus-x-face-directory'. + +Files matching `gnus-x-face-omit-files' are not considered. + +\(fn)" t nil) + +(autoload 'gnus-insert-random-x-face-header "gnus-fun" "\ +Insert a random X-Face header from `gnus-x-face-directory'. + +\(fn)" t nil) + +(autoload 'gnus-x-face-from-file "gnus-fun" "\ +Insert an X-Face header based on an image FILE. + +Depending on `gnus-convert-image-to-x-face-command' it may accept +different input formats. + +\(fn FILE)" t nil) + +(autoload 'gnus-face-from-file "gnus-fun" "\ +Return a Face header based on an image FILE. + +Depending on `gnus-convert-image-to-face-command' it may accept +different input formats. + +\(fn FILE)" t nil) + +(autoload 'gnus-convert-face-to-png "gnus-fun" "\ +Convert FACE (which is base64-encoded) to a PNG. +The PNG is returned as a string. + +\(fn FACE)" nil nil) + +(autoload 'gnus-convert-png-to-face "gnus-fun" "\ +Convert FILE to a Face. +FILE should be a PNG file that's 48x48 and smaller than or equal to +726 bytes. + +\(fn FILE)" nil nil) + +(autoload 'gnus-random-face "gnus-fun" "\ +Return randomly chosen Face from `gnus-face-directory'. + +Files matching `gnus-face-omit-files' are not considered. + +\(fn)" t nil) + +(autoload 'gnus-insert-random-face-header "gnus-fun" "\ +Insert a random Face header from `gnus-face-directory'. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-fun" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-gravatar" "gnus/gnus-gravatar.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from gnus/gnus-gravatar.el + +(autoload 'gnus-treat-from-gravatar "gnus-gravatar" "\ +Display gravatar in the From header. +If gravatar is already displayed, remove it. + +\(fn &optional FORCE)" t nil) + +(autoload 'gnus-treat-mail-gravatar "gnus-gravatar" "\ +Display gravatars in the Cc and To headers. +If gravatars are already displayed, remove them. + +\(fn &optional FORCE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-gravatar" '("gnus-gravatar-"))) + +;;;*** + +;;;### (autoloads nil "gnus-group" "gnus/gnus-group.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-group.el + +(autoload 'gnus-fetch-group "gnus-group" "\ +Start Gnus if necessary and enter GROUP. +If ARTICLES, display those articles. +Returns whether the fetching was successful or not. + +\(fn GROUP &optional ARTICLES)" t nil) + +(autoload 'gnus-fetch-group-other-frame "gnus-group" "\ +Pop up a frame and enter GROUP. + +\(fn GROUP)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-group" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-html" "gnus/gnus-html.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-html.el + +(autoload 'gnus-article-html "gnus-html" "\ + + +\(fn &optional HANDLE)" nil nil) + +(autoload 'gnus-html-prefetch-images "gnus-html" "\ + + +\(fn SUMMARY)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-html" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-icalendar" "gnus/gnus-icalendar.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from gnus/gnus-icalendar.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-icalendar" '("gnus-icalendar"))) + +;;;*** + +;;;### (autoloads nil "gnus-int" "gnus/gnus-int.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-int.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-int" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-kill" "gnus/gnus-kill.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-kill.el + +(defalias 'gnus-batch-kill 'gnus-batch-score) + +(autoload 'gnus-batch-score "gnus-kill" "\ +Run batched scoring. +Usage: emacs -batch -l ~/.emacs -l gnus -f gnus-batch-score + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-kill" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-logic" "gnus/gnus-logic.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-logic.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-logic" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-mh" "gnus/gnus-mh.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-mh.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-mh" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-ml" "gnus/gnus-ml.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-ml.el + +(autoload 'turn-on-gnus-mailing-list-mode "gnus-ml" "\ + + +\(fn)" nil nil) + +(autoload 'gnus-mailing-list-insinuate "gnus-ml" "\ +Setup group parameters from List-Post header. +If FORCE is non-nil, replace the old ones. + +\(fn &optional FORCE)" t nil) + +(autoload 'gnus-mailing-list-mode "gnus-ml" "\ +Minor mode for providing mailing-list commands. + +\\{gnus-mailing-list-mode-map} + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-ml" '("gnus-mailing-list-"))) + +;;;*** + +;;;### (autoloads nil "gnus-mlspl" "gnus/gnus-mlspl.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-mlspl.el + +(autoload 'gnus-group-split-setup "gnus-mlspl" "\ +Set up the split for `nnmail-split-fancy'. +Sets things up so that nnmail-split-fancy is used for mail +splitting, and defines the variable nnmail-split-fancy according with +group parameters. + +If AUTO-UPDATE is non-nil (prefix argument accepted, if called +interactively), it makes sure nnmail-split-fancy is re-computed before +getting new mail, by adding `gnus-group-split-update' to +`nnmail-pre-get-new-mail-hook'. + +A non-nil CATCH-ALL replaces the current value of +`gnus-group-split-default-catch-all-group'. This variable is only used +by gnus-group-split-update, and only when its CATCH-ALL argument is +nil. This argument may contain any fancy split, that will be added as +the last split in a `|' split produced by `gnus-group-split-fancy', +unless overridden by any group marked as a catch-all group. Typical +uses are as simple as the name of a default mail group, but more +elaborate fancy splits may also be useful to split mail that doesn't +match any of the group-specified splitting rules. See +`gnus-group-split-fancy' for details. + +\(fn &optional AUTO-UPDATE CATCH-ALL)" t nil) + +(autoload 'gnus-group-split-update "gnus-mlspl" "\ +Computes nnmail-split-fancy from group params and CATCH-ALL. +It does this by calling by calling (gnus-group-split-fancy nil +nil CATCH-ALL). + +If CATCH-ALL is nil, `gnus-group-split-default-catch-all-group' is used +instead. This variable is set by `gnus-group-split-setup'. + +\(fn &optional CATCH-ALL)" t nil) + +(autoload 'gnus-group-split "gnus-mlspl" "\ +Use information from group parameters in order to split mail. +See `gnus-group-split-fancy' for more information. + +`gnus-group-split' is a valid value for `nnmail-split-methods'. + +\(fn)" nil nil) + +(autoload 'gnus-group-split-fancy "gnus-mlspl" "\ +Uses information from group parameters in order to split mail. +It can be embedded into `nnmail-split-fancy' lists with the SPLIT + +\(: gnus-group-split-fancy GROUPS NO-CROSSPOST CATCH-ALL) + +GROUPS may be a regular expression or a list of group names, that will +be used to select candidate groups. If it is omitted or nil, all +existing groups are considered. + +if NO-CROSSPOST is omitted or nil, a & split will be returned, +otherwise, a | split, that does not allow crossposting, will be +returned. + +For each selected group, a SPLIT is composed like this: if SPLIT-SPEC +is specified, this split is returned as-is (unless it is nil: in this +case, the group is ignored). Otherwise, if TO-ADDRESS, TO-LIST and/or +EXTRA-ALIASES are specified, a regexp that matches any of them is +constructed (extra-aliases may be a list). Additionally, if +SPLIT-REGEXP is specified, the regexp will be extended so that it +matches this regexp too, and if SPLIT-EXCLUDE is specified, RESTRICT +clauses will be generated. + +If CATCH-ALL is nil, no catch-all handling is performed, regardless of +catch-all marks in group parameters. Otherwise, if there is no +selected group whose SPLIT-REGEXP matches the empty string, nor is +there a selected group whose SPLIT-SPEC is `catch-all', this fancy +split (say, a group name) will be appended to the returned SPLIT list, +as the last element of a `|' SPLIT. + +For example, given the following group parameters: + +nnml:mail.bar: +\((to-address . \"bar@femail.com\") + (split-regexp . \".*@femail\\\\.com\")) +nnml:mail.foo: +\((to-list . \"foo@nowhere.gov\") + (extra-aliases \"foo@localhost\" \"foo-redist@home\") + (split-exclude \"bugs-foo\" \"rambling-foo\") + (admin-address . \"foo-request@nowhere.gov\")) +nnml:mail.others: +\((split-spec . catch-all)) + +Calling (gnus-group-split-fancy nil nil \"mail.others\") returns: + +\(| (& (any \"\\\\(bar@femail\\\\.com\\\\|.*@femail\\\\.com\\\\)\" + \"mail.bar\") + (any \"\\\\(foo@nowhere\\\\.gov\\\\|foo@localhost\\\\|foo-redist@home\\\\)\" + - \"bugs-foo\" - \"rambling-foo\" \"mail.foo\")) + \"mail.others\") + +\(fn &optional GROUPS NO-CROSSPOST CATCH-ALL)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-mlspl" '("gnus-group-split-"))) + +;;;*** + +;;;### (autoloads nil "gnus-msg" "gnus/gnus-msg.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-msg.el + +(autoload 'gnus-msg-mail "gnus-msg" "\ +Start editing a mail message to be sent. +Like `message-mail', but with Gnus paraphernalia, particularly the +Gcc: header for archiving purposes. +If Gnus isn't running, a plain `message-mail' setup is used +instead. + +\(fn &optional TO SUBJECT OTHER-HEADERS CONTINUE SWITCH-ACTION YANK-ACTION SEND-ACTIONS RETURN-ACTION)" t nil) + +(autoload 'gnus-button-mailto "gnus-msg" "\ +Mail to ADDRESS. + +\(fn ADDRESS)" nil nil) + +(autoload 'gnus-button-reply "gnus-msg" "\ +Like `message-reply'. + +\(fn &optional TO-ADDRESS WIDE)" t nil) + +(define-mail-user-agent 'gnus-user-agent 'gnus-msg-mail 'message-send-and-exit 'message-kill-buffer 'message-send-hook) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-msg" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-notifications" "gnus/gnus-notifications.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-notifications.el + +(autoload 'gnus-notifications "gnus-notifications" "\ +Send a notification on new message. +This check for new messages that are in group with a level lower +or equal to `gnus-notifications-minimum-level' and send a +notification using `notifications-notify' for it. + +This is typically a function to add in +`gnus-after-getting-new-news-hook' + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-notifications" '("gnus-notifications-"))) + +;;;*** + +;;;### (autoloads nil "gnus-picon" "gnus/gnus-picon.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-picon.el + +(autoload 'gnus-treat-from-picon "gnus-picon" "\ +Display picons in the From header. +If picons are already displayed, remove them. + +\(fn)" t nil) + +(autoload 'gnus-treat-mail-picon "gnus-picon" "\ +Display picons in the Cc and To headers. +If picons are already displayed, remove them. + +\(fn)" t nil) + +(autoload 'gnus-treat-newsgroups-picon "gnus-picon" "\ +Display picons in the Newsgroups and Followup-To headers. +If picons are already displayed, remove them. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-picon" '("gnus-picon-"))) + +;;;*** + +;;;### (autoloads nil "gnus-range" "gnus/gnus-range.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-range.el + +(autoload 'gnus-sorted-difference "gnus-range" "\ +Return a list of elements of LIST1 that do not appear in LIST2. +Both lists have to be sorted over <. +The tail of LIST1 is not copied. + +\(fn LIST1 LIST2)" nil nil) + +(autoload 'gnus-sorted-ndifference "gnus-range" "\ +Return a list of elements of LIST1 that do not appear in LIST2. +Both lists have to be sorted over <. +LIST1 is modified. + +\(fn LIST1 LIST2)" nil nil) + +(autoload 'gnus-sorted-complement "gnus-range" "\ +Return a list of elements that are in LIST1 or LIST2 but not both. +Both lists have to be sorted over <. + +\(fn LIST1 LIST2)" nil nil) + +(autoload 'gnus-intersection "gnus-range" "\ + + +\(fn LIST1 LIST2)" nil nil) + +(autoload 'gnus-sorted-intersection "gnus-range" "\ +Return intersection of LIST1 and LIST2. +LIST1 and LIST2 have to be sorted over <. + +\(fn LIST1 LIST2)" nil nil) + +(autoload 'gnus-sorted-range-intersection "gnus-range" "\ +Return intersection of RANGE1 and RANGE2. +RANGE1 and RANGE2 have to be sorted over <. + +\(fn RANGE1 RANGE2)" nil nil) + +(defalias 'gnus-set-sorted-intersection 'gnus-sorted-nintersection) + +(autoload 'gnus-sorted-nintersection "gnus-range" "\ +Return intersection of LIST1 and LIST2 by modifying cdr pointers of LIST1. +LIST1 and LIST2 have to be sorted over <. + +\(fn LIST1 LIST2)" nil nil) + +(autoload 'gnus-sorted-union "gnus-range" "\ +Return union of LIST1 and LIST2. +LIST1 and LIST2 have to be sorted over <. + +\(fn LIST1 LIST2)" nil nil) + +(autoload 'gnus-sorted-nunion "gnus-range" "\ +Return union of LIST1 and LIST2 by modifying cdr pointers of LIST1. +LIST1 and LIST2 have to be sorted over <. + +\(fn LIST1 LIST2)" nil nil) + +(autoload 'gnus-add-to-sorted-list "gnus-range" "\ +Add NUM into sorted LIST by side effect. + +\(fn LIST NUM)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-range" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-registry" "gnus/gnus-registry.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from gnus/gnus-registry.el + +(autoload 'gnus-registry-initialize "gnus-registry" "\ +Initialize the Gnus registry. + +\(fn)" t nil) + +(autoload 'gnus-registry-install-hooks "gnus-registry" "\ +Install the registry hooks. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-registry" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-rfc1843" "gnus/gnus-rfc1843.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from gnus/gnus-rfc1843.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-rfc1843" '("rfc1843-"))) + +;;;*** + +;;;### (autoloads nil "gnus-salt" "gnus/gnus-salt.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-salt.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-salt" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-score" "gnus/gnus-score.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-score.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-score" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-sieve" "gnus/gnus-sieve.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-sieve.el + +(autoload 'gnus-sieve-update "gnus-sieve" "\ +Update the Sieve script in gnus-sieve-file, by replacing the region +between gnus-sieve-region-start and gnus-sieve-region-end with +\(gnus-sieve-script gnus-sieve-select-method gnus-sieve-crosspost), then +execute gnus-sieve-update-shell-command. +See the documentation for these variables and functions for details. + +\(fn)" t nil) + +(autoload 'gnus-sieve-generate "gnus-sieve" "\ +Generate the Sieve script in gnus-sieve-file, by replacing the region +between gnus-sieve-region-start and gnus-sieve-region-end with +\(gnus-sieve-script gnus-sieve-select-method gnus-sieve-crosspost). +See the documentation for these variables and functions for details. + +\(fn)" t nil) + +(autoload 'gnus-sieve-article-add-rule "gnus-sieve" "\ + + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-sieve" '("gnus-sieve-"))) + +;;;*** + +;;;### (autoloads nil "gnus-spec" "gnus/gnus-spec.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-spec.el + +(autoload 'gnus-update-format "gnus-spec" "\ +Update the format specification near point. + +\(fn VAR)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-spec" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-srvr" "gnus/gnus-srvr.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-srvr.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-srvr" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-start" "gnus/gnus-start.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-start.el + +(autoload 'gnus-declare-backend "gnus-start" "\ +Declare back end NAME with ABILITIES as a Gnus back end. + +\(fn NAME &rest ABILITIES)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-start" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-sum" "gnus/gnus-sum.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-sum.el + +(autoload 'gnus-summary-bookmark-jump "gnus-sum" "\ +Handler function for record returned by `gnus-summary-bookmark-make-record'. +BOOKMARK is a bookmark name or a bookmark record. + +\(fn BOOKMARK)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-sum" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-topic" "gnus/gnus-topic.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-topic.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-topic" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-undo" "gnus/gnus-undo.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-undo.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-undo" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-util" "gnus/gnus-util.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-util.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-util" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-uu" "gnus/gnus-uu.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-uu.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-uu" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-vm" "gnus/gnus-vm.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-vm.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-vm" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnus-win" "gnus/gnus-win.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gnus-win.el + +(autoload 'gnus-add-configuration "gnus-win" "\ +Add the window configuration CONF to `gnus-buffer-configuration'. + +\(fn CONF)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnus-win" '("gnus-"))) + +;;;*** + +;;;### (autoloads nil "gnutls" "net/gnutls.el" (0 0 0 0)) +;;; Generated autoloads from net/gnutls.el + +(defvar gnutls-min-prime-bits 256 "\ +Minimum number of prime bits accepted by GnuTLS for key exchange. +During a Diffie-Hellman handshake, if the server sends a prime +number with fewer than this number of bits, the handshake is +rejected. (The smaller the prime number, the less secure the +key exchange is against man-in-the-middle attacks.) + +A value of nil says to use the default GnuTLS value.") + +(custom-autoload 'gnutls-min-prime-bits "gnutls" t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gnutls" '("gnutls-" "open-gnutls-stream"))) + +;;;*** + +;;;### (autoloads nil "gomoku" "play/gomoku.el" (0 0 0 0)) +;;; Generated autoloads from play/gomoku.el + +(autoload 'gomoku "gomoku" "\ +Start a Gomoku game between you and Emacs. + +If a game is in progress, this command allows you to resume it. +If optional arguments N and M are given, an N by M board is used. +If prefix arg is given for N, M is prompted for. + +You and Emacs play in turn by marking a free square. You mark it with X +and Emacs marks it with O. The winner is the first to get five contiguous +marks horizontally, vertically or in diagonal. + +You play by moving the cursor over the square you choose and hitting +\\<gomoku-mode-map>\\[gomoku-human-plays]. + +This program actually plays a simplified or archaic version of the +Gomoku game, and ought to be upgraded to use the full modern rules. + +Use \\[describe-mode] for more info. + +\(fn &optional N M)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gomoku" '("gomoku-"))) + +;;;*** + +;;;### (autoloads nil "goto-addr" "net/goto-addr.el" (0 0 0 0)) +;;; Generated autoloads from net/goto-addr.el + +(define-obsolete-function-alias 'goto-address-at-mouse 'goto-address-at-point "22.1") + +(autoload 'goto-address-at-point "goto-addr" "\ +Send to the e-mail address or load the URL at point. +Send mail to address at point. See documentation for +`goto-address-find-address-at-point'. If no address is found +there, then load the URL at or before point. + +\(fn &optional EVENT)" t nil) + +(autoload 'goto-address "goto-addr" "\ +Sets up goto-address functionality in the current buffer. +Allows user to use mouse/keyboard command to click to go to a URL +or to send e-mail. +By default, goto-address binds `goto-address-at-point' to mouse-2 and C-c RET +only on URLs and e-mail addresses. + +Also fontifies the buffer appropriately (see `goto-address-fontify-p' and +`goto-address-highlight-p' for more information). + +\(fn)" t nil) +(put 'goto-address 'safe-local-eval-function t) + +(autoload 'goto-address-mode "goto-addr" "\ +Minor mode to buttonize URLs and e-mail addresses in the current buffer. +With a prefix argument ARG, enable the mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode +if ARG is omitted or nil. + +\(fn &optional ARG)" t nil) + +(autoload 'goto-address-prog-mode "goto-addr" "\ +Like `goto-address-mode', but only for comments and strings. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "goto-addr" '("goto-address-"))) + +;;;*** + +;;;### (autoloads nil "gravatar" "image/gravatar.el" (0 0 0 0)) +;;; Generated autoloads from image/gravatar.el + +(autoload 'gravatar-retrieve "gravatar" "\ +Retrieve MAIL-ADDRESS gravatar and call CB on retrieval. +You can provide a list of argument to pass to CB in CBARGS. + +\(fn MAIL-ADDRESS CB &optional CBARGS)" nil nil) + +(autoload 'gravatar-retrieve-synchronously "gravatar" "\ +Retrieve MAIL-ADDRESS gravatar and returns it. + +\(fn MAIL-ADDRESS)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gravatar" '("gravatar-"))) + +;;;*** + +;;;### (autoloads nil "grep" "progmodes/grep.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/grep.el + +(defvar grep-window-height nil "\ +Number of lines in a grep window. If nil, use `compilation-window-height'.") + +(custom-autoload 'grep-window-height "grep" t) + +(defvar grep-command nil "\ +The default grep command for \\[grep]. +If the grep program used supports an option to always include file names +in its output (such as the `-H' option to GNU grep), it's a good idea to +include it when specifying `grep-command'. + +In interactive usage, the actual value of this variable is set up +by `grep-compute-defaults'; to change the default value, use +Customize or call the function `grep-apply-setting'.") + +(custom-autoload 'grep-command "grep" nil) + +(defvar grep-find-command nil "\ +The default find command for \\[grep-find]. +In interactive usage, the actual value of this variable is set up +by `grep-compute-defaults'; to change the default value, use +Customize or call the function `grep-apply-setting'.") + +(custom-autoload 'grep-find-command "grep" nil) + +(defvar grep-setup-hook nil "\ +List of hook functions run by `grep-process-setup' (see `run-hooks').") + +(custom-autoload 'grep-setup-hook "grep" t) + +(defconst grep-regexp-alist '(("^\\(.*?[^/\n]\\):[ ]*\\([1-9][0-9]*\\)[ ]*:" 1 2 ((lambda nil (when grep-highlight-matches (let* ((beg (match-end 0)) (end (save-excursion (goto-char beg) (line-end-position))) (mbeg (text-property-any beg end 'font-lock-face grep-match-face))) (when mbeg (- mbeg beg))))) lambda nil (when grep-highlight-matches (let* ((beg (match-end 0)) (end (save-excursion (goto-char beg) (line-end-position))) (mbeg (text-property-any beg end 'font-lock-face grep-match-face)) (mend (and mbeg (next-single-property-change mbeg 'font-lock-face nil end)))) (when mend (- mend beg)))))) ("^Binary file \\(.+\\) matches$" 1 nil nil 0 1)) "\ +Regexp used to match grep hits. See `compilation-error-regexp-alist'.") + +(defvar grep-program (purecopy "grep") "\ +The default grep program for `grep-command' and `grep-find-command'. +This variable's value takes effect when `grep-compute-defaults' is called.") + +(defvar find-program (purecopy "find") "\ +The default find program. +This is used by commands like `grep-find-command', `find-dired' +and others.") + +(defvar xargs-program (purecopy "xargs") "\ +The default xargs program for `grep-find-command'. +See `grep-find-use-xargs'. +This variable's value takes effect when `grep-compute-defaults' is called.") + +(defvar grep-find-use-xargs nil "\ +How to invoke find and grep. +If `exec', use `find -exec {} ;'. +If `exec-plus' use `find -exec {} +'. +If `gnu', use `find -print0' and `xargs -0'. +Any other value means to use `find -print' and `xargs'. + +This variable's value takes effect when `grep-compute-defaults' is called.") + +(defvar grep-history nil "\ +History list for grep.") + +(defvar grep-find-history nil "\ +History list for grep-find.") + +(autoload 'grep-process-setup "grep" "\ +Setup compilation variables and buffer for `grep'. +Set up `compilation-exit-message-function' and run `grep-setup-hook'. + +\(fn)" nil nil) + +(autoload 'grep-compute-defaults "grep" "\ + + +\(fn)" nil nil) + +(autoload 'grep-mode "grep" "\ +Sets `grep-last-buffer' and `compilation-window-height'. + +\(fn)" nil nil) + +(autoload 'grep "grep" "\ +Run Grep with user-specified COMMAND-ARGS, collect output in a buffer. +While Grep runs asynchronously, you can use \\[next-error] (M-x next-error), +or \\<grep-mode-map>\\[compile-goto-error] in the *grep* buffer, to go to the lines where Grep found +matches. To kill the Grep job before it finishes, type \\[kill-compilation]. + +Noninteractively, COMMAND-ARGS should specify the Grep command-line +arguments. + +For doing a recursive `grep', see the `rgrep' command. For running +Grep in a specific directory, see `lgrep'. + +This command uses a special history list for its COMMAND-ARGS, so you +can easily repeat a grep command. + +A prefix argument says to default the COMMAND-ARGS based on the current +tag the cursor is over, substituting it into the last Grep command +in the Grep command history (or into `grep-command' if that history +list is empty). + +\(fn COMMAND-ARGS)" t nil) + +(autoload 'grep-find "grep" "\ +Run grep via find, with user-specified args COMMAND-ARGS. +Collect output in a buffer. +While find runs asynchronously, you can use the \\[next-error] command +to find the text that grep hits refer to. + +This command uses a special history list for its arguments, so you can +easily repeat a find command. + +\(fn COMMAND-ARGS)" t nil) + +(defalias 'find-grep 'grep-find) + +(autoload 'lgrep "grep" "\ +Run grep, searching for REGEXP in FILES in directory DIR. +The search is limited to file names matching shell pattern FILES. +FILES may use abbreviations defined in `grep-files-aliases', e.g. +entering `ch' is equivalent to `*.[ch]'. + +With \\[universal-argument] prefix, you can edit the constructed shell command line +before it is executed. +With two \\[universal-argument] prefixes, directly edit and run `grep-command'. + +Collect output in a buffer. While grep runs asynchronously, you +can use \\[next-error] (M-x next-error), or \\<grep-mode-map>\\[compile-goto-error] in the grep output buffer, +to go to the lines where grep found matches. + +This command shares argument histories with \\[rgrep] and \\[grep]. + +\(fn REGEXP &optional FILES DIR CONFIRM)" t nil) + +(autoload 'rgrep "grep" "\ +Recursively grep for REGEXP in FILES in directory tree rooted at DIR. +The search is limited to file names matching shell pattern FILES. +FILES may use abbreviations defined in `grep-files-aliases', e.g. +entering `ch' is equivalent to `*.[ch]'. + +With \\[universal-argument] prefix, you can edit the constructed shell command line +before it is executed. +With two \\[universal-argument] prefixes, directly edit and run `grep-find-command'. + +Collect output in a buffer. While the recursive grep is running, +you can use \\[next-error] (M-x next-error), or \\<grep-mode-map>\\[compile-goto-error] in the grep output buffer, +to visit the lines where matches were found. To kill the job +before it finishes, type \\[kill-compilation]. + +This command shares argument histories with \\[lgrep] and \\[grep-find]. + +When called programmatically and FILES is nil, REGEXP is expected +to specify a command to run. + +\(fn REGEXP &optional FILES DIR CONFIRM)" t nil) + +(autoload 'zrgrep "grep" "\ +Recursively grep for REGEXP in gzipped FILES in tree rooted at DIR. +Like `rgrep' but uses `zgrep' for `grep-program', sets the default +file name to `*.gz', and sets `grep-highlight-matches' to `always'. + +\(fn REGEXP &optional FILES DIR CONFIRM TEMPLATE)" t nil) + +(defalias 'rzgrep 'zrgrep) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "grep" '("rgrep-" "grep-" "kill-grep"))) + +;;;*** + +;;;### (autoloads nil "gssapi" "gnus/gssapi.el" (0 0 0 0)) +;;; Generated autoloads from gnus/gssapi.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gssapi" '("open-gssapi-stream" "gssapi-program"))) + +;;;*** + +;;;### (autoloads nil "gud" "progmodes/gud.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/gud.el + +(autoload 'gud-gdb "gud" "\ +Run gdb passing it COMMAND-LINE as arguments. +If COMMAND-LINE names a program FILE to debug, gdb will run in +a buffer named *gud-FILE*, and the directory containing FILE +becomes the initial working directory and source-file directory +for your debugger. +If COMMAND-LINE requests that gdb attaches to a process PID, gdb +will run in *gud-PID*, otherwise it will run in *gud*; in these +cases the initial working directory is the default-directory of +the buffer in which this command was invoked. + +\(fn COMMAND-LINE)" t nil) + +(autoload 'sdb "gud" "\ +Run sdb on program FILE in buffer *gud-FILE*. +The directory containing FILE becomes the initial working directory +and source-file directory for your debugger. + +\(fn COMMAND-LINE)" t nil) + +(autoload 'dbx "gud" "\ +Run dbx on program FILE in buffer *gud-FILE*. +The directory containing FILE becomes the initial working directory +and source-file directory for your debugger. + +\(fn COMMAND-LINE)" t nil) + +(autoload 'xdb "gud" "\ +Run xdb on program FILE in buffer *gud-FILE*. +The directory containing FILE becomes the initial working directory +and source-file directory for your debugger. + +You can set the variable `gud-xdb-directories' to a list of program source +directories if your program contains sources from more than one directory. + +\(fn COMMAND-LINE)" t nil) + +(autoload 'perldb "gud" "\ +Run perldb on program FILE in buffer *gud-FILE*. +The directory containing FILE becomes the initial working directory +and source-file directory for your debugger. + +\(fn COMMAND-LINE)" t nil) + +(autoload 'pdb "gud" "\ +Run pdb on program FILE in buffer `*gud-FILE*'. +The directory containing FILE becomes the initial working directory +and source-file directory for your debugger. + +\(fn COMMAND-LINE)" t nil) + +(autoload 'guiler "gud" "\ +Run guiler on program FILE in buffer `*gud-FILE*'. +The directory containing FILE becomes the initial working directory +and source-file directory for your debugger. + +\(fn COMMAND-LINE)" t nil) + +(autoload 'jdb "gud" "\ +Run jdb with command line COMMAND-LINE in a buffer. +The buffer is named \"*gud*\" if no initial class is given or +\"*gud-<initial-class-basename>*\" if there is. If the \"-classpath\" +switch is given, omit all whitespace between it and its value. + +See `gud-jdb-use-classpath' and `gud-jdb-classpath' documentation for +information on how jdb accesses source files. Alternatively (if +`gud-jdb-use-classpath' is nil), see `gud-jdb-directories' for the +original source file access method. + +For general information about commands available to control jdb from +gud, see `gud-mode'. + +\(fn COMMAND-LINE)" t nil) + +(autoload 'gdb-script-mode "gud" "\ +Major mode for editing GDB scripts. + +\(fn)" t nil) + +(defvar gud-tooltip-mode nil "\ +Non-nil if Gud-Tooltip mode is enabled. +See the `gud-tooltip-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `gud-tooltip-mode'.") + +(custom-autoload 'gud-tooltip-mode "gud" nil) + +(autoload 'gud-tooltip-mode "gud" "\ +Toggle the display of GUD tooltips. +With a prefix argument ARG, enable the feature if ARG is +positive, and disable it otherwise. If called from Lisp, enable +it if ARG is omitted or nil. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gud" '("gdb-" "gud-"))) + +;;;*** + +;;;### (autoloads nil "gv" "emacs-lisp/gv.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/gv.el + +(autoload 'gv-get "gv" "\ +Build the code that applies DO to PLACE. +PLACE must be a valid generalized variable. +DO must be a function; it will be called with 2 arguments: GETTER and SETTER, +where GETTER is a (copyable) Elisp expression that returns the value of PLACE, +and SETTER is a function which returns the code to set PLACE when called +with a (not necessarily copyable) Elisp expression that returns the value to +set it to. +DO must return an Elisp expression. + +\(fn PLACE DO)" nil nil) + +(autoload 'gv-letplace "gv" "\ +Build the code manipulating the generalized variable PLACE. +GETTER will be bound to a copyable expression that returns the value +of PLACE. +SETTER will be bound to a function that takes an expression V and returns +a new expression that sets PLACE to V. +BODY should return some Elisp expression E manipulating PLACE via GETTER +and SETTER. +The returned value will then be an Elisp expression that first evaluates +all the parts of PLACE that can be evaluated and then runs E. + +\(fn (GETTER SETTER) PLACE &rest BODY)" nil t) + +(function-put 'gv-letplace 'lisp-indent-function '2) + +(autoload 'gv-define-expander "gv" "\ +Use HANDLER to handle NAME as a generalized var. +NAME is a symbol: the name of a function, macro, or special form. +HANDLER is a function which takes an argument DO followed by the same +arguments as NAME. DO is a function as defined in `gv-get'. + +\(fn NAME HANDLER)" nil t) + +(function-put 'gv-define-expander 'lisp-indent-function '1) + +(autoload 'gv--defun-declaration "gv" "\ + + +\(fn SYMBOL NAME ARGS HANDLER &optional FIX)" nil nil) + +(or (assq 'gv-expander defun-declarations-alist) (let ((x `(gv-expander ,(apply-partially #'gv--defun-declaration 'gv-expander)))) (push x macro-declarations-alist) (push x defun-declarations-alist))) + +(or (assq 'gv-setter defun-declarations-alist) (push `(gv-setter ,(apply-partially #'gv--defun-declaration 'gv-setter)) defun-declarations-alist)) + +(autoload 'gv-define-setter "gv" "\ +Define a setter method for generalized variable NAME. +This macro is an easy-to-use substitute for `gv-define-expander' that works +well for simple place forms. +Assignments of VAL to (NAME ARGS...) are expanded by binding the argument +forms (VAL ARGS...) according to ARGLIST, then executing BODY, which must +return a Lisp form that does the assignment. +The first arg in ARGLIST (the one that receives VAL) receives an expression +which can do arbitrary things, whereas the other arguments are all guaranteed +to be pure and copyable. Example use: + (gv-define-setter aref (v a i) \\=`(aset ,a ,i ,v)) + +\(fn NAME ARGLIST &rest BODY)" nil t) + +(function-put 'gv-define-setter 'lisp-indent-function '2) + +(autoload 'gv-define-simple-setter "gv" "\ +Define a simple setter method for generalized variable NAME. +This macro is an easy-to-use substitute for `gv-define-expander' that works +well for simple place forms. Assignments of VAL to (NAME ARGS...) are +turned into calls of the form (SETTER ARGS... VAL). + +If FIX-RETURN is non-nil, then SETTER is not assumed to return VAL and +instead the assignment is turned into something equivalent to + (let ((temp VAL)) + (SETTER ARGS... temp) + temp) +so as to preserve the semantics of `setf'. + +\(fn NAME SETTER &optional FIX-RETURN)" nil t) + +(autoload 'setf "gv" "\ +Set each PLACE to the value of its VAL. +This is a generalized version of `setq'; the PLACEs may be symbolic +references such as (car x) or (aref x i), as well as plain symbols. +For example, (setf (cadr x) y) is equivalent to (setcar (cdr x) y). +The return value is the last VAL in the list. + +\(fn PLACE VAL PLACE VAL ...)" nil t) + +(put 'gv-place 'edebug-form-spec 'edebug-match-form) + +(autoload 'gv-ref "gv" "\ +Return a reference to PLACE. +This is like the `&' operator of the C language. +Note: this only works reliably with lexical binding mode, except for very +simple PLACEs such as (symbol-function \\='foo) which will also work in dynamic +binding mode. + +\(fn PLACE)" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gv" '("gv-"))) + +;;;*** + +;;;### (autoloads nil "handwrite" "play/handwrite.el" (0 0 0 0)) +;;; Generated autoloads from play/handwrite.el + +(autoload 'handwrite "handwrite" "\ +Turns the buffer into a \"handwritten\" document. +The functions `handwrite-10pt', `handwrite-11pt', `handwrite-12pt' +and `handwrite-13pt' set up for various sizes of output. + +Variables: `handwrite-linespace' (default 12) + `handwrite-fontsize' (default 11) + `handwrite-numlines' (default 60) + `handwrite-pagenumbering' (default nil) + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "handwrite" '("handwrite-" "menu-bar-handwrite-map"))) + +;;;*** + +;;;### (autoloads nil "hanja-util" "language/hanja-util.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from language/hanja-util.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "hanja-util" '("han"))) + +;;;*** + +;;;### (autoloads nil "hanoi" "play/hanoi.el" (0 0 0 0)) +;;; Generated autoloads from play/hanoi.el + +(autoload 'hanoi "hanoi" "\ +Towers of Hanoi diversion. Use NRINGS rings. + +\(fn NRINGS)" t nil) + +(autoload 'hanoi-unix "hanoi" "\ +Towers of Hanoi, UNIX doomsday version. +Displays 32-ring towers that have been progressing at one move per +second since 1970-01-01 00:00:00 GMT. + +Repent before ring 31 moves. + +\(fn)" t nil) + +(autoload 'hanoi-unix-64 "hanoi" "\ +Like hanoi-unix, but pretend to have a 64-bit clock. +This is, necessarily (as of Emacs 20.3), a crock. When the +current-time interface is made s2G-compliant, hanoi.el will need +to be updated. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "hanoi" '("hanoi-"))) + +;;;*** + +;;;### (autoloads nil "hashcash" "mail/hashcash.el" (0 0 0 0)) +;;; Generated autoloads from mail/hashcash.el + +(autoload 'hashcash-insert-payment "hashcash" "\ +Insert X-Payment and X-Hashcash headers with a payment for ARG + +\(fn ARG)" t nil) + +(autoload 'hashcash-insert-payment-async "hashcash" "\ +Insert X-Payment and X-Hashcash headers with a payment for ARG +Only start calculation. Results are inserted when ready. + +\(fn ARG)" t nil) + +(autoload 'hashcash-verify-payment "hashcash" "\ +Verify a hashcash payment + +\(fn TOKEN &optional RESOURCE AMOUNT)" nil nil) + +(autoload 'mail-add-payment "hashcash" "\ +Add X-Payment: and X-Hashcash: headers with a hashcash payment +for each recipient address. Prefix arg sets default payment temporarily. +Set ASYNC to t to start asynchronous calculation. (See +`mail-add-payment-async'). + +\(fn &optional ARG ASYNC)" t nil) + +(autoload 'mail-add-payment-async "hashcash" "\ +Add X-Payment: and X-Hashcash: headers with a hashcash payment +for each recipient address. Prefix arg sets default payment temporarily. +Calculation is asynchronous. + +\(fn &optional ARG)" t nil) + +(autoload 'mail-check-payment "hashcash" "\ +Look for a valid X-Payment: or X-Hashcash: header. +Prefix arg sets default accept amount temporarily. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "hashcash" '("hashcash-"))) + +;;;*** + +;;;### (autoloads nil "help-at-pt" "help-at-pt.el" (0 0 0 0)) +;;; Generated autoloads from help-at-pt.el + +(autoload 'help-at-pt-string "help-at-pt" "\ +Return the help-echo string at point. +Normally, the string produced by the `help-echo' text or overlay +property, or nil, is returned. +If KBD is non-nil, `kbd-help' is used instead, and any +`help-echo' property is ignored. In this case, the return value +can also be t, if that is the value of the `kbd-help' property. + +\(fn &optional KBD)" nil nil) + +(autoload 'help-at-pt-kbd-string "help-at-pt" "\ +Return the keyboard help string at point. +If the `kbd-help' text or overlay property at point produces a +string, return it. Otherwise, use the `help-echo' property. +If this produces no string either, return nil. + +\(fn)" nil nil) + +(autoload 'display-local-help "help-at-pt" "\ +Display local help in the echo area. +This displays a short help message, namely the string produced by +the `kbd-help' property at point. If `kbd-help' does not produce +a string, but the `help-echo' property does, then that string is +printed instead. + +A numeric argument ARG prevents display of a message in case +there is no help. While ARG can be used interactively, it is +mainly meant for use from Lisp. + +\(fn &optional ARG)" t nil) + +(autoload 'help-at-pt-cancel-timer "help-at-pt" "\ +Cancel any timer set by `help-at-pt-set-timer'. +This disables `help-at-pt-display-when-idle'. + +\(fn)" t nil) + +(autoload 'help-at-pt-set-timer "help-at-pt" "\ +Enable `help-at-pt-display-when-idle'. +This is done by setting a timer, if none is currently active. + +\(fn)" t nil) + +(defvar help-at-pt-display-when-idle 'never "\ +Automatically show local help on point-over. +If the value is t, the string obtained from any `kbd-help' or +`help-echo' property at point is automatically printed in the +echo area, if nothing else is already displayed there, or after a +quit. If both `kbd-help' and `help-echo' produce help strings, +`kbd-help' is used. If the value is a list, the help only gets +printed if there is a text or overlay property at point that is +included in this list. Suggested properties are `keymap', +`local-map', `button' and `kbd-help'. Any value other than t or +a non-empty list disables the feature. + +This variable only takes effect after a call to +`help-at-pt-set-timer'. The help gets printed after Emacs has +been idle for `help-at-pt-timer-delay' seconds. You can call +`help-at-pt-cancel-timer' to cancel the timer set by, and the +effect of, `help-at-pt-set-timer'. + +When this variable is set through Custom, `help-at-pt-set-timer' +is called automatically, unless the value is `never', in which +case `help-at-pt-cancel-timer' is called. Specifying an empty +list of properties through Custom will set the timer, thus +enabling buffer local values. It sets the actual value to nil. +Thus, Custom distinguishes between a nil value and other values +that disable the feature, which Custom identifies with `never'. +The default is `never'.") + +(custom-autoload 'help-at-pt-display-when-idle "help-at-pt" nil) + +(autoload 'scan-buf-move-to-region "help-at-pt" "\ +Go to the start of the next region with non-nil PROP property. +Then run HOOK, which should be a quoted symbol that is a normal +hook variable, or an expression evaluating to such a symbol. +Adjacent areas with different non-nil PROP properties are +considered different regions. + +With numeric argument ARG, move to the start of the ARGth next +such region, then run HOOK. If ARG is negative, move backward. +If point is already in a region, then that region does not count +toward ARG. If ARG is 0 and point is inside a region, move to +the start of that region. If ARG is 0 and point is not in a +region, print a message to that effect, but do not move point and +do not run HOOK. If there are not enough regions to move over, +an error results and the number of available regions is mentioned +in the error message. Point is not moved and HOOK is not run. + +\(fn PROP &optional ARG HOOK)" nil nil) + +(autoload 'scan-buf-next-region "help-at-pt" "\ +Go to the start of the next region with non-nil help-echo. +Print the help found there using `display-local-help'. Adjacent +areas with different non-nil help-echo properties are considered +different regions. + +With numeric argument ARG, move to the start of the ARGth next +help-echo region. If ARG is negative, move backward. If point +is already in a help-echo region, then that region does not count +toward ARG. If ARG is 0 and point is inside a help-echo region, +move to the start of that region. If ARG is 0 and point is not +in such a region, just print a message to that effect. If there +are not enough regions to move over, an error results and the +number of available regions is mentioned in the error message. + +A potentially confusing subtlety is that point can be in a +help-echo region without any local help being available. This is +because `help-echo' can be a function evaluating to nil. This +rarely happens in practice. + +\(fn &optional ARG)" t nil) + +(autoload 'scan-buf-previous-region "help-at-pt" "\ +Go to the start of the previous region with non-nil help-echo. +Print the help found there using `display-local-help'. Adjacent +areas with different non-nil help-echo properties are considered +different regions. With numeric argument ARG, behaves like +`scan-buf-next-region' with argument -ARG. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "help-at-pt" '("scan-buf-move-hook" "help-at-pt-"))) + +;;;*** + +;;;### (autoloads nil "help-fns" "help-fns.el" (0 0 0 0)) +;;; Generated autoloads from help-fns.el + +(autoload 'describe-function "help-fns" "\ +Display the full documentation of FUNCTION (a symbol). +When called from lisp, FUNCTION may also be a function object. + +\(fn FUNCTION)" t nil) + +(autoload 'help-C-file-name "help-fns" "\ +Return the name of the C file where SUBR-OR-VAR is defined. +KIND should be `var' for a variable or `subr' for a subroutine. + +\(fn SUBR-OR-VAR KIND)" nil nil) + +(autoload 'find-lisp-object-file-name "help-fns" "\ +Guess the file that defined the Lisp object OBJECT, of type TYPE. +OBJECT should be a symbol associated with a function, variable, or face; + alternatively, it can be a function definition. +If TYPE is `defvar', search for a variable definition. +If TYPE is `defface', search for a face definition. +If TYPE is not a symbol, search for a function definition. + +The return value is the absolute name of a readable file where OBJECT is +defined. If several such files exist, preference is given to a file +found via `load-path'. The return value can also be `C-source', which +means that OBJECT is a function or variable defined in C. If no +suitable file is found, return nil. + +\(fn OBJECT TYPE)" nil nil) + +(autoload 'describe-function-1 "help-fns" "\ + + +\(fn FUNCTION)" nil nil) + +(autoload 'variable-at-point "help-fns" "\ +Return the bound variable symbol found at or before point. +Return 0 if there is no such symbol. +If ANY-SYMBOL is non-nil, don't insist the symbol be bound. + +\(fn &optional ANY-SYMBOL)" nil nil) + +(autoload 'describe-variable "help-fns" "\ +Display the full documentation of VARIABLE (a symbol). +Returns the documentation as a string, also. +If VARIABLE has a buffer-local value in BUFFER or FRAME +\(default to the current buffer and current frame), +it is displayed along with the global value. + +\(fn VARIABLE &optional BUFFER FRAME)" t nil) + +(autoload 'describe-symbol "help-fns" "\ +Display the full documentation of SYMBOL. +Will show the info of SYMBOL as a function, variable, and/or face. +Optional arguments BUFFER and FRAME specify for which buffer and +frame to show the information about SYMBOL; they default to the +current buffer and the selected frame, respectively. + +\(fn SYMBOL &optional BUFFER FRAME)" t nil) + +(autoload 'describe-syntax "help-fns" "\ +Describe the syntax specifications in the syntax table of BUFFER. +The descriptions are inserted in a help buffer, which is then displayed. +BUFFER defaults to the current buffer. + +\(fn &optional BUFFER)" t nil) + +(autoload 'describe-categories "help-fns" "\ +Describe the category specifications in the current category table. +The descriptions are inserted in a buffer, which is then displayed. +If BUFFER is non-nil, then describe BUFFER's category table instead. +BUFFER should be a buffer or a buffer name. + +\(fn &optional BUFFER)" t nil) + +(autoload 'doc-file-to-man "help-fns" "\ +Produce an nroff buffer containing the doc-strings from the DOC file. + +\(fn FILE)" t nil) + +(autoload 'doc-file-to-info "help-fns" "\ +Produce a texinfo buffer with sorted doc-strings from the DOC file. + +\(fn FILE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "help-fns" '("help-" "describe-"))) + +;;;*** + +;;;### (autoloads nil "help-macro" "help-macro.el" (0 0 0 0)) +;;; Generated autoloads from help-macro.el + +(defvar three-step-help nil "\ +Non-nil means give more info about Help command in three steps. +The three steps are simple prompt, prompt with all options, and +window listing and describing the options. +A value of nil means skip the middle step, so that \\[help-command] \\[help-command] +gives the window that lists the options.") + +(custom-autoload 'three-step-help "help-macro" t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "help-macro" '("make-help-screen"))) + +;;;*** + +;;;### (autoloads nil "help-mode" "help-mode.el" (0 0 0 0)) +;;; Generated autoloads from help-mode.el + +(autoload 'help-mode "help-mode" "\ +Major mode for viewing help text and navigating references in it. +Entry to this mode runs the normal hook `help-mode-hook'. +Commands: +\\{help-mode-map} + +\(fn)" t nil) + +(autoload 'help-mode-setup "help-mode" "\ +Enter Help Mode in the current buffer. + +\(fn)" nil nil) + +(autoload 'help-mode-finish "help-mode" "\ +Finalize Help Mode setup in current buffer. + +\(fn)" nil nil) + +(autoload 'help-setup-xref "help-mode" "\ +Invoked from commands using the \"*Help*\" buffer to install some xref info. + +ITEM is a (FUNCTION . ARGS) pair appropriate for recreating the help +buffer after following a reference. INTERACTIVE-P is non-nil if the +calling command was invoked interactively. In this case the stack of +items for help buffer \"back\" buttons is cleared. + +This should be called very early, before the output buffer is cleared, +because we want to record the \"previous\" position of point so we can +restore it properly when going back. + +\(fn ITEM INTERACTIVE-P)" nil nil) + +(autoload 'help-buffer "help-mode" "\ +Return the name of a buffer for inserting help. +If `help-xref-following' is non-nil, this is the name of the +current buffer. Signal an error if this buffer is not derived +from `help-mode'. +Otherwise, return \"*Help*\", creating a buffer with that name if +it does not already exist. + +\(fn)" nil nil) + +(autoload 'help-make-xrefs "help-mode" "\ +Parse and hyperlink documentation cross-references in the given BUFFER. + +Find cross-reference information in a buffer and activate such cross +references for selection with `help-follow'. Cross-references have +the canonical form `...' and the type of reference may be +disambiguated by the preceding word(s) used in +`help-xref-symbol-regexp'. Faces only get cross-referenced if +preceded or followed by the word `face'. Variables without +variable documentation do not get cross-referenced, unless +preceded by the word `variable' or `option'. + +If the variable `help-xref-mule-regexp' is non-nil, find also +cross-reference information related to multilingual environment +\(e.g., coding-systems). This variable is also used to disambiguate +the type of reference as the same way as `help-xref-symbol-regexp'. + +A special reference `back' is made to return back through a stack of +help buffers. Variable `help-back-label' specifies the text for +that. + +\(fn &optional BUFFER)" t nil) + +(autoload 'help-xref-button "help-mode" "\ +Make a hyperlink for cross-reference text previously matched. +MATCH-NUMBER is the subexpression of interest in the last matched +regexp. TYPE is the type of button to use. Any remaining arguments are +passed to the button's help-function when it is invoked. +See `help-make-xrefs'. + +\(fn MATCH-NUMBER TYPE &rest ARGS)" nil nil) + +(autoload 'help-insert-xref-button "help-mode" "\ +Insert STRING and make a hyperlink from cross-reference text on it. +TYPE is the type of button to use. Any remaining arguments are passed +to the button's help-function when it is invoked. +See `help-make-xrefs'. + +\(fn STRING TYPE &rest ARGS)" nil nil) + +(autoload 'help-xref-on-pp "help-mode" "\ +Add xrefs for symbols in `pp's output between FROM and TO. + +\(fn FROM TO)" nil nil) + +(define-obsolete-function-alias 'help-xref-interned 'describe-symbol "25.1") + +(autoload 'help-bookmark-jump "help-mode" "\ +Jump to help-mode bookmark BOOKMARK. +Handler function for record returned by `help-bookmark-make-record'. +BOOKMARK is a bookmark name or a bookmark record. + +\(fn BOOKMARK)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "help-mode" '("help-" "describe-symbol-backends"))) + +;;;*** + +;;;### (autoloads nil "helper" "emacs-lisp/helper.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/helper.el + +(autoload 'Helper-describe-bindings "helper" "\ +Describe local key bindings of current mode. + +\(fn)" t nil) + +(autoload 'Helper-help "helper" "\ +Provide help for current mode. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helper" '("Helper-"))) + +;;;*** + +;;;### (autoloads nil "hex-util" "hex-util.el" (0 0 0 0)) +;;; Generated autoloads from hex-util.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "hex-util" '("encode-hex-string" "decode-hex-string"))) + +;;;*** + +;;;### (autoloads nil "hexl" "hexl.el" (0 0 0 0)) +;;; Generated autoloads from hexl.el + +(autoload 'hexl-mode "hexl" "\ +\\<hexl-mode-map>A mode for editing binary files in hex dump format. +This is not an ordinary major mode; it alters some aspects +of the current mode's behavior, but not all; also, you can exit +Hexl mode and return to the previous mode using `hexl-mode-exit'. + +This function automatically converts a buffer into the hexl format +using the function `hexlify-buffer'. + +Each line in the buffer has an \"address\" (displayed in hexadecimal) +representing the offset into the file that the characters on this line +are at and 16 characters from the file (displayed as hexadecimal +values grouped every `hexl-bits' bits, and as their ASCII values). + +If any of the characters (displayed as ASCII characters) are +unprintable (control or meta characters) they will be replaced by +periods. + +If `hexl-mode' is invoked with an argument the buffer is assumed to be +in hexl format. + +A sample format: + + HEX ADDR: 0011 2233 4455 6677 8899 aabb ccdd eeff ASCII-TEXT + -------- ---- ---- ---- ---- ---- ---- ---- ---- ---------------- + 00000000: 5468 6973 2069 7320 6865 786c 2d6d 6f64 This is hexl-mod + 00000010: 652e 2020 4561 6368 206c 696e 6520 7265 e. Each line re + 00000020: 7072 6573 656e 7473 2031 3620 6279 7465 presents 16 byte + 00000030: 7320 6173 2068 6578 6164 6563 696d 616c s as hexadecimal + 00000040: 2041 5343 4949 0a61 6e64 2070 7269 6e74 ASCII.and print + 00000050: 6162 6c65 2041 5343 4949 2063 6861 7261 able ASCII chara + 00000060: 6374 6572 732e 2020 416e 7920 636f 6e74 cters. Any cont + 00000070: 726f 6c20 6f72 206e 6f6e 2d41 5343 4949 rol or non-ASCII + 00000080: 2063 6861 7261 6374 6572 730a 6172 6520 characters.are + 00000090: 6469 7370 6c61 7965 6420 6173 2070 6572 displayed as per + 000000a0: 696f 6473 2069 6e20 7468 6520 7072 696e iods in the prin + 000000b0: 7461 626c 6520 6368 6172 6163 7465 7220 table character + 000000c0: 7265 6769 6f6e 2e0a region.. + +Movement is as simple as movement in a normal Emacs text buffer. +Most cursor movement bindings are the same: use \\[hexl-backward-char], \\[hexl-forward-char], \\[hexl-next-line], and \\[hexl-previous-line] +to move the cursor left, right, down, and up. + +Advanced cursor movement commands (ala \\[hexl-beginning-of-line], \\[hexl-end-of-line], \\[hexl-beginning-of-buffer], and \\[hexl-end-of-buffer]) are +also supported. + +There are several ways to change text in hexl mode: + +ASCII characters (character between space (0x20) and tilde (0x7E)) are +bound to self-insert so you can simply type the character and it will +insert itself (actually overstrike) into the buffer. + +\\[hexl-quoted-insert] followed by another keystroke allows you to insert the key even if +it isn't bound to self-insert. An octal number can be supplied in place +of another key to insert the octal number's ASCII representation. + +\\[hexl-insert-hex-char] will insert a given hexadecimal value (if it is between 0 and 0xFF) +into the buffer at the current point. + +\\[hexl-insert-octal-char] will insert a given octal value (if it is between 0 and 0377) +into the buffer at the current point. + +\\[hexl-insert-decimal-char] will insert a given decimal value (if it is between 0 and 255) +into the buffer at the current point. + +\\[hexl-mode-exit] will exit `hexl-mode'. + +Note: saving the file with any of the usual Emacs commands +will actually convert it back to binary format while saving. + +You can use \\[hexl-find-file] to visit a file in Hexl mode. + +\\[describe-bindings] for advanced commands. + +\(fn &optional ARG)" t nil) + +(autoload 'hexl-find-file "hexl" "\ +Edit file FILENAME as a binary file in hex dump format. +Switch to a buffer visiting file FILENAME, creating one if none exists, +and edit the file in `hexl-mode'. + +\(fn FILENAME)" t nil) + +(autoload 'hexlify-buffer "hexl" "\ +Convert a binary buffer to hexl format. +This discards the buffer's undo information. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "hexl" '("hexl-" "dehexlify-buffer"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "hfy-cmap" "hfy-cmap.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from hfy-cmap.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "hfy-cmap" '("hfy-" "htmlfontify-unload-rgb-file"))) + +;;;*** + +;;;### (autoloads nil "hi-lock" "hi-lock.el" (0 0 0 0)) +;;; Generated autoloads from hi-lock.el + +(autoload 'hi-lock-mode "hi-lock" "\ +Toggle selective highlighting of patterns (Hi Lock mode). +With a prefix argument ARG, enable Hi Lock mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Hi Lock mode is automatically enabled when you invoke any of the +highlighting commands listed below, such as \\[highlight-regexp]. +To enable Hi Lock mode in all buffers, use `global-hi-lock-mode' +or add (global-hi-lock-mode 1) to your init file. + +In buffers where Font Lock mode is enabled, patterns are +highlighted using font lock. In buffers where Font Lock mode is +disabled, patterns are applied using overlays; in this case, the +highlighting will not be updated as you type. + +When Hi Lock mode is enabled, a \"Regexp Highlighting\" submenu +is added to the \"Edit\" menu. The commands in the submenu, +which can be called interactively, are: + +\\[highlight-regexp] REGEXP FACE + Highlight matches of pattern REGEXP in current buffer with FACE. + +\\[highlight-phrase] PHRASE FACE + Highlight matches of phrase PHRASE in current buffer with FACE. + (PHRASE can be any REGEXP, but spaces will be replaced by matches + to whitespace and initial lower-case letters will become case insensitive.) + +\\[highlight-lines-matching-regexp] REGEXP FACE + Highlight lines containing matches of REGEXP in current buffer with FACE. + +\\[highlight-symbol-at-point] + Highlight the symbol found near point without prompting, using the next + available face automatically. + +\\[unhighlight-regexp] REGEXP + Remove highlighting on matches of REGEXP in current buffer. + +\\[hi-lock-write-interactive-patterns] + Write active REGEXPs into buffer as comments (if possible). They may + be read the next time file is loaded or when the \\[hi-lock-find-patterns] command + is issued. The inserted regexps are in the form of font lock keywords. + (See `font-lock-keywords'.) They may be edited and re-loaded with \\[hi-lock-find-patterns], + any valid `font-lock-keywords' form is acceptable. When a file is + loaded the patterns are read if `hi-lock-file-patterns-policy' is + `ask' and the user responds y to the prompt, or if + `hi-lock-file-patterns-policy' is bound to a function and that + function returns t. + +\\[hi-lock-find-patterns] + Re-read patterns stored in buffer (in the format produced by \\[hi-lock-write-interactive-patterns]). + +When hi-lock is started and if the mode is not excluded or patterns +rejected, the beginning of the buffer is searched for lines of the +form: + Hi-lock: FOO + +where FOO is a list of patterns. The patterns must start before +position (number of characters into buffer) +`hi-lock-file-patterns-range'. Patterns will be read until +Hi-lock: end is found. A mode is excluded if it's in the list +`hi-lock-exclude-modes'. + +\(fn &optional ARG)" t nil) + +(defvar global-hi-lock-mode nil "\ +Non-nil if Global Hi-Lock mode is enabled. +See the `global-hi-lock-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `global-hi-lock-mode'.") + +(custom-autoload 'global-hi-lock-mode "hi-lock" nil) + +(autoload 'global-hi-lock-mode "hi-lock" "\ +Toggle Hi-Lock mode in all buffers. +With prefix ARG, enable Global Hi-Lock mode if ARG is positive; +otherwise, disable it. If called from Lisp, enable the mode if +ARG is omitted or nil. + +Hi-Lock mode is enabled in all buffers where +`turn-on-hi-lock-if-enabled' would do it. +See `hi-lock-mode' for more information on Hi-Lock mode. + +\(fn &optional ARG)" t nil) + +(defalias 'highlight-lines-matching-regexp 'hi-lock-line-face-buffer) + +(autoload 'hi-lock-line-face-buffer "hi-lock" "\ +Set face of all lines containing a match of REGEXP to FACE. +Interactively, prompt for REGEXP using `read-regexp', then FACE. +Use the global history list for FACE. + +Use Font lock mode, if enabled, to highlight REGEXP. Otherwise, +use overlays for highlighting. If overlays are used, the +highlighting will not update as you type. + +\(fn REGEXP &optional FACE)" t nil) + +(defalias 'highlight-regexp 'hi-lock-face-buffer) + +(autoload 'hi-lock-face-buffer "hi-lock" "\ +Set face of each match of REGEXP to FACE. +Interactively, prompt for REGEXP using `read-regexp', then FACE. +Use the global history list for FACE. + +Use Font lock mode, if enabled, to highlight REGEXP. Otherwise, +use overlays for highlighting. If overlays are used, the +highlighting will not update as you type. + +\(fn REGEXP &optional FACE)" t nil) + +(defalias 'highlight-phrase 'hi-lock-face-phrase-buffer) + +(autoload 'hi-lock-face-phrase-buffer "hi-lock" "\ +Set face of each match of phrase REGEXP to FACE. +Interactively, prompt for REGEXP using `read-regexp', then FACE. +Use the global history list for FACE. + +When called interactively, replace whitespace in user-provided +regexp with arbitrary whitespace, and make initial lower-case +letters case-insensitive, before highlighting with `hi-lock-set-pattern'. + +Use Font lock mode, if enabled, to highlight REGEXP. Otherwise, +use overlays for highlighting. If overlays are used, the +highlighting will not update as you type. + +\(fn REGEXP &optional FACE)" t nil) + +(defalias 'highlight-symbol-at-point 'hi-lock-face-symbol-at-point) + +(autoload 'hi-lock-face-symbol-at-point "hi-lock" "\ +Highlight each instance of the symbol at point. +Uses the next face from `hi-lock-face-defaults' without prompting, +unless you use a prefix argument. +Uses `find-tag-default-as-symbol-regexp' to retrieve the symbol at point. + +This uses Font lock mode if it is enabled; otherwise it uses overlays, +in which case the highlighting will not update as you type. + +\(fn)" t nil) + +(defalias 'unhighlight-regexp 'hi-lock-unface-buffer) + +(autoload 'hi-lock-unface-buffer "hi-lock" "\ +Remove highlighting of each match to REGEXP set by hi-lock. +Interactively, prompt for REGEXP, accepting only regexps +previously inserted by hi-lock interactive functions. +If REGEXP is t (or if \\[universal-argument] was specified interactively), +then remove all hi-lock highlighting. + +\(fn REGEXP)" t nil) + +(autoload 'hi-lock-write-interactive-patterns "hi-lock" "\ +Write interactively added patterns, if any, into buffer at point. + +Interactively added patterns are those normally specified using +`highlight-regexp' and `highlight-lines-matching-regexp'; they can +be found in variable `hi-lock-interactive-patterns'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "hi-lock" '("hi-lock-" "turn-on-hi-lock-if-enabled"))) + +;;;*** + +;;;### (autoloads nil "hideif" "progmodes/hideif.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/hideif.el + +(autoload 'hide-ifdef-mode "hideif" "\ +Toggle features to hide/show #ifdef blocks (Hide-Ifdef mode). +With a prefix argument ARG, enable Hide-Ifdef mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Hide-Ifdef mode is a buffer-local minor mode for use with C and +C-like major modes. When enabled, code within #ifdef constructs +that the C preprocessor would eliminate may be hidden from view. +Several variables affect how the hiding is done: + +`hide-ifdef-env' + An association list of defined and undefined symbols for the + current project. Initially, the global value of `hide-ifdef-env' + is used. This variable was a buffer-local variable, which limits + hideif to parse only one C/C++ file at a time. We've extended + hideif to support parsing a C/C++ project containing multiple C/C++ + source files opened simultaneously in different buffers. Therefore + `hide-ifdef-env' can no longer be buffer local but must be global. + +`hide-ifdef-define-alist' + An association list of defined symbol lists. + Use `hide-ifdef-set-define-alist' to save the current `hide-ifdef-env' + and `hide-ifdef-use-define-alist' to set the current `hide-ifdef-env' + from one of the lists in `hide-ifdef-define-alist'. + +`hide-ifdef-lines' + Set to non-nil to not show #if, #ifdef, #ifndef, #else, and + #endif lines when hiding. + +`hide-ifdef-initially' + Indicates whether `hide-ifdefs' should be called when Hide-Ifdef mode + is activated. + +`hide-ifdef-read-only' + Set to non-nil if you want to make buffers read only while hiding. + After `show-ifdefs', read-only status is restored to previous value. + +\\{hide-ifdef-mode-map} + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "hideif" '("hif-" "hide-ifdef" "show-ifdef" "previous-ifdef" "next-ifdef" "up-ifdef" "down-ifdef" "backward-ifdef" "forward-ifdef" "intern-safe"))) + +;;;*** + +;;;### (autoloads nil "hideshow" "progmodes/hideshow.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/hideshow.el + +(defvar hs-special-modes-alist (mapcar 'purecopy '((c-mode "{" "}" "/[*/]" nil nil) (c++-mode "{" "}" "/[*/]" nil nil) (bibtex-mode ("@\\S(*\\(\\s(\\)" 1)) (java-mode "{" "}" "/[*/]" nil nil) (js-mode "{" "}" "/[*/]" nil))) "\ +Alist for initializing the hideshow variables for different modes. +Each element has the form + (MODE START END COMMENT-START FORWARD-SEXP-FUNC ADJUST-BEG-FUNC). + +If non-nil, hideshow will use these values as regexps to define blocks +and comments, respectively for major mode MODE. + +START, END and COMMENT-START are regular expressions. A block is +defined as text surrounded by START and END. + +As a special case, START may be a list of the form (COMPLEX-START +MDATA-SELECTOR), where COMPLEX-START is a regexp w/ multiple parts and +MDATA-SELECTOR an integer that specifies which sub-match is the proper +place to adjust point, before calling `hs-forward-sexp-func'. Point +is adjusted to the beginning of the specified match. For example, +see the `hs-special-modes-alist' entry for `bibtex-mode'. + +For some major modes, `forward-sexp' does not work properly. In those +cases, FORWARD-SEXP-FUNC specifies another function to use instead. + +See the documentation for `hs-adjust-block-beginning' to see what is the +use of ADJUST-BEG-FUNC. + +If any of the elements is left nil or omitted, hideshow tries to guess +appropriate values. The regexps should not contain leading or trailing +whitespace. Case does not matter.") + +(autoload 'hs-minor-mode "hideshow" "\ +Minor mode to selectively hide/show code and comment blocks. +With a prefix argument ARG, enable the mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode +if ARG is omitted or nil. + +When hideshow minor mode is on, the menu bar is augmented with hideshow +commands and the hideshow commands are enabled. +The value (hs . t) is added to `buffer-invisibility-spec'. + +The main commands are: `hs-hide-all', `hs-show-all', `hs-hide-block', +`hs-show-block', `hs-hide-level' and `hs-toggle-hiding'. There is also +`hs-hide-initial-comment-block' and `hs-mouse-toggle-hiding'. + +Turning hideshow minor mode off reverts the menu bar and the +variables to default values and disables the hideshow commands. + +Lastly, the normal hook `hs-minor-mode-hook' is run using `run-hooks'. + +Key bindings: +\\{hs-minor-mode-map} + +\(fn &optional ARG)" t nil) + +(autoload 'turn-off-hideshow "hideshow" "\ +Unconditionally turn off `hs-minor-mode'. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "hideshow" '("hs-"))) + +;;;*** + +;;;### (autoloads nil "hilit-chg" "hilit-chg.el" (0 0 0 0)) +;;; Generated autoloads from hilit-chg.el + +(autoload 'highlight-changes-mode "hilit-chg" "\ +Toggle highlighting changes in this buffer (Highlight Changes mode). +With a prefix argument ARG, enable Highlight Changes mode if ARG +is positive, and disable it otherwise. If called from Lisp, +enable the mode if ARG is omitted or nil. + +When Highlight Changes is enabled, changes are marked with a text +property. Normally they are displayed in a distinctive face, but +command \\[highlight-changes-visible-mode] can be used to toggle +this on and off. + +Other functions for buffers in this mode include: +\\[highlight-changes-next-change] - move point to beginning of next change +\\[highlight-changes-previous-change] - move to beginning of previous change +\\[highlight-changes-remove-highlight] - remove the change face from the region +\\[highlight-changes-rotate-faces] - rotate different \"ages\" of changes +through various faces. +\\[highlight-compare-with-file] - mark text as changed by comparing this +buffer with the contents of a file +\\[highlight-compare-buffers] highlights differences between two buffers. + +\(fn &optional ARG)" t nil) + +(autoload 'highlight-changes-visible-mode "hilit-chg" "\ +Toggle visibility of highlighting due to Highlight Changes mode. +With a prefix argument ARG, enable Highlight Changes Visible mode +if ARG is positive, and disable it otherwise. If called from +Lisp, enable the mode if ARG is omitted or nil. + +Highlight Changes Visible mode only has an effect when Highlight +Changes mode is on. When enabled, the changed text is displayed +in a distinctive face. + +The default value can be customized with variable +`highlight-changes-visibility-initial-state'. + +This command does not itself set Highlight Changes mode. + +\(fn &optional ARG)" t nil) + +(autoload 'highlight-changes-remove-highlight "hilit-chg" "\ +Remove the change face from the region between BEG and END. +This allows you to manually remove highlighting from uninteresting changes. + +\(fn BEG END)" t nil) + +(autoload 'highlight-changes-next-change "hilit-chg" "\ +Move to the beginning of the next change, if in Highlight Changes mode. + +\(fn)" t nil) + +(autoload 'highlight-changes-previous-change "hilit-chg" "\ +Move to the beginning of the previous change, if in Highlight Changes mode. + +\(fn)" t nil) + +(autoload 'highlight-changes-rotate-faces "hilit-chg" "\ +Rotate the faces if in Highlight Changes mode and the changes are visible. + +Current changes are displayed in the face described by the first element +of `highlight-changes-face-list', one level older changes are shown in +face described by the second element, and so on. Very old changes remain +shown in the last face in the list. + +You can automatically rotate colors when the buffer is saved by adding +this function to `write-file-functions' as a buffer-local value. To do +this, eval the following in the buffer to be saved: + + (add-hook \\='write-file-functions \\='highlight-changes-rotate-faces nil t) + +\(fn)" t nil) + +(autoload 'highlight-compare-buffers "hilit-chg" "\ +Compare two buffers and highlight the differences. + +The default is the current buffer and the one in the next window. + +If either buffer is modified and is visiting a file, you are prompted +to save the file. + +Unless the buffer is unmodified and visiting a file, the buffer is +written to a temporary file for comparison. + +If a buffer is read-only, differences will be highlighted but no property +changes are made, so \\[highlight-changes-next-change] and +\\[highlight-changes-previous-change] will not work. + +\(fn BUF-A BUF-B)" t nil) + +(autoload 'highlight-compare-with-file "hilit-chg" "\ +Compare this buffer with a file, and highlight differences. + +If the buffer has a backup filename, it is used as the default when +this function is called interactively. + +If the current buffer is visiting the file being compared against, it +also will have its differences highlighted. Otherwise, the file is +read in temporarily but the buffer is deleted. + +If the buffer is read-only, differences will be highlighted but no property +changes are made, so \\[highlight-changes-next-change] and +\\[highlight-changes-previous-change] will not work. + +\(fn FILE-B)" t nil) + +(defvar global-highlight-changes-mode nil "\ +Non-nil if Global Highlight-Changes mode is enabled. +See the `global-highlight-changes-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `global-highlight-changes-mode'.") + +(custom-autoload 'global-highlight-changes-mode "hilit-chg" nil) + +(autoload 'global-highlight-changes-mode "hilit-chg" "\ +Toggle Highlight-Changes mode in all buffers. +With prefix ARG, enable Global Highlight-Changes mode if ARG is positive; +otherwise, disable it. If called from Lisp, enable the mode if +ARG is omitted or nil. + +Highlight-Changes mode is enabled in all buffers where +`highlight-changes-mode-turn-on' would do it. +See `highlight-changes-mode' for more information on Highlight-Changes mode. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "hilit-chg" '("highlight-" "hilit-chg-" "global-highlight-changes"))) + +;;;*** + +;;;### (autoloads nil "hippie-exp" "hippie-exp.el" (0 0 0 0)) +;;; Generated autoloads from hippie-exp.el +(push (purecopy '(hippie-exp 1 6)) package--builtin-versions) + +(defvar hippie-expand-try-functions-list '(try-complete-file-name-partially try-complete-file-name try-expand-all-abbrevs try-expand-list try-expand-line try-expand-dabbrev try-expand-dabbrev-all-buffers try-expand-dabbrev-from-kill try-complete-lisp-symbol-partially try-complete-lisp-symbol) "\ +The list of expansion functions tried in order by `hippie-expand'. +To change the behavior of `hippie-expand', remove, change the order of, +or insert functions in this list.") + +(custom-autoload 'hippie-expand-try-functions-list "hippie-exp" t) + +(autoload 'hippie-expand "hippie-exp" "\ +Try to expand text before point, using multiple methods. +The expansion functions in `hippie-expand-try-functions-list' are +tried in order, until a possible expansion is found. Repeated +application of `hippie-expand' inserts successively possible +expansions. +With a positive numeric argument, jumps directly to the ARG next +function in this list. With a negative argument or just \\[universal-argument], +undoes the expansion. + +\(fn ARG)" t nil) + +(autoload 'make-hippie-expand-function "hippie-exp" "\ +Construct a function similar to `hippie-expand'. +Make it use the expansion functions in TRY-LIST. An optional second +argument VERBOSE non-nil makes the function verbose. + +\(fn TRY-LIST &optional VERBOSE)" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "hippie-exp" '("hippie-expand-" "he-" "try-"))) + +;;;*** + +;;;### (autoloads nil "hl-line" "hl-line.el" (0 0 0 0)) +;;; Generated autoloads from hl-line.el + +(autoload 'hl-line-mode "hl-line" "\ +Toggle highlighting of the current line (Hl-Line mode). +With a prefix argument ARG, enable Hl-Line mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Hl-Line mode is a buffer-local minor mode. If +`hl-line-sticky-flag' is non-nil, Hl-Line mode highlights the +line about the buffer's point in all windows. Caveat: the +buffer's point might be different from the point of a +non-selected window. Hl-Line mode uses the function +`hl-line-highlight' on `post-command-hook' in this case. + +When `hl-line-sticky-flag' is nil, Hl-Line mode highlights the +line about point in the selected window only. In this case, it +uses the function `hl-line-maybe-unhighlight' in +addition to `hl-line-highlight' on `post-command-hook'. + +\(fn &optional ARG)" t nil) + +(defvar global-hl-line-mode nil "\ +Non-nil if Global Hl-Line mode is enabled. +See the `global-hl-line-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `global-hl-line-mode'.") + +(custom-autoload 'global-hl-line-mode "hl-line" nil) + +(autoload 'global-hl-line-mode "hl-line" "\ +Toggle line highlighting in all buffers (Global Hl-Line mode). +With a prefix argument ARG, enable Global Hl-Line mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +If `global-hl-line-sticky-flag' is non-nil, Global Hl-Line mode +highlights the line about the current buffer's point in all live +windows. + +Global-Hl-Line mode uses the functions `global-hl-line-highlight' +and `global-hl-line-maybe-unhighlight' on `post-command-hook'. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "hl-line" '("hl-line-" "global-hl-line-"))) + +;;;*** + +;;;### (autoloads nil "hmac-def" "net/hmac-def.el" (0 0 0 0)) +;;; Generated autoloads from net/hmac-def.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "hmac-def" '("define-hmac-function"))) + +;;;*** + +;;;### (autoloads nil "hmac-md5" "net/hmac-md5.el" (0 0 0 0)) +;;; Generated autoloads from net/hmac-md5.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "hmac-md5" '("hmac-md5" "md5-binary"))) + +;;;*** + +;;;### (autoloads nil "holidays" "calendar/holidays.el" (0 0 0 0)) +;;; Generated autoloads from calendar/holidays.el + +(defvar holiday-general-holidays (mapcar 'purecopy '((holiday-fixed 1 1 "New Year's Day") (holiday-float 1 1 3 "Martin Luther King Day") (holiday-fixed 2 2 "Groundhog Day") (holiday-fixed 2 14 "Valentine's Day") (holiday-float 2 1 3 "President's Day") (holiday-fixed 3 17 "St. Patrick's Day") (holiday-fixed 4 1 "April Fools' Day") (holiday-float 5 0 2 "Mother's Day") (holiday-float 5 1 -1 "Memorial Day") (holiday-fixed 6 14 "Flag Day") (holiday-float 6 0 3 "Father's Day") (holiday-fixed 7 4 "Independence Day") (holiday-float 9 1 1 "Labor Day") (holiday-float 10 1 2 "Columbus Day") (holiday-fixed 10 31 "Halloween") (holiday-fixed 11 11 "Veteran's Day") (holiday-float 11 4 4 "Thanksgiving"))) "\ +General holidays. Default value is for the United States. +See the documentation for `calendar-holidays' for details.") + +(custom-autoload 'holiday-general-holidays "holidays" t) + +(put 'holiday-general-holidays 'risky-local-variable t) + +(defvar holiday-oriental-holidays (mapcar 'purecopy '((holiday-chinese-new-year) (if calendar-chinese-all-holidays-flag (append (holiday-chinese 1 15 "Lantern Festival") (holiday-chinese-qingming) (holiday-chinese 5 5 "Dragon Boat Festival") (holiday-chinese 7 7 "Double Seventh Festival") (holiday-chinese 8 15 "Mid-Autumn Festival") (holiday-chinese 9 9 "Double Ninth Festival") (holiday-chinese-winter-solstice))))) "\ +Oriental holidays. +See the documentation for `calendar-holidays' for details.") + +(custom-autoload 'holiday-oriental-holidays "holidays" t) + +(put 'holiday-oriental-holidays 'risky-local-variable t) + +(defvar holiday-local-holidays nil "\ +Local holidays. +See the documentation for `calendar-holidays' for details.") + +(custom-autoload 'holiday-local-holidays "holidays" t) + +(put 'holiday-local-holidays 'risky-local-variable t) + +(defvar holiday-other-holidays nil "\ +User defined holidays. +See the documentation for `calendar-holidays' for details.") + +(custom-autoload 'holiday-other-holidays "holidays" t) + +(put 'holiday-other-holidays 'risky-local-variable t) + +(defvar holiday-hebrew-holidays (mapcar 'purecopy '((holiday-hebrew-passover) (holiday-hebrew-rosh-hashanah) (holiday-hebrew-hanukkah) (if calendar-hebrew-all-holidays-flag (append (holiday-hebrew-tisha-b-av) (holiday-hebrew-misc))))) "\ +Jewish holidays. +See the documentation for `calendar-holidays' for details.") + +(custom-autoload 'holiday-hebrew-holidays "holidays" t) + +(put 'holiday-hebrew-holidays 'risky-local-variable t) + +(defvar holiday-christian-holidays (mapcar 'purecopy '((holiday-easter-etc) (holiday-fixed 12 25 "Christmas") (if calendar-christian-all-holidays-flag (append (holiday-fixed 1 6 "Epiphany") (holiday-julian 12 25 "Christmas (Julian calendar)") (holiday-greek-orthodox-easter) (holiday-fixed 8 15 "Assumption") (holiday-advent 0 "Advent"))))) "\ +Christian holidays. +See the documentation for `calendar-holidays' for details.") + +(custom-autoload 'holiday-christian-holidays "holidays" t) + +(put 'holiday-christian-holidays 'risky-local-variable t) + +(defvar holiday-islamic-holidays (mapcar 'purecopy '((holiday-islamic-new-year) (holiday-islamic 9 1 "Ramadan Begins") (if calendar-islamic-all-holidays-flag (append (holiday-islamic 1 10 "Ashura") (holiday-islamic 3 12 "Mulad-al-Nabi") (holiday-islamic 7 26 "Shab-e-Mi'raj") (holiday-islamic 8 15 "Shab-e-Bara't") (holiday-islamic 9 27 "Shab-e Qadr") (holiday-islamic 10 1 "Id-al-Fitr") (holiday-islamic 12 10 "Id-al-Adha"))))) "\ +Islamic holidays. +See the documentation for `calendar-holidays' for details.") + +(custom-autoload 'holiday-islamic-holidays "holidays" t) + +(put 'holiday-islamic-holidays 'risky-local-variable t) + +(defvar holiday-bahai-holidays (mapcar 'purecopy '((holiday-bahai-new-year) (holiday-bahai-ridvan) (holiday-fixed 5 23 "Declaration of the Báb") (holiday-fixed 5 29 "Ascension of Bahá’u’lláh") (holiday-fixed 7 9 "Martyrdom of the Báb") (holiday-fixed 10 20 "Birth of the Báb") (holiday-fixed 11 12 "Birth of Bahá’u’lláh") (if calendar-bahai-all-holidays-flag (append (holiday-fixed 11 26 "Day of the Covenant") (holiday-fixed 11 28 "Ascension of `Abdu’l-Bahá"))))) "\ +Bahá’í holidays. +See the documentation for `calendar-holidays' for details.") + +(custom-autoload 'holiday-bahai-holidays "holidays" t) + +(put 'holiday-bahai-holidays 'risky-local-variable t) + +(defvar holiday-solar-holidays (mapcar 'purecopy '((solar-equinoxes-solstices) (holiday-sexp calendar-daylight-savings-starts (format "Daylight Saving Time Begins %s" (solar-time-string (/ calendar-daylight-savings-starts-time (float 60)) calendar-standard-time-zone-name))) (holiday-sexp calendar-daylight-savings-ends (format "Daylight Saving Time Ends %s" (solar-time-string (/ calendar-daylight-savings-ends-time (float 60)) calendar-daylight-time-zone-name))))) "\ +Sun-related holidays. +See the documentation for `calendar-holidays' for details.") + +(custom-autoload 'holiday-solar-holidays "holidays" t) + +(put 'holiday-solar-holidays 'risky-local-variable t) + +(put 'calendar-holidays 'risky-local-variable t) + +(autoload 'holidays "holidays" "\ +Display the holidays for last month, this month, and next month. +If called with an optional prefix argument ARG, prompts for month and year. +This function is suitable for execution in a init file. + +\(fn &optional ARG)" t nil) + +(autoload 'list-holidays "holidays" "\ +Display holidays for years Y1 to Y2 (inclusive). +Y2 defaults to Y1. The optional list of holidays L defaults to +`calendar-holidays'. If you want to control what holidays are +displayed, use a different list. For example, + + (list-holidays 2006 2006 + (append holiday-general-holidays holiday-local-holidays)) + +will display holidays for the year 2006 defined in the two +mentioned lists, and nothing else. + +When called interactively, this command offers a choice of +holidays, based on the variables `holiday-solar-holidays' etc. See the +documentation of `calendar-holidays' for a list of the variables +that control the choices, as well as a description of the format +of a holiday list. + +The optional LABEL is used to label the buffer created. + +\(fn Y1 &optional Y2 L LABEL)" t nil) + +(defalias 'holiday-list 'list-holidays) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "holidays" '("holiday-" "calendar-"))) + +;;;*** + +;;;### (autoloads nil "htmlfontify" "htmlfontify.el" (0 0 0 0)) +;;; Generated autoloads from htmlfontify.el +(push (purecopy '(htmlfontify 0 21)) package--builtin-versions) + +(autoload 'htmlfontify-buffer "htmlfontify" "\ +Create a new buffer, named for the current buffer + a .html extension, +containing an inline CSS-stylesheet and formatted CSS-markup HTML +that reproduces the look of the current Emacs buffer as closely +as possible. + +Dangerous characters in the existing buffer are turned into HTML +entities, so you should even be able to do HTML-within-HTML +fontified display. + +You should, however, note that random control or non-ASCII +characters such as ^L (U+000C FORM FEED (FF)) or ¤ (U+00A4 +CURRENCY SIGN) won't get mapped yet. + +If the SRCDIR and FILE arguments are set, lookup etags derived +entries in the `hfy-tags-cache' and add HTML anchors and +hyperlinks as appropriate. + +\(fn &optional SRCDIR FILE)" t nil) + +(autoload 'htmlfontify-copy-and-link-dir "htmlfontify" "\ +Trawl SRCDIR and write fontified-and-hyperlinked output in DSTDIR. +F-EXT and L-EXT specify values for `hfy-extn' and `hfy-link-extn'. + +You may also want to set `hfy-page-header' and `hfy-page-footer'. + +\(fn SRCDIR DSTDIR &optional F-EXT L-EXT)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "htmlfontify" '("hfy-" "htmlfontify-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ibuf-ext" "ibuf-ext.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from ibuf-ext.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ibuf-ext" '("ibuffer-" "file" "shell-command-" "starred-name" "size" "alphabetic" "major-mode" "mod" "print" "predicate" "content" "view-and-eval" "visiting-file" "derived-mode" "directory" "basename" "name" "used-mode" "query-replace" "rename-uniquely" "revert" "replace-regexp" "eval"))) + +;;;*** + +;;;### (autoloads nil "ibuf-macs" "ibuf-macs.el" (0 0 0 0)) +;;; Generated autoloads from ibuf-macs.el + +(autoload 'define-ibuffer-column "ibuf-macs" "\ +Define a column SYMBOL for use with `ibuffer-formats'. + +BODY will be called with `buffer' bound to the buffer object, and +`mark' bound to the current mark on the buffer. The original ibuffer +buffer will be bound to `ibuffer-buf'. + +If NAME is given, it will be used as a title for the column. +Otherwise, the title will default to a capitalized version of the +SYMBOL's name. PROPS is a plist of additional properties to add to +the text, such as `mouse-face'. And SUMMARIZER, if given, is a +function which will be passed a list of all the strings in its column; +it should return a string to display at the bottom. + +If HEADER-MOUSE-MAP is given, it will be used as a keymap for the +title of the column. + +Note that this macro expands into a `defun' for a function named +ibuffer-make-column-NAME. If INLINE is non-nil, then the form will be +inlined into the compiled format versions. This means that if you +change its definition, you should explicitly call +`ibuffer-recompile-formats'. + +\(fn SYMBOL (&key NAME INLINE PROPS SUMMARIZER) &rest BODY)" nil t) + +(function-put 'define-ibuffer-column 'lisp-indent-function 'defun) + +(autoload 'define-ibuffer-sorter "ibuf-macs" "\ +Define a method of sorting named NAME. +DOCUMENTATION is the documentation of the function, which will be called +`ibuffer-do-sort-by-NAME'. +DESCRIPTION is a short string describing the sorting method. + +For sorting, the forms in BODY will be evaluated with `a' bound to one +buffer object, and `b' bound to another. BODY should return a non-nil +value if and only if `a' is \"less than\" `b'. + +\(fn NAME DOCUMENTATION (&key DESCRIPTION) &rest BODY)" nil t) + +(function-put 'define-ibuffer-sorter 'lisp-indent-function '1) + +(function-put 'define-ibuffer-sorter 'doc-string-elt '2) + +(autoload 'define-ibuffer-op "ibuf-macs" "\ +Generate a function which operates on a buffer. +OP becomes the name of the function; if it doesn't begin with +`ibuffer-do-', then that is prepended to it. +When an operation is performed, this function will be called once for +each marked buffer, with that buffer current. + +ARGS becomes the formal parameters of the function. +DOCUMENTATION becomes the docstring of the function. +INTERACTIVE becomes the interactive specification of the function. +MARK describes which type of mark (:deletion, or nil) this operation +uses. :deletion means the function operates on buffers marked for +deletion, otherwise it acts on normally marked buffers. +MODIFIER-P describes how the function modifies buffers. This is used +to set the modification flag of the Ibuffer buffer itself. Valid +values are: + nil - the function never modifiers buffers + t - the function it always modifies buffers + :maybe - attempt to discover this information by comparing the + buffer's modification flag. +DANGEROUS is a boolean which should be set if the user should be +prompted before performing this operation. +OPSTRING is a string which will be displayed to the user after the +operation is complete, in the form: + \"Operation complete; OPSTRING x buffers\" +ACTIVE-OPSTRING is a string which will be displayed to the user in a +confirmation message, in the form: + \"Really ACTIVE-OPSTRING x buffers?\" +BEFORE is a form to evaluate before start the operation. +AFTER is a form to evaluate once the operation is complete. +COMPLEX means this function is special; if COMPLEX is nil BODY +evaluates once for each marked buffer, MBUF, with MBUF current +and saving the point. If COMPLEX is non-nil, BODY evaluates +without requiring MBUF current. +BODY define the operation; they are forms to evaluate per each +marked buffer. BODY is evaluated with `buf' bound to the +buffer object. + +\(fn OP ARGS DOCUMENTATION (&key INTERACTIVE MARK MODIFIER-P DANGEROUS OPSTRING ACTIVE-OPSTRING BEFORE AFTER COMPLEX) &rest BODY)" nil t) + +(function-put 'define-ibuffer-op 'lisp-indent-function '2) + +(function-put 'define-ibuffer-op 'doc-string-elt '3) + +(autoload 'define-ibuffer-filter "ibuf-macs" "\ +Define a filter named NAME. +DOCUMENTATION is the documentation of the function. +READER is a form which should read a qualifier from the user. +DESCRIPTION is a short string describing the filter. + +BODY should contain forms which will be evaluated to test whether or +not a particular buffer should be displayed or not. The forms in BODY +will be evaluated with BUF bound to the buffer object, and QUALIFIER +bound to the current value of the filter. + +\(fn NAME DOCUMENTATION (&key READER DESCRIPTION) &rest BODY)" nil t) + +(function-put 'define-ibuffer-filter 'lisp-indent-function '2) + +(function-put 'define-ibuffer-filter 'doc-string-elt '2) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ibuf-macs" '("ibuffer-"))) + +;;;*** + +;;;### (autoloads nil "ibuffer" "ibuffer.el" (0 0 0 0)) +;;; Generated autoloads from ibuffer.el + +(autoload 'ibuffer-list-buffers "ibuffer" "\ +Display a list of buffers, in another window. +If optional argument FILES-ONLY is non-nil, then add a filter for +buffers which are visiting a file. + +\(fn &optional FILES-ONLY)" t nil) + +(autoload 'ibuffer-other-window "ibuffer" "\ +Like `ibuffer', but displayed in another window by default. +If optional argument FILES-ONLY is non-nil, then add a filter for +buffers which are visiting a file. + +\(fn &optional FILES-ONLY)" t nil) + +(autoload 'ibuffer "ibuffer" "\ +Begin using Ibuffer to edit a list of buffers. +Type `h' after entering ibuffer for more information. + +All arguments are optional. +OTHER-WINDOW-P says to use another window. +NAME specifies the name of the buffer (defaults to \"*Ibuffer*\"). +QUALIFIERS is an initial set of filtering qualifiers to use; + see `ibuffer-filtering-qualifiers'. +NOSELECT means don't select the Ibuffer buffer. +SHRINK means shrink the buffer to minimal size. The special + value `onewindow' means always use another window. +FILTER-GROUPS is an initial set of filtering groups to use; + see `ibuffer-filter-groups'. +FORMATS is the value to use for `ibuffer-formats'. + If specified, then the variable `ibuffer-formats' will have + that value locally in this buffer. + +\(fn &optional OTHER-WINDOW-P NAME QUALIFIERS NOSELECT SHRINK FILTER-GROUPS FORMATS)" t nil) + +(autoload 'ibuffer-jump "ibuffer" "\ +Call Ibuffer and set point at the line listing the current buffer. +If optional arg OTHER-WINDOW is non-nil, then use another window. + +\(fn &optional OTHER-WINDOW)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ibuffer" '("ibuffer-" "filename" "process" "mark" "mod" "size" "name" "locked" "read-only"))) + +;;;*** + +;;;### (autoloads nil "icalendar" "calendar/icalendar.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from calendar/icalendar.el +(push (purecopy '(icalendar 0 19)) package--builtin-versions) + +(autoload 'icalendar-export-file "icalendar" "\ +Export diary file to iCalendar format. +All diary entries in the file DIARY-FILENAME are converted to iCalendar +format. The result is appended to the file ICAL-FILENAME. + +\(fn DIARY-FILENAME ICAL-FILENAME)" t nil) + +(autoload 'icalendar-export-region "icalendar" "\ +Export region in diary file to iCalendar format. +All diary entries in the region from MIN to MAX in the current buffer are +converted to iCalendar format. The result is appended to the file +ICAL-FILENAME. +This function attempts to return t if something goes wrong. In this +case an error string which describes all the errors and problems is +written into the buffer `*icalendar-errors*'. + +\(fn MIN MAX ICAL-FILENAME)" t nil) + +(autoload 'icalendar-import-file "icalendar" "\ +Import an iCalendar file and append to a diary file. +Argument ICAL-FILENAME output iCalendar file. +Argument DIARY-FILENAME input `diary-file'. +Optional argument NON-MARKING determines whether events are created as +non-marking or not. + +\(fn ICAL-FILENAME DIARY-FILENAME &optional NON-MARKING)" t nil) + +(autoload 'icalendar-import-buffer "icalendar" "\ +Extract iCalendar events from current buffer. + +This function searches the current buffer for the first iCalendar +object, reads it and adds all VEVENT elements to the diary +DIARY-FILE. + +It will ask for each appointment whether to add it to the diary +unless DO-NOT-ASK is non-nil. When called interactively, +DO-NOT-ASK is nil, so that you are asked for each event. + +NON-MARKING determines whether diary events are created as +non-marking. + +Return code t means that importing worked well, return code nil +means that an error has occurred. Error messages will be in the +buffer `*icalendar-errors*'. + +\(fn &optional DIARY-FILE DO-NOT-ASK NON-MARKING)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "icalendar" '("icalendar-"))) + +;;;*** + +;;;### (autoloads nil "icomplete" "icomplete.el" (0 0 0 0)) +;;; Generated autoloads from icomplete.el + +(defvar icomplete-mode nil "\ +Non-nil if Icomplete mode is enabled. +See the `icomplete-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `icomplete-mode'.") + +(custom-autoload 'icomplete-mode "icomplete" nil) + +(autoload 'icomplete-mode "icomplete" "\ +Toggle incremental minibuffer completion (Icomplete mode). +With a prefix argument ARG, enable Icomplete mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +When this global minor mode is enabled, typing in the minibuffer +continuously displays a list of possible completions that match +the string you have typed. See `icomplete-completions' for a +description of how prospective completions are displayed. + +For more information, see Info node `(emacs)Icomplete'. +For options you can set, `\\[customize-group] icomplete'. + +You can use the following key bindings to navigate and select +completions: + +\\{icomplete-minibuffer-map} + +\(fn &optional ARG)" t nil) +(when (locate-library "obsolete/iswitchb") + (autoload 'iswitchb-mode "iswitchb" "Toggle Iswitchb mode." t) + (make-obsolete 'iswitchb-mode + "use `icomplete-mode' or `ido-mode' instead." "24.4")) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "icomplete" '("icomplete-"))) + +;;;*** + +;;;### (autoloads nil "icon" "progmodes/icon.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/icon.el + +(autoload 'icon-mode "icon" "\ +Major mode for editing Icon code. +Expression and list commands understand all Icon brackets. +Tab indents for Icon code. +Paragraphs are separated by blank lines only. +Delete converts tabs to spaces as it moves back. +\\{icon-mode-map} +Variables controlling indentation style: + icon-tab-always-indent + Non-nil means TAB in Icon mode should always reindent the current line, + regardless of where in the line point is when the TAB command is used. + icon-auto-newline + Non-nil means automatically newline before and after braces + inserted in Icon code. + icon-indent-level + Indentation of Icon statements within surrounding block. + The surrounding block's indentation is the indentation + of the line on which the open-brace appears. + icon-continued-statement-offset + Extra indentation given to a substatement, such as the + then-clause of an if or body of a while. + icon-continued-brace-offset + Extra indentation given to a brace that starts a substatement. + This is in addition to `icon-continued-statement-offset'. + icon-brace-offset + Extra indentation for line if it starts with an open brace. + icon-brace-imaginary-offset + An open brace following other text is treated as if it were + this far to the right of the start of its line. + +Turning on Icon mode calls the value of the variable `icon-mode-hook' +with no args, if that value is non-nil. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "icon" '("indent-icon-exp" "icon-" "electric-icon-brace" "end-of-icon-defun" "beginning-of-icon-defun" "mark-icon-function" "calculate-icon-indent"))) + +;;;*** + +;;;### (autoloads nil "idlw-complete-structtag" "progmodes/idlw-complete-structtag.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from progmodes/idlw-complete-structtag.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "idlw-complete-structtag" '("idlwave-"))) + +;;;*** + +;;;### (autoloads nil "idlw-help" "progmodes/idlw-help.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from progmodes/idlw-help.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "idlw-help" '("idlwave-"))) + +;;;*** + +;;;### (autoloads nil "idlw-shell" "progmodes/idlw-shell.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from progmodes/idlw-shell.el + +(autoload 'idlwave-shell "idlw-shell" "\ +Run an inferior IDL, with I/O through buffer `(idlwave-shell-buffer)'. +If buffer exists but shell process is not running, start new IDL. +If buffer exists and shell process is running, just switch to the buffer. + +When called with a prefix ARG, or when `idlwave-shell-use-dedicated-frame' +is non-nil, the shell buffer and the source buffers will be in +separate frames. + +The command to run comes from variable `idlwave-shell-explicit-file-name', +with options taken from `idlwave-shell-command-line-options'. + +The buffer is put in `idlwave-shell-mode', providing commands for sending +input and controlling the IDL job. See help on `idlwave-shell-mode'. +See also the variable `idlwave-shell-prompt-pattern'. + +\(Type \\[describe-mode] in the shell buffer for a list of commands.) + +\(fn &optional ARG QUICK)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "idlw-shell" '("idlwave-"))) + +;;;*** + +;;;### (autoloads nil "idlw-toolbar" "progmodes/idlw-toolbar.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from progmodes/idlw-toolbar.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "idlw-toolbar" '("idlwave-toolbar-"))) + +;;;*** + +;;;### (autoloads nil "idlwave" "progmodes/idlwave.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/idlwave.el +(push (purecopy '(idlwave 6 1 22)) package--builtin-versions) + +(autoload 'idlwave-mode "idlwave" "\ +Major mode for editing IDL source files (version 6.1_em22). + +The main features of this mode are + +1. Indentation and Formatting + -------------------------- + Like other Emacs programming modes, C-j inserts a newline and indents. + TAB is used for explicit indentation of the current line. + + To start a continuation line, use \\[idlwave-split-line]. This + function can also be used in the middle of a line to split the line + at that point. When used inside a long constant string, the string + is split at that point with the `+' concatenation operator. + + Comments are indented as follows: + + `;;;' Indentation remains unchanged. + `;;' Indent like the surrounding code + `;' Indent to a minimum column. + + The indentation of comments starting in column 0 is never changed. + + Use \\[idlwave-fill-paragraph] to refill a paragraph inside a + comment. The indentation of the second line of the paragraph + relative to the first will be retained. Use + \\[idlwave-auto-fill-mode] to toggle auto-fill mode for these + comments. When the variable `idlwave-fill-comment-line-only' is + nil, code can also be auto-filled and auto-indented. + + To convert pre-existing IDL code to your formatting style, mark the + entire buffer with \\[mark-whole-buffer] and execute + \\[idlwave-expand-region-abbrevs]. Then mark the entire buffer + again followed by \\[indent-region] (`indent-region'). + +2. Routine Info + ------------ + IDLWAVE displays information about the calling sequence and the + accepted keyword parameters of a procedure or function with + \\[idlwave-routine-info]. \\[idlwave-find-module] jumps to the + source file of a module. These commands know about system + routines, all routines in idlwave-mode buffers and (when the + idlwave-shell is active) about all modules currently compiled under + this shell. It also makes use of pre-compiled or custom-scanned + user and library catalogs many popular libraries ship with by + default. Use \\[idlwave-update-routine-info] to update this + information, which is also used for completion (see item 4). + +3. Online IDL Help + --------------- + + \\[idlwave-context-help] displays the IDL documentation relevant + for the system variable, keyword, or routines at point. A single + key stroke gets you directly to the right place in the docs. See + the manual to configure where and how the HTML help is displayed. + +4. Completion + ---------- + \\[idlwave-complete] completes the names of procedures, functions + class names, keyword parameters, system variables and tags, class + tags, structure tags, filenames and much more. It is context + sensitive and figures out what is expected at point. Lower case + strings are completed in lower case, other strings in mixed or + upper case. + +5. Code Templates and Abbreviations + -------------------------------- + Many Abbreviations are predefined to expand to code fragments and templates. + The abbreviations start generally with a `\\'. Some examples: + + \\pr PROCEDURE template + \\fu FUNCTION template + \\c CASE statement template + \\sw SWITCH statement template + \\f FOR loop template + \\r REPEAT Loop template + \\w WHILE loop template + \\i IF statement template + \\elif IF-ELSE statement template + \\b BEGIN + + For a full list, use \\[idlwave-list-abbrevs]. Some templates also + have direct keybindings - see the list of keybindings below. + + \\[idlwave-doc-header] inserts a documentation header at the + beginning of the current program unit (pro, function or main). + Change log entries can be added to the current program unit with + \\[idlwave-doc-modification]. + +6. Automatic Case Conversion + ------------------------- + The case of reserved words and some abbrevs is controlled by + `idlwave-reserved-word-upcase' and `idlwave-abbrev-change-case'. + +7. Automatic END completion + ------------------------ + If the variable `idlwave-expand-generic-end' is non-nil, each END typed + will be converted to the specific version, like ENDIF, ENDFOR, etc. + +8. Hooks + ----- + Loading idlwave.el runs `idlwave-load-hook'. + Turning on `idlwave-mode' runs `idlwave-mode-hook'. + +9. Documentation and Customization + ------------------------------- + Info documentation for this package is available. Use + \\[idlwave-info] to display (complain to your sysadmin if that does + not work). For Postscript, PDF, and HTML versions of the + documentation, check IDLWAVE's homepage at URL + `http://github.com/jdtsmith/idlwave'. + IDLWAVE has customize support - see the group `idlwave'. + +10.Keybindings + ----------- + Here is a list of all keybindings of this mode. + If some of the key bindings below show with ??, use \\[describe-key] + followed by the key sequence to see what the key sequence does. + +\\{idlwave-mode-map} + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "idlwave" '("idlwave-"))) + +;;;*** + +;;;### (autoloads nil "ido" "ido.el" (0 0 0 0)) +;;; Generated autoloads from ido.el + +(defvar ido-mode nil "\ +Determines for which buffer/file Ido should be enabled. +The following values are possible: +- `buffer': Turn only on Ido buffer behavior (switching, killing, + displaying...) +- `file': Turn only on Ido file behavior (finding, writing, inserting...) +- `both': Turn on Ido buffer and file behavior. +- nil: Turn off any Ido switching. + +Setting this variable directly does not take effect; +use either \\[customize] or the function `ido-mode'.") + +(custom-autoload 'ido-mode "ido" nil) + +(autoload 'ido-mode "ido" "\ +Toggle Ido mode on or off. +With ARG, turn Ido mode on if arg is positive, off otherwise. +Turning on Ido mode will remap (via a minor-mode keymap) the default +keybindings for the `find-file' and `switch-to-buffer' families of +commands to the Ido versions of these functions. +However, if ARG arg equals `files', remap only commands for files, or +if it equals `buffers', remap only commands for buffer switching. +This function also adds a hook to the minibuffer. + +\(fn &optional ARG)" t nil) + +(autoload 'ido-switch-buffer "ido" "\ +Switch to another buffer. +The buffer is displayed according to `ido-default-buffer-method' -- the +default is to show it in the same window, unless it is already visible +in another frame. + +As you type in a string, all of the buffers matching the string are +displayed if substring-matching is used (default). Look at +`ido-enable-prefix' and `ido-toggle-prefix'. When you have found the +buffer you want, it can then be selected. As you type, most keys have +their normal keybindings, except for the following: \\<ido-buffer-completion-map> + +RET Select the buffer at the front of the list of matches. + If the list is empty, possibly prompt to create new buffer. + +\\[ido-select-text] Use the current input string verbatim. + +\\[ido-next-match] Put the first element at the end of the list. +\\[ido-prev-match] Put the last element at the start of the list. +\\[ido-complete] Complete a common suffix to the current string that matches + all buffers. If there is only one match, select that buffer. + If there is no common suffix, show a list of all matching buffers + in a separate window. +\\[ido-edit-input] Edit input string. +\\[ido-fallback-command] Fallback to non-ido version of current command. +\\[ido-toggle-regexp] Toggle regexp searching. +\\[ido-toggle-prefix] Toggle between substring and prefix matching. +\\[ido-toggle-case] Toggle case-sensitive searching of buffer names. +\\[ido-completion-help] Show list of matching buffers in separate window. +\\[ido-enter-find-file] Drop into `ido-find-file'. +\\[ido-kill-buffer-at-head] Kill buffer at head of buffer list. +\\[ido-toggle-ignore] Toggle ignoring buffers listed in `ido-ignore-buffers'. + +\(fn)" t nil) + +(autoload 'ido-switch-buffer-other-window "ido" "\ +Switch to another buffer and show it in another window. +The buffer name is selected interactively by typing a substring. +For details of keybindings, see `ido-switch-buffer'. + +\(fn)" t nil) + +(autoload 'ido-display-buffer "ido" "\ +Display a buffer in another window but don't select it. +The buffer name is selected interactively by typing a substring. +For details of keybindings, see `ido-switch-buffer'. + +\(fn)" t nil) + +(autoload 'ido-display-buffer-other-frame "ido" "\ +Display a buffer preferably in another frame. +The buffer name is selected interactively by typing a substring. +For details of keybindings, see `ido-switch-buffer'. + +\(fn)" t nil) + +(autoload 'ido-kill-buffer "ido" "\ +Kill a buffer. +The buffer name is selected interactively by typing a substring. +For details of keybindings, see `ido-switch-buffer'. + +\(fn)" t nil) + +(autoload 'ido-insert-buffer "ido" "\ +Insert contents of a buffer in current buffer after point. +The buffer name is selected interactively by typing a substring. +For details of keybindings, see `ido-switch-buffer'. + +\(fn)" t nil) + +(autoload 'ido-switch-buffer-other-frame "ido" "\ +Switch to another buffer and show it in another frame. +The buffer name is selected interactively by typing a substring. +For details of keybindings, see `ido-switch-buffer'. + +\(fn)" t nil) + +(autoload 'ido-find-file-in-dir "ido" "\ +Switch to another file starting from DIR. + +\(fn DIR)" t nil) + +(autoload 'ido-find-file "ido" "\ +Edit file with name obtained via minibuffer. +The file is displayed according to `ido-default-file-method' -- the +default is to show it in the same window, unless it is already visible +in another frame. + +The file name is selected interactively by typing a substring. As you +type in a string, all of the filenames matching the string are displayed +if substring-matching is used (default). Look at `ido-enable-prefix' and +`ido-toggle-prefix'. When you have found the filename you want, it can +then be selected. As you type, most keys have their normal keybindings, +except for the following: \\<ido-file-completion-map> + +RET Select the file at the front of the list of matches. + If the list is empty, possibly prompt to create new file. + +\\[ido-select-text] Use the current input string verbatim. + +\\[ido-next-match] Put the first element at the end of the list. +\\[ido-prev-match] Put the last element at the start of the list. +\\[ido-complete] Complete a common suffix to the current string that matches + all files. If there is only one match, select that file. + If there is no common suffix, show a list of all matching files + in a separate window. +\\[ido-magic-delete-char] Open the specified directory in Dired mode. +\\[ido-edit-input] Edit input string (including directory). +\\[ido-prev-work-directory] Go to previous directory in work directory history. +\\[ido-next-work-directory] Go to next directory in work directory history. +\\[ido-merge-work-directories] Search for file in the work directory history. +\\[ido-forget-work-directory] Remove current directory from the work directory history. +\\[ido-prev-work-file] Cycle to previous file in work file history. +\\[ido-next-work-file] Cycle to next file in work file history. +\\[ido-wide-find-file-or-pop-dir] Prompt for a file and use find to locate it. +\\[ido-wide-find-dir-or-delete-dir] Prompt for a directory and use find to locate it. +\\[ido-make-directory] Prompt for a directory to create in current directory. +\\[ido-fallback-command] Fallback to non-Ido version of current command. +\\[ido-toggle-regexp] Toggle regexp searching. +\\[ido-toggle-prefix] Toggle between substring and prefix matching. +\\[ido-toggle-case] Toggle case-sensitive searching of file names. +\\[ido-toggle-literal] Toggle literal reading of this file. +\\[ido-completion-help] Show list of matching files in separate window. +\\[ido-toggle-ignore] Toggle ignoring files listed in `ido-ignore-files'. + +\(fn)" t nil) + +(autoload 'ido-find-file-other-window "ido" "\ +Switch to another file and show it in another window. +The file name is selected interactively by typing a substring. +For details of keybindings, see `ido-find-file'. + +\(fn)" t nil) + +(autoload 'ido-find-alternate-file "ido" "\ +Switch to another file and show it in another window. +The file name is selected interactively by typing a substring. +For details of keybindings, see `ido-find-file'. + +\(fn)" t nil) + +(autoload 'ido-find-alternate-file-other-window "ido" "\ +Find file as a replacement for the file in the next window. +The file name is selected interactively by typing a substring. +For details of keybindings, see `ido-find-file'. + +\(fn)" t nil) + +(autoload 'ido-find-file-read-only "ido" "\ +Edit file read-only with name obtained via minibuffer. +The file name is selected interactively by typing a substring. +For details of keybindings, see `ido-find-file'. + +\(fn)" t nil) + +(autoload 'ido-find-file-read-only-other-window "ido" "\ +Edit file read-only in other window with name obtained via minibuffer. +The file name is selected interactively by typing a substring. +For details of keybindings, see `ido-find-file'. + +\(fn)" t nil) + +(autoload 'ido-find-file-read-only-other-frame "ido" "\ +Edit file read-only in other frame with name obtained via minibuffer. +The file name is selected interactively by typing a substring. +For details of keybindings, see `ido-find-file'. + +\(fn)" t nil) + +(autoload 'ido-display-file "ido" "\ +Display a file in another window but don't select it. +The file name is selected interactively by typing a substring. +For details of keybindings, see `ido-find-file'. + +\(fn)" t nil) + +(autoload 'ido-find-file-other-frame "ido" "\ +Switch to another file and show it in another frame. +The file name is selected interactively by typing a substring. +For details of keybindings, see `ido-find-file'. + +\(fn)" t nil) + +(autoload 'ido-write-file "ido" "\ +Write current buffer to a file. +The file name is selected interactively by typing a substring. +For details of keybindings, see `ido-find-file'. + +\(fn)" t nil) + +(autoload 'ido-insert-file "ido" "\ +Insert contents of file in current buffer. +The file name is selected interactively by typing a substring. +For details of keybindings, see `ido-find-file'. + +\(fn)" t nil) + +(autoload 'ido-dired "ido" "\ +Call `dired' the Ido way. +The directory is selected interactively by typing a substring. +For details of keybindings, see `ido-find-file'. + +\(fn)" t nil) + +(autoload 'ido-dired-other-window "ido" "\ +\"Edit\" a directory. Like `ido-dired' but selects in another window. +The directory is selected interactively by typing a substring. +For details of keybindings, see `ido-find-file'. + +\(fn)" t nil) + +(autoload 'ido-dired-other-frame "ido" "\ +\"Edit\" a directory. Like `ido-dired' but makes a new frame. +The directory is selected interactively by typing a substring. +For details of keybindings, see `ido-find-file'. + +\(fn)" t nil) + +(autoload 'ido-read-buffer "ido" "\ +Ido replacement for the built-in `read-buffer'. +Return the name of a buffer selected. +PROMPT is the prompt to give to the user. DEFAULT if given is the default +buffer to be selected, which will go to the front of the list. +If REQUIRE-MATCH is non-nil, an existing buffer must be selected. + +\(fn PROMPT &optional DEFAULT REQUIRE-MATCH PREDICATE)" nil nil) + +(autoload 'ido-read-file-name "ido" "\ +Ido replacement for the built-in `read-file-name'. +Read file name, prompting with PROMPT and completing in directory DIR. +See `read-file-name' for additional parameters. + +\(fn PROMPT &optional DIR DEFAULT-FILENAME MUSTMATCH INITIAL PREDICATE)" nil nil) + +(autoload 'ido-read-directory-name "ido" "\ +Ido replacement for the built-in `read-directory-name'. +Read directory name, prompting with PROMPT and completing in directory DIR. +See `read-directory-name' for additional parameters. + +\(fn PROMPT &optional DIR DEFAULT-DIRNAME MUSTMATCH INITIAL)" nil nil) + +(autoload 'ido-completing-read "ido" "\ +Ido replacement for the built-in `completing-read'. +Read a string in the minibuffer with Ido-style completion. +PROMPT is a string to prompt with; normally it ends in a colon and a space. +CHOICES is a list of strings which are the possible completions. +PREDICATE and INHERIT-INPUT-METHOD are currently ignored; they are included + to be compatible with `completing-read'. +If REQUIRE-MATCH is non-nil, the user is not allowed to exit unless + the input is (or completes to) an element of CHOICES or is null. + If the input is null, `ido-completing-read' returns DEF, or an empty + string if DEF is nil, regardless of the value of REQUIRE-MATCH. +If INITIAL-INPUT is non-nil, insert it in the minibuffer initially, + with point positioned at the end. +HIST, if non-nil, specifies a history list. +DEF, if non-nil, is the default value. + +\(fn PROMPT CHOICES &optional PREDICATE REQUIRE-MATCH INITIAL-INPUT HIST DEF INHERIT-INPUT-METHOD)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ido" '("ido-"))) + +;;;*** + +;;;### (autoloads nil "ielm" "ielm.el" (0 0 0 0)) +;;; Generated autoloads from ielm.el + +(autoload 'ielm "ielm" "\ +Interactively evaluate Emacs Lisp expressions. +Switches to the buffer `*ielm*', or creates it if it does not exist. +See `inferior-emacs-lisp-mode' for details. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ielm" '("inferior-emacs-lisp-mode" "ielm-"))) + +;;;*** + +;;;### (autoloads nil "ietf-drums" "mail/ietf-drums.el" (0 0 0 0)) +;;; Generated autoloads from mail/ietf-drums.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ietf-drums" '("ietf-drums-"))) + +;;;*** + +;;;### (autoloads nil "iimage" "iimage.el" (0 0 0 0)) +;;; Generated autoloads from iimage.el + +(define-obsolete-function-alias 'turn-on-iimage-mode 'iimage-mode "24.1") + +(autoload 'iimage-mode "iimage" "\ +Toggle Iimage mode on or off. +With a prefix argument ARG, enable Iimage mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil, and toggle it if ARG is `toggle'. +\\{iimage-mode-map} + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "iimage" '("iimage-" "turn-off-iimage-mode"))) + +;;;*** + +;;;### (autoloads nil "image" "image.el" (0 0 0 0)) +;;; Generated autoloads from image.el + +(autoload 'image-type-from-data "image" "\ +Determine the image type from image data DATA. +Value is a symbol specifying the image type or nil if type cannot +be determined. + +\(fn DATA)" nil nil) + +(autoload 'image-type-from-buffer "image" "\ +Determine the image type from data in the current buffer. +Value is a symbol specifying the image type or nil if type cannot +be determined. + +\(fn)" nil nil) + +(autoload 'image-type-from-file-header "image" "\ +Determine the type of image file FILE from its first few bytes. +Value is a symbol specifying the image type, or nil if type cannot +be determined. + +\(fn FILE)" nil nil) + +(autoload 'image-type-from-file-name "image" "\ +Determine the type of image file FILE from its name. +Value is a symbol specifying the image type, or nil if type cannot +be determined. + +\(fn FILE)" nil nil) + +(autoload 'image-type "image" "\ +Determine and return image type. +SOURCE is an image file name or image data. +Optional TYPE is a symbol describing the image type. If TYPE is omitted +or nil, try to determine the image type from its first few bytes +of image data. If that doesn't work, and SOURCE is a file name, +use its file extension as image type. +Optional DATA-P non-nil means SOURCE is a string containing image data. + +\(fn SOURCE &optional TYPE DATA-P)" nil nil) + +(autoload 'image-type-available-p "image" "\ +Return non-nil if image type TYPE is available. +Image types are symbols like `xbm' or `jpeg'. + +\(fn TYPE)" nil nil) + +(autoload 'image-type-auto-detected-p "image" "\ +Return t if the current buffer contains an auto-detectable image. +This function is intended to be used from `magic-fallback-mode-alist'. + +The buffer is considered to contain an auto-detectable image if +its beginning matches an image type in `image-type-header-regexps', +and that image type is present in `image-type-auto-detectable' with a +non-nil value. If that value is non-nil, but not t, then the image type +must be available. + +\(fn)" nil nil) + +(autoload 'create-image "image" "\ +Create an image. +FILE-OR-DATA is an image file name or image data. +Optional TYPE is a symbol describing the image type. If TYPE is omitted +or nil, try to determine the image type from its first few bytes +of image data. If that doesn't work, and FILE-OR-DATA is a file name, +use its file extension as image type. +Optional DATA-P non-nil means FILE-OR-DATA is a string containing image data. +Optional PROPS are additional image attributes to assign to the image, +like, e.g. `:mask MASK'. +Value is the image created, or nil if images of type TYPE are not supported. + +Images should not be larger than specified by `max-image-size'. + +Image file names that are not absolute are searched for in the +\"images\" sub-directory of `data-directory' and +`x-bitmap-file-path' (in that order). + +\(fn FILE-OR-DATA &optional TYPE DATA-P &rest PROPS)" nil nil) + +(autoload 'put-image "image" "\ +Put image IMAGE in front of POS in the current buffer. +IMAGE must be an image created with `create-image' or `defimage'. +IMAGE is displayed by putting an overlay into the current buffer with a +`before-string' STRING that has a `display' property whose value is the +image. STRING is defaulted if you omit it. +The overlay created will have the `put-image' property set to t. +POS may be an integer or marker. +AREA is where to display the image. AREA nil or omitted means +display it in the text area, a value of `left-margin' means +display it in the left marginal area, a value of `right-margin' +means display it in the right marginal area. + +\(fn IMAGE POS &optional STRING AREA)" nil nil) + +(autoload 'insert-image "image" "\ +Insert IMAGE into current buffer at point. +IMAGE is displayed by inserting STRING into the current buffer +with a `display' property whose value is the image. STRING +defaults to a single space if you omit it. +AREA is where to display the image. AREA nil or omitted means +display it in the text area, a value of `left-margin' means +display it in the left marginal area, a value of `right-margin' +means display it in the right marginal area. +SLICE specifies slice of IMAGE to insert. SLICE nil or omitted +means insert whole image. SLICE is a list (X Y WIDTH HEIGHT) +specifying the X and Y positions and WIDTH and HEIGHT of image area +to insert. A float value 0.0 - 1.0 means relative to the width or +height of the image; integer values are taken as pixel values. + +\(fn IMAGE &optional STRING AREA SLICE)" nil nil) + +(autoload 'insert-sliced-image "image" "\ +Insert IMAGE into current buffer at point. +IMAGE is displayed by inserting STRING into the current buffer +with a `display' property whose value is the image. The default +STRING is a single space. +AREA is where to display the image. AREA nil or omitted means +display it in the text area, a value of `left-margin' means +display it in the left marginal area, a value of `right-margin' +means display it in the right marginal area. +The image is automatically split into ROWS x COLS slices. + +\(fn IMAGE &optional STRING AREA ROWS COLS)" nil nil) + +(autoload 'remove-images "image" "\ +Remove images between START and END in BUFFER. +Remove only images that were put in BUFFER with calls to `put-image'. +BUFFER nil or omitted means use the current buffer. + +\(fn START END &optional BUFFER)" nil nil) + +(autoload 'find-image "image" "\ +Find an image, choosing one of a list of image specifications. + +SPECS is a list of image specifications. + +Each image specification in SPECS is a property list. The contents of +a specification are image type dependent. All specifications must at +least contain the properties `:type TYPE' and either `:file FILE' or +`:data DATA', where TYPE is a symbol specifying the image type, +e.g. `xbm', FILE is the file to load the image from, and DATA is a +string containing the actual image data. The specification whose TYPE +is supported, and FILE exists, is used to construct the image +specification to be returned. Return nil if no specification is +satisfied. + +The image is looked for in `image-load-path'. + +Image files should not be larger than specified by `max-image-size'. + +\(fn SPECS)" nil nil) + +(autoload 'defimage "image" "\ +Define SYMBOL as an image, and return SYMBOL. + +SPECS is a list of image specifications. DOC is an optional +documentation string. + +Each image specification in SPECS is a property list. The contents of +a specification are image type dependent. All specifications must at +least contain the properties `:type TYPE' and either `:file FILE' or +`:data DATA', where TYPE is a symbol specifying the image type, +e.g. `xbm', FILE is the file to load the image from, and DATA is a +string containing the actual image data. The first image +specification whose TYPE is supported, and FILE exists, is used to +define SYMBOL. + +Example: + + (defimage test-image ((:type xpm :file \"~/test1.xpm\") + (:type xbm :file \"~/test1.xbm\"))) + +\(fn SYMBOL SPECS &optional DOC)" nil t) + +(function-put 'defimage 'doc-string-elt '3) + +(autoload 'imagemagick-register-types "image" "\ +Register file types that can be handled by ImageMagick. +This function is called at startup, after loading the init file. +It registers the ImageMagick types returned by `imagemagick-filter-types'. + +Registered image types are added to `auto-mode-alist', so that +Emacs visits them in Image mode. They are also added to +`image-type-file-name-regexps', so that the `image-type' function +recognizes these files as having image type `imagemagick'. + +If Emacs is compiled without ImageMagick support, this does nothing. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "image" '("image"))) + +;;;*** + +;;;### (autoloads nil "image-dired" "image-dired.el" (0 0 0 0)) +;;; Generated autoloads from image-dired.el +(push (purecopy '(image-dired 0 4 11)) package--builtin-versions) + +(autoload 'image-dired-dired-toggle-marked-thumbs "image-dired" "\ +Toggle thumbnails in front of file names in the dired buffer. +If no marked file could be found, insert or hide thumbnails on the +current line. ARG, if non-nil, specifies the files to use instead +of the marked files. If ARG is an integer, use the next ARG (or +previous -ARG, if ARG<0) files. + +\(fn &optional ARG)" t nil) + +(autoload 'image-dired-dired-with-window-configuration "image-dired" "\ +Open directory DIR and create a default window configuration. + +Convenience command that: + + - Opens dired in folder DIR + - Splits windows in most useful (?) way + - Set `truncate-lines' to t + +After the command has finished, you would typically mark some +image files in dired and type +\\[image-dired-display-thumbs] (`image-dired-display-thumbs'). + +If called with prefix argument ARG, skip splitting of windows. + +The current window configuration is saved and can be restored by +calling `image-dired-restore-window-configuration'. + +\(fn DIR &optional ARG)" t nil) + +(autoload 'image-dired-display-thumbs "image-dired" "\ +Display thumbnails of all marked files, in `image-dired-thumbnail-buffer'. +If a thumbnail image does not exist for a file, it is created on the +fly. With prefix argument ARG, display only thumbnail for file at +point (this is useful if you have marked some files but want to show +another one). + +Recommended usage is to split the current frame horizontally so that +you have the dired buffer in the left window and the +`image-dired-thumbnail-buffer' buffer in the right window. + +With optional argument APPEND, append thumbnail to thumbnail buffer +instead of erasing it first. + +Optional argument DO-NOT-POP controls if `pop-to-buffer' should be +used or not. If non-nil, use `display-buffer' instead of +`pop-to-buffer'. This is used from functions like +`image-dired-next-line-and-display' and +`image-dired-previous-line-and-display' where we do not want the +thumbnail buffer to be selected. + +\(fn &optional ARG APPEND DO-NOT-POP)" t nil) + +(autoload 'image-dired-show-all-from-dir "image-dired" "\ +Make a preview buffer for all images in DIR and display it. +If the number of files in DIR matching `image-file-name-regexp' +exceeds `image-dired-show-all-from-dir-max-files', a warning will be +displayed. + +\(fn DIR)" t nil) + +(defalias 'image-dired 'image-dired-show-all-from-dir) + +(define-obsolete-function-alias 'tumme 'image-dired "24.4") + +(autoload 'image-dired-tag-files "image-dired" "\ +Tag marked file(s) in dired. With prefix ARG, tag file at point. + +\(fn ARG)" t nil) + +(autoload 'image-dired-delete-tag "image-dired" "\ +Remove tag for selected file(s). +With prefix argument ARG, remove tag from file at point. + +\(fn ARG)" t nil) + +(autoload 'image-dired-jump-thumbnail-buffer "image-dired" "\ +Jump to thumbnail buffer. + +\(fn)" t nil) + +(autoload 'image-dired-minor-mode "image-dired" "\ +Setup easy-to-use keybindings for the commands to be used in dired mode. +Note that n, p and <down> and <up> will be hijacked and bound to +`image-dired-dired-x-line'. + +\(fn &optional ARG)" t nil) + +(define-obsolete-function-alias 'image-dired-setup-dired-keybindings 'image-dired-minor-mode "26.1") + +(autoload 'image-dired-display-thumbs-append "image-dired" "\ +Append thumbnails to `image-dired-thumbnail-buffer'. + +\(fn)" t nil) + +(autoload 'image-dired-display-thumb "image-dired" "\ +Shorthand for `image-dired-display-thumbs' with prefix argument. + +\(fn)" t nil) + +(autoload 'image-dired-dired-display-external "image-dired" "\ +Display file at point using an external viewer. + +\(fn)" t nil) + +(autoload 'image-dired-dired-display-image "image-dired" "\ +Display current image file. +See documentation for `image-dired-display-image' for more information. +With prefix argument ARG, display image in its original size. + +\(fn &optional ARG)" t nil) + +(autoload 'image-dired-dired-comment-files "image-dired" "\ +Add comment to current or marked files in dired. + +\(fn)" t nil) + +(autoload 'image-dired-mark-tagged-files "image-dired" "\ +Use regexp to mark files with matching tag. +A `tag' is a keyword, a piece of meta data, associated with an +image file and stored in image-dired's database file. This command +lets you input a regexp and this will be matched against all tags +on all image files in the database file. The files that have a +matching tag will be marked in the dired buffer. + +\(fn)" t nil) + +(autoload 'image-dired-dired-edit-comment-and-tags "image-dired" "\ +Edit comment and tags of current or marked image files. +Edit comment and tags for all marked image files in an +easy-to-use form. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "image-dired" '("image-dired-"))) + +;;;*** + +;;;### (autoloads nil "image-file" "image-file.el" (0 0 0 0)) +;;; Generated autoloads from image-file.el + +(defvar image-file-name-extensions (purecopy '("png" "jpeg" "jpg" "gif" "tiff" "tif" "xbm" "xpm" "pbm" "pgm" "ppm" "pnm" "svg")) "\ +A list of image-file filename extensions. +Filenames having one of these extensions are considered image files, +in addition to those matching `image-file-name-regexps'. + +See `auto-image-file-mode'; if `auto-image-file-mode' is enabled, +setting this variable directly does not take effect unless +`auto-image-file-mode' is re-enabled; this happens automatically when +the variable is set using \\[customize].") + +(custom-autoload 'image-file-name-extensions "image-file" nil) + +(defvar image-file-name-regexps nil "\ +List of regexps matching image-file filenames. +Filenames matching one of these regexps are considered image files, +in addition to those with an extension in `image-file-name-extensions'. + +See function `auto-image-file-mode'; if `auto-image-file-mode' is +enabled, setting this variable directly does not take effect unless +`auto-image-file-mode' is re-enabled; this happens automatically when +the variable is set using \\[customize].") + +(custom-autoload 'image-file-name-regexps "image-file" nil) + +(autoload 'image-file-name-regexp "image-file" "\ +Return a regular expression matching image-file filenames. + +\(fn)" nil nil) + +(autoload 'insert-image-file "image-file" "\ +Insert the image file FILE into the current buffer. +Optional arguments VISIT, BEG, END, and REPLACE are interpreted as for +the command `insert-file-contents'. + +\(fn FILE &optional VISIT BEG END REPLACE)" nil nil) + +(defvar auto-image-file-mode nil "\ +Non-nil if Auto-Image-File mode is enabled. +See the `auto-image-file-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `auto-image-file-mode'.") + +(custom-autoload 'auto-image-file-mode "image-file" nil) + +(autoload 'auto-image-file-mode "image-file" "\ +Toggle visiting of image files as images (Auto Image File mode). +With a prefix argument ARG, enable Auto Image File mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +An image file is one whose name has an extension in +`image-file-name-extensions', or matches a regexp in +`image-file-name-regexps'. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "image-file" '("image-file-"))) + +;;;*** + +;;;### (autoloads nil "image-mode" "image-mode.el" (0 0 0 0)) +;;; Generated autoloads from image-mode.el + +(autoload 'image-mode "image-mode" "\ +Major mode for image files. +You can use \\<image-mode-map>\\[image-toggle-display] or \\<image-mode-map>\\[image-toggle-hex-display] +to toggle between display as an image and display as text or hex. + +Key bindings: +\\{image-mode-map} + +\(fn)" t nil) + +(autoload 'image-minor-mode "image-mode" "\ +Toggle Image minor mode in this buffer. +With a prefix argument ARG, enable Image minor mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Image minor mode provides the key \\<image-mode-map>\\[image-toggle-display], +to switch back to `image-mode' and display an image file as the +actual image. + +\(fn &optional ARG)" t nil) + +(autoload 'image-mode-to-text "image-mode" "\ +Set a non-image mode as major mode in combination with image minor mode. +A non-mage major mode found from `auto-mode-alist' or fundamental mode +displays an image file as text. + +\(fn)" nil nil) + +(autoload 'image-bookmark-jump "image-mode" "\ + + +\(fn BMK)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "image-mode" '("image-"))) + +;;;*** + +;;;### (autoloads nil "imap" "net/imap.el" (0 0 0 0)) +;;; Generated autoloads from net/imap.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "imap" '("imap-"))) + +;;;*** + +;;;### (autoloads nil "imenu" "imenu.el" (0 0 0 0)) +;;; Generated autoloads from imenu.el + +(defvar imenu-sort-function nil "\ +The function to use for sorting the index mouse-menu. + +Affects only the mouse index menu. + +Set this to nil if you don't want any sorting (faster). +The items in the menu are then presented in the order they were found +in the buffer. + +Set it to `imenu--sort-by-name' if you want alphabetic sorting. + +The function should take two arguments and return t if the first +element should come before the second. The arguments are cons cells; +\(NAME . POSITION). Look at `imenu--sort-by-name' for an example.") + +(custom-autoload 'imenu-sort-function "imenu" t) + +(defvar imenu-generic-expression nil "\ +List of definition matchers for creating an Imenu index. +Each element of this list should have the form + + (MENU-TITLE REGEXP INDEX [FUNCTION] [ARGUMENTS...]) + +MENU-TITLE should be nil (in which case the matches for this +element are put in the top level of the buffer index) or a +string (which specifies the title of a submenu into which the +matches are put). +REGEXP is a regular expression matching a definition construct +which is to be displayed in the menu. REGEXP may also be a +function, called without arguments. It is expected to search +backwards. It must return true and set `match-data' if it finds +another element. +INDEX is an integer specifying which subexpression of REGEXP +matches the definition's name; this subexpression is displayed as +the menu item. +FUNCTION, if present, specifies a function to call when the index +item is selected by the user. This function is called with +arguments consisting of the item name, the buffer position, and +the ARGUMENTS. + +The variable `imenu-case-fold-search' determines whether or not +the regexp matches are case sensitive, and `imenu-syntax-alist' +can be used to alter the syntax table for the search. + +If non-nil this pattern is passed to `imenu--generic-function' to +create a buffer index. + +For example, see the value of `fortran-imenu-generic-expression' +used by `fortran-mode' with `imenu-syntax-alist' set locally to +give the characters which normally have \"symbol\" syntax +\"word\" syntax during matching.") +(put 'imenu-generic-expression 'risky-local-variable t) + +(make-variable-buffer-local 'imenu-generic-expression) + +(defvar imenu-create-index-function 'imenu-default-create-index-function "\ +The function to use for creating an index alist of the current buffer. + +It should be a function that takes no arguments and returns +an index alist of the current buffer. The function is +called within a `save-excursion'. + +See `imenu--index-alist' for the format of the buffer index alist.") + +(make-variable-buffer-local 'imenu-create-index-function) + +(defvar imenu-prev-index-position-function 'beginning-of-defun "\ +Function for finding the next index position. + +If `imenu-create-index-function' is set to +`imenu-default-create-index-function', then you must set this variable +to a function that will find the next index, looking backwards in the +file. + +The function should leave point at the place to be connected to the +index and it should return nil when it doesn't find another index.") + +(make-variable-buffer-local 'imenu-prev-index-position-function) + +(defvar imenu-extract-index-name-function nil "\ +Function for extracting the index item name, given a position. + +This function is called after `imenu-prev-index-position-function' +finds a position for an index item, with point at that position. +It should return the name for that index item.") + +(make-variable-buffer-local 'imenu-extract-index-name-function) + +(defvar imenu-name-lookup-function nil "\ +Function to compare string with index item. + +This function will be called with two strings, and should return +non-nil if they match. + +If nil, comparison is done with `string='. +Set this to some other function for more advanced comparisons, +such as \"begins with\" or \"name matches and number of +arguments match\".") + +(make-variable-buffer-local 'imenu-name-lookup-function) + +(defvar imenu-default-goto-function 'imenu-default-goto-function "\ +The default function called when selecting an Imenu item. +The function in this variable is called when selecting a normal index-item.") + +(make-variable-buffer-local 'imenu-default-goto-function) +(put 'imenu--index-alist 'risky-local-variable t) + +(make-variable-buffer-local 'imenu-syntax-alist) + +(make-variable-buffer-local 'imenu-case-fold-search) + +(autoload 'imenu-add-to-menubar "imenu" "\ +Add an `imenu' entry to the menu bar for the current buffer. +NAME is a string used to name the menu bar item. +See the command `imenu' for more information. + +\(fn NAME)" t nil) + +(autoload 'imenu-add-menubar-index "imenu" "\ +Add an Imenu \"Index\" entry on the menu bar for the current buffer. + +A trivial interface to `imenu-add-to-menubar' suitable for use in a hook. + +\(fn)" t nil) + +(autoload 'imenu "imenu" "\ +Jump to a place in the buffer chosen using a buffer menu or mouse menu. +INDEX-ITEM specifies the position. See `imenu-choose-buffer-index' +for more information. + +\(fn INDEX-ITEM)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "imenu" '("imenu-"))) + +;;;*** + +;;;### (autoloads nil "ind-util" "language/ind-util.el" (0 0 0 0)) +;;; Generated autoloads from language/ind-util.el + +(autoload 'indian-compose-region "ind-util" "\ +Compose the region according to `composition-function-table'. + +\(fn FROM TO)" t nil) + +(autoload 'indian-compose-string "ind-util" "\ + + +\(fn STRING)" nil nil) + +(autoload 'in-is13194-post-read-conversion "ind-util" "\ + + +\(fn LEN)" nil nil) + +(autoload 'in-is13194-pre-write-conversion "ind-util" "\ + + +\(fn FROM TO)" nil nil) + +(autoload 'indian-2-column-to-ucs-region "ind-util" "\ +Convert old Emacs Devanagari characters to UCS. + +\(fn FROM TO)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ind-util" '("indian-" "ucs-to-is"))) + +;;;*** + +;;;### (autoloads nil "inf-lisp" "progmodes/inf-lisp.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/inf-lisp.el + +(autoload 'inferior-lisp "inf-lisp" "\ +Run an inferior Lisp process, input and output via buffer `*inferior-lisp*'. +If there is a process already running in `*inferior-lisp*', just switch +to that buffer. +With argument, allows you to edit the command line (default is value +of `inferior-lisp-program'). Runs the hooks from +`inferior-lisp-mode-hook' (after the `comint-mode-hook' is run). +\(Type \\[describe-mode] in the process buffer for a list of commands.) + +\(fn CMD)" t nil) + +(defalias 'run-lisp 'inferior-lisp) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "inf-lisp" '("inferior-lisp-" "lisp-" "switch-to-lisp"))) + +;;;*** + +;;;### (autoloads nil "info" "info.el" (0 0 0 0)) +;;; Generated autoloads from info.el + +(defcustom Info-default-directory-list (let* ((config-dir (file-name-as-directory (or (and (featurep 'ns) (let ((dir (expand-file-name "../info" data-directory))) (if (file-directory-p dir) dir))) configure-info-directory))) (prefixes (prune-directory-list '("/usr/local/" "/usr/" "/opt/"))) (suffixes '("share/" "")) (standard-info-dirs (apply #'nconc (mapcar (lambda (pfx) (let ((dirs (mapcar (lambda (sfx) (concat pfx sfx "info/")) suffixes))) (prune-directory-list dirs))) prefixes))) (dirs (if (member config-dir standard-info-dirs) (nconc standard-info-dirs (list config-dir)) (cons config-dir standard-info-dirs)))) (if (not (eq system-type 'windows-nt)) dirs (let* ((instdir (file-name-directory invocation-directory)) (dir1 (expand-file-name "../info/" instdir)) (dir2 (expand-file-name "../../../info/" instdir))) (cond ((file-exists-p dir1) (append dirs (list dir1))) ((file-exists-p dir2) (append dirs (list dir2))) (t dirs))))) "\ +Default list of directories to search for Info documentation files. +They are searched in the order they are given in the list. +Therefore, the directory of Info files that come with Emacs +normally should come last (so that local files override standard ones), +unless Emacs is installed into a non-standard directory. In the latter +case, the directory of Info files that come with Emacs should be +first in this list. + +Once Info is started, the list of directories to search +comes from the variable `Info-directory-list'. +This variable `Info-default-directory-list' is used as the default +for initializing `Info-directory-list' when Info is started, unless +the environment variable INFOPATH is set. + +Although this is a customizable variable, that is mainly for technical +reasons. Normally, you should either set INFOPATH or customize +`Info-additional-directory-list', rather than changing this variable." :initialize (quote custom-initialize-delay) :type (quote (repeat directory)) :group (quote info)) + +(autoload 'info-other-window "info" "\ +Like `info' but show the Info buffer in another window. + +\(fn &optional FILE-OR-NODE BUFFER)" t nil) + (put 'info 'info-file (purecopy "emacs")) + +(autoload 'info "info" "\ +Enter Info, the documentation browser. +Optional argument FILE-OR-NODE specifies the file to examine; +the default is the top-level directory of Info. +Called from a program, FILE-OR-NODE may specify an Info node of the form +\"(FILENAME)NODENAME\". +Optional argument BUFFER specifies the Info buffer name; +the default buffer name is *info*. If BUFFER exists, +just switch to BUFFER. Otherwise, create a new buffer +with the top-level Info directory. + +In interactive use, a non-numeric prefix argument directs +this command to read a file name from the minibuffer. + +A numeric prefix argument of N selects an Info buffer named \"*info*<N>\". + +The search path for Info files is in the variable `Info-directory-list'. +The top-level Info directory is made by combining all the files named `dir' +in all the directories in that path. + +See a list of available Info commands in `Info-mode'. + +\(fn &optional FILE-OR-NODE BUFFER)" t nil) + +(autoload 'info-emacs-manual "info" "\ +Display the Emacs manual in Info mode. + +\(fn)" t nil) + +(autoload 'info-emacs-bug "info" "\ +Display the \"Reporting Bugs\" section of the Emacs manual in Info mode. + +\(fn)" t nil) + +(autoload 'info-standalone "info" "\ +Run Emacs as a standalone Info reader. +Usage: emacs -f info-standalone [filename] +In standalone mode, \\<Info-mode-map>\\[Info-exit] exits Emacs itself. + +\(fn)" nil nil) + +(autoload 'Info-on-current-buffer "info" "\ +Use Info mode to browse the current Info buffer. +With a prefix arg, this queries for the node name to visit first; +otherwise, that defaults to `Top'. + +\(fn &optional NODENAME)" t nil) + +(autoload 'Info-directory "info" "\ +Go to the Info directory node. + +\(fn)" t nil) + +(autoload 'Info-index "info" "\ +Look up a string TOPIC in the index for this manual and go to that entry. +If there are no exact matches to the specified topic, this chooses +the first match which is a case-insensitive substring of a topic. +Use the \\<Info-mode-map>\\[Info-index-next] command to see the other matches. +Give an empty topic name to go to the Index node itself. + +\(fn TOPIC)" t nil) + +(autoload 'info-apropos "info" "\ +Grovel indices of all known Info files on your system for STRING. +Build a menu of the possible matches. + +\(fn STRING)" t nil) + +(autoload 'info-finder "info" "\ +Display descriptions of the keywords in the Finder virtual manual. +In interactive use, a prefix argument directs this command to read +a list of keywords separated by comma. After that, it displays a node +with a list of packages that contain all specified keywords. + +\(fn &optional KEYWORDS)" t nil) + +(autoload 'Info-mode "info" "\ +Info mode provides commands for browsing through the Info documentation tree. +Documentation in Info is divided into \"nodes\", each of which discusses +one topic and contains references to other nodes which discuss related +topics. Info has commands to follow the references and show you other nodes. + +\\<Info-mode-map>\\[Info-help] Invoke the Info tutorial. +\\[Info-exit] Quit Info: reselect previously selected buffer. + +Selecting other nodes: +\\[Info-mouse-follow-nearest-node] + Follow a node reference you click on. + This works with menu items, cross references, and + the \"next\", \"previous\" and \"up\", depending on where you click. +\\[Info-follow-nearest-node] Follow a node reference near point, like \\[Info-mouse-follow-nearest-node]. +\\[Info-next] Move to the \"next\" node of this node. +\\[Info-prev] Move to the \"previous\" node of this node. +\\[Info-up] Move \"up\" from this node. +\\[Info-menu] Pick menu item specified by name (or abbreviation). + Picking a menu item causes another node to be selected. +\\[Info-directory] Go to the Info directory node. +\\[Info-top-node] Go to the Top node of this file. +\\[Info-final-node] Go to the final node in this file. +\\[Info-backward-node] Go backward one node, considering all nodes as forming one sequence. +\\[Info-forward-node] Go forward one node, considering all nodes as forming one sequence. +\\[Info-next-reference] Move cursor to next cross-reference or menu item. +\\[Info-prev-reference] Move cursor to previous cross-reference or menu item. +\\[Info-follow-reference] Follow a cross reference. Reads name of reference. +\\[Info-history-back] Move back in history to the last node you were at. +\\[Info-history-forward] Move forward in history to the node you returned from after using \\[Info-history-back]. +\\[Info-history] Go to menu of visited nodes. +\\[Info-toc] Go to table of contents of the current Info file. + +Moving within a node: +\\[Info-scroll-up] Normally, scroll forward a full screen. + Once you scroll far enough in a node that its menu appears on the + screen but after point, the next scroll moves into its first + subnode. When after all menu items (or if there is no menu), + move up to the parent node. +\\[Info-scroll-down] Normally, scroll backward. If the beginning of the buffer is + already visible, try to go to the previous menu entry, or up + if there is none. +\\[beginning-of-buffer] Go to beginning of node. + +Advanced commands: +\\[Info-search] Search through this Info file for specified regexp, + and select the node in which the next occurrence is found. +\\[Info-search-case-sensitively] Search through this Info file for specified regexp case-sensitively. +\\[isearch-forward], \\[isearch-forward-regexp] Use Isearch to search through multiple Info nodes. +\\[Info-index] Search for a topic in this manual's Index and go to index entry. +\\[Info-index-next] (comma) Move to the next match from a previous \\<Info-mode-map>\\[Info-index] command. +\\[Info-virtual-index] Look for a string and display the index node with results. +\\[info-apropos] Look for a string in the indices of all manuals. +\\[Info-goto-node] Move to node specified by name. + You may include a filename as well, as (FILENAME)NODENAME. +1 .. 9 Pick first ... ninth item in node's menu. + Every third `*' is highlighted to help pick the right number. +\\[Info-copy-current-node-name] Put name of current Info node in the kill ring. +\\[clone-buffer] Select a new cloned Info buffer in another window. +\\[universal-argument] \\[info] Move to new Info file with completion. +\\[universal-argument] N \\[info] Select Info buffer with prefix number in the name *info*<N>. + +\(fn)" t nil) + (put 'Info-goto-emacs-command-node 'info-file (purecopy "emacs")) + +(autoload 'Info-goto-emacs-command-node "info" "\ +Go to the Info node in the Emacs manual for command COMMAND. +The command is found by looking up in Emacs manual's indices +or in another manual found via COMMAND's `info-file' property or +the variable `Info-file-list-for-emacs'. +COMMAND must be a symbol or string. + +\(fn COMMAND)" t nil) + (put 'Info-goto-emacs-key-command-node 'info-file (purecopy "emacs")) + +(autoload 'Info-goto-emacs-key-command-node "info" "\ +Go to the node in the Emacs manual which describes the command bound to KEY. +KEY is a string. +Interactively, if the binding is `execute-extended-command', a command is read. +The command is found by looking up in Emacs manual's indices +or in another manual found via COMMAND's `info-file' property or +the variable `Info-file-list-for-emacs'. + +\(fn KEY)" t nil) + +(autoload 'Info-speedbar-browser "info" "\ +Initialize speedbar to display an Info node browser. +This will add a speedbar major display mode. + +\(fn)" t nil) + +(autoload 'Info-bookmark-jump "info" "\ +This implements the `handler' function interface for the record +type returned by `Info-bookmark-make-record', which see. + +\(fn BMK)" nil nil) + +(autoload 'info-display-manual "info" "\ +Display an Info buffer displaying MANUAL. +If there is an existing Info buffer for MANUAL, display it. +Otherwise, visit the manual in a new Info buffer. In interactive +use, a prefix argument directs this command to limit the +completion alternatives to currently visited manuals. + +\(fn MANUAL)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "info" '("info-" "Info-"))) + +;;;*** + +;;;### (autoloads nil "info-look" "info-look.el" (0 0 0 0)) +;;; Generated autoloads from info-look.el + +(autoload 'info-lookup-reset "info-look" "\ +Throw away all cached data. +This command is useful if the user wants to start at the beginning without +quitting Emacs, for example, after some Info documents were updated on the +system. + +\(fn)" t nil) + (put 'info-lookup-symbol 'info-file "emacs") + +(autoload 'info-lookup-symbol "info-look" "\ +Display the definition of SYMBOL, as found in the relevant manual. +When this command is called interactively, it reads SYMBOL from the +minibuffer. In the minibuffer, use M-n to yank the default argument +value into the minibuffer so you can edit it. The default symbol is the +one found at point. + +With prefix arg MODE a query for the symbol help mode is offered. + +\(fn SYMBOL &optional MODE)" t nil) + (put 'info-lookup-file 'info-file "emacs") + +(autoload 'info-lookup-file "info-look" "\ +Display the documentation of a file. +When this command is called interactively, it reads FILE from the minibuffer. +In the minibuffer, use M-n to yank the default file name +into the minibuffer so you can edit it. +The default file name is the one found at point. + +With prefix arg MODE a query for the file help mode is offered. + +\(fn FILE &optional MODE)" t nil) + +(autoload 'info-complete-symbol "info-look" "\ +Perform completion on symbol preceding point. + +\(fn &optional MODE)" t nil) + +(autoload 'info-complete-file "info-look" "\ +Perform completion on file preceding point. + +\(fn &optional MODE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "info-look" '("info-"))) + +;;;*** + +;;;### (autoloads nil "info-xref" "info-xref.el" (0 0 0 0)) +;;; Generated autoloads from info-xref.el +(push (purecopy '(info-xref 3)) package--builtin-versions) + +(autoload 'info-xref-check "info-xref" "\ +Check external references in FILENAME, an info document. +Interactively from an `Info-mode' or `texinfo-mode' buffer the +current info file is the default. + +Results are shown in a `compilation-mode' buffer. The format is +a bit rough, but there shouldn't be many problems normally. The +file:line:column: is the info document, but of course normally +any correction should be made in the original .texi file. +Finding the right place in the .texi is a manual process. + +When a target info file doesn't exist there's obviously no way to +validate node references within it. A message is given for +missing target files once per source document. It could be +simply that you don't have the target installed, or it could be a +mistake in the reference. + +Indirect info files are understood, just pass the top-level +foo.info to `info-xref-check' and it traverses all sub-files. +Compressed info files are accepted too as usual for `Info-mode'. + +\"makeinfo\" checks references internal to an info document, but +not external references, which makes it rather easy for mistakes +to creep in or node name changes to go unnoticed. +`Info-validate' doesn't check external references either. + +\(fn FILENAME)" t nil) + +(autoload 'info-xref-check-all "info-xref" "\ +Check external references in all info documents in the info path. +`Info-directory-list' and `Info-additional-directory-list' are +the info paths. See `info-xref-check' for how each file is +checked. + +The search for \"all\" info files is rather permissive, since +info files don't necessarily have a \".info\" extension and in +particular the Emacs manuals normally don't. If you have a +source code directory in `Info-directory-list' then a lot of +extraneous files might be read. This will be time consuming but +should be harmless. + +\(fn)" t nil) + +(autoload 'info-xref-check-all-custom "info-xref" "\ +Check info references in all customize groups and variables. +Info references can be in `custom-manual' or `info-link' entries +of the `custom-links' for a variable. + +Any `custom-load' autoloads in variables are loaded in order to +get full link information. This will be a lot of Lisp packages +and can take a long time. + +\(fn)" t nil) + +(autoload 'info-xref-docstrings "info-xref" "\ +Check docstring info node references in source files. +The given files are searched for docstring hyperlinks like + + Info node `(elisp)Documentation Tips' + +and those links checked by attempting to visit the target nodes +as per `info-xref-check' does. + +Interactively filenames are read as a wildcard pattern like +\"foo*.el\", with the current file as a default. Usually this +will be lisp sources, but anything with such hyperlinks can be +checked, including the Emacs .c sources (or the etc/DOC file of +all builtins). + +Because info node hyperlinks are found by a simple regexp search +in the files, the Lisp code checked doesn't have to be loaded, +and links can be in the file commentary or elsewhere too. Even +.elc files can usually be checked successfully if you don't have +the sources handy. + +\(fn FILENAME-LIST)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "info-xref" '("info-xref-"))) + +;;;*** + +;;;### (autoloads nil "informat" "informat.el" (0 0 0 0)) +;;; Generated autoloads from informat.el + +(autoload 'Info-tagify "informat" "\ +Create or update Info file tag table in current buffer or in a region. + +\(fn &optional INPUT-BUFFER-NAME)" t nil) + +(defvar Info-split-threshold 262144 "\ +The number of characters by which `Info-split' splits an info file.") + +(custom-autoload 'Info-split-threshold "informat" t) + +(autoload 'Info-split "informat" "\ +Split an info file into an indirect file plus bounded-size subfiles. +Each subfile will be up to the number of characters that +`Info-split-threshold' specifies, plus one node. + +To use this command, first visit a large Info file that has a tag +table. The buffer is modified into a (small) indirect info file which +should be saved in place of the original visited file. + +The subfiles are written in the same directory the original file is +in, with names generated by appending `-' and a number to the original +file name. The indirect file still functions as an Info file, but it +contains just the tag table and a directory of subfiles. + +\(fn)" t nil) + +(autoload 'Info-validate "informat" "\ +Check current buffer for validity as an Info file. +Check that every node pointer points to an existing node. + +\(fn)" t nil) + +(autoload 'batch-info-validate "informat" "\ +Runs `Info-validate' on the files remaining on the command line. +Must be used only with -batch, and kills Emacs on completion. +Each file will be processed even if an error occurred previously. +For example, invoke \"emacs -batch -f batch-info-validate $info/ ~/*.info\" + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "informat" '("Info-validate-"))) + +;;;*** + +;;;### (autoloads nil "inline" "emacs-lisp/inline.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/inline.el + +(autoload 'define-inline "inline" "\ + + +\(fn NAME ARGS &rest BODY)" nil t) + +(function-put 'define-inline 'lisp-indent-function 'defun) + +(function-put 'define-inline 'doc-string-elt '3) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "inline" '("inline-"))) + +;;;*** + +;;;### (autoloads nil "inversion" "cedet/inversion.el" (0 0 0 0)) +;;; Generated autoloads from cedet/inversion.el +(push (purecopy '(inversion 1 3)) package--builtin-versions) + +(autoload 'inversion-require-emacs "inversion" "\ +Declare that you need either EMACS-VER, XEMACS-VER or SXEMACS-ver. +Only checks one based on which kind of Emacs is being run. + +\(fn EMACS-VER XEMACS-VER SXEMACS-VER)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "inversion" '("inversion-"))) + +;;;*** + +;;;### (autoloads nil "isearch-x" "international/isearch-x.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from international/isearch-x.el + +(autoload 'isearch-toggle-specified-input-method "isearch-x" "\ +Select an input method and turn it on in interactive search. + +\(fn)" t nil) + +(autoload 'isearch-toggle-input-method "isearch-x" "\ +Toggle input method in interactive search. + +\(fn)" t nil) + +(autoload 'isearch-process-search-multibyte-characters "isearch-x" "\ + + +\(fn LAST-CHAR &optional COUNT)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "isearch-x" '("isearch-"))) + +;;;*** + +;;;### (autoloads nil "isearchb" "isearchb.el" (0 0 0 0)) +;;; Generated autoloads from isearchb.el +(push (purecopy '(isearchb 1 5)) package--builtin-versions) + +(autoload 'isearchb-activate "isearchb" "\ +Active isearchb mode for subsequent alphanumeric keystrokes. +Executing this command again will terminate the search; or, if +the search has not yet begun, will toggle to the last buffer +accessed via isearchb. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "isearchb" '("isearchb"))) + +;;;*** + +;;;### (autoloads nil "iso-ascii" "international/iso-ascii.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from international/iso-ascii.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "iso-ascii" '("iso-ascii-"))) + +;;;*** + +;;;### (autoloads nil "iso-cvt" "international/iso-cvt.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from international/iso-cvt.el + +(autoload 'iso-spanish "iso-cvt" "\ +Translate net conventions for Spanish to ISO 8859-1. +Translate the region between FROM and TO using the table +`iso-spanish-trans-tab'. +Optional arg BUFFER is ignored (for use in `format-alist'). + +\(fn FROM TO &optional BUFFER)" t nil) + +(autoload 'iso-german "iso-cvt" "\ +Translate net conventions for German to ISO 8859-1. +Translate the region FROM and TO using the table +`iso-german-trans-tab'. +Optional arg BUFFER is ignored (for use in `format-alist'). + +\(fn FROM TO &optional BUFFER)" t nil) + +(autoload 'iso-iso2tex "iso-cvt" "\ +Translate ISO 8859-1 characters to TeX sequences. +Translate the region between FROM and TO using the table +`iso-iso2tex-trans-tab'. +Optional arg BUFFER is ignored (for use in `format-alist'). + +\(fn FROM TO &optional BUFFER)" t nil) + +(autoload 'iso-tex2iso "iso-cvt" "\ +Translate TeX sequences to ISO 8859-1 characters. +Translate the region between FROM and TO using the table +`iso-tex2iso-trans-tab'. +Optional arg BUFFER is ignored (for use in `format-alist'). + +\(fn FROM TO &optional BUFFER)" t nil) + +(autoload 'iso-gtex2iso "iso-cvt" "\ +Translate German TeX sequences to ISO 8859-1 characters. +Translate the region between FROM and TO using the table +`iso-gtex2iso-trans-tab'. +Optional arg BUFFER is ignored (for use in `format-alist'). + +\(fn FROM TO &optional BUFFER)" t nil) + +(autoload 'iso-iso2gtex "iso-cvt" "\ +Translate ISO 8859-1 characters to German TeX sequences. +Translate the region between FROM and TO using the table +`iso-iso2gtex-trans-tab'. +Optional arg BUFFER is ignored (for use in `format-alist'). + +\(fn FROM TO &optional BUFFER)" t nil) + +(autoload 'iso-iso2duden "iso-cvt" "\ +Translate ISO 8859-1 characters to Duden sequences. +Translate the region between FROM and TO using the table +`iso-iso2duden-trans-tab'. +Optional arg BUFFER is ignored (for use in `format-alist'). + +\(fn FROM TO &optional BUFFER)" t nil) + +(autoload 'iso-iso2sgml "iso-cvt" "\ +Translate ISO 8859-1 characters in the region to SGML entities. +Use entities from \"ISO 8879:1986//ENTITIES Added Latin 1//EN\". +Optional arg BUFFER is ignored (for use in `format-alist'). + +\(fn FROM TO &optional BUFFER)" t nil) + +(autoload 'iso-sgml2iso "iso-cvt" "\ +Translate SGML entities in the region to ISO 8859-1 characters. +Use entities from \"ISO 8879:1986//ENTITIES Added Latin 1//EN\". +Optional arg BUFFER is ignored (for use in `format-alist'). + +\(fn FROM TO &optional BUFFER)" t nil) + +(autoload 'iso-cvt-read-only "iso-cvt" "\ +Warn that format is read-only. + +\(fn &rest IGNORE)" t nil) + +(autoload 'iso-cvt-write-only "iso-cvt" "\ +Warn that format is write-only. + +\(fn &rest IGNORE)" t nil) + +(autoload 'iso-cvt-define-menu "iso-cvt" "\ +Add submenus to the File menu, to convert to and from various formats. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "iso-cvt" '("iso-"))) + +;;;*** + +;;;### (autoloads nil "iso-transl" "international/iso-transl.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from international/iso-transl.el + (define-key key-translation-map "\C-x8" 'iso-transl-ctl-x-8-map) + (autoload 'iso-transl-ctl-x-8-map "iso-transl" "Keymap for C-x 8 prefix." t 'keymap) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "iso-transl" '("iso-transl-"))) + +;;;*** + +;;;### (autoloads nil "ispell" "textmodes/ispell.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/ispell.el + +(put 'ispell-check-comments 'safe-local-variable (lambda (a) (memq a '(nil t exclusive)))) + +(defvar ispell-personal-dictionary nil "\ +File name of your personal spelling dictionary, or nil. +If nil, the default personal dictionary for your spelling checker is used.") + +(custom-autoload 'ispell-personal-dictionary "ispell" t) + +(put 'ispell-local-dictionary 'safe-local-variable 'string-or-null-p) + +(defvar ispell-menu-map nil "\ +Key map for ispell menu.") + +(defvar ispell-menu-map-needed (unless ispell-menu-map 'reload)) + +(if ispell-menu-map-needed (progn (setq ispell-menu-map (make-sparse-keymap "Spell")) (define-key ispell-menu-map [ispell-change-dictionary] `(menu-item ,(purecopy "Change Dictionary...") ispell-change-dictionary :help ,(purecopy "Supply explicit dictionary file name"))) (define-key ispell-menu-map [ispell-kill-ispell] `(menu-item ,(purecopy "Kill Process") (lambda nil (interactive) (ispell-kill-ispell nil 'clear)) :enable (and (boundp 'ispell-process) ispell-process (eq (ispell-process-status) 'run)) :help ,(purecopy "Terminate Ispell subprocess"))) (define-key ispell-menu-map [ispell-pdict-save] `(menu-item ,(purecopy "Save Dictionary") (lambda nil (interactive) (ispell-pdict-save t t)) :help ,(purecopy "Save personal dictionary"))) (define-key ispell-menu-map [ispell-customize] `(menu-item ,(purecopy "Customize...") (lambda nil (interactive) (customize-group 'ispell)) :help ,(purecopy "Customize spell checking options"))) (define-key ispell-menu-map [ispell-help] `(menu-item ,(purecopy "Help") (lambda nil (interactive) (describe-function 'ispell-help)) :help ,(purecopy "Show standard Ispell keybindings and commands"))) (define-key ispell-menu-map [flyspell-mode] `(menu-item ,(purecopy "Automatic spell checking (Flyspell)") flyspell-mode :help ,(purecopy "Check spelling while you edit the text") :button (:toggle bound-and-true-p flyspell-mode))) (define-key ispell-menu-map [ispell-complete-word] `(menu-item ,(purecopy "Complete Word") ispell-complete-word :help ,(purecopy "Complete word at cursor using dictionary"))) (define-key ispell-menu-map [ispell-complete-word-interior-frag] `(menu-item ,(purecopy "Complete Word Fragment") ispell-complete-word-interior-frag :help ,(purecopy "Complete word fragment at cursor"))))) + +(if ispell-menu-map-needed (progn (define-key ispell-menu-map [ispell-continue] `(menu-item ,(purecopy "Continue Spell-Checking") ispell-continue :enable (and (boundp 'ispell-region-end) (marker-position ispell-region-end) (equal (marker-buffer ispell-region-end) (current-buffer))) :help ,(purecopy "Continue spell checking last region"))) (define-key ispell-menu-map [ispell-word] `(menu-item ,(purecopy "Spell-Check Word") ispell-word :help ,(purecopy "Spell-check word at cursor"))) (define-key ispell-menu-map [ispell-comments-and-strings] `(menu-item ,(purecopy "Spell-Check Comments") ispell-comments-and-strings :help ,(purecopy "Spell-check only comments and strings"))))) + +(if ispell-menu-map-needed (progn (define-key ispell-menu-map [ispell-region] `(menu-item ,(purecopy "Spell-Check Region") ispell-region :enable mark-active :help ,(purecopy "Spell-check text in marked region"))) (define-key ispell-menu-map [ispell-message] `(menu-item ,(purecopy "Spell-Check Message") ispell-message :visible (eq major-mode 'mail-mode) :help ,(purecopy "Skip headers and included message text"))) (define-key ispell-menu-map [ispell-buffer] `(menu-item ,(purecopy "Spell-Check Buffer") ispell-buffer :help ,(purecopy "Check spelling of selected buffer"))) (fset 'ispell-menu-map (symbol-value 'ispell-menu-map)))) + +(defvar ispell-skip-region-alist `((ispell-words-keyword forward-line) (ispell-dictionary-keyword forward-line) (ispell-pdict-keyword forward-line) (ispell-parsing-keyword forward-line) (,(purecopy "^---*BEGIN PGP [A-Z ]*--*") \, (purecopy "^---*END PGP [A-Z ]*--*")) (,(purecopy "^begin [0-9][0-9][0-9] [^ ]+$") \, (purecopy "\nend\n")) (,(purecopy "^%!PS-Adobe-[123].0") \, (purecopy "\n%%EOF\n")) (,(purecopy "^---* \\(Start of \\)?[Ff]orwarded [Mm]essage") \, (purecopy "^---* End of [Ff]orwarded [Mm]essage"))) "\ +Alist expressing beginning and end of regions not to spell check. +The alist key must be a regular expression. +Valid forms include: + (KEY) - just skip the key. + (KEY . REGEXP) - skip to the end of REGEXP. REGEXP may be string or symbol. + (KEY REGEXP) - skip to end of REGEXP. REGEXP must be a string. + (KEY FUNCTION ARGS) - FUNCTION called with ARGS returns end of region.") + +(defvar ispell-tex-skip-alists (purecopy '((("\\\\addcontentsline" ispell-tex-arg-end 2) ("\\\\add\\(tocontents\\|vspace\\)" ispell-tex-arg-end) ("\\\\\\([aA]lph\\|arabic\\)" ispell-tex-arg-end) ("\\\\cref" ispell-tex-arg-end) ("\\\\bibliographystyle" ispell-tex-arg-end) ("\\\\makebox" ispell-tex-arg-end 0) ("\\\\e?psfig" ispell-tex-arg-end) ("\\\\document\\(class\\|style\\)" . "\\\\begin[ \n]*{[ \n]*document[ \n]*}")) (("\\(figure\\|table\\)\\*?" ispell-tex-arg-end 0) ("list" ispell-tex-arg-end 2) ("program" . "\\\\end[ \n]*{[ \n]*program[ \n]*}") ("verbatim\\*?" . "\\\\end[ \n]*{[ \n]*verbatim\\*?[ \n]*}")))) "\ +Lists of regions to be skipped in TeX mode. +First list is used raw. +Second list has key placed inside \\begin{}. + +Delete or add any regions you want to be automatically selected +for skipping in latex mode.") + +(defconst ispell-html-skip-alists '(("<[cC][oO][dD][eE]\\>[^>]*>" "</[cC][oO][dD][eE]*>") ("<[sS][cC][rR][iI][pP][tT]\\>[^>]*>" "</[sS][cC][rR][iI][pP][tT]>") ("<[aA][pP][pP][lL][eE][tT]\\>[^>]*>" "</[aA][pP][pP][lL][eE][tT]>") ("<[vV][eE][rR][bB]\\>[^>]*>" "<[vV][eE][rR][bB]\\>[^>]*>") ("<[tT][tT]/" "/") ("<[^ \n>]" ">") ("&[^ \n;]" "[; \n]")) "\ +Lists of start and end keys to skip in HTML buffers. +Same format as `ispell-skip-region-alist'. +Note - substrings of other matches must come last + (e.g. \"<[tT][tT]/\" and \"<[^ \\t\\n>]\").") +(put 'ispell-local-pdict 'safe-local-variable 'stringp) + (define-key esc-map "$" 'ispell-word) + +(autoload 'ispell-word "ispell" "\ +Check spelling of word under or before the cursor. +If the word is not found in dictionary, display possible corrections +in a window allowing you to choose one. + +If optional argument FOLLOWING is non-nil or if `ispell-following-word' +is non-nil when called interactively, then the following word +\(rather than preceding) is checked when the cursor is not over a word. +When the optional argument QUIETLY is non-nil or `ispell-quietly' is non-nil +when called interactively, non-corrective messages are suppressed. + +With a prefix argument (or if CONTINUE is non-nil), +resume interrupted spell-checking of a buffer or region. + +Interactively, in Transient Mark mode when the mark is active, call +`ispell-region' to check the active region for spelling errors. + +Word syntax is controlled by the definition of the chosen dictionary, +which is in `ispell-local-dictionary-alist' or `ispell-dictionary-alist'. + +This will check or reload the dictionary. Use \\[ispell-change-dictionary] +or \\[ispell-region] to update the Ispell process. + +Return values: +nil word is correct or spelling is accepted. +0 word is inserted into buffer-local definitions. +\"word\" word corrected from word list. +\(\"word\" arg) word is hand entered. +quit spell session exited. + +\(fn &optional FOLLOWING QUIETLY CONTINUE REGION)" t nil) + +(autoload 'ispell-pdict-save "ispell" "\ +Check to see if the personal dictionary has been modified. +If so, ask if it needs to be saved. + +\(fn &optional NO-QUERY FORCE-SAVE)" t nil) + +(autoload 'ispell-help "ispell" "\ +Display a list of the options available when a misspelling is encountered. + +Selections are: + +DIGIT: Replace the word with a digit offered in the *Choices* buffer. +SPC: Accept word this time. +`i': Accept word and insert into private dictionary. +`a': Accept word for this session. +`A': Accept word and place in `buffer-local dictionary'. +`r': Replace word with typed-in value. Rechecked. +`R': Replace word with typed-in value. Query-replaced in buffer. Rechecked. +`?': Show these commands. +`x': Exit spelling buffer. Move cursor to original point. +`X': Exit spelling buffer. Leaves cursor at the current point, and permits + the aborted check to be completed later. +`q': Quit spelling session (Kills ispell process). +`l': Look up typed-in replacement in alternate dictionary. Wildcards okay. +`u': Like `i', but the word is lower-cased first. +`m': Place typed-in value in personal dictionary, then recheck current word. +`C-l': Redraw screen. +`C-r': Recursive edit. +`C-z': Suspend Emacs or iconify frame. + +\(fn)" nil nil) + +(autoload 'ispell-kill-ispell "ispell" "\ +Kill current Ispell process (so that you may start a fresh one). +With NO-ERROR, just return non-nil if there was no Ispell running. +With CLEAR, buffer session localwords are cleaned. + +\(fn &optional NO-ERROR CLEAR)" t nil) + +(autoload 'ispell-change-dictionary "ispell" "\ +Change to dictionary DICT for Ispell. +With a prefix arg, set it \"globally\", for all buffers. +Without a prefix arg, set it \"locally\", just for this buffer. + +By just answering RET you can find out what the current dictionary is. + +\(fn DICT &optional ARG)" t nil) + +(autoload 'ispell-region "ispell" "\ +Interactively check a region for spelling errors. +Return nil if spell session was terminated, otherwise returns shift offset +amount for last line processed. + +\(fn REG-START REG-END &optional RECHECKP SHIFT)" t nil) + +(autoload 'ispell-comments-and-strings "ispell" "\ +Check comments and strings in the current buffer for spelling errors. + +\(fn)" t nil) + +(autoload 'ispell-buffer "ispell" "\ +Check the current buffer for spelling errors interactively. + +\(fn)" t nil) + +(autoload 'ispell-buffer-with-debug "ispell" "\ +`ispell-buffer' with some output sent to `ispell-debug-buffer' buffer. +If APPEND is non-n il, append the info to previous buffer if exists. + +\(fn &optional APPEND)" t nil) + +(autoload 'ispell-continue "ispell" "\ +Continue a halted spelling session beginning with the current word. + +\(fn)" t nil) + +(autoload 'ispell-complete-word "ispell" "\ +Try to complete the word before or at point. +If optional INTERIOR-FRAG is non-nil, then the word may be a character +sequence inside of a word. + +Standard ispell choices are then available. + +\(fn &optional INTERIOR-FRAG)" t nil) + +(autoload 'ispell-complete-word-interior-frag "ispell" "\ +Completes word matching character sequence inside a word. + +\(fn)" t nil) + +(autoload 'ispell "ispell" "\ +Interactively check a region or buffer for spelling errors. +If `transient-mark-mode' is on, and a region is active, spell-check +that region. Otherwise spell-check the buffer. + +Ispell dictionaries are not distributed with Emacs. If you are +looking for a dictionary, please see the distribution of the GNU ispell +program, or do an Internet search; there are various dictionaries +available on the net. + +\(fn)" t nil) + +(autoload 'ispell-minor-mode "ispell" "\ +Toggle last-word spell checking (Ispell minor mode). +With a prefix argument ARG, enable Ispell minor mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Ispell minor mode is a buffer-local minor mode. When enabled, +typing SPC or RET warns you if the previous word is incorrectly +spelled. + +All the buffer-local variables and dictionaries are ignored. To +read them into the running Ispell process, type \\[ispell-word] +SPC. + +For spell-checking \"on the fly\", not just after typing SPC or +RET, use `flyspell-mode'. + +\(fn &optional ARG)" t nil) + +(autoload 'ispell-message "ispell" "\ +Check the spelling of a mail message or news post. +Don't check spelling of message headers except the Subject field. +Don't check included messages. + +To abort spell checking of a message region and send the message anyway, +use the `x' command. (Any subsequent regions will be checked.) +The `X' command aborts sending the message so that you can edit the buffer. + +To spell-check whenever a message is sent, include the appropriate lines +in your init file: + (add-hook \\='message-send-hook #\\='ispell-message) ;; GNUS 5 + (add-hook \\='news-inews-hook #\\='ispell-message) ;; GNUS 4 + (add-hook \\='mail-send-hook #\\='ispell-message) + (add-hook \\='mh-before-send-letter-hook #\\='ispell-message) + +You can bind this to the key C-c i in GNUS or mail by adding to +`news-reply-mode-hook' or `mail-mode-hook' the following lambda expression: + (function (lambda () (local-set-key \"\\C-ci\" \\='ispell-message))) + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ispell" '("ispell-" "check-ispell-version"))) + +;;;*** + +;;;### (autoloads nil "ja-dic-cnv" "international/ja-dic-cnv.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from international/ja-dic-cnv.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ja-dic-cnv" '("skkdic-" "batch-skkdic-convert" "ja-dic-filename"))) + +;;;*** + +;;;### (autoloads nil "ja-dic-utl" "international/ja-dic-utl.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from international/ja-dic-utl.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ja-dic-utl" '("skkdic-"))) + +;;;*** + +;;;### (autoloads nil "japan-util" "language/japan-util.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from language/japan-util.el + +(autoload 'setup-japanese-environment-internal "japan-util" "\ + + +\(fn)" nil nil) + +(autoload 'japanese-katakana "japan-util" "\ +Convert argument to Katakana and return that. +The argument may be a character or string. The result has the same type. +The argument object is not altered--the value is a copy. +Optional argument HANKAKU t means to convert to `hankaku' Katakana +\(`japanese-jisx0201-kana'), in which case return value +may be a string even if OBJ is a character if two Katakanas are +necessary to represent OBJ. + +\(fn OBJ &optional HANKAKU)" nil nil) + +(autoload 'japanese-hiragana "japan-util" "\ +Convert argument to Hiragana and return that. +The argument may be a character or string. The result has the same type. +The argument object is not altered--the value is a copy. + +\(fn OBJ)" nil nil) + +(autoload 'japanese-hankaku "japan-util" "\ +Convert argument to `hankaku' and return that. +The argument may be a character or string. The result has the same type. +The argument object is not altered--the value is a copy. +Optional argument ASCII-ONLY non-nil means to return only ASCII character. + +\(fn OBJ &optional ASCII-ONLY)" nil nil) + +(autoload 'japanese-zenkaku "japan-util" "\ +Convert argument to `zenkaku' and return that. +The argument may be a character or string. The result has the same type. +The argument object is not altered--the value is a copy. + +\(fn OBJ)" nil nil) + +(autoload 'japanese-katakana-region "japan-util" "\ +Convert Japanese `hiragana' chars in the region to `katakana' chars. +Optional argument HANKAKU t means to convert to `hankaku katakana' character +of which charset is `japanese-jisx0201-kana'. + +\(fn FROM TO &optional HANKAKU)" t nil) + +(autoload 'japanese-hiragana-region "japan-util" "\ +Convert Japanese `katakana' chars in the region to `hiragana' chars. + +\(fn FROM TO)" t nil) + +(autoload 'japanese-hankaku-region "japan-util" "\ +Convert Japanese `zenkaku' chars in the region to `hankaku' chars. +`Zenkaku' chars belong to `japanese-jisx0208' +`Hankaku' chars belong to `ascii' or `japanese-jisx0201-kana'. +Optional argument ASCII-ONLY non-nil means to convert only to ASCII char. + +\(fn FROM TO &optional ASCII-ONLY)" t nil) + +(autoload 'japanese-zenkaku-region "japan-util" "\ +Convert hankaku' chars in the region to Japanese `zenkaku' chars. +`Zenkaku' chars belong to `japanese-jisx0208' +`Hankaku' chars belong to `ascii' or `japanese-jisx0201-kana'. +Optional argument KATAKANA-ONLY non-nil means to convert only KATAKANA char. + +\(fn FROM TO &optional KATAKANA-ONLY)" t nil) + +(autoload 'read-hiragana-string "japan-util" "\ +Read a Hiragana string from the minibuffer, prompting with string PROMPT. +If non-nil, second arg INITIAL-INPUT is a string to insert before reading. + +\(fn PROMPT &optional INITIAL-INPUT)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "japan-util" '("japanese-"))) + +;;;*** + +;;;### (autoloads nil "jka-compr" "jka-compr.el" (0 0 0 0)) +;;; Generated autoloads from jka-compr.el + +(defvar jka-compr-inhibit nil "\ +Non-nil means inhibit automatic uncompression temporarily. +Lisp programs can bind this to t to do that. +It is not recommended to set this variable permanently to anything but nil.") + +(autoload 'jka-compr-handler "jka-compr" "\ + + +\(fn OPERATION &rest ARGS)" nil nil) + +(autoload 'jka-compr-uninstall "jka-compr" "\ +Uninstall jka-compr. +This removes the entries in `file-name-handler-alist' and `auto-mode-alist' +and `inhibit-local-variables-suffixes' that were added +by `jka-compr-installed'. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "jka-compr" '("jka-compr-" "compression-error"))) + +;;;*** + +;;;### (autoloads nil "js" "progmodes/js.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/js.el +(push (purecopy '(js 9)) package--builtin-versions) + +(autoload 'js-mode "js" "\ +Major mode for editing JavaScript. + +\(fn)" t nil) + +(autoload 'js-jsx-mode "js" "\ +Major mode for editing JSX. + +To customize the indentation for this mode, set the SGML offset +variables (`sgml-basic-offset', `sgml-attribute-offset' et al.) +locally, like so: + + (defun set-jsx-indentation () + (setq-local sgml-basic-offset js-indent-level)) + (add-hook \\='js-jsx-mode-hook #\\='set-jsx-indentation) + +\(fn)" t nil) + (defalias 'javascript-mode 'js-mode) + +(dolist (name (list "node" "nodejs" "gjs" "rhino")) (add-to-list 'interpreter-mode-alist (cons (purecopy name) 'js-mode))) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "js" '("js-" "with-js"))) + +;;;*** + +;;;### (autoloads nil "json" "json.el" (0 0 0 0)) +;;; Generated autoloads from json.el +(push (purecopy '(json 1 4)) package--builtin-versions) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "json" '("json-"))) + +;;;*** + +;;;### (autoloads nil "kermit" "kermit.el" (0 0 0 0)) +;;; Generated autoloads from kermit.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "kermit" '("kermit-"))) + +;;;*** + +;;;### (autoloads nil "keypad" "emulation/keypad.el" (0 0 0 0)) +;;; Generated autoloads from emulation/keypad.el + +(defvar keypad-setup nil "\ +Specifies the keypad setup for unshifted keypad keys when NumLock is off. +When selecting the plain numeric keypad setup, the character returned by the +decimal key must be specified.") + +(custom-autoload 'keypad-setup "keypad" nil) + +(defvar keypad-numlock-setup nil "\ +Specifies the keypad setup for unshifted keypad keys when NumLock is on. +When selecting the plain numeric keypad setup, the character returned by the +decimal key must be specified.") + +(custom-autoload 'keypad-numlock-setup "keypad" nil) + +(defvar keypad-shifted-setup nil "\ +Specifies the keypad setup for shifted keypad keys when NumLock is off. +When selecting the plain numeric keypad setup, the character returned by the +decimal key must be specified.") + +(custom-autoload 'keypad-shifted-setup "keypad" nil) + +(defvar keypad-numlock-shifted-setup nil "\ +Specifies the keypad setup for shifted keypad keys when NumLock is off. +When selecting the plain numeric keypad setup, the character returned by the +decimal key must be specified.") + +(custom-autoload 'keypad-numlock-shifted-setup "keypad" nil) + +(autoload 'keypad-setup "keypad" "\ +Set keypad bindings in `function-key-map' according to SETUP. +If optional second argument NUMLOCK is non-nil, the NumLock On bindings +are changed. Otherwise, the NumLock Off bindings are changed. +If optional third argument SHIFT is non-nil, the shifted keypad +keys are bound. + + Setup Binding + ------------------------------------------------------------- + `prefix' Command prefix argument, i.e. M-0 .. M-9 and M-- + `S-cursor' Bind shifted keypad keys to the shifted cursor movement keys. + `cursor' Bind keypad keys to the cursor movement keys. + `numeric' Plain numeric keypad, i.e. 0 .. 9 and . (or DECIMAL arg) + `none' Removes all bindings for keypad keys in function-key-map; + this enables any user-defined bindings for the keypad keys + in the global and local keymaps. + +If SETUP is `numeric' and the optional fourth argument DECIMAL is non-nil, +the decimal key on the keypad is mapped to DECIMAL instead of `.' + +\(fn SETUP &optional NUMLOCK SHIFT DECIMAL)" nil nil) + +;;;*** + +;;;### (autoloads nil "kinsoku" "international/kinsoku.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from international/kinsoku.el + +(autoload 'kinsoku "kinsoku" "\ +Go to a line breaking position near point by doing `kinsoku' processing. +LINEBEG is a buffer position we can't break a line before. + +`Kinsoku' processing is to prohibit specific characters to be placed +at beginning of line or at end of line. Characters not to be placed +at beginning and end of line have character category `>' and `<' +respectively. This restriction is dissolved by making a line longer or +shorter. + +`Kinsoku' is a Japanese word which originally means ordering to stay +in one place, and is used for the text processing described above in +the context of text formatting. + +\(fn LINEBEG)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "kinsoku" '("kinsoku-"))) + +;;;*** + +;;;### (autoloads nil "kkc" "international/kkc.el" (0 0 0 0)) +;;; Generated autoloads from international/kkc.el + +(defvar kkc-after-update-conversion-functions nil "\ +Functions to run after a conversion is selected in `japanese' input method. +With this input method, a user can select a proper conversion from +candidate list. Each time he changes the selection, functions in this +list are called with two arguments; starting and ending buffer +positions that contains the current selection.") + +(autoload 'kkc-region "kkc" "\ +Convert Kana string in the current region to Kanji-Kana mixed string. +Users can select a desirable conversion interactively. +When called from a program, expects two arguments, +positions FROM and TO (integers or markers) specifying the target region. +When it returns, the point is at the tail of the selected conversion, +and the return value is the length of the conversion. + +\(fn FROM TO)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "kkc" '("kkc-"))) + +;;;*** + +;;;### (autoloads nil "kmacro" "kmacro.el" (0 0 0 0)) +;;; Generated autoloads from kmacro.el + (global-set-key "\C-x(" 'kmacro-start-macro) + (global-set-key "\C-x)" 'kmacro-end-macro) + (global-set-key "\C-xe" 'kmacro-end-and-call-macro) + (global-set-key [f3] 'kmacro-start-macro-or-insert-counter) + (global-set-key [f4] 'kmacro-end-or-call-macro) + (global-set-key "\C-x\C-k" 'kmacro-keymap) + (autoload 'kmacro-keymap "kmacro" "Keymap for keyboard macro commands." t 'keymap) + +(autoload 'kmacro-exec-ring-item "kmacro" "\ +Execute item ITEM from the macro ring. +ARG is the number of times to execute the item. + +\(fn ITEM ARG)" nil nil) + +(autoload 'kmacro-start-macro "kmacro" "\ +Record subsequent keyboard input, defining a keyboard macro. +The commands are recorded even as they are executed. +Use \\[kmacro-end-macro] to finish recording and make the macro available. +Use \\[kmacro-end-and-call-macro] to execute the macro. + +Non-nil arg (prefix arg) means append to last macro defined. + +With \\[universal-argument] prefix, append to last keyboard macro +defined. Depending on `kmacro-execute-before-append', this may begin +by re-executing the last macro as if you typed it again. + +Otherwise, it sets `kmacro-counter' to ARG or 0 if missing before +defining the macro. + +Use \\[kmacro-insert-counter] to insert (and increment) the macro counter. +The counter value can be set or modified via \\[kmacro-set-counter] and \\[kmacro-add-counter]. +The format of the counter can be modified via \\[kmacro-set-format]. + +Use \\[kmacro-name-last-macro] to give it a permanent name. +Use \\[kmacro-bind-to-key] to bind it to a key sequence. + +\(fn ARG)" t nil) + +(autoload 'kmacro-end-macro "kmacro" "\ +Finish defining a keyboard macro. +The definition was started by \\[kmacro-start-macro]. +The macro is now available for use via \\[kmacro-call-macro], +or it can be given a name with \\[kmacro-name-last-macro] and then invoked +under that name. + +With numeric arg, repeat macro now that many times, +counting the definition just completed as the first repetition. +An argument of zero means repeat until error. + +\(fn ARG)" t nil) + +(autoload 'kmacro-call-macro "kmacro" "\ +Call the keyboard MACRO that you defined with \\[kmacro-start-macro]. +A prefix argument serves as a repeat count. Zero means repeat until error. +MACRO defaults to `last-kbd-macro'. + +When you call the macro, you can call the macro again by repeating +just the last key in the key sequence that you used to call this +command. See `kmacro-call-repeat-key' and `kmacro-call-repeat-with-arg' +for details on how to adjust or disable this behavior. + +To make a macro permanent so you can call it even after defining +others, use \\[kmacro-name-last-macro]. + +\(fn ARG &optional NO-REPEAT END-MACRO MACRO)" t nil) + +(autoload 'kmacro-start-macro-or-insert-counter "kmacro" "\ +Record subsequent keyboard input, defining a keyboard macro. +The commands are recorded even as they are executed. + +Sets the `kmacro-counter' to ARG (or 0 if no prefix arg) before defining the +macro. + +With \\[universal-argument], appends to current keyboard macro (keeping +the current value of `kmacro-counter'). + +When defining/executing macro, inserts macro counter and increments +the counter with ARG or 1 if missing. With \\[universal-argument], +inserts previous `kmacro-counter' (but do not modify counter). + +The macro counter can be modified via \\[kmacro-set-counter] and \\[kmacro-add-counter]. +The format of the counter can be modified via \\[kmacro-set-format]. + +\(fn ARG)" t nil) + +(autoload 'kmacro-end-or-call-macro "kmacro" "\ +End kbd macro if currently being defined; else call last kbd macro. +With numeric prefix ARG, repeat macro that many times. +With \\[universal-argument], call second macro in macro ring. + +\(fn ARG &optional NO-REPEAT)" t nil) + +(autoload 'kmacro-end-and-call-macro "kmacro" "\ +Call last keyboard macro, ending it first if currently being defined. +With numeric prefix ARG, repeat macro that many times. +Zero argument means repeat until there is an error. + +To give a macro a permanent name, so you can call it +even after defining other macros, use \\[kmacro-name-last-macro]. + +\(fn ARG &optional NO-REPEAT)" t nil) + +(autoload 'kmacro-end-call-mouse "kmacro" "\ +Move point to the position clicked with the mouse and call last kbd macro. +If kbd macro currently being defined end it before activating it. + +\(fn EVENT)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "kmacro" '("kmacro-"))) + +;;;*** + +;;;### (autoloads nil "korea-util" "language/korea-util.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from language/korea-util.el + +(defvar default-korean-keyboard (purecopy (if (string-match "3" (or (getenv "HANGUL_KEYBOARD_TYPE") "")) "3" "")) "\ +The kind of Korean keyboard for Korean input method. +\"\" for 2, \"3\" for 3.") + +(autoload 'setup-korean-environment-internal "korea-util" "\ + + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "korea-util" '("exit-korean-environment" "korean-key-bindings" "isearch-" "quail-hangul-switch-" "toggle-korean-input-method"))) + +;;;*** + +;;;### (autoloads nil "lao-util" "language/lao-util.el" (0 0 0 0)) +;;; Generated autoloads from language/lao-util.el + +(autoload 'lao-compose-string "lao-util" "\ + + +\(fn STR)" nil nil) + +(autoload 'lao-transcribe-single-roman-syllable-to-lao "lao-util" "\ +Transcribe a Romanized Lao syllable in the region FROM and TO to Lao string. +Only the first syllable is transcribed. +The value has the form: (START END LAO-STRING), where +START and END are the beginning and end positions of the Roman Lao syllable, +LAO-STRING is the Lao character transcription of it. + +Optional 3rd arg STR, if non-nil, is a string to search for Roman Lao +syllable. In that case, FROM and TO are indexes to STR. + +\(fn FROM TO &optional STR)" nil nil) + +(autoload 'lao-transcribe-roman-to-lao-string "lao-util" "\ +Transcribe Romanized Lao string STR to Lao character string. + +\(fn STR)" nil nil) + +(autoload 'lao-composition-function "lao-util" "\ + + +\(fn GSTRING)" nil nil) + +(autoload 'lao-compose-region "lao-util" "\ + + +\(fn FROM TO)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lao-util" '("lao-"))) + +;;;*** + +;;;### (autoloads nil "latexenc" "international/latexenc.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from international/latexenc.el + +(defvar latex-inputenc-coding-alist (purecopy '(("ansinew" . windows-1252) ("applemac" . mac-roman) ("ascii" . us-ascii) ("cp1250" . windows-1250) ("cp1252" . windows-1252) ("cp1257" . cp1257) ("cp437de" . cp437) ("cp437" . cp437) ("cp850" . cp850) ("cp852" . cp852) ("cp858" . cp858) ("cp865" . cp865) ("latin1" . iso-8859-1) ("latin2" . iso-8859-2) ("latin3" . iso-8859-3) ("latin4" . iso-8859-4) ("latin5" . iso-8859-5) ("latin9" . iso-8859-15) ("next" . next) ("utf8" . utf-8) ("utf8x" . utf-8))) "\ +Mapping from LaTeX encodings in \"inputenc.sty\" to Emacs coding systems. +LaTeX encodings are specified with \"\\usepackage[encoding]{inputenc}\". +Used by the function `latexenc-find-file-coding-system'.") + +(custom-autoload 'latex-inputenc-coding-alist "latexenc" t) + +(autoload 'latexenc-inputenc-to-coding-system "latexenc" "\ +Return the corresponding coding-system for the specified input encoding. +Return nil if no matching coding system can be found. + +\(fn INPUTENC)" nil nil) + +(autoload 'latexenc-coding-system-to-inputenc "latexenc" "\ +Return the corresponding input encoding for the specified coding system. +Return nil if no matching input encoding can be found. + +\(fn CS)" nil nil) + +(autoload 'latexenc-find-file-coding-system "latexenc" "\ +Determine the coding system of a LaTeX file if it uses \"inputenc.sty\". +The mapping from LaTeX's \"inputenc.sty\" encoding names to Emacs +coding system names is determined from `latex-inputenc-coding-alist'. + +\(fn ARG-LIST)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "latexenc" '("latexenc-dont-use-"))) + +;;;*** + +;;;### (autoloads nil "latin1-disp" "international/latin1-disp.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from international/latin1-disp.el + +(defvar latin1-display nil "\ +Set up Latin-1/ASCII display for ISO8859 character sets. +This is done for each character set in the list `latin1-display-sets', +if no font is available to display it. Characters are displayed using +the corresponding Latin-1 characters where they match. Otherwise +ASCII sequences are used, mostly following the Latin prefix input +methods. Some different ASCII sequences are used if +`latin1-display-mnemonic' is non-nil. + +This option also treats some characters in the `mule-unicode-...' +charsets if you don't have a Unicode font with which to display them. + +Setting this variable directly does not take effect; +use either \\[customize] or the function `latin1-display'.") + +(custom-autoload 'latin1-display "latin1-disp" nil) + +(autoload 'latin1-display "latin1-disp" "\ +Set up Latin-1/ASCII display for the arguments character SETS. +See option `latin1-display' for the method. The members of the list +must be in `latin1-display-sets'. With no arguments, reset the +display for all of `latin1-display-sets'. See also +`latin1-display-setup'. + +\(fn &rest SETS)" nil nil) + +(defvar latin1-display-ucs-per-lynx nil "\ +Set up Latin-1/ASCII display for Unicode characters. +This uses the transliterations of the Lynx browser. The display isn't +changed if the display can render Unicode characters. + +Setting this variable directly does not take effect; +use either \\[customize] or the function `latin1-display'.") + +(custom-autoload 'latin1-display-ucs-per-lynx "latin1-disp" nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "latin1-disp" '("latin1-display-"))) + +;;;*** + +;;;### (autoloads nil "ld-script" "progmodes/ld-script.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from progmodes/ld-script.el + +(autoload 'ld-script-mode "ld-script" "\ +A major mode to edit GNU ld script files + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ld-script" '("ld-script-"))) + +;;;*** + +;;;### (autoloads nil "ldap" "net/ldap.el" (0 0 0 0)) +;;; Generated autoloads from net/ldap.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ldap" '("ldap-"))) + +;;;*** + +;;;### (autoloads nil "legacy-gnus-agent" "gnus/legacy-gnus-agent.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from gnus/legacy-gnus-agent.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "legacy-gnus-agent" '("gnus-agent-"))) + +;;;*** + +;;;### (autoloads nil "let-alist" "emacs-lisp/let-alist.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from emacs-lisp/let-alist.el +(push (purecopy '(let-alist 1 0 5)) package--builtin-versions) + +(autoload 'let-alist "let-alist" "\ +Let-bind dotted symbols to their cdrs in ALIST and execute BODY. +Dotted symbol is any symbol starting with a `.'. Only those present +in BODY are let-bound and this search is done at compile time. + +For instance, the following code + + (let-alist alist + (if (and .title .body) + .body + .site + .site.contents)) + +essentially expands to + + (let ((.title (cdr (assq \\='title alist))) + (.body (cdr (assq \\='body alist))) + (.site (cdr (assq \\='site alist))) + (.site.contents (cdr (assq \\='contents (cdr (assq \\='site alist)))))) + (if (and .title .body) + .body + .site + .site.contents)) + +If you nest `let-alist' invocations, the inner one can't access +the variables of the outer one. You can, however, access alists +inside the original alist by using dots inside the symbol, as +displayed in the example above. + +\(fn ALIST &rest BODY)" nil t) + +(function-put 'let-alist 'lisp-indent-function '1) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "let-alist" '("let-alist--"))) + +;;;*** + +;;;### (autoloads nil "life" "play/life.el" (0 0 0 0)) +;;; Generated autoloads from play/life.el + +(autoload 'life "life" "\ +Run Conway's Life simulation. +The starting pattern is randomly selected. Prefix arg (optional first +arg non-nil from a program) is the number of seconds to sleep between +generations (this defaults to 1). + +\(fn &optional SLEEPTIME)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "life" '("life-"))) + +;;;*** + +;;;### (autoloads nil "linum" "linum.el" (0 0 0 0)) +;;; Generated autoloads from linum.el +(push (purecopy '(linum 0 9 24)) package--builtin-versions) + +(autoload 'linum-mode "linum" "\ +Toggle display of line numbers in the left margin (Linum mode). +With a prefix argument ARG, enable Linum mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode +if ARG is omitted or nil. + +Linum mode is a buffer-local minor mode. + +\(fn &optional ARG)" t nil) + +(defvar global-linum-mode nil "\ +Non-nil if Global Linum mode is enabled. +See the `global-linum-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `global-linum-mode'.") + +(custom-autoload 'global-linum-mode "linum" nil) + +(autoload 'global-linum-mode "linum" "\ +Toggle Linum mode in all buffers. +With prefix ARG, enable Global Linum mode if ARG is positive; +otherwise, disable it. If called from Lisp, enable the mode if +ARG is omitted or nil. + +Linum mode is enabled in all buffers where +`linum-on' would do it. +See `linum-mode' for more information on Linum mode. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "linum" '("linum-"))) + +;;;*** + +;;;### (autoloads nil "lisp-mnt" "emacs-lisp/lisp-mnt.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from emacs-lisp/lisp-mnt.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lisp-mnt" '("lm-"))) + +;;;*** + +;;;### (autoloads nil "loadhist" "loadhist.el" (0 0 0 0)) +;;; Generated autoloads from loadhist.el + +(autoload 'unload-feature "loadhist" "\ +Unload the library that provided FEATURE. +If the feature is required by any other loaded code, and prefix arg FORCE +is nil, raise an error. + +Standard unloading activities include restoring old autoloads for +functions defined by the library, undoing any additions that the +library has made to hook variables or to `auto-mode-alist', undoing +ELP profiling of functions in that library, unproviding any features +provided by the library, and canceling timers held in variables +defined by the library. + +If a function `FEATURE-unload-function' is defined, this function +calls it with no arguments, before doing anything else. That function +can do whatever is appropriate to undo the loading of the library. If +`FEATURE-unload-function' returns non-nil, that suppresses the +standard unloading of the library. Otherwise the standard unloading +proceeds. + +`FEATURE-unload-function' has access to the package's list of +definitions in the variable `unload-function-defs-list' and could +remove symbols from it in the event that the package has done +something strange, such as redefining an Emacs function. + +\(fn FEATURE &optional FORCE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "loadhist" '("unload-" "loadhist-hook-functions" "read-feature" "feature-" "file-"))) + +;;;*** + +;;;### (autoloads nil "locate" "locate.el" (0 0 0 0)) +;;; Generated autoloads from locate.el + +(defvar locate-ls-subdir-switches (purecopy "-al") "\ +`ls' switches for inserting subdirectories in `*Locate*' buffers. +This should contain the \"-l\" switch, but not the \"-F\" or \"-b\" switches.") + +(custom-autoload 'locate-ls-subdir-switches "locate" t) + +(autoload 'locate "locate" "\ +Run the program `locate', putting results in `*Locate*' buffer. +Pass it SEARCH-STRING as argument. Interactively, prompt for SEARCH-STRING. +With prefix arg ARG, prompt for the exact shell command to run instead. + +This program searches for those file names in a database that match +SEARCH-STRING and normally outputs all matching absolute file names, +one per line. The database normally consists of all files on your +system, or of all files that you have access to. Consult the +documentation of the program for the details about how it determines +which file names match SEARCH-STRING. (Those details vary highly with +the version.) + +You can specify another program for this command to run by customizing +the variables `locate-command' or `locate-make-command-line'. + +The main use of FILTER is to implement `locate-with-filter'. See +the docstring of that function for its meaning. + +After preparing the results buffer, this runs `dired-mode-hook' and +then `locate-post-command-hook'. + +\(fn SEARCH-STRING &optional FILTER ARG)" t nil) + +(autoload 'locate-with-filter "locate" "\ +Run the executable program `locate' with a filter. +This function is similar to the function `locate', which see. +The difference is that, when invoked interactively, the present function +prompts for both SEARCH-STRING and FILTER. It passes SEARCH-STRING +to the locate executable program. It produces a `*Locate*' buffer +that lists only those lines in the output of the locate program that +contain a match for the regular expression FILTER; this is often useful +to constrain a big search. + +ARG is the interactive prefix arg, which has the same effect as in `locate'. + +When called from Lisp, this function is identical with `locate', +except that FILTER is not optional. + +\(fn SEARCH-STRING FILTER &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "locate" '("locate-"))) + +;;;*** + +;;;### (autoloads nil "log-edit" "vc/log-edit.el" (0 0 0 0)) +;;; Generated autoloads from vc/log-edit.el + +(autoload 'log-edit "log-edit" "\ +Setup a buffer to enter a log message. +The buffer is put in mode MODE or `log-edit-mode' if MODE is nil. +\\<log-edit-mode-map> +If SETUP is non-nil, erase the buffer and run `log-edit-hook'. +Set mark and point around the entire contents of the buffer, so +that it is easy to kill the contents of the buffer with +\\[kill-region]. Once the user is done editing the message, +invoking the command \\[log-edit-done] (`log-edit-done') will +call CALLBACK to do the actual commit. + +PARAMS if non-nil is an alist of variables and buffer-local +values to give them in the Log Edit buffer. Possible keys and +associated values: + `log-edit-listfun' -- function taking no arguments that returns the list of + files that are concerned by the current operation (using relative names); + `log-edit-diff-function' -- function taking no arguments that + displays a diff of the files concerned by the current operation. + `vc-log-fileset' -- the VC fileset to be committed (if any). + +If BUFFER is non-nil `log-edit' will jump to that buffer, use it +to edit the log message and go back to the current buffer when +done. Otherwise, it uses the current buffer. + +\(fn CALLBACK &optional SETUP PARAMS BUFFER MODE &rest IGNORE)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "log-edit" '("log-edit-" "vc-log-"))) + +;;;*** + +;;;### (autoloads nil "log-view" "vc/log-view.el" (0 0 0 0)) +;;; Generated autoloads from vc/log-view.el + +(autoload 'log-view-mode "log-view" "\ +Major mode for browsing CVS log output. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "log-view" '("log-view-"))) + +;;;*** + +;;;### (autoloads nil "lpr" "lpr.el" (0 0 0 0)) +;;; Generated autoloads from lpr.el + +(defvar lpr-windows-system (memq system-type '(ms-dos windows-nt)) "\ +Non-nil if running on MS-DOS or MS Windows.") + +(defvar lpr-lp-system (memq system-type '(usg-unix-v hpux)) "\ +Non-nil if running on a system type that uses the \"lp\" command.") + +(defvar printer-name (and (eq system-type 'ms-dos) "PRN") "\ +The name of a local printer to which data is sent for printing. +\(Note that PostScript files are sent to `ps-printer-name', which see.) + +On Unix-like systems, a string value should be a name understood by +lpr's -P option; otherwise the value should be nil. + +On MS-DOS and MS-Windows systems, a string value is taken as the name of +a printer device or port, provided `lpr-command' is set to \"\". +Typical non-default settings would be \"LPT1\" to \"LPT3\" for parallel +printers, or \"COM1\" to \"COM4\" or \"AUX\" for serial printers, or +\"//hostname/printer\" for a shared network printer. You can also set +it to the name of a file, in which case the output gets appended to that +file. If you want to discard the printed output, set this to \"NUL\".") + +(custom-autoload 'printer-name "lpr" t) + +(defvar lpr-switches nil "\ +List of strings to pass as extra options for the printer program. +It is recommended to set `printer-name' instead of including an explicit +switch on this list. +See `lpr-command'.") + +(custom-autoload 'lpr-switches "lpr" t) + +(defvar lpr-command (purecopy (cond (lpr-windows-system "") (lpr-lp-system "lp") (t "lpr"))) "\ +Name of program for printing a file. + +On MS-DOS and MS-Windows systems, if the value is an empty string then +Emacs will write directly to the printer port named by `printer-name'. +The programs `print' and `nprint' (the standard print programs on +Windows NT and Novell Netware respectively) are handled specially, using +`printer-name' as the destination for output; any other program is +treated like `lpr' except that an explicit filename is given as the last +argument.") + +(custom-autoload 'lpr-command "lpr" t) + +(autoload 'lpr-buffer "lpr" "\ +Print buffer contents without pagination or page headers. +See the variables `lpr-switches' and `lpr-command' +for customization of the printer command. + +\(fn)" t nil) + +(autoload 'print-buffer "lpr" "\ +Paginate and print buffer contents. + +The variable `lpr-headers-switches' controls how to paginate. +If it is nil (the default), we run the `pr' program (or whatever program +`lpr-page-header-program' specifies) to paginate. +`lpr-page-header-switches' specifies the switches for that program. + +Otherwise, the switches in `lpr-headers-switches' are used +in the print command itself; we expect them to request pagination. + +See the variables `lpr-switches' and `lpr-command' +for further customization of the printer command. + +\(fn)" t nil) + +(autoload 'lpr-region "lpr" "\ +Print region contents without pagination or page headers. +See the variables `lpr-switches' and `lpr-command' +for customization of the printer command. + +\(fn START END)" t nil) + +(autoload 'print-region "lpr" "\ +Paginate and print the region contents. + +The variable `lpr-headers-switches' controls how to paginate. +If it is nil (the default), we run the `pr' program (or whatever program +`lpr-page-header-program' specifies) to paginate. +`lpr-page-header-switches' specifies the switches for that program. + +Otherwise, the switches in `lpr-headers-switches' are used +in the print command itself; we expect them to request pagination. + +See the variables `lpr-switches' and `lpr-command' +for further customization of the printer command. + +\(fn START END)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lpr" '("lpr-" "print"))) + +;;;*** + +;;;### (autoloads nil "ls-lisp" "ls-lisp.el" (0 0 0 0)) +;;; Generated autoloads from ls-lisp.el + +(defvar ls-lisp-support-shell-wildcards t "\ +Non-nil means ls-lisp treats file patterns as shell wildcards. +Otherwise they are treated as Emacs regexps (for backward compatibility).") + +(custom-autoload 'ls-lisp-support-shell-wildcards "ls-lisp" t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ls-lisp" '("ls-lisp-"))) + +;;;*** + +;;;### (autoloads nil "lunar" "calendar/lunar.el" (0 0 0 0)) +;;; Generated autoloads from calendar/lunar.el + +(autoload 'lunar-phases "lunar" "\ +Display the quarters of the moon for last month, this month, and next month. +If called with an optional prefix argument ARG, prompts for month and year. +This function is suitable for execution in an init file. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "lunar" '("lunar-" "diary-lunar-phases" "calendar-lunar-phases"))) + +;;;*** + +;;;### (autoloads nil "m4-mode" "progmodes/m4-mode.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/m4-mode.el + +(autoload 'm4-mode "m4-mode" "\ +A major mode to edit m4 macro files. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "m4-mode" '("m4-"))) + +;;;*** + +;;;### (autoloads nil "macros" "macros.el" (0 0 0 0)) +;;; Generated autoloads from macros.el + +(autoload 'name-last-kbd-macro "macros" "\ +Assign a name to the last keyboard macro defined. +Argument SYMBOL is the name to define. +The symbol's function definition becomes the keyboard macro string. +Such a \"function\" cannot be called from Lisp, but it is a valid editor command. + +\(fn SYMBOL)" t nil) + +(autoload 'insert-kbd-macro "macros" "\ +Insert in buffer the definition of kbd macro MACRONAME, as Lisp code. +MACRONAME should be a symbol. +Optional second arg KEYS means also record the keys it is on +\(this is the prefix argument, when calling interactively). + +This Lisp code will, when executed, define the kbd macro with the same +definition it has now. If you say to record the keys, the Lisp code +will also rebind those keys to the macro. Only global key bindings +are recorded since executing this Lisp code always makes global +bindings. + +To save a kbd macro, visit a file of Lisp code such as your `~/.emacs', +use this command, and then save the file. + +\(fn MACRONAME &optional KEYS)" t nil) + +(autoload 'kbd-macro-query "macros" "\ +Query user during kbd macro execution. + With prefix argument, enters recursive edit, reading keyboard +commands even within a kbd macro. You can give different commands +each time the macro executes. + Without prefix argument, asks whether to continue running the macro. +Your options are: \\<query-replace-map> +\\[act] Finish this iteration normally and continue with the next. +\\[skip] Skip the rest of this iteration, and start the next. +\\[exit] Stop the macro entirely right now. +\\[recenter] Redisplay the screen, then ask again. +\\[edit] Enter recursive edit; ask again when you exit from that. + +\(fn FLAG)" t nil) + +(autoload 'apply-macro-to-region-lines "macros" "\ +Apply last keyboard macro to all lines in the region. +For each line that begins in the region, move to the beginning of +the line, and run the last keyboard macro. + +When called from lisp, this function takes two arguments TOP and +BOTTOM, describing the current region. TOP must be before BOTTOM. +The optional third argument MACRO specifies a keyboard macro to +execute. + +This is useful for quoting or unquoting included text, adding and +removing comments, or producing tables where the entries are regular. + +For example, in Usenet articles, sections of text quoted from another +author are indented, or have each line start with `>'. To quote a +section of text, define a keyboard macro which inserts `>', put point +and mark at opposite ends of the quoted section, and use +`\\[apply-macro-to-region-lines]' to mark the entire section. + +Suppose you wanted to build a keyword table in C where each entry +looked like this: + + { \"foo\", foo_data, foo_function }, + { \"bar\", bar_data, bar_function }, + { \"baz\", baz_data, baz_function }, + +You could enter the names in this format: + + foo + bar + baz + +and write a macro to massage a word into a table entry: + + \\C-x ( + \\M-d { \"\\C-y\", \\C-y_data, \\C-y_function }, + \\C-x ) + +and then select the region of un-tablified names and use +`\\[apply-macro-to-region-lines]' to build the table from the names. + +\(fn TOP BOTTOM &optional MACRO)" t nil) + (define-key ctl-x-map "q" 'kbd-macro-query) + +;;;*** + +;;;### (autoloads nil "mail-extr" "mail/mail-extr.el" (0 0 0 0)) +;;; Generated autoloads from mail/mail-extr.el + +(autoload 'mail-extract-address-components "mail-extr" "\ +Given an RFC-822 address ADDRESS, extract full name and canonical address. +Returns a list of the form (FULL-NAME CANONICAL-ADDRESS). If no +name can be extracted, FULL-NAME will be nil. Also see +`mail-extr-ignore-single-names' and +`mail-extr-ignore-realname-equals-mailbox-name'. + +If the optional argument ALL is non-nil, then ADDRESS can contain zero +or more recipients, separated by commas, and we return a list of +the form ((FULL-NAME CANONICAL-ADDRESS) ...) with one element for +each recipient. If ALL is nil, then if ADDRESS contains more than +one recipients, all but the first is ignored. + +ADDRESS may be a string or a buffer. If it is a buffer, the visible +\(narrowed) portion of the buffer will be interpreted as the address. +\(This feature exists so that the clever caller might be able to avoid +consing a string.) + +\(fn ADDRESS &optional ALL)" nil nil) + +(autoload 'what-domain "mail-extr" "\ +Convert mail domain DOMAIN to the country it corresponds to. + +\(fn DOMAIN)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mail-extr" '("mail-extr-"))) + +;;;*** + +;;;### (autoloads nil "mail-hist" "mail/mail-hist.el" (0 0 0 0)) +;;; Generated autoloads from mail/mail-hist.el + +(autoload 'mail-hist-define-keys "mail-hist" "\ +Define keys for accessing mail header history. For use in hooks. + +\(fn)" nil nil) + +(autoload 'mail-hist-enable "mail-hist" "\ + + +\(fn)" nil nil) + +(defvar mail-hist-keep-history t "\ +Non-nil means keep a history for headers and text of outgoing mail.") + +(custom-autoload 'mail-hist-keep-history "mail-hist" t) + +(autoload 'mail-hist-put-headers-into-history "mail-hist" "\ +Put headers and contents of this message into mail header history. +Each header has its own independent history, as does the body of the +message. + +This function normally would be called when the message is sent. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mail-hist" '("mail-hist-"))) + +;;;*** + +;;;### (autoloads nil "mail-parse" "mail/mail-parse.el" (0 0 0 0)) +;;; Generated autoloads from mail/mail-parse.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mail-parse" '("mail-"))) + +;;;*** + +;;;### (autoloads nil "mail-prsvr" "mail/mail-prsvr.el" (0 0 0 0)) +;;; Generated autoloads from mail/mail-prsvr.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mail-prsvr" '("mail-parse-"))) + +;;;*** + +;;;### (autoloads nil "mail-source" "gnus/mail-source.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from gnus/mail-source.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mail-source" '("mail-source"))) + +;;;*** + +;;;### (autoloads nil "mail-utils" "mail/mail-utils.el" (0 0 0 0)) +;;; Generated autoloads from mail/mail-utils.el + +(defvar mail-use-rfc822 nil "\ +If non-nil, use a full, hairy RFC822 parser on mail addresses. +Otherwise, (the default) use a smaller, somewhat faster, and +often correct parser.") + +(custom-autoload 'mail-use-rfc822 "mail-utils" t) + +(defvar mail-dont-reply-to-names nil "\ +Regexp specifying addresses to prune from a reply message. +If this is nil, it is set the first time you compose a reply, to +a value which excludes your own email address. + +Matching addresses are excluded from the CC field in replies, and +also the To field, unless this would leave an empty To field.") + +(custom-autoload 'mail-dont-reply-to-names "mail-utils" t) + +(autoload 'mail-file-babyl-p "mail-utils" "\ +Return non-nil if FILE is a Babyl file. + +\(fn FILE)" nil nil) + +(autoload 'mail-quote-printable "mail-utils" "\ +Convert a string to the \"quoted printable\" Q encoding if necessary. +If the string contains only ASCII characters and no troublesome ones, +we return it unconverted. + +If the optional argument WRAPPER is non-nil, +we add the wrapper characters =?ISO-8859-1?Q?....?=. + +\(fn STRING &optional WRAPPER)" nil nil) + +(autoload 'mail-quote-printable-region "mail-utils" "\ +Convert the region to the \"quoted printable\" Q encoding. +If the optional argument WRAPPER is non-nil, +we add the wrapper characters =?ISO-8859-1?Q?....?=. + +\(fn BEG END &optional WRAPPER)" t nil) + +(autoload 'mail-unquote-printable "mail-utils" "\ +Undo the \"quoted printable\" encoding. +If the optional argument WRAPPER is non-nil, +we expect to find and remove the wrapper characters =?ISO-8859-1?Q?....?=. + +\(fn STRING &optional WRAPPER)" nil nil) + +(autoload 'mail-unquote-printable-region "mail-utils" "\ +Undo the \"quoted printable\" encoding in buffer from BEG to END. +If the optional argument WRAPPER is non-nil, +we expect to find and remove the wrapper characters =?ISO-8859-1?Q?....?=. +On encountering malformed quoted-printable text, exits with an error, +unless NOERROR is non-nil, in which case it continues, and returns nil +when finished. Returns non-nil on successful completion. +If UNIBYTE is non-nil, insert converted characters as unibyte. +That is useful if you are going to character code decoding afterward, +as Rmail does. + +\(fn BEG END &optional WRAPPER NOERROR UNIBYTE)" t nil) + +(autoload 'mail-fetch-field "mail-utils" "\ +Return the value of the header field whose type is FIELD-NAME. +If second arg LAST is non-nil, use the last field of type FIELD-NAME. +If third arg ALL is non-nil, concatenate all such fields with commas between. +If 4th arg LIST is non-nil, return a list of all such fields. +The buffer should be narrowed to just the header, else false +matches may be returned from the message body. + +\(fn FIELD-NAME &optional LAST ALL LIST)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mail-utils" '("mail-"))) + +;;;*** + +;;;### (autoloads nil "mailabbrev" "mail/mailabbrev.el" (0 0 0 0)) +;;; Generated autoloads from mail/mailabbrev.el + +(defvar mail-abbrevs-mode nil "\ +Non-nil if Mail-Abbrevs mode is enabled. +See the `mail-abbrevs-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `mail-abbrevs-mode'.") + +(custom-autoload 'mail-abbrevs-mode "mailabbrev" nil) + +(autoload 'mail-abbrevs-mode "mailabbrev" "\ +Toggle abbrev expansion of mail aliases (Mail Abbrevs mode). +With a prefix argument ARG, enable Mail Abbrevs mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Mail Abbrevs mode is a global minor mode. When enabled, +abbrev-like expansion is performed when editing certain mail +headers (those specified by `mail-abbrev-mode-regexp'), based on +the entries in your `mail-personal-alias-file'. + +\(fn &optional ARG)" t nil) + +(autoload 'mail-abbrevs-setup "mailabbrev" "\ +Initialize use of the `mailabbrev' package. + +\(fn)" nil nil) + +(autoload 'build-mail-abbrevs "mailabbrev" "\ +Read mail aliases from personal mail alias file and set `mail-abbrevs'. +By default this is the file specified by `mail-personal-alias-file'. + +\(fn &optional FILE RECURSIVEP)" nil nil) + +(autoload 'define-mail-abbrev "mailabbrev" "\ +Define NAME as a mail alias abbrev that translates to DEFINITION. +If DEFINITION contains multiple addresses, separate them with commas. + +Optional argument FROM-MAILRC-FILE means that DEFINITION comes +from a mailrc file. In that case, addresses are separated with +spaces and addresses with embedded spaces are surrounded by +double-quotes. + +\(fn NAME DEFINITION &optional FROM-MAILRC-FILE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mailabbrev" '("merge-mail-abbrevs" "mail-" "rebuild-mail-abbrevs"))) + +;;;*** + +;;;### (autoloads nil "mailalias" "mail/mailalias.el" (0 0 0 0)) +;;; Generated autoloads from mail/mailalias.el + +(defvar mail-complete-style 'angles "\ +Specifies how \\[mail-complete] formats the full name when it completes. +If nil, they contain just the return address like: + king@grassland.com +If `parens', they look like: + king@grassland.com (Elvis Parsley) +If `angles', they look like: + Elvis Parsley <king@grassland.com>") + +(custom-autoload 'mail-complete-style "mailalias" t) + +(autoload 'expand-mail-aliases "mailalias" "\ +Expand all mail aliases in suitable header fields found between BEG and END. +If interactive, expand in header fields. +Suitable header fields are `To', `From', `CC' and `BCC', `Reply-to', and +their `Resent-' variants. + +Optional second arg EXCLUDE may be a regular expression defining text to be +removed from alias expansions. + +\(fn BEG END &optional EXCLUDE)" t nil) + +(autoload 'define-mail-alias "mailalias" "\ +Define NAME as a mail alias that translates to DEFINITION. +This means that sending a message to NAME will actually send to DEFINITION. + +Normally, the addresses in DEFINITION must be separated by commas. +If FROM-MAILRC-FILE is non-nil, then addresses in DEFINITION +can be separated by spaces; an address can contain spaces +if it is quoted with double-quotes. + +\(fn NAME DEFINITION &optional FROM-MAILRC-FILE)" t nil) + +(autoload 'mail-completion-at-point-function "mailalias" "\ +Compute completion data for mail aliases. +For use on `completion-at-point-functions'. + +\(fn)" nil nil) + +(autoload 'mail-complete "mailalias" "\ +Perform completion on header field or word preceding point. +Completable headers are according to `mail-complete-alist'. If none matches +current header, calls `mail-complete-function' and passes prefix ARG if any. + +\(fn ARG)" t nil) + +(make-obsolete 'mail-complete 'mail-completion-at-point-function '"24.1") + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mailalias" '("mail-" "build-mail-aliases"))) + +;;;*** + +;;;### (autoloads nil "mailcap" "net/mailcap.el" (0 0 0 0)) +;;; Generated autoloads from net/mailcap.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mailcap" '("mailcap-"))) + +;;;*** + +;;;### (autoloads nil "mailclient" "mail/mailclient.el" (0 0 0 0)) +;;; Generated autoloads from mail/mailclient.el + +(autoload 'mailclient-send-it "mailclient" "\ +Pass current buffer on to the system's mail client. +Suitable value for `send-mail-function'. +The mail client is taken to be the handler of mailto URLs. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mailclient" '("mailclient-"))) + +;;;*** + +;;;### (autoloads nil "mailheader" "mail/mailheader.el" (0 0 0 0)) +;;; Generated autoloads from mail/mailheader.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mailheader" '("mail-header"))) + +;;;*** + +;;;### (autoloads nil "mairix" "net/mairix.el" (0 0 0 0)) +;;; Generated autoloads from net/mairix.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mairix" '("mairix-"))) + +;;;*** + +;;;### (autoloads nil "make-mode" "progmodes/make-mode.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from progmodes/make-mode.el + +(autoload 'makefile-mode "make-mode" "\ +Major mode for editing standard Makefiles. + +If you are editing a file for a different make, try one of the +variants `makefile-automake-mode', `makefile-gmake-mode', +`makefile-makepp-mode', `makefile-bsdmake-mode' or, +`makefile-imake-mode'. All but the last should be correctly +chosen based on the file name, except if it is *.mk. This +function ends by invoking the function(s) `makefile-mode-hook'. + +It is strongly recommended to use `font-lock-mode', because that +provides additional parsing information. This is used for +example to see that a rule action `echo foo: bar' is a not rule +dependency, despite the colon. + +\\{makefile-mode-map} + +In the browser, use the following keys: + +\\{makefile-browser-map} + +Makefile mode can be configured by modifying the following variables: + +`makefile-browser-buffer-name': + Name of the macro- and target browser buffer. + +`makefile-target-colon': + The string that gets appended to all target names + inserted by `makefile-insert-target'. + \":\" or \"::\" are quite common values. + +`makefile-macro-assign': + The string that gets appended to all macro names + inserted by `makefile-insert-macro'. + The normal value should be \" = \", since this is what + standard make expects. However, newer makes such as dmake + allow a larger variety of different macro assignments, so you + might prefer to use \" += \" or \" := \" . + +`makefile-tab-after-target-colon': + If you want a TAB (instead of a space) to be appended after the + target colon, then set this to a non-nil value. + +`makefile-browser-leftmost-column': + Number of blanks to the left of the browser selection mark. + +`makefile-browser-cursor-column': + Column in which the cursor is positioned when it moves + up or down in the browser. + +`makefile-browser-selected-mark': + String used to mark selected entries in the browser. + +`makefile-browser-unselected-mark': + String used to mark unselected entries in the browser. + +`makefile-browser-auto-advance-after-selection-p': + If this variable is set to a non-nil value the cursor + will automagically advance to the next line after an item + has been selected in the browser. + +`makefile-pickup-everything-picks-up-filenames-p': + If this variable is set to a non-nil value then + `makefile-pickup-everything' also picks up filenames as targets + (i.e. it calls `makefile-pickup-filenames-as-targets'), otherwise + filenames are omitted. + +`makefile-cleanup-continuations': + If this variable is set to a non-nil value then Makefile mode + will assure that no line in the file ends with a backslash + (the continuation character) followed by any whitespace. + This is done by silently removing the trailing whitespace, leaving + the backslash itself intact. + IMPORTANT: Please note that enabling this option causes Makefile mode + to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \"it seems necessary\". + +`makefile-browser-hook': + A function or list of functions to be called just before the + browser is entered. This is executed in the makefile buffer. + +`makefile-special-targets-list': + List of special targets. You will be offered to complete + on one of those in the minibuffer whenever you enter a `.'. + at the beginning of a line in Makefile mode. + +\(fn)" t nil) + +(autoload 'makefile-automake-mode "make-mode" "\ +An adapted `makefile-mode' that knows about automake. + +\(fn)" t nil) + +(autoload 'makefile-gmake-mode "make-mode" "\ +An adapted `makefile-mode' that knows about gmake. + +\(fn)" t nil) + +(autoload 'makefile-makepp-mode "make-mode" "\ +An adapted `makefile-mode' that knows about makepp. + +\(fn)" t nil) + +(autoload 'makefile-bsdmake-mode "make-mode" "\ +An adapted `makefile-mode' that knows about BSD make. + +\(fn)" t nil) + +(autoload 'makefile-imake-mode "make-mode" "\ +An adapted `makefile-mode' that knows about imake. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "make-mode" '("makefile-"))) + +;;;*** + +;;;### (autoloads nil "makeinfo" "textmodes/makeinfo.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/makeinfo.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "makeinfo" '("makeinfo-"))) + +;;;*** + +;;;### (autoloads nil "makesum" "makesum.el" (0 0 0 0)) +;;; Generated autoloads from makesum.el + +(autoload 'make-command-summary "makesum" "\ +Make a summary of current key bindings in the buffer *Summary*. +Previous contents of that buffer are killed first. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "makesum" '("double-column"))) + +;;;*** + +;;;### (autoloads nil "man" "man.el" (0 0 0 0)) +;;; Generated autoloads from man.el + +(defalias 'manual-entry 'man) + +(autoload 'man "man" "\ +Get a Un*x manual page and put it in a buffer. +This command is the top-level command in the man package. +It runs a Un*x command to retrieve and clean a manpage in the +background and places the results in a `Man-mode' browsing +buffer. The variable `Man-width' defines the number of columns in +formatted manual pages. The buffer is displayed immediately. +The variable `Man-notify-method' defines how the buffer is displayed. +If a buffer already exists for this man page, it will be displayed +without running the man command. + +For a manpage from a particular section, use either of the +following. \"cat(1)\" is how cross-references appear and is +passed to man as \"1 cat\". + + cat(1) + 1 cat + +To see manpages from all sections related to a subject, use an +\"all pages\" option (which might be \"-a\" if it's not the +default), then step through with `Man-next-manpage' (\\<Man-mode-map>\\[Man-next-manpage]) etc. +Add to `Man-switches' to make this option permanent. + + -a chmod + +An explicit filename can be given too. Use -l if it might +otherwise look like a page name. + + /my/file/name.1.gz + -l somefile.1 + +An \"apropos\" query with -k gives a buffer of matching page +names or descriptions. The pattern argument is usually an +\"grep -E\" style regexp. + + -k pattern + +\(fn MAN-ARGS)" t nil) + +(autoload 'man-follow "man" "\ +Get a Un*x manual page of the item under point and put it in a buffer. + +\(fn MAN-ARGS)" t nil) + +(autoload 'Man-bookmark-jump "man" "\ +Default bookmark handler for Man buffers. + +\(fn BOOKMARK)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "man" '("Man-" "man"))) + +;;;*** + +;;;### (autoloads nil "mantemp" "progmodes/mantemp.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/mantemp.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mantemp" '("mantemp-"))) + +;;;*** + +;;;### (autoloads nil "map" "emacs-lisp/map.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/map.el +(push (purecopy '(map 1 1)) package--builtin-versions) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "map" '("map"))) + +;;;*** + +;;;### (autoloads nil "master" "master.el" (0 0 0 0)) +;;; Generated autoloads from master.el +(push (purecopy '(master 1 0 2)) package--builtin-versions) + +(autoload 'master-mode "master" "\ +Toggle Master mode. +With a prefix argument ARG, enable Master mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +When Master mode is enabled, you can scroll the slave buffer +using the following commands: + +\\{master-mode-map} + +The slave buffer is stored in the buffer-local variable `master-of'. +You can set this variable using `master-set-slave'. You can show +yourself the value of `master-of' by calling `master-show-slave'. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "master" '("master-"))) + +;;;*** + +;;;### (autoloads nil "mb-depth" "mb-depth.el" (0 0 0 0)) +;;; Generated autoloads from mb-depth.el + +(defvar minibuffer-depth-indicate-mode nil "\ +Non-nil if Minibuffer-Depth-Indicate mode is enabled. +See the `minibuffer-depth-indicate-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `minibuffer-depth-indicate-mode'.") + +(custom-autoload 'minibuffer-depth-indicate-mode "mb-depth" nil) + +(autoload 'minibuffer-depth-indicate-mode "mb-depth" "\ +Toggle Minibuffer Depth Indication mode. +With a prefix argument ARG, enable Minibuffer Depth Indication +mode if ARG is positive, and disable it otherwise. If called +from Lisp, enable the mode if ARG is omitted or nil. + +Minibuffer Depth Indication mode is a global minor mode. When +enabled, any recursive use of the minibuffer will show the +recursion depth in the minibuffer prompt. This is only useful if +`enable-recursive-minibuffers' is non-nil. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mb-depth" '("minibuffer-depth-"))) + +;;;*** + +;;;### (autoloads nil "md4" "md4.el" (0 0 0 0)) +;;; Generated autoloads from md4.el +(push (purecopy '(md4 1 0)) package--builtin-versions) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "md4" '("md4"))) + +;;;*** + +;;;### (autoloads nil "message" "gnus/message.el" (0 0 0 0)) +;;; Generated autoloads from gnus/message.el + +(define-mail-user-agent 'message-user-agent 'message-mail 'message-send-and-exit 'message-kill-buffer 'message-send-hook) + +(autoload 'message-mode "message" "\ +Major mode for editing mail and news to be sent. +Like Text Mode but with these additional commands:\\<message-mode-map> +C-c C-s `message-send' (send the message) C-c C-c `message-send-and-exit' +C-c C-d Postpone sending the message C-c C-k Kill the message +C-c C-f move to a header field (and create it if there isn't): + C-c C-f C-t move to To C-c C-f C-s move to Subject + C-c C-f C-c move to Cc C-c C-f C-b move to Bcc + C-c C-f C-w move to Fcc C-c C-f C-r move to Reply-To + C-c C-f C-u move to Summary C-c C-f C-n move to Newsgroups + C-c C-f C-k move to Keywords C-c C-f C-d move to Distribution + C-c C-f C-o move to From (\"Originator\") + C-c C-f C-f move to Followup-To + C-c C-f C-m move to Mail-Followup-To + C-c C-f C-e move to Expires + C-c C-f C-i cycle through Importance values + C-c C-f s change subject and append \"(was: <Old Subject>)\" + C-c C-f x crossposting with FollowUp-To header and note in body + C-c C-f t replace To: header with contents of Cc: or Bcc: + C-c C-f a Insert X-No-Archive: header and a note in the body +C-c C-t `message-insert-to' (add a To header to a news followup) +C-c C-l `message-to-list-only' (removes all but list address in to/cc) +C-c C-n `message-insert-newsgroups' (add a Newsgroup header to a news reply) +C-c C-b `message-goto-body' (move to beginning of message text). +C-c C-i `message-goto-signature' (move to the beginning of the signature). +C-c C-w `message-insert-signature' (insert `message-signature-file' file). +C-c C-y `message-yank-original' (insert current message, if any). +C-c C-q `message-fill-yanked-message' (fill what was yanked). +C-c C-e `message-elide-region' (elide the text between point and mark). +C-c C-v `message-delete-not-region' (remove the text outside the region). +C-c C-z `message-kill-to-signature' (kill the text up to the signature). +C-c C-r `message-caesar-buffer-body' (rot13 the message body). +C-c C-a `mml-attach-file' (attach a file as MIME). +C-c C-u `message-insert-or-toggle-importance' (insert or cycle importance). +C-c M-n `message-insert-disposition-notification-to' (request receipt). +C-c M-m `message-mark-inserted-region' (mark region with enclosing tags). +C-c M-f `message-mark-insert-file' (insert file marked with enclosing tags). +M-RET `message-newline-and-reformat' (break the line and reformat). + +\(fn)" t nil) + +(autoload 'message-mail "message" "\ +Start editing a mail message to be sent. +OTHER-HEADERS is an alist of header/value pairs. CONTINUE says whether +to continue editing a message already being composed. SWITCH-FUNCTION +is a function used to switch to and display the mail buffer. + +\(fn &optional TO SUBJECT OTHER-HEADERS CONTINUE SWITCH-FUNCTION YANK-ACTION SEND-ACTIONS RETURN-ACTION &rest IGNORED)" t nil) + +(autoload 'message-news "message" "\ +Start editing a news article to be sent. + +\(fn &optional NEWSGROUPS SUBJECT)" t nil) + +(autoload 'message-reply "message" "\ +Start editing a reply to the article in the current buffer. + +\(fn &optional TO-ADDRESS WIDE SWITCH-FUNCTION)" t nil) + +(autoload 'message-wide-reply "message" "\ +Make a \"wide\" reply to the message in the current buffer. + +\(fn &optional TO-ADDRESS)" t nil) + +(autoload 'message-followup "message" "\ +Follow up to the message in the current buffer. +If TO-NEWSGROUPS, use that as the new Newsgroups line. + +\(fn &optional TO-NEWSGROUPS)" t nil) + +(autoload 'message-cancel-news "message" "\ +Cancel an article you posted. +If ARG, allow editing of the cancellation message. + +\(fn &optional ARG)" t nil) + +(autoload 'message-supersede "message" "\ +Start composing a message to supersede the current message. +This is done simply by taking the old article and adding a Supersedes +header line with the old Message-ID. + +\(fn)" t nil) + +(autoload 'message-recover "message" "\ +Reread contents of current buffer from its last auto-save file. + +\(fn)" t nil) + +(autoload 'message-forward "message" "\ +Forward the current message via mail. +Optional NEWS will use news to forward instead of mail. +Optional DIGEST will use digest to forward. + +\(fn &optional NEWS DIGEST)" t nil) + +(autoload 'message-forward-make-body "message" "\ + + +\(fn FORWARD-BUFFER &optional DIGEST)" nil nil) + +(autoload 'message-forward-rmail-make-body "message" "\ + + +\(fn FORWARD-BUFFER)" nil nil) + +(autoload 'message-insinuate-rmail "message" "\ +Let RMAIL use message to forward. + +\(fn)" t nil) + +(autoload 'message-resend "message" "\ +Resend the current article to ADDRESS. + +\(fn ADDRESS)" t nil) + +(autoload 'message-bounce "message" "\ +Re-mail the current message. +This only makes sense if the current message is a bounce message that +contains some mail you have written which has been bounced back to +you. + +\(fn)" t nil) + +(autoload 'message-mail-other-window "message" "\ +Like `message-mail' command, but display mail buffer in another window. + +\(fn &optional TO SUBJECT)" t nil) + +(autoload 'message-mail-other-frame "message" "\ +Like `message-mail' command, but display mail buffer in another frame. + +\(fn &optional TO SUBJECT)" t nil) + +(autoload 'message-news-other-window "message" "\ +Start editing a news article to be sent. + +\(fn &optional NEWSGROUPS SUBJECT)" t nil) + +(autoload 'message-news-other-frame "message" "\ +Start editing a news article to be sent. + +\(fn &optional NEWSGROUPS SUBJECT)" t nil) + +(autoload 'message-bold-region "message" "\ +Bold all nonblank characters in the region. +Works by overstriking characters. +Called from program, takes two arguments START and END +which specify the range to operate on. + +\(fn START END)" t nil) + +(autoload 'message-unbold-region "message" "\ +Remove all boldness (overstruck characters) in the region. +Called from program, takes two arguments START and END +which specify the range to operate on. + +\(fn START END)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "message" '("message-" "nil"))) + +;;;*** + +;;;### (autoloads nil "meta-mode" "progmodes/meta-mode.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from progmodes/meta-mode.el +(push (purecopy '(meta-mode 1 0)) package--builtin-versions) + +(autoload 'metafont-mode "meta-mode" "\ +Major mode for editing Metafont sources. + +\(fn)" t nil) + +(autoload 'metapost-mode "meta-mode" "\ +Major mode for editing MetaPost sources. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "meta-mode" '("meta" "font-lock-match-meta-declaration-item-and-skip-to-next"))) + +;;;*** + +;;;### (autoloads nil "metamail" "mail/metamail.el" (0 0 0 0)) +;;; Generated autoloads from mail/metamail.el + +(autoload 'metamail-interpret-header "metamail" "\ +Interpret a header part of a MIME message in current buffer. +Its body part is not interpreted at all. + +\(fn)" t nil) + +(autoload 'metamail-interpret-body "metamail" "\ +Interpret a body part of a MIME message in current buffer. +Optional argument VIEWMODE specifies the value of the +EMACS_VIEW_MODE environment variable (defaulted to 1). +Optional argument NODISPLAY non-nil means buffer is not +redisplayed as output is inserted. +Its header part is not interpreted at all. + +\(fn &optional VIEWMODE NODISPLAY)" t nil) + +(autoload 'metamail-buffer "metamail" "\ +Process current buffer through `metamail'. +Optional argument VIEWMODE specifies the value of the +EMACS_VIEW_MODE environment variable (defaulted to 1). +Optional argument BUFFER specifies a buffer to be filled (nil +means current). +Optional argument NODISPLAY non-nil means buffer is not +redisplayed as output is inserted. + +\(fn &optional VIEWMODE BUFFER NODISPLAY)" t nil) + +(autoload 'metamail-region "metamail" "\ +Process current region through `metamail'. +Optional argument VIEWMODE specifies the value of the +EMACS_VIEW_MODE environment variable (defaulted to 1). +Optional argument BUFFER specifies a buffer to be filled (nil +means current). +Optional argument NODISPLAY non-nil means buffer is not +redisplayed as output is inserted. + +\(fn BEG END &optional VIEWMODE BUFFER NODISPLAY)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "metamail" '("metamail-"))) + +;;;*** + +;;;### (autoloads nil "mh-acros" "mh-e/mh-acros.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-acros.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-acros" '("mh-" "with-mh-folder-updating" "defun-mh" "defmacro-mh"))) + +;;;*** + +;;;### (autoloads nil "mh-alias" "mh-e/mh-alias.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-alias.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-alias" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-buffers" "mh-e/mh-buffers.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-buffers.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-buffers" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-comp" "mh-e/mh-comp.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-comp.el + +(autoload 'mh-smail "mh-comp" "\ +Compose a message with the MH mail system. +See `mh-send' for more details on composing mail. + +\(fn)" t nil) + +(autoload 'mh-smail-other-window "mh-comp" "\ +Compose a message with the MH mail system in other window. +See `mh-send' for more details on composing mail. + +\(fn)" t nil) + +(autoload 'mh-smail-batch "mh-comp" "\ +Compose a message with the MH mail system. + +This function does not prompt the user for any header fields, and +thus is suitable for use by programs that want to create a mail +buffer. Users should use \\[mh-smail] to compose mail. + +Optional arguments for setting certain fields include TO, +SUBJECT, and OTHER-HEADERS. Additional arguments are IGNORED. + +This function remains for Emacs 21 compatibility. New +applications should use `mh-user-agent-compose'. + +\(fn &optional TO SUBJECT OTHER-HEADERS &rest IGNORED)" nil nil) + +(define-mail-user-agent 'mh-e-user-agent 'mh-user-agent-compose 'mh-send-letter 'mh-fully-kill-draft 'mh-before-send-letter-hook) + +(autoload 'mh-user-agent-compose "mh-comp" "\ +Set up mail composition draft with the MH mail system. +This is the `mail-user-agent' entry point to MH-E. This function +conforms to the contract specified by `define-mail-user-agent' +which means that this function should accept the same arguments +as `compose-mail'. + +The optional arguments TO and SUBJECT specify recipients and the +initial Subject field, respectively. + +OTHER-HEADERS is an alist specifying additional header fields. +Elements look like (HEADER . VALUE) where both HEADER and VALUE +are strings. + +CONTINUE, SWITCH-FUNCTION, YANK-ACTION, SEND-ACTIONS, and +RETURN-ACTION and any additional arguments are IGNORED. + +\(fn &optional TO SUBJECT OTHER-HEADERS CONTINUE SWITCH-FUNCTION YANK-ACTION SEND-ACTIONS RETURN-ACTION &rest IGNORED)" nil nil) + +(autoload 'mh-send-letter "mh-comp" "\ +Save draft and send message. + +When you are all through editing a message, you send it with this +command. You can give a prefix argument ARG to monitor the first stage +of the delivery; this output can be found in a buffer called \"*MH-E +Mail Delivery*\". + +The hook `mh-before-send-letter-hook' is run at the beginning of +this command. For example, if you want to check your spelling in +your message before sending, add the function `ispell-message'. + +Unless `mh-insert-auto-fields' had previously been called +manually, the function `mh-insert-auto-fields' is called to +insert fields based upon the recipients. If fields are added, you +are given a chance to see and to confirm these fields before the +message is actually sent. You can do away with this confirmation +by turning off the option `mh-auto-fields-prompt-flag'. + +In case the MH \"send\" program is installed under a different name, +use `mh-send-prog' to tell MH-E the name. + +The hook `mh-annotate-msg-hook' is run after annotating the +message and scan line. + +\(fn &optional ARG)" t nil) + +(autoload 'mh-fully-kill-draft "mh-comp" "\ +Quit editing and delete draft message. + +If for some reason you are not happy with the draft, you can use +this command to kill the draft buffer and delete the draft +message. Use the command \\[kill-buffer] if you don't want to +delete the draft message. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-comp" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-compat" "mh-e/mh-compat.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-compat.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-compat" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-e" "mh-e/mh-e.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-e.el +(push (purecopy '(mh-e 8 6 -4)) package--builtin-versions) + +(put 'mh-progs 'risky-local-variable t) + +(put 'mh-lib 'risky-local-variable t) + +(put 'mh-lib-progs 'risky-local-variable t) + +(autoload 'mh-version "mh-e" "\ +Display version information about MH-E and the MH mail handling system. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-e" '("mh-" "defgroup-mh" "defcustom-mh" "defface-mh"))) + +;;;*** + +;;;### (autoloads nil "mh-folder" "mh-e/mh-folder.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-folder.el + +(autoload 'mh-rmail "mh-folder" "\ +Incorporate new mail with MH. +Scan an MH folder if ARG is non-nil. + +This function is an entry point to MH-E, the Emacs interface to +the MH mail system. + +\(fn &optional ARG)" t nil) + +(autoload 'mh-nmail "mh-folder" "\ +Check for new mail in inbox folder. +Scan an MH folder if ARG is non-nil. + +This function is an entry point to MH-E, the Emacs interface to +the MH mail system. + +\(fn &optional ARG)" t nil) + +(autoload 'mh-folder-mode "mh-folder" "\ +Major MH-E mode for \"editing\" an MH folder scan listing.\\<mh-folder-mode-map> + +You can show the message the cursor is pointing to, and step through +the messages. Messages can be marked for deletion or refiling into +another folder; these commands are executed all at once with a +separate command. + +Options that control this mode can be changed with +\\[customize-group]; specify the \"mh\" group. In particular, please +see the `mh-scan-format-file' option if you wish to modify scan's +format. + +When a folder is visited, the hook `mh-folder-mode-hook' is run. + +Ranges +====== +Many commands that operate on individual messages, such as +`mh-forward' or `mh-refile-msg' take a RANGE argument. This argument +can be used in several ways. + +If you provide the prefix argument (\\[universal-argument]) to +these commands, then you will be prompted for the message range. +This can be any valid MH range which can include messages, +sequences, and the abbreviations (described in the mh(1) man +page): + +<num1>-<num2> + Indicates all messages in the range <num1> to <num2>, inclusive. + The range must be nonempty. + +<num>:N +<num>:+N +<num>:-N + Up to N messages beginning with (or ending with) message num. Num + may be any of the predefined symbols: first, prev, cur, next or + last. + +first:N +prev:N +next:N +last:N + The first, previous, next or last messages, if they exist. + +all + All of the messages. + +For example, a range that shows all of these things is `1 2 3 +5-10 last:5 unseen'. + +If the option `transient-mark-mode' is set to t and you set a +region in the MH-Folder buffer, then the MH-E command will +perform the operation on all messages in that region. + +\\{mh-folder-mode-map} + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-folder" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-funcs" "mh-e/mh-funcs.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-funcs.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-funcs" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-identity" "mh-e/mh-identity.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from mh-e/mh-identity.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-identity" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-inc" "mh-e/mh-inc.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-inc.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-inc" '("mh-inc-spool-"))) + +;;;*** + +;;;### (autoloads nil "mh-junk" "mh-e/mh-junk.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-junk.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-junk" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-letter" "mh-e/mh-letter.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-letter.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-letter" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-limit" "mh-e/mh-limit.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-limit.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-limit" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-mime" "mh-e/mh-mime.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-mime.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-mime" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-print" "mh-e/mh-print.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-print.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-print" '("mh-p"))) + +;;;*** + +;;;### (autoloads nil "mh-scan" "mh-e/mh-scan.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-scan.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-scan" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-search" "mh-e/mh-search.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-search.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-search" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-seq" "mh-e/mh-seq.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-seq.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-seq" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-show" "mh-e/mh-show.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-show.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-show" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-speed" "mh-e/mh-speed.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-speed.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-speed" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-thread" "mh-e/mh-thread.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-thread.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-thread" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-tool-bar" "mh-e/mh-tool-bar.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from mh-e/mh-tool-bar.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-tool-bar" '("mh-tool-bar-"))) + +;;;*** + +;;;### (autoloads nil "mh-utils" "mh-e/mh-utils.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-utils.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-utils" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mh-xface" "mh-e/mh-xface.el" (0 0 0 0)) +;;; Generated autoloads from mh-e/mh-xface.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mh-xface" '("mh-"))) + +;;;*** + +;;;### (autoloads nil "mhtml-mode" "textmodes/mhtml-mode.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from textmodes/mhtml-mode.el + +(autoload 'mhtml-mode "mhtml-mode" "\ +Major mode based on `html-mode', but works with embedded JS and CSS. + +Code inside a <script> element is indented using the rules from +`js-mode'; and code inside a <style> element is indented using +the rules from `css-mode'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mhtml-mode" '("mhtml-"))) + +;;;*** + +;;;### (autoloads nil "midnight" "midnight.el" (0 0 0 0)) +;;; Generated autoloads from midnight.el + +(defvar midnight-mode nil "\ +Non-nil if Midnight mode is enabled. +See the `midnight-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `midnight-mode'.") + +(custom-autoload 'midnight-mode "midnight" nil) + +(autoload 'midnight-mode "midnight" "\ +Non-nil means run `midnight-hook' at midnight. + +\(fn &optional ARG)" t nil) + +(autoload 'clean-buffer-list "midnight" "\ +Kill old buffers that have not been displayed recently. +The relevant variables are `clean-buffer-list-delay-general', +`clean-buffer-list-delay-special', `clean-buffer-list-kill-buffer-names', +`clean-buffer-list-kill-never-buffer-names', +`clean-buffer-list-kill-regexps' and +`clean-buffer-list-kill-never-regexps'. +While processing buffers, this procedure displays messages containing +the current date/time, buffer name, how many seconds ago it was +displayed (can be nil if the buffer was never displayed) and its +lifetime, i.e., its \"age\" when it will be purged. + +\(fn)" t nil) + +(autoload 'midnight-delay-set "midnight" "\ +Modify `midnight-timer' according to `midnight-delay'. +Sets the first argument SYMB (which must be symbol `midnight-delay') +to its second argument TM. + +\(fn SYMB TM)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "midnight" '("midnight-" "clean-buffer-list-"))) + +;;;*** + +;;;### (autoloads nil "minibuf-eldef" "minibuf-eldef.el" (0 0 0 0)) +;;; Generated autoloads from minibuf-eldef.el + +(defvar minibuffer-electric-default-mode nil "\ +Non-nil if Minibuffer-Electric-Default mode is enabled. +See the `minibuffer-electric-default-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `minibuffer-electric-default-mode'.") + +(custom-autoload 'minibuffer-electric-default-mode "minibuf-eldef" nil) + +(autoload 'minibuffer-electric-default-mode "minibuf-eldef" "\ +Toggle Minibuffer Electric Default mode. +With a prefix argument ARG, enable Minibuffer Electric Default +mode if ARG is positive, and disable it otherwise. If called +from Lisp, enable the mode if ARG is omitted or nil. + +Minibuffer Electric Default mode is a global minor mode. When +enabled, minibuffer prompts that show a default value only show +the default when it's applicable -- that is, when hitting RET +would yield the default value. If the user modifies the input +such that hitting RET would enter a non-default value, the prompt +is modified to remove the default indication. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "minibuf-eldef" '("minibuf"))) + +;;;*** + +;;;### (autoloads nil "misc" "misc.el" (0 0 0 0)) +;;; Generated autoloads from misc.el + +(autoload 'copy-from-above-command "misc" "\ +Copy characters from previous nonblank line, starting just above point. +Copy ARG characters, but not past the end of that line. +If no argument given, copy the entire rest of the line. +The characters copied are inserted in the buffer before point. + +\(fn &optional ARG)" t nil) + +(autoload 'zap-up-to-char "misc" "\ +Kill up to, but not including ARGth occurrence of CHAR. +Case is ignored if `case-fold-search' is non-nil in the current buffer. +Goes backward if ARG is negative; error if CHAR not found. +Ignores CHAR at point. + +\(fn ARG CHAR)" t nil) + +(autoload 'mark-beginning-of-buffer "misc" "\ +Set mark at the beginning of the buffer. + +\(fn)" t nil) + +(autoload 'mark-end-of-buffer "misc" "\ +Set mark at the end of the buffer. + +\(fn)" t nil) + +(autoload 'upcase-char "misc" "\ +Uppercasify ARG chars starting from point. Point doesn't move. + +\(fn ARG)" t nil) + +(autoload 'forward-to-word "misc" "\ +Move forward until encountering the beginning of a word. +With argument, do this that many times. + +\(fn ARG)" t nil) + +(autoload 'backward-to-word "misc" "\ +Move backward until encountering the end of a word. +With argument, do this that many times. + +\(fn ARG)" t nil) + +(autoload 'butterfly "misc" "\ +Use butterflies to flip the desired bit on the drive platter. +Open hands and let the delicate wings flap once. The disturbance +ripples outward, changing the flow of the eddy currents in the +upper atmosphere. These cause momentary pockets of higher-pressure +air to form, which act as lenses that deflect incoming cosmic rays, +focusing them to strike the drive platter and flip the desired bit. +You can type `M-x butterfly C-M-c' to run it. This is a permuted +variation of `C-x M-c M-butterfly' from url `http://xkcd.com/378/'. + +\(fn)" t nil) + +(autoload 'list-dynamic-libraries "misc" "\ +Display a list of all dynamic libraries known to Emacs. +\(These are the libraries listed in `dynamic-library-alist'.) +If optional argument LOADED-ONLY-P (interactively, prefix arg) +is non-nil, only libraries already loaded are listed. +Optional argument BUFFER specifies a buffer to use, instead of +\"*Dynamic Libraries*\". +The return value is always nil. + +\(fn &optional LOADED-ONLY-P BUFFER)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "misc" '("list-dynamic-libraries--"))) + +;;;*** + +;;;### (autoloads nil "misearch" "misearch.el" (0 0 0 0)) +;;; Generated autoloads from misearch.el + (add-hook 'isearch-mode-hook 'multi-isearch-setup) + +(defvar multi-isearch-next-buffer-function nil "\ +Function to call to get the next buffer to search. + +When this variable is set to a function that returns a buffer, then +after typing another \\[isearch-forward] or \\[isearch-backward] at a failing search, the search goes +to the next buffer in the series and continues searching for the +next occurrence. + +This function should return the next buffer (it doesn't need to switch +to it), or nil if it can't find the next buffer (when it reaches the +end of the search space). + +The first argument of this function is the current buffer where the +search is currently searching. It defines the base buffer relative to +which this function should find the next buffer. When the isearch +direction is backward (when option `isearch-forward' is nil), this function +should return the previous buffer to search. + +If the second argument of this function WRAP is non-nil, then it +should return the first buffer in the series; and for the backward +search, it should return the last buffer in the series.") + +(defvar multi-isearch-next-buffer-current-function nil "\ +The currently active function to get the next buffer to search. +Initialized from `multi-isearch-next-buffer-function' when +Isearch starts.") + +(defvar multi-isearch-current-buffer nil "\ +The buffer where the search is currently searching. +The value is nil when the search still is in the initial buffer.") + +(defvar multi-isearch-buffer-list nil "\ +Sequence of buffers visited by multiple buffers Isearch. +This is nil if Isearch is not currently searching more than one buffer.") + +(defvar multi-isearch-file-list nil "\ +Sequence of files visited by multiple file buffers Isearch.") + +(autoload 'multi-isearch-setup "misearch" "\ +Set up isearch to search multiple buffers. +Intended to be added to `isearch-mode-hook'. + +\(fn)" nil nil) + +(autoload 'multi-isearch-buffers "misearch" "\ +Start multi-buffer Isearch on a list of BUFFERS. +This list can contain live buffers or their names. +Interactively read buffer names to search, one by one, ended with RET. +With a prefix argument, ask for a regexp, and search in buffers +whose names match the specified regexp. + +\(fn BUFFERS)" t nil) + +(autoload 'multi-isearch-buffers-regexp "misearch" "\ +Start multi-buffer regexp Isearch on a list of BUFFERS. +This list can contain live buffers or their names. +Interactively read buffer names to search, one by one, ended with RET. +With a prefix argument, ask for a regexp, and search in buffers +whose names match the specified regexp. + +\(fn BUFFERS)" t nil) + +(autoload 'multi-isearch-files "misearch" "\ +Start multi-buffer Isearch on a list of FILES. +Relative file names in this list are expanded to absolute +file names using the current buffer's value of `default-directory'. +Interactively read file names to search, one by one, ended with RET. +With a prefix argument, ask for a wildcard, and search in file buffers +whose file names match the specified wildcard. + +\(fn FILES)" t nil) + +(autoload 'multi-isearch-files-regexp "misearch" "\ +Start multi-buffer regexp Isearch on a list of FILES. +Relative file names in this list are expanded to absolute +file names using the current buffer's value of `default-directory'. +Interactively read file names to search, one by one, ended with RET. +With a prefix argument, ask for a wildcard, and search in file buffers +whose file names match the specified wildcard. + +\(fn FILES)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "misearch" '("multi-isearch-" "misearch-unload-function"))) + +;;;*** + +;;;### (autoloads nil "mixal-mode" "progmodes/mixal-mode.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from progmodes/mixal-mode.el +(push (purecopy '(mixal-mode 0 1)) package--builtin-versions) + +(autoload 'mixal-mode "mixal-mode" "\ +Major mode for the mixal asm language. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mixal-mode" '("mixal-"))) + +;;;*** + +;;;### (autoloads nil "mm-archive" "gnus/mm-archive.el" (0 0 0 0)) +;;; Generated autoloads from gnus/mm-archive.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mm-archive" '("mm-"))) + +;;;*** + +;;;### (autoloads nil "mm-bodies" "gnus/mm-bodies.el" (0 0 0 0)) +;;; Generated autoloads from gnus/mm-bodies.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mm-bodies" '("mm-"))) + +;;;*** + +;;;### (autoloads nil "mm-decode" "gnus/mm-decode.el" (0 0 0 0)) +;;; Generated autoloads from gnus/mm-decode.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mm-decode" '("mm-"))) + +;;;*** + +;;;### (autoloads nil "mm-encode" "gnus/mm-encode.el" (0 0 0 0)) +;;; Generated autoloads from gnus/mm-encode.el + +(autoload 'mm-default-file-encoding "mm-encode" "\ +Return a default encoding for FILE. + +\(fn FILE)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mm-encode" '("mm-"))) + +;;;*** + +;;;### (autoloads nil "mm-extern" "gnus/mm-extern.el" (0 0 0 0)) +;;; Generated autoloads from gnus/mm-extern.el + +(autoload 'mm-extern-cache-contents "mm-extern" "\ +Put the external-body part of HANDLE into its cache. + +\(fn HANDLE)" nil nil) + +(autoload 'mm-inline-external-body "mm-extern" "\ +Show the external-body part of HANDLE. +This function replaces the buffer of HANDLE with a buffer contains +the entire message. +If NO-DISPLAY is nil, display it. Otherwise, do nothing after replacing. + +\(fn HANDLE &optional NO-DISPLAY)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mm-extern" '("mm-extern-"))) + +;;;*** + +;;;### (autoloads nil "mm-partial" "gnus/mm-partial.el" (0 0 0 0)) +;;; Generated autoloads from gnus/mm-partial.el + +(autoload 'mm-inline-partial "mm-partial" "\ +Show the partial part of HANDLE. +This function replaces the buffer of HANDLE with a buffer contains +the entire message. +If NO-DISPLAY is nil, display it. Otherwise, do nothing after replacing. + +\(fn HANDLE &optional NO-DISPLAY)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mm-partial" '("mm-partial-find-parts"))) + +;;;*** + +;;;### (autoloads nil "mm-url" "gnus/mm-url.el" (0 0 0 0)) +;;; Generated autoloads from gnus/mm-url.el + +(autoload 'mm-url-insert-file-contents "mm-url" "\ +Insert file contents of URL. +If `mm-url-use-external' is non-nil, use `mm-url-program'. + +\(fn URL)" nil nil) + +(autoload 'mm-url-insert-file-contents-external "mm-url" "\ +Insert file contents of URL using `mm-url-program'. + +\(fn URL)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mm-url" '("mm-url-"))) + +;;;*** + +;;;### (autoloads nil "mm-util" "gnus/mm-util.el" (0 0 0 0)) +;;; Generated autoloads from gnus/mm-util.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mm-util" '("mm-"))) + +;;;*** + +;;;### (autoloads nil "mm-uu" "gnus/mm-uu.el" (0 0 0 0)) +;;; Generated autoloads from gnus/mm-uu.el + +(autoload 'mm-uu-dissect "mm-uu" "\ +Dissect the current buffer and return a list of uu handles. +The optional NOHEADER means there's no header in the buffer. +MIME-TYPE specifies a MIME type and parameters, which defaults to the +value of `mm-uu-text-plain-type'. + +\(fn &optional NOHEADER MIME-TYPE)" nil nil) + +(autoload 'mm-uu-dissect-text-parts "mm-uu" "\ +Dissect text parts and put uu handles into HANDLE. +Assume text has been decoded if DECODED is non-nil. + +\(fn HANDLE &optional DECODED)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mm-uu" '("mm-"))) + +;;;*** + +;;;### (autoloads nil "mm-view" "gnus/mm-view.el" (0 0 0 0)) +;;; Generated autoloads from gnus/mm-view.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mm-view" '("mm-"))) + +;;;*** + +;;;### (autoloads nil "mml" "gnus/mml.el" (0 0 0 0)) +;;; Generated autoloads from gnus/mml.el + +(autoload 'mml-to-mime "mml" "\ +Translate the current buffer from MML to MIME. + +\(fn)" nil nil) + +(autoload 'mml-attach-file "mml" "\ +Attach a file to the outgoing MIME message. +The file is not inserted or encoded until you send the message with +`\\[message-send-and-exit]' or `\\[message-send]' in Message mode, +or `\\[mail-send-and-exit]' or `\\[mail-send]' in Mail mode. + +FILE is the name of the file to attach. TYPE is its +content-type, a string of the form \"type/subtype\". DESCRIPTION +is a one-line description of the attachment. The DISPOSITION +specifies how the attachment is intended to be displayed. It can +be either \"inline\" (displayed automatically within the message +body) or \"attachment\" (separate from the body). + +If given a prefix interactively, no prompting will be done for +the TYPE, DESCRIPTION or DISPOSITION values. Instead defaults +will be computed and used. + +\(fn FILE &optional TYPE DESCRIPTION DISPOSITION)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mml" '("mime-to-mml" "mml-"))) + +;;;*** + +;;;### (autoloads nil "mml-sec" "gnus/mml-sec.el" (0 0 0 0)) +;;; Generated autoloads from gnus/mml-sec.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mml-sec" '("mml-"))) + +;;;*** + +;;;### (autoloads nil "mml-smime" "gnus/mml-smime.el" (0 0 0 0)) +;;; Generated autoloads from gnus/mml-smime.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mml-smime" '("mml-smime-"))) + +;;;*** + +;;;### (autoloads nil "mml1991" "gnus/mml1991.el" (0 0 0 0)) +;;; Generated autoloads from gnus/mml1991.el + +(autoload 'mml1991-encrypt "mml1991" "\ + + +\(fn CONT &optional SIGN)" nil nil) + +(autoload 'mml1991-sign "mml1991" "\ + + +\(fn CONT)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mml1991" '("mml1991-"))) + +;;;*** + +;;;### (autoloads nil "mml2015" "gnus/mml2015.el" (0 0 0 0)) +;;; Generated autoloads from gnus/mml2015.el + +(autoload 'mml2015-decrypt "mml2015" "\ + + +\(fn HANDLE CTL)" nil nil) + +(autoload 'mml2015-decrypt-test "mml2015" "\ + + +\(fn HANDLE CTL)" nil nil) + +(autoload 'mml2015-verify "mml2015" "\ + + +\(fn HANDLE CTL)" nil nil) + +(autoload 'mml2015-verify-test "mml2015" "\ + + +\(fn HANDLE CTL)" nil nil) + +(autoload 'mml2015-encrypt "mml2015" "\ + + +\(fn CONT &optional SIGN)" nil nil) + +(autoload 'mml2015-sign "mml2015" "\ + + +\(fn CONT)" nil nil) + +(autoload 'mml2015-self-encrypt "mml2015" "\ + + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mml2015" '("mml2015-"))) + +;;;*** + +;;;### (autoloads nil "mode-local" "cedet/mode-local.el" (0 0 0 0)) +;;; Generated autoloads from cedet/mode-local.el + +(put 'define-overloadable-function 'doc-string-elt 3) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mode-local" '("make-obsolete-overload" "mode-local-" "deactivate-mode-local-bindings" "def" "describe-mode-local-" "xref-mode-local-" "overload-" "fetch-overload" "function-overload-p" "set" "with-mode-local" "activate-mode-local-bindings" "new-mode-local-bindings" "get-mode-local-parent"))) + +;;;*** + +;;;### (autoloads nil "modula2" "progmodes/modula2.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/modula2.el + +(defalias 'modula-2-mode 'm2-mode) + +(autoload 'm2-mode "modula2" "\ +This is a mode intended to support program development in Modula-2. +All control constructs of Modula-2 can be reached by typing C-c +followed by the first character of the construct. +\\<m2-mode-map> + \\[m2-begin] begin \\[m2-case] case + \\[m2-definition] definition \\[m2-else] else + \\[m2-for] for \\[m2-header] header + \\[m2-if] if \\[m2-module] module + \\[m2-loop] loop \\[m2-or] or + \\[m2-procedure] procedure Control-c Control-w with + \\[m2-record] record \\[m2-stdio] stdio + \\[m2-type] type \\[m2-until] until + \\[m2-var] var \\[m2-while] while + \\[m2-export] export \\[m2-import] import + \\[m2-begin-comment] begin-comment \\[m2-end-comment] end-comment + \\[suspend-emacs] suspend Emacs \\[m2-toggle] toggle + \\[m2-compile] compile \\[m2-next-error] next-error + \\[m2-link] link + + `m2-indent' controls the number of spaces for each indentation. + `m2-compile-command' holds the command to compile a Modula-2 program. + `m2-link-command' holds the command to link a Modula-2 program. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "modula2" '("m3-font-lock-keywords" "m2-"))) + +;;;*** + +;;;### (autoloads nil "morse" "play/morse.el" (0 0 0 0)) +;;; Generated autoloads from play/morse.el + +(autoload 'morse-region "morse" "\ +Convert all text in a given region to morse code. + +\(fn BEG END)" t nil) + +(autoload 'unmorse-region "morse" "\ +Convert morse coded text in region to ordinary ASCII text. + +\(fn BEG END)" t nil) + +(autoload 'nato-region "morse" "\ +Convert all text in a given region to NATO phonetic alphabet. + +\(fn BEG END)" t nil) + +(autoload 'denato-region "morse" "\ +Convert NATO phonetic alphabet in region to ordinary ASCII text. + +\(fn BEG END)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "morse" '("nato-alphabet" "morse-code"))) + +;;;*** + +;;;### (autoloads nil "mouse-copy" "mouse-copy.el" (0 0 0 0)) +;;; Generated autoloads from mouse-copy.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mouse-copy" '("mouse-"))) + +;;;*** + +;;;### (autoloads nil "mouse-drag" "mouse-drag.el" (0 0 0 0)) +;;; Generated autoloads from mouse-drag.el + +(autoload 'mouse-drag-throw "mouse-drag" "\ +\"Throw\" the page according to a mouse drag. + +A \"throw\" is scrolling the page at a speed relative to the distance +from the original mouse click to the current mouse location. Try it; +you'll like it. It's easier to observe than to explain. + +If the mouse is clicked and released in the same place of time we +assume that the user didn't want to scroll but wanted to whatever +mouse-2 used to do, so we pass it through. + +Throw scrolling was inspired (but is not identical to) the \"hand\" +option in MacPaint, or the middle button in Tk text widgets. + +If `mouse-throw-with-scroll-bar' is non-nil, then this command scrolls +in the opposite direction. (Different people have different ideas +about which direction is natural. Perhaps it has to do with which +hemisphere you're in.) + +To test this function, evaluate: + (global-set-key [down-mouse-2] \\='mouse-drag-throw) + +\(fn START-EVENT)" t nil) + +(autoload 'mouse-drag-drag "mouse-drag" "\ +\"Drag\" the page according to a mouse drag. + +Drag scrolling moves the page according to the movement of the mouse. +You \"grab\" the character under the mouse and move it around. + +If the mouse is clicked and released in the same place of time we +assume that the user didn't want to scroll but wanted to whatever +mouse-2 used to do, so we pass it through. + +Drag scrolling is identical to the \"hand\" option in MacPaint, or the +middle button in Tk text widgets. + +To test this function, evaluate: + (global-set-key [down-mouse-2] \\='mouse-drag-drag) + +\(fn START-EVENT)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mouse-drag" '("mouse-"))) + +;;;*** + +;;;### (autoloads nil "mpc" "mpc.el" (0 0 0 0)) +;;; Generated autoloads from mpc.el + +(autoload 'mpc "mpc" "\ +Main entry point for MPC. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mpc" '("mpc-" "tag-browser-tagtypes"))) + +;;;*** + +;;;### (autoloads nil "mpuz" "play/mpuz.el" (0 0 0 0)) +;;; Generated autoloads from play/mpuz.el + +(autoload 'mpuz "mpuz" "\ +Multiplication puzzle with GNU Emacs. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mpuz" '("mpuz-"))) + +;;;*** + +;;;### (autoloads nil "msb" "msb.el" (0 0 0 0)) +;;; Generated autoloads from msb.el + +(defvar msb-mode nil "\ +Non-nil if Msb mode is enabled. +See the `msb-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `msb-mode'.") + +(custom-autoload 'msb-mode "msb" nil) + +(autoload 'msb-mode "msb" "\ +Toggle Msb mode. +With a prefix argument ARG, enable Msb mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode +if ARG is omitted or nil. + +This mode overrides the binding(s) of `mouse-buffer-menu' to provide a +different buffer menu using the function `msb'. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "msb" '("mouse-select-buffer" "msb"))) + +;;;*** + +;;;### (autoloads nil "mspools" "mail/mspools.el" (0 0 0 0)) +;;; Generated autoloads from mail/mspools.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mspools" '("mspools-"))) + +;;;*** + +;;;### (autoloads nil "mule-diag" "international/mule-diag.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from international/mule-diag.el + +(autoload 'list-character-sets "mule-diag" "\ +Display a list of all character sets. + +The D column contains the dimension of this character set. The CH +column contains the number of characters in a block of this character +set. The FINAL-BYTE column contains an ISO-2022 <final-byte> to use +in the designation escape sequence for this character set in +ISO-2022-based coding systems. + +With prefix ARG, the output format gets more cryptic, +but still shows the full information. + +\(fn ARG)" t nil) + +(autoload 'read-charset "mule-diag" "\ +Read a character set from the minibuffer, prompting with string PROMPT. +It must be an Emacs character set listed in the variable `charset-list'. + +Optional arguments are DEFAULT-VALUE and INITIAL-INPUT. +DEFAULT-VALUE, if non-nil, is the default value. +INITIAL-INPUT, if non-nil, is a string inserted in the minibuffer initially. +See the documentation of the function `completing-read' for the detailed +meanings of these arguments. + +\(fn PROMPT &optional DEFAULT-VALUE INITIAL-INPUT)" nil nil) + +(autoload 'list-charset-chars "mule-diag" "\ +Display a list of characters in character set CHARSET. + +\(fn CHARSET)" t nil) + +(autoload 'describe-character-set "mule-diag" "\ +Display information about built-in character set CHARSET. + +\(fn CHARSET)" t nil) + +(autoload 'describe-coding-system "mule-diag" "\ +Display information about CODING-SYSTEM. + +\(fn CODING-SYSTEM)" t nil) + +(autoload 'describe-current-coding-system-briefly "mule-diag" "\ +Display coding systems currently used in a brief format in echo area. + +The format is \"F[..],K[..],T[..],P>[..],P<[..], default F[..],P<[..],P<[..]\", +where mnemonics of the following coding systems come in this order +in place of `..': + `buffer-file-coding-system' (of the current buffer) + eol-type of `buffer-file-coding-system' (of the current buffer) + Value returned by `keyboard-coding-system' + eol-type of `keyboard-coding-system' + Value returned by `terminal-coding-system'. + eol-type of `terminal-coding-system' + `process-coding-system' for read (of the current buffer, if any) + eol-type of `process-coding-system' for read (of the current buffer, if any) + `process-coding-system' for write (of the current buffer, if any) + eol-type of `process-coding-system' for write (of the current buffer, if any) + default `buffer-file-coding-system' + eol-type of default `buffer-file-coding-system' + `default-process-coding-system' for read + eol-type of `default-process-coding-system' for read + `default-process-coding-system' for write + eol-type of `default-process-coding-system' + +\(fn)" t nil) + +(autoload 'describe-current-coding-system "mule-diag" "\ +Display coding systems currently used, in detail. + +\(fn)" t nil) + +(autoload 'list-coding-systems "mule-diag" "\ +Display a list of all coding systems. +This shows the mnemonic letter, name, and description of each coding system. + +With prefix ARG, the output format gets more cryptic, +but still contains full information about each coding system. + +\(fn &optional ARG)" t nil) + +(autoload 'list-coding-categories "mule-diag" "\ +Display a list of all coding categories. + +\(fn)" nil nil) + +(autoload 'describe-font "mule-diag" "\ +Display information about a font whose name is FONTNAME. +The font must be already used by Emacs. + +\(fn FONTNAME)" t nil) + +(autoload 'describe-fontset "mule-diag" "\ +Display information about FONTSET. +This shows which font is used for which character(s). + +\(fn FONTSET)" t nil) + +(autoload 'list-fontsets "mule-diag" "\ +Display a list of all fontsets. +This shows the name, size, and style of each fontset. +With prefix arg, also list the fonts contained in each fontset; +see the function `describe-fontset' for the format of the list. + +\(fn ARG)" t nil) + +(autoload 'list-input-methods "mule-diag" "\ +Display information about all input methods. + +\(fn)" t nil) + +(autoload 'mule-diag "mule-diag" "\ +Display diagnosis of the multilingual environment (Mule). + +This shows various information related to the current multilingual +environment, including lists of input methods, coding systems, +character sets, and fontsets (if Emacs is running under a window +system which uses fontsets). + +\(fn)" t nil) + +(autoload 'font-show-log "mule-diag" "\ +Show log of font listing and opening. +Prefix arg LIMIT says how many fonts to show for each listing. +The default is 20. If LIMIT is negative, do not limit the listing. + +\(fn &optional LIMIT)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mule-diag" '("insert-section" "list-" "print-" "describe-font-internal" "charset-history" "non-iso-charset-alist" "sort-listed-character-sets"))) + +;;;*** + +;;;### (autoloads nil "mule-util" "international/mule-util.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from international/mule-util.el + +(autoload 'store-substring "mule-util" "\ +Embed OBJ (string or character) at index IDX of STRING. + +\(fn STRING IDX OBJ)" nil nil) + +(autoload 'truncate-string-to-width "mule-util" "\ +Truncate string STR to end at column END-COLUMN. +The optional 3rd arg START-COLUMN, if non-nil, specifies the starting +column; that means to return the characters occupying columns +START-COLUMN ... END-COLUMN of STR. Both END-COLUMN and START-COLUMN +are specified in terms of character display width in the current +buffer; see also `char-width'. + +The optional 4th arg PADDING, if non-nil, specifies a padding +character (which should have a display width of 1) to add at the end +of the result if STR doesn't reach column END-COLUMN, or if END-COLUMN +comes in the middle of a character in STR. PADDING is also added at +the beginning of the result if column START-COLUMN appears in the +middle of a character in STR. + +If PADDING is nil, no padding is added in these cases, so +the resulting string may be narrower than END-COLUMN. + +If ELLIPSIS is non-nil, it should be a string which will replace the +end of STR (including any padding) if it extends beyond END-COLUMN, +unless the display width of STR is equal to or less than the display +width of ELLIPSIS. If it is non-nil and not a string, then ELLIPSIS +defaults to `truncate-string-ellipsis'. + +\(fn STR END-COLUMN &optional START-COLUMN PADDING ELLIPSIS)" nil nil) + +(defsubst nested-alist-p (obj) "\ +Return t if OBJ is a nested alist. + +Nested alist is a list of the form (ENTRY . BRANCHES), where ENTRY is +any Lisp object, and BRANCHES is a list of cons cells of the form +\(KEY-ELEMENT . NESTED-ALIST). + +You can use a nested alist to store any Lisp object (ENTRY) for a key +sequence KEYSEQ, where KEYSEQ is a sequence of KEY-ELEMENT. KEYSEQ +can be a string, a vector, or a list." (and obj (listp obj) (listp (cdr obj)))) + +(autoload 'set-nested-alist "mule-util" "\ +Set ENTRY for KEYSEQ in a nested alist ALIST. +Optional 4th arg LEN non-nil means the first LEN elements in KEYSEQ + are considered. +Optional 5th argument BRANCHES if non-nil is branches for a keyseq +longer than KEYSEQ. +See the documentation of `nested-alist-p' for more detail. + +\(fn KEYSEQ ENTRY ALIST &optional LEN BRANCHES)" nil nil) + +(autoload 'lookup-nested-alist "mule-util" "\ +Look up key sequence KEYSEQ in nested alist ALIST. Return the definition. +Optional 3rd argument LEN specifies the length of KEYSEQ. +Optional 4th argument START specifies index of the starting key. +The returned value is normally a nested alist of which +car part is the entry for KEYSEQ. +If ALIST is not deep enough for KEYSEQ, return number which is + how many key elements at the front of KEYSEQ it takes + to reach a leaf in ALIST. +Optional 5th argument NIL-FOR-TOO-LONG non-nil means return nil + even if ALIST is not deep enough. + +\(fn KEYSEQ ALIST &optional LEN START NIL-FOR-TOO-LONG)" nil nil) + +(autoload 'coding-system-post-read-conversion "mule-util" "\ +Return the value of CODING-SYSTEM's `post-read-conversion' property. + +\(fn CODING-SYSTEM)" nil nil) + +(autoload 'coding-system-pre-write-conversion "mule-util" "\ +Return the value of CODING-SYSTEM's `pre-write-conversion' property. + +\(fn CODING-SYSTEM)" nil nil) + +(autoload 'coding-system-translation-table-for-decode "mule-util" "\ +Return the value of CODING-SYSTEM's `decode-translation-table' property. + +\(fn CODING-SYSTEM)" nil nil) + +(autoload 'coding-system-translation-table-for-encode "mule-util" "\ +Return the value of CODING-SYSTEM's `encode-translation-table' property. + +\(fn CODING-SYSTEM)" nil nil) + +(autoload 'with-coding-priority "mule-util" "\ +Execute BODY like `progn' with CODING-SYSTEMS at the front of priority list. +CODING-SYSTEMS is a list of coding systems. See `set-coding-system-priority'. +This affects the implicit sorting of lists of coding systems returned by +operations such as `find-coding-systems-region'. + +\(fn CODING-SYSTEMS &rest BODY)" nil t) +(put 'with-coding-priority 'lisp-indent-function 1) + +(autoload 'detect-coding-with-priority "mule-util" "\ +Detect a coding system of the text between FROM and TO with PRIORITY-LIST. +PRIORITY-LIST is an alist of coding categories vs the corresponding +coding systems ordered by priority. + +\(fn FROM TO PRIORITY-LIST)" nil t) + +(make-obsolete 'detect-coding-with-priority 'with-coding-priority '"23.1") + +(autoload 'detect-coding-with-language-environment "mule-util" "\ +Detect a coding system for the text between FROM and TO with LANG-ENV. +The detection takes into account the coding system priorities for the +language environment LANG-ENV. + +\(fn FROM TO LANG-ENV)" nil nil) + +(autoload 'char-displayable-p "mule-util" "\ +Return non-nil if we should be able to display CHAR. +On a multi-font display, the test is only whether there is an +appropriate font from the selected frame's fontset to display +CHAR's charset in general. Since fonts may be specified on a +per-character basis, this may not be accurate. + +\(fn CHAR)" nil nil) + +(autoload 'filepos-to-bufferpos "mule-util" "\ +Try to return the buffer position corresponding to a particular file position. +The file position is given as a (0-based) BYTE count. +The function presumes the file is encoded with CODING-SYSTEM, which defaults +to `buffer-file-coding-system'. +QUALITY can be: + `approximate', in which case we may cut some corners to avoid + excessive work. + `exact', in which case we may end up re-(en/de)coding a large + part of the file/buffer, this can be expensive and slow. + nil, in which case we may return nil rather than an approximation. + +\(fn BYTE &optional QUALITY CODING-SYSTEM)" nil nil) + +(autoload 'bufferpos-to-filepos "mule-util" "\ +Try to return the file byte corresponding to a particular buffer POSITION. +Value is the file position given as a (0-based) byte count. +The function presumes the file is encoded with CODING-SYSTEM, which defaults +to `buffer-file-coding-system'. +QUALITY can be: + `approximate', in which case we may cut some corners to avoid + excessive work. + `exact', in which case we may end up re-(en/de)coding a large + part of the file/buffer, this can be expensive and slow. + nil, in which case we may return nil rather than an approximation. + +\(fn POSITION &optional QUALITY CODING-SYSTEM)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mule-util" '("filepos-to-bufferpos--dos" "truncate-string-ellipsis"))) + +;;;*** + +;;;### (autoloads nil "mwheel" "mwheel.el" (0 0 0 0)) +;;; Generated autoloads from mwheel.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mwheel" '("mwheel-" "mouse-wheel-"))) + +;;;*** + +;;;### (autoloads nil "net-utils" "net/net-utils.el" (0 0 0 0)) +;;; Generated autoloads from net/net-utils.el + +(autoload 'ifconfig "net-utils" "\ +Run `ifconfig-program' and display diagnostic output. + +\(fn)" t nil) + +(autoload 'iwconfig "net-utils" "\ +Run `iwconfig-program' and display diagnostic output. + +\(fn)" t nil) + +(autoload 'netstat "net-utils" "\ +Run `netstat-program' and display diagnostic output. + +\(fn)" t nil) + +(autoload 'arp "net-utils" "\ +Run `arp-program' and display diagnostic output. + +\(fn)" t nil) + +(autoload 'route "net-utils" "\ +Run `route-program' and display diagnostic output. + +\(fn)" t nil) + +(autoload 'traceroute "net-utils" "\ +Run `traceroute-program' for TARGET. + +\(fn TARGET)" t nil) + +(autoload 'ping "net-utils" "\ +Ping HOST. +If your system's ping continues until interrupted, you can try setting +`ping-program-options'. + +\(fn HOST)" t nil) + +(autoload 'nslookup-host "net-utils" "\ +Look up the DNS information for HOST (name or IP address). +Optional argument NAME-SERVER says which server to use for +DNS resolution. +Interactively, prompt for NAME-SERVER if invoked with prefix argument. + +This command uses `nslookup-program' for looking up the DNS information. + +\(fn HOST &optional NAME-SERVER)" t nil) + +(autoload 'nslookup "net-utils" "\ +Run `nslookup-program'. + +\(fn)" t nil) + +(autoload 'dns-lookup-host "net-utils" "\ +Look up the DNS information for HOST (name or IP address). +Optional argument NAME-SERVER says which server to use for +DNS resolution. +Interactively, prompt for NAME-SERVER if invoked with prefix argument. + +This command uses `dns-lookup-program' for looking up the DNS information. + +\(fn HOST &optional NAME-SERVER)" t nil) + +(autoload 'run-dig "net-utils" "\ +Look up DNS information for HOST (name or IP address). +Optional argument NAME-SERVER says which server to use for +DNS resolution. +Interactively, prompt for NAME-SERVER if invoked with prefix argument. + +This command uses `dig-program' for looking up the DNS information. + +\(fn HOST &optional NAME-SERVER)" t nil) + +(autoload 'ftp "net-utils" "\ +Run `ftp-program' to connect to HOST. + +\(fn HOST)" t nil) + +(autoload 'finger "net-utils" "\ +Finger USER on HOST. +This command uses `finger-X.500-host-regexps' +and `network-connection-service-alist', which see. + +\(fn USER HOST)" t nil) + +(autoload 'whois "net-utils" "\ +Send SEARCH-STRING to server defined by the `whois-server-name' variable. +If `whois-guess-server' is non-nil, then try to deduce the correct server +from SEARCH-STRING. With argument, prompt for whois server. +The port is deduced from `network-connection-service-alist'. + +\(fn ARG SEARCH-STRING)" t nil) + +(autoload 'whois-reverse-lookup "net-utils" "\ + + +\(fn)" t nil) + +(autoload 'network-connection-to-service "net-utils" "\ +Open a network connection to SERVICE on HOST. +This command uses `network-connection-service-alist', which see. + +\(fn HOST SERVICE)" t nil) + +(autoload 'network-connection "net-utils" "\ +Open a network connection to HOST on PORT. + +\(fn HOST PORT)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "net-utils" '("nslookup-" "net" "whois-" "ftp-" "finger-X.500-host-regexps" "route-program" "run-network-program" "smbclient" "ifconfig-program" "iwconfig-program" "ipconfig" "dig-program" "dns-lookup-program" "arp-program" "ping-program" "traceroute-program"))) + +;;;*** + +;;;### (autoloads nil "netrc" "net/netrc.el" (0 0 0 0)) +;;; Generated autoloads from net/netrc.el + +(autoload 'netrc-credentials "netrc" "\ +Return a user name/password pair. +Port specifications will be prioritized in the order they are +listed in the PORTS list. + +\(fn MACHINE &rest PORTS)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "netrc" '("netrc-"))) + +;;;*** + +;;;### (autoloads nil "network-stream" "net/network-stream.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from net/network-stream.el + +(autoload 'open-network-stream "network-stream" "\ +Open a TCP connection to HOST, optionally with encryption. +Normally, return a network process object; with a non-nil +:return-list parameter, return a list instead (see below). +Input and output work as for subprocesses; `delete-process' +closes it. + +NAME is the name for the process. It is modified if necessary to + make it unique. +BUFFER is a buffer or buffer name to associate with the process. + Process output goes at end of that buffer. BUFFER may be nil, + meaning that the process is not associated with any buffer. +HOST is the name or IP address of the host to connect to. +SERVICE is the name of the service desired, or an integer or + integer string specifying a port number to connect to. + +The remaining PARAMETERS should be a sequence of keywords and +values: + +:type specifies the connection type, one of the following: + nil or `network' + -- Begin with an ordinary network connection, and if + the parameters :success and :capability-command + are also supplied, try to upgrade to an encrypted + connection via STARTTLS. Even if that + fails (e.g. if HOST does not support TLS), retain + an unencrypted connection. + `plain' -- An ordinary, unencrypted network connection. + `starttls' -- Begin with an ordinary connection, and try + upgrading via STARTTLS. If that fails for any + reason, drop the connection; in that case the + returned object is a killed process. + `tls' -- A TLS connection. + `ssl' -- Equivalent to `tls'. + `shell' -- A shell connection. + +:return-list specifies this function's return value. + If omitted or nil, return a process object. A non-nil means to + return (PROC . PROPS), where PROC is a process object and PROPS + is a plist of connection properties, with these keywords: + :greeting -- the greeting returned by HOST (a string), or nil. + :capabilities -- a string representing HOST's capabilities, + or nil if none could be found. + :type -- the resulting connection type; `plain' (unencrypted) + or `tls' (TLS-encrypted). + +:end-of-command specifies a regexp matching the end of a command. + +:end-of-capability specifies a regexp matching the end of the + response to the command specified for :capability-command. + It defaults to the regexp specified for :end-of-command. + +:success specifies a regexp matching a message indicating a + successful STARTTLS negotiation. For instance, the default + should be \"^3\" for an NNTP connection. + +:capability-command specifies a command used to query the HOST + for its capabilities. For instance, for IMAP this should be + \"1 CAPABILITY\\r\\n\". + +:starttls-function specifies a function for handling STARTTLS. + This function should take one parameter, the response to the + capability command, and should return the command to switch on + STARTTLS if the server supports STARTTLS, and nil otherwise. + +:always-query-capabilities says whether to query the server for + capabilities, even if we're doing a `plain' network connection. + +:client-certificate should either be a list where the first + element is the certificate key file name, and the second + element is the certificate file name itself, or t, which + means that `auth-source' will be queried for the key and the + certificate. This parameter will only be used when doing TLS + or STARTTLS connections. + +:use-starttls-if-possible is a boolean that says to do opportunistic +STARTTLS upgrades even if Emacs doesn't have built-in TLS functionality. + +:warn-unless-encrypted is a boolean which, if :return-list is +non-nil, is used warn the user if the connection isn't encrypted. + +:nogreeting is a boolean that can be used to inhibit waiting for +a greeting from the server. + +:nowait, if non-nil, says the connection should be made +asynchronously, if possible. + +:shell-command is a format-spec string that can be used if :type +is `shell'. It has two specs, %s for host and %p for port +number. Example: \"ssh gateway nc %s %p\". + +:tls-parameters is a list that should be supplied if you're +opening a TLS connection. The first element is the TLS +type (either `gnutls-x509pki' or `gnutls-anon'), and the +remaining elements should be a keyword list accepted by +gnutls-boot (as returned by `gnutls-boot-parameters'). + +\(fn NAME BUFFER HOST SERVICE &rest PARAMETERS)" nil nil) + +(defalias 'open-protocol-stream 'open-network-stream) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "network-stream" '("network-stream-"))) + +;;;*** + +;;;### (autoloads nil "newst-backend" "net/newst-backend.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from net/newst-backend.el + +(autoload 'newsticker-running-p "newst-backend" "\ +Check whether newsticker is running. +Return t if newsticker is running, nil otherwise. Newsticker is +considered to be running if the newsticker timer list is not empty. + +\(fn)" nil nil) + +(autoload 'newsticker-start "newst-backend" "\ +Start the newsticker. +Start the timers for display and retrieval. If the newsticker, i.e. the +timers, are running already a warning message is printed unless +DO-NOT-COMPLAIN-IF-RUNNING is not nil. +Run `newsticker-start-hook' if newsticker was not running already. + +\(fn &optional DO-NOT-COMPLAIN-IF-RUNNING)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "newst-backend" '("newsticker-"))) + +;;;*** + +;;;### (autoloads nil "newst-plainview" "net/newst-plainview.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from net/newst-plainview.el + +(autoload 'newsticker-plainview "newst-plainview" "\ +Start newsticker plainview. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "newst-plainview" '("newsticker-"))) + +;;;*** + +;;;### (autoloads nil "newst-reader" "net/newst-reader.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from net/newst-reader.el + +(autoload 'newsticker-show-news "newst-reader" "\ +Start reading news. You may want to bind this to a key. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "newst-reader" '("newsticker-"))) + +;;;*** + +;;;### (autoloads nil "newst-ticker" "net/newst-ticker.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from net/newst-ticker.el + +(autoload 'newsticker-ticker-running-p "newst-ticker" "\ +Check whether newsticker's actual ticker is running. +Return t if ticker is running, nil otherwise. Newsticker is +considered to be running if the newsticker timer list is not +empty. + +\(fn)" nil nil) + +(autoload 'newsticker-start-ticker "newst-ticker" "\ +Start newsticker's ticker (but not the news retrieval). +Start display timer for the actual ticker if wanted and not +running already. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "newst-ticker" '("newsticker-"))) + +;;;*** + +;;;### (autoloads nil "newst-treeview" "net/newst-treeview.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from net/newst-treeview.el + +(autoload 'newsticker-treeview "newst-treeview" "\ +Start newsticker treeview. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "newst-treeview" '("newsticker-"))) + +;;;*** + +;;;### (autoloads nil "newsticker" "net/newsticker.el" (0 0 0 0)) +;;; Generated autoloads from net/newsticker.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "newsticker" '("newsticker-version"))) + +;;;*** + +;;;### (autoloads nil "nnagent" "gnus/nnagent.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnagent.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnagent" '("nnagent-"))) + +;;;*** + +;;;### (autoloads nil "nnbabyl" "gnus/nnbabyl.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnbabyl.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnbabyl" '("nnbabyl-"))) + +;;;*** + +;;;### (autoloads nil "nndiary" "gnus/nndiary.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nndiary.el + +(autoload 'nndiary-generate-nov-databases "nndiary" "\ +Generate NOV databases in all nndiary directories. + +\(fn &optional SERVER)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nndiary" '("nndiary-"))) + +;;;*** + +;;;### (autoloads nil "nndir" "gnus/nndir.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nndir.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nndir" '("nndir-"))) + +;;;*** + +;;;### (autoloads nil "nndoc" "gnus/nndoc.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nndoc.el + +(autoload 'nndoc-add-type "nndoc" "\ +Add document DEFINITION to the list of nndoc document definitions. +If POSITION is nil or `last', the definition will be added +as the last checked definition, if t or `first', add as the +first definition, and if any other symbol, add after that +symbol in the alist. + +\(fn DEFINITION &optional POSITION)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nndoc" '("nndoc-"))) + +;;;*** + +;;;### (autoloads nil "nndraft" "gnus/nndraft.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nndraft.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nndraft" '("nndraft-"))) + +;;;*** + +;;;### (autoloads nil "nneething" "gnus/nneething.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nneething.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nneething" '("nneething-"))) + +;;;*** + +;;;### (autoloads nil "nnfolder" "gnus/nnfolder.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnfolder.el + +(autoload 'nnfolder-generate-active-file "nnfolder" "\ +Look for mbox folders in the nnfolder directory and make them into groups. +This command does not work if you use short group names. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnfolder" '("nnfolder-"))) + +;;;*** + +;;;### (autoloads nil "nngateway" "gnus/nngateway.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nngateway.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nngateway" '("nngateway-"))) + +;;;*** + +;;;### (autoloads nil "nnheader" "gnus/nnheader.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnheader.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnheader" '("nntp-" "nnheader-" "mail-header-" "make-" "gnus-"))) + +;;;*** + +;;;### (autoloads nil "nnimap" "gnus/nnimap.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnimap.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnimap" '("nnimap"))) + +;;;*** + +;;;### (autoloads nil "nnir" "gnus/nnir.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnir.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnir" '("nnir-" "gnus-"))) + +;;;*** + +;;;### (autoloads nil "nnmail" "gnus/nnmail.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnmail.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnmail" '("nnmail-"))) + +;;;*** + +;;;### (autoloads nil "nnmaildir" "gnus/nnmaildir.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnmaildir.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnmaildir" '("nnmaildir-"))) + +;;;*** + +;;;### (autoloads nil "nnmairix" "gnus/nnmairix.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnmairix.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnmairix" '("nnmairix-"))) + +;;;*** + +;;;### (autoloads nil "nnmbox" "gnus/nnmbox.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnmbox.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnmbox" '("nnmbox-"))) + +;;;*** + +;;;### (autoloads nil "nnmh" "gnus/nnmh.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnmh.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnmh" '("nnmh-"))) + +;;;*** + +;;;### (autoloads nil "nnml" "gnus/nnml.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnml.el + +(autoload 'nnml-generate-nov-databases "nnml" "\ +Generate NOV databases in all nnml directories. + +\(fn &optional SERVER)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnml" '("nnml-"))) + +;;;*** + +;;;### (autoloads nil "nnnil" "gnus/nnnil.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnnil.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnnil" '("nnnil-"))) + +;;;*** + +;;;### (autoloads nil "nnoo" "gnus/nnoo.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnoo.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnoo" '("nnoo-" "defvoo" "deffoo"))) + +;;;*** + +;;;### (autoloads nil "nnregistry" "gnus/nnregistry.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnregistry.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnregistry" '("nnregistry-"))) + +;;;*** + +;;;### (autoloads nil "nnrss" "gnus/nnrss.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnrss.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnrss" '("nnrss-"))) + +;;;*** + +;;;### (autoloads nil "nnspool" "gnus/nnspool.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnspool.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnspool" '("news-inews-program" "nnspool-"))) + +;;;*** + +;;;### (autoloads nil "nntp" "gnus/nntp.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nntp.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nntp" '("nntp-"))) + +;;;*** + +;;;### (autoloads nil "nnvirtual" "gnus/nnvirtual.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnvirtual.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnvirtual" '("nnvirtual-"))) + +;;;*** + +;;;### (autoloads nil "nnweb" "gnus/nnweb.el" (0 0 0 0)) +;;; Generated autoloads from gnus/nnweb.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nnweb" '("nnweb-"))) + +;;;*** + +;;;### (autoloads nil "notifications" "notifications.el" (0 0 0 0)) +;;; Generated autoloads from notifications.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "notifications" '("notifications-"))) + +;;;*** + +;;;### (autoloads nil "novice" "novice.el" (0 0 0 0)) +;;; Generated autoloads from novice.el + +(define-obsolete-variable-alias 'disabled-command-hook 'disabled-command-function "22.1") + +(defvar disabled-command-function 'disabled-command-function "\ +Function to call to handle disabled commands. +If nil, the feature is disabled, i.e., all commands work normally.") + +(autoload 'disabled-command-function "novice" "\ + + +\(fn &optional CMD KEYS)" nil nil) + +(autoload 'enable-command "novice" "\ +Allow COMMAND to be executed without special confirmation from now on. +COMMAND must be a symbol. +This command alters the user's .emacs file so that this will apply +to future sessions. + +\(fn COMMAND)" t nil) + +(autoload 'disable-command "novice" "\ +Require special confirmation to execute COMMAND from now on. +COMMAND must be a symbol. +This command alters your init file so that this choice applies to +future sessions. + +\(fn COMMAND)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "novice" '("en/disable-command"))) + +;;;*** + +;;;### (autoloads nil "nroff-mode" "textmodes/nroff-mode.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from textmodes/nroff-mode.el + +(autoload 'nroff-mode "nroff-mode" "\ +Major mode for editing text intended for nroff to format. +\\{nroff-mode-map} +Turning on Nroff mode runs `text-mode-hook', then `nroff-mode-hook'. +Also, try `nroff-electric-mode', for automatically inserting +closing requests for requests that are used in matched pairs. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nroff-mode" '("nroff-"))) + +;;;*** + +;;;### (autoloads nil "nsm" "net/nsm.el" (0 0 0 0)) +;;; Generated autoloads from net/nsm.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nsm" '("network-security-level" "nsm-"))) + +;;;*** + +;;;### (autoloads nil "ntlm" "net/ntlm.el" (0 0 0 0)) +;;; Generated autoloads from net/ntlm.el +(push (purecopy '(ntlm 2 1 0)) package--builtin-versions) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ntlm" '("ntlm-"))) + +;;;*** + +;;;### (autoloads nil "nxml-enc" "nxml/nxml-enc.el" (0 0 0 0)) +;;; Generated autoloads from nxml/nxml-enc.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nxml-enc" '("nxml-"))) + +;;;*** + +;;;### (autoloads nil "nxml-maint" "nxml/nxml-maint.el" (0 0 0 0)) +;;; Generated autoloads from nxml/nxml-maint.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nxml-maint" '("nxml-insert-target-repertoire-glyph-set"))) + +;;;*** + +;;;### (autoloads nil "nxml-mode" "nxml/nxml-mode.el" (0 0 0 0)) +;;; Generated autoloads from nxml/nxml-mode.el + +(autoload 'nxml-mode "nxml-mode" "\ +Major mode for editing XML. + +\\[nxml-finish-element] finishes the current element by inserting an end-tag. +C-c C-i closes a start-tag with `>' and then inserts a balancing end-tag +leaving point between the start-tag and end-tag. +\\[nxml-balanced-close-start-tag-block] is similar but for block rather than inline elements: +the start-tag, point, and end-tag are all left on separate lines. +If `nxml-slash-auto-complete-flag' is non-nil, then inserting a `</' +automatically inserts the rest of the end-tag. + +\\[completion-at-point] performs completion on the symbol preceding point. + +\\[nxml-dynamic-markup-word] uses the contents of the current buffer +to choose a tag to put around the word preceding point. + +Sections of the document can be displayed in outline form. The +variable `nxml-section-element-name-regexp' controls when an element +is recognized as a section. The same key sequences that change +visibility in outline mode are used except that they start with C-c C-o +instead of C-c. + +Validation is provided by the related minor-mode `rng-validate-mode'. +This also makes completion schema- and context- sensitive. Element +names, attribute names, attribute values and namespace URIs can all be +completed. By default, `rng-validate-mode' is automatically enabled. +You can toggle it using \\[rng-validate-mode] or change the default by +customizing `rng-nxml-auto-validate-flag'. + +\\[indent-for-tab-command] indents the current line appropriately. +This can be customized using the variable `nxml-child-indent' +and the variable `nxml-attribute-indent'. + +\\[nxml-insert-named-char] inserts a character reference using +the character's name (by default, the Unicode name). +\\[universal-argument] \\[nxml-insert-named-char] inserts the character directly. + +The Emacs commands that normally operate on balanced expressions will +operate on XML markup items. Thus \\[forward-sexp] will move forward +across one markup item; \\[backward-sexp] will move backward across +one markup item; \\[kill-sexp] will kill the following markup item; +\\[mark-sexp] will mark the following markup item. By default, each +tag each treated as a single markup item; to make the complete element +be treated as a single markup item, set the variable +`nxml-sexp-element-flag' to t. For more details, see the function +`nxml-forward-balanced-item'. + +\\[nxml-backward-up-element] and \\[nxml-down-element] move up and down the element structure. + +Many aspects this mode can be customized using +\\[customize-group] nxml RET. + +\(fn)" t nil) +(defalias 'xml-mode 'nxml-mode) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nxml-mode" '("nxml-"))) + +;;;*** + +;;;### (autoloads nil "nxml-ns" "nxml/nxml-ns.el" (0 0 0 0)) +;;; Generated autoloads from nxml/nxml-ns.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nxml-ns" '("nxml-ns-"))) + +;;;*** + +;;;### (autoloads nil "nxml-outln" "nxml/nxml-outln.el" (0 0 0 0)) +;;; Generated autoloads from nxml/nxml-outln.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nxml-outln" '("nxml-"))) + +;;;*** + +;;;### (autoloads nil "nxml-parse" "nxml/nxml-parse.el" (0 0 0 0)) +;;; Generated autoloads from nxml/nxml-parse.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nxml-parse" '("nxml-"))) + +;;;*** + +;;;### (autoloads nil "nxml-rap" "nxml/nxml-rap.el" (0 0 0 0)) +;;; Generated autoloads from nxml/nxml-rap.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nxml-rap" '("nxml-"))) + +;;;*** + +;;;### (autoloads nil "nxml-util" "nxml/nxml-util.el" (0 0 0 0)) +;;; Generated autoloads from nxml/nxml-util.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nxml-util" '("nxml-"))) + +;;;*** + +;;;### (autoloads nil "ob-C" "org/ob-C.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-C.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-C" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-R" "org/ob-R.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-R.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-R" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-asymptote" "org/ob-asymptote.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from org/ob-asymptote.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-asymptote" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-awk" "org/ob-awk.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-awk.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-awk" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-calc" "org/ob-calc.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-calc.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-calc" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-clojure" "org/ob-clojure.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-clojure.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-clojure" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-comint" "org/ob-comint.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-comint.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-comint" '("org-babel-comint-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ob-core" "org/ob-core.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/ob-core.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-core" '("org-"))) + +;;;*** + +;;;### (autoloads nil "ob-css" "org/ob-css.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-css.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-css" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-ditaa" "org/ob-ditaa.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-ditaa.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-ditaa" '("org-"))) + +;;;*** + +;;;### (autoloads nil "ob-dot" "org/ob-dot.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-dot.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-dot" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-emacs-lisp" "org/ob-emacs-lisp.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from org/ob-emacs-lisp.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-emacs-lisp" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-eval" "org/ob-eval.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-eval.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-eval" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-exp" "org/ob-exp.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-exp.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-exp" '("org-"))) + +;;;*** + +;;;### (autoloads nil "ob-fortran" "org/ob-fortran.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-fortran.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-fortran" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-gnuplot" "org/ob-gnuplot.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-gnuplot.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-gnuplot" '("org-babel-" "*org-babel-gnuplot-"))) + +;;;*** + +;;;### (autoloads nil "ob-haskell" "org/ob-haskell.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-haskell.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-haskell" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-io" "org/ob-io.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-io.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-io" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-java" "org/ob-java.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-java.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-java" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-js" "org/ob-js.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-js.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-js" '("org-babel-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ob-keys" "org/ob-keys.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/ob-keys.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-keys" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-latex" "org/ob-latex.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-latex.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-latex" '("org-babel-" "convert-pdf"))) + +;;;*** + +;;;### (autoloads nil "ob-ledger" "org/ob-ledger.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-ledger.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-ledger" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-lilypond" "org/ob-lilypond.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-lilypond.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-lilypond" '("org-babel-" "lilypond-mode"))) + +;;;*** + +;;;### (autoloads nil "ob-lisp" "org/ob-lisp.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-lisp.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-lisp" '("org-babel-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ob-lob" "org/ob-lob.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/ob-lob.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-lob" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-makefile" "org/ob-makefile.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-makefile.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-makefile" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-maxima" "org/ob-maxima.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-maxima.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-maxima" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-mscgen" "org/ob-mscgen.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-mscgen.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-mscgen" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-ocaml" "org/ob-ocaml.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-ocaml.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-ocaml" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-octave" "org/ob-octave.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-octave.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-octave" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-org" "org/ob-org.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-org.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-org" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-perl" "org/ob-perl.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-perl.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-perl" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-picolisp" "org/ob-picolisp.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-picolisp.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-picolisp" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-plantuml" "org/ob-plantuml.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-plantuml.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-plantuml" '("org-"))) + +;;;*** + +;;;### (autoloads nil "ob-python" "org/ob-python.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-python.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-python" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-ref" "org/ob-ref.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-ref.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-ref" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-ruby" "org/ob-ruby.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-ruby.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-ruby" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-sass" "org/ob-sass.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-sass.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-sass" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-scala" "org/ob-scala.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-scala.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-scala" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-scheme" "org/ob-scheme.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-scheme.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-scheme" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-screen" "org/ob-screen.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-screen.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-screen" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-sh" "org/ob-sh.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-sh.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-sh" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-shen" "org/ob-shen.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-shen.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-shen" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-sql" "org/ob-sql.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-sql.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-sql" '("org-babel-" "dbstring-mysql"))) + +;;;*** + +;;;### (autoloads nil "ob-sqlite" "org/ob-sqlite.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-sqlite.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-sqlite" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "ob-table" "org/ob-table.el" (0 0 0 0)) +;;; Generated autoloads from org/ob-table.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-table" '("org-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ob-tangle" "org/ob-tangle.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/ob-tangle.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ob-tangle" '("org-babel-"))) + +;;;*** + +;;;### (autoloads nil "octave" "progmodes/octave.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/octave.el + +(autoload 'octave-mode "octave" "\ +Major mode for editing Octave code. + +Octave is a high-level language, primarily intended for numerical +computations. It provides a convenient command line interface +for solving linear and nonlinear problems numerically. Function +definitions can also be stored in files and used in batch mode. + +See Info node `(octave-mode) Using Octave Mode' for more details. + +Key bindings: +\\{octave-mode-map} + +\(fn)" t nil) + +(autoload 'inferior-octave "octave" "\ +Run an inferior Octave process, I/O via `inferior-octave-buffer'. +This buffer is put in Inferior Octave mode. See `inferior-octave-mode'. + +Unless ARG is non-nil, switches to this buffer. + +The elements of the list `inferior-octave-startup-args' are sent as +command line arguments to the inferior Octave process on startup. + +Additional commands to be executed on startup can be provided either in +the file specified by `inferior-octave-startup-file' or by the default +startup file, `~/.emacs-octave'. + +\(fn &optional ARG)" t nil) + +(defalias 'run-octave 'inferior-octave) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "octave" '("octave-" "inferior-octave-"))) + +;;;*** + +;;;### (autoloads nil "ogonek" "international/ogonek.el" (0 0 0 0)) +;;; Generated autoloads from international/ogonek.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ogonek" '("ogonek-"))) + +;;;*** + +;;;### (autoloads nil "opascal" "progmodes/opascal.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/opascal.el + +(define-obsolete-function-alias 'delphi-mode 'opascal-mode "24.4") + +(autoload 'opascal-mode "opascal" "\ +Major mode for editing OPascal code.\\<opascal-mode-map> +\\[opascal-find-unit] - Search for a OPascal source file. +\\[opascal-fill-comment] - Fill the current comment. +\\[opascal-new-comment-line] - If in a // comment, do a new comment line. + +\\[indent-region] also works for indenting a whole region. + +Customization: + + `opascal-indent-level' (default 3) + Indentation of OPascal statements with respect to containing block. + `opascal-compound-block-indent' (default 0) + Extra indentation for blocks in compound statements. + `opascal-case-label-indent' (default 0) + Extra indentation for case statement labels. + `opascal-search-path' (default .) + Directories to search when finding external units. + `opascal-verbose' (default nil) + If true then OPascal token processing progress is reported to the user. + +Coloring: + + `opascal-keyword-face' (default `font-lock-keyword-face') + Face used to color OPascal keywords. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "opascal" '("opascal-"))) + +;;;*** + +;;;### (autoloads nil "org" "org/org.el" (0 0 0 0)) +;;; Generated autoloads from org/org.el + +(autoload 'org-babel-do-load-languages "org" "\ +Load the languages defined in `org-babel-load-languages'. + +\(fn SYM VALUE)" nil nil) + +(autoload 'org-babel-load-file "org" "\ +Load Emacs Lisp source code blocks in the Org-mode FILE. +This function exports the source code using `org-babel-tangle' +and then loads the resulting file using `load-file'. With prefix +arg (noninteractively: 2nd arg) COMPILE the tangled Emacs Lisp +file to byte-code before it is loaded. + +\(fn FILE &optional COMPILE)" t nil) + +(autoload 'org-version "org" "\ +Show the org-mode version in the echo area. +With prefix argument HERE, insert it at point. +When FULL is non-nil, use a verbose version string. +When MESSAGE is non-nil, display a message with the version. + +\(fn &optional HERE FULL MESSAGE)" t nil) + +(autoload 'turn-on-orgtbl "org" "\ +Unconditionally turn on `orgtbl-mode'. + +\(fn)" nil nil) + +(autoload 'org-clock-persistence-insinuate "org" "\ +Set up hooks for clock persistence. + +\(fn)" nil nil) + +(autoload 'org-mode "org" "\ +Outline-based notes management and organizer, alias +\"Carsten's outline-mode for keeping track of everything.\" + +Org-mode develops organizational tasks around a NOTES file which +contains information about projects as plain text. Org-mode is +implemented on top of outline-mode, which is ideal to keep the content +of large files well structured. It supports ToDo items, deadlines and +time stamps, which magically appear in the diary listing of the Emacs +calendar. Tables are easily created with a built-in table editor. +Plain text URL-like links connect to websites, emails (VM), Usenet +messages (Gnus), BBDB entries, and any files related to the project. +For printing and sharing of notes, an Org-mode file (or a part of it) +can be exported as a structured ASCII or HTML file. + +The following commands are available: + +\\{org-mode-map} + +\(fn)" t nil) + +(autoload 'org-cycle "org" "\ +TAB-action and visibility cycling for Org-mode. + +This is the command invoked in Org-mode by the TAB key. Its main purpose +is outline visibility cycling, but it also invokes other actions +in special contexts. + +- When this function is called with a prefix argument, rotate the entire + buffer through 3 states (global cycling) + 1. OVERVIEW: Show only top-level headlines. + 2. CONTENTS: Show all headlines of all levels, but no body text. + 3. SHOW ALL: Show everything. + When called with two `C-u C-u' prefixes, switch to the startup visibility, + determined by the variable `org-startup-folded', and by any VISIBILITY + properties in the buffer. + When called with three `C-u C-u C-u' prefixed, show the entire buffer, + including any drawers. + +- When inside a table, re-align the table and move to the next field. + +- When point is at the beginning of a headline, rotate the subtree started + by this line through 3 different states (local cycling) + 1. FOLDED: Only the main headline is shown. + 2. CHILDREN: The main headline and the direct children are shown. + From this state, you can move to one of the children + and zoom in further. + 3. SUBTREE: Show the entire subtree, including body text. + If there is no subtree, switch directly from CHILDREN to FOLDED. + +- When point is at the beginning of an empty headline and the variable + `org-cycle-level-after-item/entry-creation' is set, cycle the level + of the headline by demoting and promoting it to likely levels. This + speeds up creation document structure by pressing TAB once or several + times right after creating a new headline. + +- When there is a numeric prefix, go up to a heading with level ARG, do + a `show-subtree' and return to the previous cursor position. If ARG + is negative, go up that many levels. + +- When point is not at the beginning of a headline, execute the global + binding for TAB, which is re-indenting the line. See the option + `org-cycle-emulate-tab' for details. + +- Special case: if point is at the beginning of the buffer and there is + no headline in line 1, this function will act as if called with prefix arg + (C-u TAB, same as S-TAB) also when called without prefix arg. + But only if also the variable `org-cycle-global-at-bob' is t. + +\(fn &optional ARG)" t nil) + +(autoload 'org-global-cycle "org" "\ +Cycle the global visibility. For details see `org-cycle'. +With \\[universal-argument] prefix arg, switch to startup visibility. +With a numeric prefix, show all headlines up to that level. + +\(fn &optional ARG)" t nil) +(put 'orgstruct-heading-prefix-regexp 'safe-local-variable 'stringp) + +(autoload 'orgstruct-mode "org" "\ +Toggle the minor mode `orgstruct-mode'. +This mode is for using Org-mode structure commands in other +modes. The following keys behave as if Org-mode were active, if +the cursor is on a headline, or on a plain list item (both as +defined by Org-mode). + +\(fn &optional ARG)" t nil) + +(autoload 'turn-on-orgstruct "org" "\ +Unconditionally turn on `orgstruct-mode'. + +\(fn)" nil nil) + +(autoload 'turn-on-orgstruct++ "org" "\ +Unconditionally turn on `orgstruct++-mode'. + +\(fn)" nil nil) + +(autoload 'org-run-like-in-org-mode "org" "\ +Run a command, pretending that the current buffer is in Org-mode. +This will temporarily bind local variables that are typically bound in +Org-mode to the values they have in Org-mode, and then interactively +call CMD. + +\(fn CMD)" nil nil) + +(autoload 'org-store-link "org" "\ +\\<org-mode-map>Store an org-link to the current location. +This link is added to `org-stored-links' and can later be inserted +into an org-buffer with \\[org-insert-link]. + +For some link types, a prefix arg is interpreted. +For links to Usenet articles, arg negates `org-gnus-prefer-web-links'. +For file links, arg negates `org-context-in-file-links'. + +A double prefix arg force skipping storing functions that are not +part of Org's core. + +A triple prefix arg force storing a link for each line in the +active region. + +\(fn ARG)" t nil) + +(autoload 'org-insert-link-global "org" "\ +Insert a link like Org-mode does. +This command can be called in any mode to insert a link in Org-mode syntax. + +\(fn)" t nil) + +(autoload 'org-open-at-point-global "org" "\ +Follow a link like Org-mode does. +This command can be called in any mode to follow a link that has +Org-mode syntax. + +\(fn)" t nil) + +(autoload 'org-open-link-from-string "org" "\ +Open a link in the string S, as if it was in Org-mode. + +\(fn S &optional ARG REFERENCE-BUFFER)" t nil) + +(autoload 'org-switchb "org" "\ +Switch between Org buffers. +With one prefix argument, restrict available buffers to files. +With two prefix arguments, restrict available buffers to agenda files. + +Defaults to `iswitchb' for buffer name completion. +Set `org-completion-use-ido' to make it use ido instead. + +\(fn &optional ARG)" t nil) + +(defalias 'org-ido-switchb 'org-switchb) + +(defalias 'org-iswitchb 'org-switchb) + +(autoload 'org-cycle-agenda-files "org" "\ +Cycle through the files in `org-agenda-files'. +If the current buffer visits an agenda file, find the next one in the list. +If the current buffer does not, find the first agenda file. + +\(fn)" t nil) + +(autoload 'org-submit-bug-report "org" "\ +Submit a bug report on Org-mode via mail. + +Don't hesitate to report any problems or inaccurate documentation. + +If you don't have setup sending mail from (X)Emacs, please copy the +output buffer into your mail program, as it gives us important +information about your Org-mode version and configuration. + +\(fn)" t nil) + +(autoload 'org-reload "org" "\ +Reload all org lisp files. +With prefix arg UNCOMPILED, load the uncompiled versions. + +\(fn &optional UNCOMPILED)" t nil) + +(autoload 'org-customize "org" "\ +Call the customize function with org as argument. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org" '("org" "turn-on-org-cdlatex"))) + +;;;*** + +;;;### (autoloads nil "org-agenda" "org/org-agenda.el" (0 0 0 0)) +;;; Generated autoloads from org/org-agenda.el + +(autoload 'org-toggle-sticky-agenda "org-agenda" "\ +Toggle `org-agenda-sticky'. + +\(fn &optional ARG)" t nil) + +(autoload 'org-agenda "org-agenda" "\ +Dispatch agenda commands to collect entries to the agenda buffer. +Prompts for a command to execute. Any prefix arg will be passed +on to the selected command. The default selections are: + +a Call `org-agenda-list' to display the agenda for current day or week. +t Call `org-todo-list' to display the global todo list. +T Call `org-todo-list' to display the global todo list, select only + entries with a specific TODO keyword (the user gets a prompt). +m Call `org-tags-view' to display headlines with tags matching + a condition (the user is prompted for the condition). +M Like `m', but select only TODO entries, no ordinary headlines. +L Create a timeline for the current buffer. +e Export views to associated files. +s Search entries for keywords. +S Search entries for keywords, only with TODO keywords. +/ Multi occur across all agenda files and also files listed + in `org-agenda-text-search-extra-files'. +< Restrict agenda commands to buffer, subtree, or region. + Press several times to get the desired effect. +> Remove a previous restriction. +# List \"stuck\" projects. +! Configure what \"stuck\" means. +C Configure custom agenda commands. + +More commands can be added by configuring the variable +`org-agenda-custom-commands'. In particular, specific tags and TODO keyword +searches can be pre-defined in this way. + +If the current buffer is in Org-mode and visiting a file, you can also +first press `<' once to indicate that the agenda should be temporarily +\(until the next use of \\[org-agenda]) restricted to the current file. +Pressing `<' twice means to restrict to the current subtree or region +\(if active). + +\(fn &optional ARG ORG-KEYS RESTRICTION)" t nil) + +(autoload 'org-batch-agenda "org-agenda" "\ +Run an agenda command in batch mode and send the result to STDOUT. +If CMD-KEY is a string of length 1, it is used as a key in +`org-agenda-custom-commands' and triggers this command. If it is a +longer string it is used as a tags/todo match string. +Parameters are alternating variable names and values that will be bound +before running the agenda command. + +\(fn CMD-KEY &rest PARAMETERS)" nil t) + +(autoload 'org-batch-agenda-csv "org-agenda" "\ +Run an agenda command in batch mode and send the result to STDOUT. +If CMD-KEY is a string of length 1, it is used as a key in +`org-agenda-custom-commands' and triggers this command. If it is a +longer string it is used as a tags/todo match string. +Parameters are alternating variable names and values that will be bound +before running the agenda command. + +The output gives a line for each selected agenda item. Each +item is a list of comma-separated values, like this: + +category,head,type,todo,tags,date,time,extra,priority-l,priority-n + +category The category of the item +head The headline, without TODO kwd, TAGS and PRIORITY +type The type of the agenda entry, can be + todo selected in TODO match + tagsmatch selected in tags match + diary imported from diary + deadline a deadline on given date + scheduled scheduled on given date + timestamp entry has timestamp on given date + closed entry was closed on given date + upcoming-deadline warning about deadline + past-scheduled forwarded scheduled item + block entry has date block including g. date +todo The todo keyword, if any +tags All tags including inherited ones, separated by colons +date The relevant date, like 2007-2-14 +time The time, like 15:00-16:50 +extra Sting with extra planning info +priority-l The priority letter if any was given +priority-n The computed numerical priority +agenda-day The day in the agenda where this is listed + +\(fn CMD-KEY &rest PARAMETERS)" nil t) + +(autoload 'org-store-agenda-views "org-agenda" "\ +Store agenda views. + +\(fn &rest PARAMETERS)" t nil) + +(autoload 'org-batch-store-agenda-views "org-agenda" "\ +Run all custom agenda commands that have a file argument. + +\(fn &rest PARAMETERS)" nil t) + +(autoload 'org-agenda-list "org-agenda" "\ +Produce a daily/weekly view from all files in variable `org-agenda-files'. +The view will be for the current day or week, but from the overview buffer +you will be able to go to other days/weeks. + +With a numeric prefix argument in an interactive call, the agenda will +span ARG days. Lisp programs should instead specify SPAN to change +the number of days. SPAN defaults to `org-agenda-span'. + +START-DAY defaults to TODAY, or to the most recent match for the weekday +given in `org-agenda-start-on-weekday'. + +When WITH-HOUR is non-nil, only include scheduled and deadline +items if they have an hour specification like [h]h:mm. + +\(fn &optional ARG START-DAY SPAN WITH-HOUR)" t nil) + +(autoload 'org-search-view "org-agenda" "\ +Show all entries that contain a phrase or words or regular expressions. + +With optional prefix argument TODO-ONLY, only consider entries that are +TODO entries. The argument STRING can be used to pass a default search +string into this function. If EDIT-AT is non-nil, it means that the +user should get a chance to edit this string, with cursor at position +EDIT-AT. + +The search string can be viewed either as a phrase that should be found as +is, or it can be broken into a number of snippets, each of which must match +in a Boolean way to select an entry. The default depends on the variable +`org-agenda-search-view-always-boolean'. +Even if this is turned off (the default) you can always switch to +Boolean search dynamically by preceding the first word with \"+\" or \"-\". + +The default is a direct search of the whole phrase, where each space in +the search string can expand to an arbitrary amount of whitespace, +including newlines. + +If using a Boolean search, the search string is split on whitespace and +each snippet is searched separately, with logical AND to select an entry. +Words prefixed with a minus must *not* occur in the entry. Words without +a prefix or prefixed with a plus must occur in the entry. Matching is +case-insensitive. Words are enclosed by word delimiters (i.e. they must +match whole words, not parts of a word) if +`org-agenda-search-view-force-full-words' is set (default is nil). + +Boolean search snippets enclosed by curly braces are interpreted as +regular expressions that must or (when preceded with \"-\") must not +match in the entry. Snippets enclosed into double quotes will be taken +as a whole, to include whitespace. + +- If the search string starts with an asterisk, search only in headlines. +- If (possibly after the leading star) the search string starts with an + exclamation mark, this also means to look at TODO entries only, an effect + that can also be achieved with a prefix argument. +- If (possibly after star and exclamation mark) the search string starts + with a colon, this will mean that the (non-regexp) snippets of the + Boolean search must match as full words. + +This command searches the agenda files, and in addition the files listed +in `org-agenda-text-search-extra-files'. + +\(fn &optional TODO-ONLY STRING EDIT-AT)" t nil) + +(autoload 'org-todo-list "org-agenda" "\ +Show all (not done) TODO entries from all agenda file in a single list. +The prefix arg can be used to select a specific TODO keyword and limit +the list to these. When using \\[universal-argument], you will be prompted +for a keyword. A numeric prefix directly selects the Nth keyword in +`org-todo-keywords-1'. + +\(fn &optional ARG)" t nil) + +(autoload 'org-tags-view "org-agenda" "\ +Show all headlines for all `org-agenda-files' matching a TAGS criterion. +The prefix arg TODO-ONLY limits the search to TODO entries. + +\(fn &optional TODO-ONLY MATCH)" t nil) + +(autoload 'org-agenda-list-stuck-projects "org-agenda" "\ +Create agenda view for projects that are stuck. +Stuck projects are project that have no next actions. For the definitions +of what a project is and how to check if it stuck, customize the variable +`org-stuck-projects'. + +\(fn &rest IGNORE)" t nil) + +(autoload 'org-diary "org-agenda" "\ +Return diary information from org files. +This function can be used in a \"sexp\" diary entry in the Emacs calendar. +It accesses org files and extracts information from those files to be +listed in the diary. The function accepts arguments specifying what +items should be listed. For a list of arguments allowed here, see the +variable `org-agenda-entry-types'. + +The call in the diary file should look like this: + + &%%(org-diary) ~/path/to/some/orgfile.org + +Use a separate line for each org file to check. Or, if you omit the file name, +all files listed in `org-agenda-files' will be checked automatically: + + &%%(org-diary) + +If you don't give any arguments (as in the example above), the default value +of `org-agenda-entry-types' is used: (:deadline :scheduled :timestamp :sexp). +So the example above may also be written as + + &%%(org-diary :deadline :timestamp :sexp :scheduled) + +The function expects the lisp variables `entry' and `date' to be provided +by the caller, because this is how the calendar works. Don't use this +function from a program - use `org-agenda-get-day-entries' instead. + +\(fn &rest ARGS)" nil nil) + +(autoload 'org-agenda-check-for-timestamp-as-reason-to-ignore-todo-item "org-agenda" "\ +Do we have a reason to ignore this TODO entry because it has a time stamp? + +\(fn &optional END)" nil nil) + +(autoload 'org-agenda-set-restriction-lock "org-agenda" "\ +Set restriction lock for agenda, to current subtree or file. +Restriction will be the file if TYPE is `file', or if TYPE is the +universal prefix `(4)', or if the cursor is before the first headline +in the file. Otherwise, restriction will be to the current subtree. + +\(fn &optional TYPE)" t nil) + +(autoload 'org-calendar-goto-agenda "org-agenda" "\ +Compute the Org-mode agenda for the calendar date displayed at the cursor. +This is a command that has to be installed in `calendar-mode-map'. + +\(fn)" t nil) + +(autoload 'org-agenda-to-appt "org-agenda" "\ +Activate appointments found in `org-agenda-files'. +With a \\[universal-argument] prefix, refresh the list of +appointments. + +If FILTER is t, interactively prompt the user for a regular +expression, and filter out entries that don't match it. + +If FILTER is a string, use this string as a regular expression +for filtering entries out. + +If FILTER is a function, filter out entries against which +calling the function returns nil. This function takes one +argument: an entry from `org-agenda-get-day-entries'. + +FILTER can also be an alist with the car of each cell being +either `headline' or `category'. For example: + + ((headline \"IMPORTANT\") + (category \"Work\")) + +will only add headlines containing IMPORTANT or headlines +belonging to the \"Work\" category. + +ARGS are symbols indicating what kind of entries to consider. +By default `org-agenda-to-appt' will use :deadline*, :scheduled* +\(i.e., deadlines and scheduled items with a hh:mm specification) +and :timestamp entries. See the docstring of `org-diary' for +details and examples. + +If an entry has a APPT_WARNTIME property, its value will be used +to override `appt-message-warning-time'. + +\(fn &optional REFRESH FILTER &rest ARGS)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-agenda" '("org-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "org-archive" +;;;;;; "org/org-archive.el" (0 0 0 0)) +;;; Generated autoloads from org/org-archive.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-archive" '("org-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "org-attach" "org/org-attach.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/org-attach.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-attach" '("org-attach-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "org-bbdb" "org/org-bbdb.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/org-bbdb.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-bbdb" '("org-bbdb-"))) + +;;;*** + +;;;### (autoloads nil "org-bibtex" "org/org-bibtex.el" (0 0 0 0)) +;;; Generated autoloads from org/org-bibtex.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-bibtex" '("org-"))) + +;;;*** + +;;;### (autoloads nil "org-capture" "org/org-capture.el" (0 0 0 0)) +;;; Generated autoloads from org/org-capture.el + +(autoload 'org-capture-string "org-capture" "\ +Capture STRING with the template selected by KEYS. + +\(fn STRING &optional KEYS)" t nil) + +(autoload 'org-capture "org-capture" "\ +Capture something. +\\<org-capture-mode-map> +This will let you select a template from `org-capture-templates', and then +file the newly captured information. The text is immediately inserted +at the target location, and an indirect buffer is shown where you can +edit it. Pressing \\[org-capture-finalize] brings you back to the previous state +of Emacs, so that you can continue your work. + +When called interactively with a \\[universal-argument] prefix argument GOTO, don't capture +anything, just go to the file/headline where the selected template +stores its notes. With a double prefix argument \\[universal-argument] \\[universal-argument], go to the last note +stored. + +When called with a `C-0' (zero) prefix, insert a template at point. + +ELisp programs can set KEYS to a string associated with a template +in `org-capture-templates'. In this case, interactive selection +will be bypassed. + +If `org-capture-use-agenda-date' is non-nil, capturing from the +agenda will use the date at point as the default date. Then, a +`C-1' prefix will tell the capture process to use the HH:MM time +of the day at point (if any) or the current HH:MM time. + +\(fn &optional GOTO KEYS)" t nil) + +(autoload 'org-capture-import-remember-templates "org-capture" "\ +Set `org-capture-templates' to be similar to `org-remember-templates'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-capture" '("org-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "org-clock" "org/org-clock.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/org-clock.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-clock" '("org-"))) + +;;;*** + +;;;### (autoloads nil "org-colview" "org/org-colview.el" (0 0 0 0)) +;;; Generated autoloads from org/org-colview.el + +(autoload 'org-columns-remove-overlays "org-colview" "\ +Remove all currently active column overlays. + +\(fn)" t nil) + +(autoload 'org-columns-get-format-and-top-level "org-colview" "\ + + +\(fn)" nil nil) + +(autoload 'org-columns "org-colview" "\ +Turn on column view on an org-mode file. +When COLUMNS-FMT-STRING is non-nil, use it as the column format. + +\(fn &optional COLUMNS-FMT-STRING)" t nil) + +(autoload 'org-columns-compute "org-colview" "\ +Sum the values of property PROPERTY hierarchically, for the entire buffer. + +\(fn PROPERTY)" t nil) + +(autoload 'org-columns-number-to-string "org-colview" "\ +Convert a computed column number to a string value, according to FMT. + +\(fn N FMT &optional PRINTF)" nil nil) + +(autoload 'org-dblock-write:columnview "org-colview" "\ +Write the column view table. +PARAMS is a property list of parameters: + +:width enforce same column widths with <N> specifiers. +:id the :ID: property of the entry where the columns view + should be built. When the symbol `local', call locally. + When `global' call column view with the cursor at the beginning + of the buffer (usually this means that the whole buffer switches + to column view). When \"file:path/to/file.org\", invoke column + view at the start of that file. Otherwise, the ID is located + using `org-id-find'. +:hlines When t, insert a hline before each item. When a number, insert + a hline before each level <= that number. +:vlines When t, make each column a colgroup to enforce vertical lines. +:maxlevel When set to a number, don't capture headlines below this level. +:skip-empty-rows + When t, skip rows where all specifiers other than ITEM are empty. +:format When non-nil, specify the column view format to use. + +\(fn PARAMS)" nil nil) + +(autoload 'org-insert-columns-dblock "org-colview" "\ +Create a dynamic block capturing a column view table. + +\(fn)" t nil) + +(autoload 'org-agenda-columns "org-colview" "\ +Turn on or update column view in the agenda. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-colview" '("org-"))) + +;;;*** + +;;;### (autoloads nil "org-compat" "org/org-compat.el" (0 0 0 0)) +;;; Generated autoloads from org/org-compat.el + +(autoload 'org-check-version "org-compat" "\ +Try very hard to provide sensible version strings. + +\(fn)" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-compat" '("org-"))) + +;;;*** + +;;;### (autoloads nil "org-crypt" "org/org-crypt.el" (0 0 0 0)) +;;; Generated autoloads from org/org-crypt.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-crypt" '("org-"))) + +;;;*** + +;;;### (autoloads nil "org-ctags" "org/org-ctags.el" (0 0 0 0)) +;;; Generated autoloads from org/org-ctags.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-ctags" '("org-ctags-" "y-or-n-minibuffer"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "org-datetree" +;;;;;; "org/org-datetree.el" (0 0 0 0)) +;;; Generated autoloads from org/org-datetree.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-datetree" '("org-datetree-"))) + +;;;*** + +;;;### (autoloads nil "org-docview" "org/org-docview.el" (0 0 0 0)) +;;; Generated autoloads from org/org-docview.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-docview" '("org-docview-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "org-element" +;;;;;; "org/org-element.el" (0 0 0 0)) +;;; Generated autoloads from org/org-element.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-element" '("org-element-"))) + +;;;*** + +;;;### (autoloads nil "org-entities" "org/org-entities.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from org/org-entities.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-entities" '("replace-amp" "org-entit"))) + +;;;*** + +;;;### (autoloads nil "org-eshell" "org/org-eshell.el" (0 0 0 0)) +;;; Generated autoloads from org/org-eshell.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-eshell" '("org-eshell-"))) + +;;;*** + +;;;### (autoloads nil "org-faces" "org/org-faces.el" (0 0 0 0)) +;;; Generated autoloads from org/org-faces.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-faces" '("org-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "org-feed" "org/org-feed.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/org-feed.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-feed" '("org-feed-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "org-footnote" +;;;;;; "org/org-footnote.el" (0 0 0 0)) +;;; Generated autoloads from org/org-footnote.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-footnote" '("org-footnote-"))) + +;;;*** + +;;;### (autoloads nil "org-gnus" "org/org-gnus.el" (0 0 0 0)) +;;; Generated autoloads from org/org-gnus.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-gnus" '("org-gnus-"))) + +;;;*** + +;;;### (autoloads nil "org-habit" "org/org-habit.el" (0 0 0 0)) +;;; Generated autoloads from org/org-habit.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-habit" '("org-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "org-id" "org/org-id.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/org-id.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-id" '("org-id-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "org-indent" "org/org-indent.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/org-indent.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-indent" '("org-"))) + +;;;*** + +;;;### (autoloads nil "org-info" "org/org-info.el" (0 0 0 0)) +;;; Generated autoloads from org/org-info.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-info" '("org-info-"))) + +;;;*** + +;;;### (autoloads nil "org-inlinetask" "org/org-inlinetask.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from org/org-inlinetask.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-inlinetask" '("org-inlinetask-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "org-irc" "org/org-irc.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/org-irc.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-irc" '("org-irc-"))) + +;;;*** + +;;;### (autoloads nil "org-list" "org/org-list.el" (0 0 0 0)) +;;; Generated autoloads from org/org-list.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-list" '("org-"))) + +;;;*** + +;;;### (autoloads nil "org-macro" "org/org-macro.el" (0 0 0 0)) +;;; Generated autoloads from org/org-macro.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-macro" '("org-macro-"))) + +;;;*** + +;;;### (autoloads nil "org-macs" "org/org-macs.el" (0 0 0 0)) +;;; Generated autoloads from org/org-macs.el + +(autoload 'org-load-noerror-mustsuffix "org-macs" "\ +Load FILE with optional arguments NOERROR and MUSTSUFFIX. Drop the MUSTSUFFIX argument for XEmacs, which doesn't recognize it. + +\(fn FILE)" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-macs" '("org-"))) + +;;;*** + +;;;### (autoloads nil "org-mhe" "org/org-mhe.el" (0 0 0 0)) +;;; Generated autoloads from org/org-mhe.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-mhe" '("org-mhe-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "org-mobile" "org/org-mobile.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/org-mobile.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-mobile" '("org-mobile-"))) + +;;;*** + +;;;### (autoloads nil "org-mouse" "org/org-mouse.el" (0 0 0 0)) +;;; Generated autoloads from org/org-mouse.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-mouse" '("org-mouse-"))) + +;;;*** + +;;;### (autoloads nil "org-pcomplete" "org/org-pcomplete.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from org/org-pcomplete.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-pcomplete" '("org-" "pcomplete/org-mode/"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "org-plot" "org/org-plot.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/org-plot.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-plot" '("org-plot"))) + +;;;*** + +;;;### (autoloads nil "org-protocol" "org/org-protocol.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from org/org-protocol.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-protocol" '("org-protocol-"))) + +;;;*** + +;;;### (autoloads nil "org-rmail" "org/org-rmail.el" (0 0 0 0)) +;;; Generated autoloads from org/org-rmail.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-rmail" '("org-rmail-"))) + +;;;*** + +;;;### (autoloads nil "org-src" "org/org-src.el" (0 0 0 0)) +;;; Generated autoloads from org/org-src.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-src" '("org-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "org-table" "org/org-table.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/org-table.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-table" '("org" "*orgtbl-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "org-timer" "org/org-timer.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/org-timer.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-timer" '("org-timer-"))) + +;;;*** + +;;;### (autoloads nil "org-version" "org/org-version.el" (0 0 0 0)) +;;; Generated autoloads from org/org-version.el + +(autoload 'org-release "org-version" "\ +The release version of org-mode. + Inserted by installing org-mode or when a release is made. + +\(fn)" nil nil) + +(autoload 'org-git-version "org-version" "\ +The Git version of org-mode. + Inserted by installing org-mode or when a release is made. + +\(fn)" nil nil) + +;;;*** + +;;;### (autoloads nil "org-w3m" "org/org-w3m.el" (0 0 0 0)) +;;; Generated autoloads from org/org-w3m.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-w3m" '("org-w3m-"))) + +;;;*** + +;;;### (autoloads nil "outline" "outline.el" (0 0 0 0)) +;;; Generated autoloads from outline.el +(put 'outline-regexp 'safe-local-variable 'stringp) +(put 'outline-heading-end-regexp 'safe-local-variable 'stringp) + +(autoload 'outline-mode "outline" "\ +Set major mode for editing outlines with selective display. +Headings are lines which start with asterisks: one for major headings, +two for subheadings, etc. Lines not starting with asterisks are body lines. + +Body text or subheadings under a heading can be made temporarily +invisible, or visible again. Invisible lines are attached to the end +of the heading, so they move with it, if the line is killed and yanked +back. A heading with text hidden under it is marked with an ellipsis (...). + +\\{outline-mode-map} +The commands `outline-hide-subtree', `outline-show-subtree', +`outline-show-children', `outline-hide-entry', +`outline-show-entry', `outline-hide-leaves', and `outline-show-branches' +are used when point is on a heading line. + +The variable `outline-regexp' can be changed to control what is a heading. +A line is a heading if `outline-regexp' matches something at the +beginning of the line. The longer the match, the deeper the level. + +Turning on outline mode calls the value of `text-mode-hook' and then of +`outline-mode-hook', if they are non-nil. + +\(fn)" t nil) + +(autoload 'outline-minor-mode "outline" "\ +Toggle Outline minor mode. +With a prefix argument ARG, enable Outline minor mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +See the command `outline-mode' for more information on this mode. + +\(fn &optional ARG)" t nil) +(put 'outline-level 'risky-local-variable t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "outline" '("outline-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ox" "org/ox.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/ox.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ox" '("org-export-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ox-ascii" "org/ox-ascii.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/ox-ascii.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ox-ascii" '("org-ascii-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ox-beamer" "org/ox-beamer.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/ox-beamer.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ox-beamer" '("org-beamer-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ox-html" "org/ox-html.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/ox-html.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ox-html" '("org-html-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ox-icalendar" +;;;;;; "org/ox-icalendar.el" (0 0 0 0)) +;;; Generated autoloads from org/ox-icalendar.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ox-icalendar" '("org-icalendar-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ox-latex" "org/ox-latex.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/ox-latex.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ox-latex" '("org-latex-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ox-man" "org/ox-man.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/ox-man.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ox-man" '("org-man-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ox-md" "org/ox-md.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/ox-md.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ox-md" '("org-md-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ox-odt" "org/ox-odt.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/ox-odt.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ox-odt" '("org-odt-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ox-org" "org/ox-org.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/ox-org.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ox-org" '("org-org-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ox-publish" "org/ox-publish.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/ox-publish.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ox-publish" '("org-publish-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ox-texinfo" "org/ox-texinfo.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from org/ox-texinfo.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ox-texinfo" '("org-texinfo-"))) + +;;;*** + +;;;### (autoloads nil "package" "emacs-lisp/package.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/package.el +(push (purecopy '(package 1 1 0)) package--builtin-versions) + +(defvar package-enable-at-startup t "\ +Whether to activate installed packages when Emacs starts. +If non-nil, packages are activated after reading the init file +and before `after-init-hook'. Activation is not done if +`user-init-file' is nil (e.g. Emacs was started with \"-q\"). + +Even if the value is nil, you can type \\[package-initialize] to +activate the package system at any time.") + +(custom-autoload 'package-enable-at-startup "package" t) + +(autoload 'package-initialize "package" "\ +Load Emacs Lisp packages, and activate them. +The variable `package-load-list' controls which packages to load. +If optional arg NO-ACTIVATE is non-nil, don't activate packages. +If `user-init-file' does not mention `(package-initialize)', add +it to the file. +If called as part of loading `user-init-file', set +`package-enable-at-startup' to nil, to prevent accidentally +loading packages twice. +It is not necessary to adjust `load-path' or `require' the +individual packages after calling `package-initialize' -- this is +taken care of by `package-initialize'. + +\(fn &optional NO-ACTIVATE)" t nil) + +(autoload 'package-import-keyring "package" "\ +Import keys from FILE. + +\(fn &optional FILE)" t nil) + +(autoload 'package-refresh-contents "package" "\ +Download descriptions of all configured ELPA packages. +For each archive configured in the variable `package-archives', +inform Emacs about the latest versions of all packages it offers, +and make them available for download. +Optional argument ASYNC specifies whether to perform the +downloads in the background. + +\(fn &optional ASYNC)" t nil) + +(autoload 'package-install "package" "\ +Install the package PKG. +PKG can be a `package-desc' or a symbol naming one of the available packages +in an archive in `package-archives'. Interactively, prompt for its name. + +If called interactively or if DONT-SELECT nil, add PKG to +`package-selected-packages'. + +If PKG is a `package-desc' and it is already installed, don't try +to install it but still mark it as selected. + +\(fn PKG &optional DONT-SELECT)" t nil) + +(autoload 'package-install-from-buffer "package" "\ +Install a package from the current buffer. +The current buffer is assumed to be a single .el or .tar file or +a directory. These must follow the packaging guidelines (see +info node `(elisp)Packaging'). + +Specially, if current buffer is a directory, the -pkg.el +description file is not mandatory, in which case the information +is derived from the main .el file in the directory. + +Downloads and installs required packages as needed. + +\(fn)" t nil) + +(autoload 'package-install-file "package" "\ +Install a package from a file. +The file can either be a tar file, an Emacs Lisp file, or a +directory. + +\(fn FILE)" t nil) + +(autoload 'package-install-selected-packages "package" "\ +Ensure packages in `package-selected-packages' are installed. +If some packages are not installed propose to install them. + +\(fn)" t nil) + +(autoload 'package-reinstall "package" "\ +Reinstall package PKG. +PKG should be either a symbol, the package name, or a `package-desc' +object. + +\(fn PKG)" t nil) + +(autoload 'package-autoremove "package" "\ +Remove packages that are no more needed. + +Packages that are no more needed by other packages in +`package-selected-packages' and their dependencies +will be deleted. + +\(fn)" t nil) + +(autoload 'describe-package "package" "\ +Display the full documentation of PACKAGE (a symbol). + +\(fn PACKAGE)" t nil) + +(autoload 'list-packages "package" "\ +Display a list of packages. +This first fetches the updated list of packages before +displaying, unless a prefix argument NO-FETCH is specified. +The list is displayed in a buffer named `*Packages*'. + +\(fn &optional NO-FETCH)" t nil) + +(defalias 'package-list-packages 'list-packages) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "package" '("package-" "define-package" "describe-package-1" "bad-signature"))) + +;;;*** + +;;;### (autoloads nil "package-x" "emacs-lisp/package-x.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from emacs-lisp/package-x.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "package-x" '("package-"))) + +;;;*** + +;;;### (autoloads nil "page-ext" "textmodes/page-ext.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/page-ext.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "page-ext" '("previous-page" "pages-" "sort-pages-" "original-page-delimiter" "add-new-page" "next-page" "ctl-x-ctl-p-map"))) + +;;;*** + +;;;### (autoloads nil "paren" "paren.el" (0 0 0 0)) +;;; Generated autoloads from paren.el + +(defvar show-paren-mode nil "\ +Non-nil if Show-Paren mode is enabled. +See the `show-paren-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `show-paren-mode'.") + +(custom-autoload 'show-paren-mode "paren" nil) + +(autoload 'show-paren-mode "paren" "\ +Toggle visualization of matching parens (Show Paren mode). +With a prefix argument ARG, enable Show Paren mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Show Paren mode is a global minor mode. When enabled, any +matching parenthesis is highlighted in `show-paren-style' after +`show-paren-delay' seconds of Emacs idle time. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "paren" '("show-paren-"))) + +;;;*** + +;;;### (autoloads nil "parse-time" "calendar/parse-time.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from calendar/parse-time.el +(put 'parse-time-rules 'risky-local-variable t) + +(autoload 'parse-time-string "parse-time" "\ +Parse the time-string STRING into (SEC MIN HOUR DAY MON YEAR DOW DST TZ). +STRING should be on something resembling an RFC2822 string, a la +\"Fri, 25 Mar 2016 16:24:56 +0100\", but this function is +somewhat liberal in what format it accepts, and will attempt to +return a \"likely\" value even for somewhat malformed strings. +The values returned are identical to those of `decode-time', but +any values that are unknown are returned as nil. + +\(fn STRING)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "parse-time" '("parse-"))) + +;;;*** + +;;;### (autoloads nil "pascal" "progmodes/pascal.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/pascal.el + +(autoload 'pascal-mode "pascal" "\ +Major mode for editing Pascal code.\\<pascal-mode-map> +TAB indents for Pascal code. Delete converts tabs to spaces as it moves back. + +\\[completion-at-point] completes the word around current point with respect to position in code +\\[completion-help-at-point] shows all possible completions at this point. + +Other useful functions are: + +\\[pascal-mark-defun] - Mark function. +\\[pascal-insert-block] - insert begin ... end; +\\[pascal-star-comment] - insert (* ... *) +\\[pascal-comment-area] - Put marked area in a comment, fixing nested comments. +\\[pascal-uncomment-area] - Uncomment an area commented with \\[pascal-comment-area]. +\\[pascal-beg-of-defun] - Move to beginning of current function. +\\[pascal-end-of-defun] - Move to end of current function. +\\[pascal-goto-defun] - Goto function prompted for in the minibuffer. +\\[pascal-outline-mode] - Enter `pascal-outline-mode'. + +Variables controlling indentation/edit style: + + `pascal-indent-level' (default 3) + Indentation of Pascal statements with respect to containing block. + `pascal-case-indent' (default 2) + Indentation for case statements. + `pascal-auto-newline' (default nil) + Non-nil means automatically newline after semicolons and the punctuation + mark after an end. + `pascal-indent-nested-functions' (default t) + Non-nil means nested functions are indented. + `pascal-tab-always-indent' (default t) + Non-nil means TAB in Pascal mode should always reindent the current line, + regardless of where in the line point is when the TAB command is used. + `pascal-auto-endcomments' (default t) + Non-nil means a comment { ... } is set after the ends which ends cases and + functions. The name of the function or case will be set between the braces. + `pascal-auto-lineup' (default t) + List of contexts where auto lineup of :'s or ='s should be done. + +See also the user variables `pascal-type-keywords', `pascal-start-keywords' and +`pascal-separator-keywords'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pascal" '("pascal-" "electric-pascal-"))) + +;;;*** + +;;;### (autoloads nil "password-cache" "password-cache.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from password-cache.el + +(defvar password-cache t "\ +Whether to cache passwords.") + +(custom-autoload 'password-cache "password-cache" t) + +(defvar password-cache-expiry 16 "\ +How many seconds passwords are cached, or nil to disable expiring. +Whether passwords are cached at all is controlled by `password-cache'.") + +(custom-autoload 'password-cache-expiry "password-cache" t) + +(autoload 'password-in-cache-p "password-cache" "\ +Check if KEY is in the cache. + +\(fn KEY)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "password-cache" '("password-"))) + +;;;*** + +;;;### (autoloads nil "pcase" "emacs-lisp/pcase.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/pcase.el + +(autoload 'pcase "pcase" "\ +Evaluate EXP and attempt to match it against structural patterns. +CASES is a list of elements of the form (PATTERN CODE...). + +A structural PATTERN describes a template that identifies a class +of values. For example, the pattern \\=`(,foo ,bar) matches any +two element list, binding its elements to symbols named `foo' and +`bar' -- in much the same way that `cl-destructuring-bind' would. + +A significant difference from `cl-destructuring-bind' is that, if +a pattern match fails, the next case is tried until either a +successful match is found or there are no more cases. + +Another difference is that pattern elements may be quoted, +meaning they must match exactly: The pattern \\='(foo bar) +matches only against two element lists containing the symbols +`foo' and `bar' in that order. (As a short-hand, atoms always +match themselves, such as numbers or strings, and need not be +quoted.) + +Lastly, a pattern can be logical, such as (pred numberp), that +matches any number-like element; or the symbol `_', that matches +anything. Also, when patterns are backquoted, a comma may be +used to introduce logical patterns inside backquoted patterns. + +The complete list of standard patterns is as follows: + + _ matches anything. + SYMBOL matches anything and binds it to SYMBOL. + If a SYMBOL is used twice in the same pattern + the second occurrence becomes an `eq'uality test. + (or PAT...) matches if any of the patterns matches. + (and PAT...) matches if all the patterns match. + \\='VAL matches if the object is `equal' to VAL. + ATOM is a shorthand for \\='ATOM. + ATOM can be a keyword, an integer, or a string. + (pred FUN) matches if FUN applied to the object returns non-nil. + (guard BOOLEXP) matches if BOOLEXP evaluates to non-nil. + (let PAT EXP) matches if EXP matches PAT. + (app FUN PAT) matches if FUN applied to the object matches PAT. + +Additional patterns can be defined using `pcase-defmacro'. + +The FUN argument in the `app' pattern may have the following forms: + SYMBOL or (lambda ARGS BODY) in which case it's called with one argument. + (F ARG1 .. ARGn) in which case F gets called with an n+1'th argument + which is the value being matched. +So a FUN of the form SYMBOL is equivalent to (FUN). +FUN can refer to variables bound earlier in the pattern. + +See Info node `(elisp) Pattern matching case statement' in the +Emacs Lisp manual for more information and examples. + +\(fn EXP &rest CASES)" nil t) + +(function-put 'pcase 'lisp-indent-function '1) + +(autoload 'pcase-exhaustive "pcase" "\ +The exhaustive version of `pcase' (which see). + +\(fn EXP &rest CASES)" nil t) + +(function-put 'pcase-exhaustive 'lisp-indent-function '1) + +(autoload 'pcase-lambda "pcase" "\ +Like `lambda' but allow each argument to be a pattern. +I.e. accepts the usual &optional and &rest keywords, but every +formal argument can be any pattern accepted by `pcase' (a mere +variable name being but a special case of it). + +\(fn LAMBDA-LIST &rest BODY)" nil t) + +(function-put 'pcase-lambda 'doc-string-elt '2) + +(function-put 'pcase-lambda 'lisp-indent-function 'defun) + +(autoload 'pcase-let* "pcase" "\ +Like `let*' but where you can use `pcase' patterns for bindings. +BODY should be an expression, and BINDINGS should be a list of bindings +of the form (PAT EXP). + +\(fn BINDINGS &rest BODY)" nil t) + +(function-put 'pcase-let* 'lisp-indent-function '1) + +(autoload 'pcase-let "pcase" "\ +Like `let' but where you can use `pcase' patterns for bindings. +BODY should be a list of expressions, and BINDINGS should be a list of bindings +of the form (PAT EXP). +The macro is expanded and optimized under the assumption that those +patterns *will* match, so a mismatch may go undetected or may cause +any kind of error. + +\(fn BINDINGS &rest BODY)" nil t) + +(function-put 'pcase-let 'lisp-indent-function '1) + +(autoload 'pcase-dolist "pcase" "\ +Like `dolist' but where the binding can be a `pcase' pattern. + +\(fn (PATTERN LIST) BODY...)" nil t) + +(function-put 'pcase-dolist 'lisp-indent-function '1) + +(autoload 'pcase-defmacro "pcase" "\ +Define a new kind of pcase PATTERN, by macro expansion. +Patterns of the form (NAME ...) will be expanded according +to this macro. + +\(fn NAME ARGS &rest BODY)" nil t) + +(function-put 'pcase-defmacro 'lisp-indent-function '2) + +(function-put 'pcase-defmacro 'doc-string-elt '3) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pcase" '("pcase-"))) + +;;;*** + +;;;### (autoloads nil "pcmpl-cvs" "pcmpl-cvs.el" (0 0 0 0)) +;;; Generated autoloads from pcmpl-cvs.el + +(autoload 'pcomplete/cvs "pcmpl-cvs" "\ +Completion rules for the `cvs' command. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pcmpl-cvs" '("pcmpl-cvs-"))) + +;;;*** + +;;;### (autoloads nil "pcmpl-gnu" "pcmpl-gnu.el" (0 0 0 0)) +;;; Generated autoloads from pcmpl-gnu.el + +(autoload 'pcomplete/gzip "pcmpl-gnu" "\ +Completion for `gzip'. + +\(fn)" nil nil) + +(autoload 'pcomplete/bzip2 "pcmpl-gnu" "\ +Completion for `bzip2'. + +\(fn)" nil nil) + +(autoload 'pcomplete/make "pcmpl-gnu" "\ +Completion for GNU `make'. + +\(fn)" nil nil) + +(autoload 'pcomplete/tar "pcmpl-gnu" "\ +Completion for the GNU tar utility. + +\(fn)" nil nil) + +(autoload 'pcomplete/find "pcmpl-gnu" "\ +Completion for the GNU find utility. + +\(fn)" nil nil) + +(defalias 'pcomplete/gdb 'pcomplete/xargs) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pcmpl-gnu" '("pcmpl-gnu-"))) + +;;;*** + +;;;### (autoloads nil "pcmpl-linux" "pcmpl-linux.el" (0 0 0 0)) +;;; Generated autoloads from pcmpl-linux.el + +(autoload 'pcomplete/kill "pcmpl-linux" "\ +Completion for GNU/Linux `kill', using /proc filesystem. + +\(fn)" nil nil) + +(autoload 'pcomplete/umount "pcmpl-linux" "\ +Completion for GNU/Linux `umount'. + +\(fn)" nil nil) + +(autoload 'pcomplete/mount "pcmpl-linux" "\ +Completion for GNU/Linux `mount'. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pcmpl-linux" '("pcomplete-pare-list" "pcmpl-linux-"))) + +;;;*** + +;;;### (autoloads nil "pcmpl-rpm" "pcmpl-rpm.el" (0 0 0 0)) +;;; Generated autoloads from pcmpl-rpm.el + +(autoload 'pcomplete/rpm "pcmpl-rpm" "\ +Completion for the `rpm' command. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pcmpl-rpm" '("pcmpl-rpm-"))) + +;;;*** + +;;;### (autoloads nil "pcmpl-unix" "pcmpl-unix.el" (0 0 0 0)) +;;; Generated autoloads from pcmpl-unix.el + +(autoload 'pcomplete/cd "pcmpl-unix" "\ +Completion for `cd'. + +\(fn)" nil nil) + +(defalias 'pcomplete/pushd 'pcomplete/cd) + +(autoload 'pcomplete/rmdir "pcmpl-unix" "\ +Completion for `rmdir'. + +\(fn)" nil nil) + +(autoload 'pcomplete/rm "pcmpl-unix" "\ +Completion for `rm'. + +\(fn)" nil nil) + +(autoload 'pcomplete/xargs "pcmpl-unix" "\ +Completion for `xargs'. + +\(fn)" nil nil) + +(defalias 'pcomplete/time 'pcomplete/xargs) + +(autoload 'pcomplete/which "pcmpl-unix" "\ +Completion for `which'. + +\(fn)" nil nil) + +(autoload 'pcomplete/chown "pcmpl-unix" "\ +Completion for the `chown' command. + +\(fn)" nil nil) + +(autoload 'pcomplete/chgrp "pcmpl-unix" "\ +Completion for the `chgrp' command. + +\(fn)" nil nil) + +(autoload 'pcomplete/ssh "pcmpl-unix" "\ +Completion rules for the `ssh' command. + +\(fn)" nil nil) + +(autoload 'pcomplete/scp "pcmpl-unix" "\ +Completion rules for the `scp' command. +Includes files as well as host names followed by a colon. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pcmpl-unix" '("pcmpl-"))) + +;;;*** + +;;;### (autoloads nil "pcmpl-x" "pcmpl-x.el" (0 0 0 0)) +;;; Generated autoloads from pcmpl-x.el + +(autoload 'pcomplete/tlmgr "pcmpl-x" "\ +Completion for the `tlmgr' command. + +\(fn)" nil nil) + +(autoload 'pcomplete/ack "pcmpl-x" "\ +Completion for the `ack' command. +Start an argument with `-' to complete short options and `--' for +long options. + +\(fn)" nil nil) + +(defalias 'pcomplete/ack-grep 'pcomplete/ack) + +(autoload 'pcomplete/ag "pcmpl-x" "\ +Completion for the `ag' command. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pcmpl-x" '("pcmpl-x-"))) + +;;;*** + +;;;### (autoloads nil "pcomplete" "pcomplete.el" (0 0 0 0)) +;;; Generated autoloads from pcomplete.el + +(autoload 'pcomplete "pcomplete" "\ +Support extensible programmable completion. +To use this function, just bind the TAB key to it, or add it to your +completion functions list (it should occur fairly early in the list). + +\(fn &optional INTERACTIVELY)" t nil) + +(autoload 'pcomplete-reverse "pcomplete" "\ +If cycling completion is in use, cycle backwards. + +\(fn)" t nil) + +(autoload 'pcomplete-expand-and-complete "pcomplete" "\ +Expand the textual value of the current argument. +This will modify the current buffer. + +\(fn)" t nil) + +(autoload 'pcomplete-continue "pcomplete" "\ +Complete without reference to any cycling completions. + +\(fn)" t nil) + +(autoload 'pcomplete-expand "pcomplete" "\ +Expand the textual value of the current argument. +This will modify the current buffer. + +\(fn)" t nil) + +(autoload 'pcomplete-help "pcomplete" "\ +Display any help information relative to the current argument. + +\(fn)" t nil) + +(autoload 'pcomplete-list "pcomplete" "\ +Show the list of possible completions for the current argument. + +\(fn)" t nil) + +(autoload 'pcomplete-comint-setup "pcomplete" "\ +Setup a comint buffer to use pcomplete. +COMPLETEF-SYM should be the symbol where the +dynamic-complete-functions are kept. For comint mode itself, +this is `comint-dynamic-complete-functions'. + +\(fn COMPLETEF-SYM)" nil nil) + +(autoload 'pcomplete-shell-setup "pcomplete" "\ +Setup `shell-mode' to use pcomplete. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pcomplete" '("pcomplete-"))) + +;;;*** + +;;;### (autoloads nil "pcvs" "vc/pcvs.el" (0 0 0 0)) +;;; Generated autoloads from vc/pcvs.el + +(autoload 'cvs-checkout "pcvs" "\ +Run a `cvs checkout MODULES' in DIR. +Feed the output to a *cvs* buffer, display it in the current window, +and run `cvs-mode' on it. + +With a prefix argument, prompt for cvs FLAGS to use. + +\(fn MODULES DIR FLAGS &optional ROOT)" t nil) + +(autoload 'cvs-quickdir "pcvs" "\ +Open a *cvs* buffer on DIR without running cvs. +With a prefix argument, prompt for a directory to use. +A prefix arg >8 (ex: \\[universal-argument] \\[universal-argument]), + prevents reuse of an existing *cvs* buffer. +Optional argument NOSHOW if non-nil means not to display the buffer. +FLAGS is ignored. + +\(fn DIR &optional FLAGS NOSHOW)" t nil) + +(autoload 'cvs-examine "pcvs" "\ +Run a `cvs -n update' in the specified DIRECTORY. +That is, check what needs to be done, but don't change the disc. +Feed the output to a *cvs* buffer and run `cvs-mode' on it. +With a prefix argument, prompt for a directory and cvs FLAGS to use. +A prefix arg >8 (ex: \\[universal-argument] \\[universal-argument]), + prevents reuse of an existing *cvs* buffer. +Optional argument NOSHOW if non-nil means not to display the buffer. + +\(fn DIRECTORY FLAGS &optional NOSHOW)" t nil) + +(autoload 'cvs-update "pcvs" "\ +Run a `cvs update' in the current working DIRECTORY. +Feed the output to a *cvs* buffer and run `cvs-mode' on it. +With a \\[universal-argument] prefix argument, prompt for a directory to use. +A prefix arg >8 (ex: \\[universal-argument] \\[universal-argument]), + prevents reuse of an existing *cvs* buffer. +The prefix is also passed to `cvs-flags-query' to select the FLAGS + passed to cvs. + +\(fn DIRECTORY FLAGS)" t nil) + +(autoload 'cvs-status "pcvs" "\ +Run a `cvs status' in the current working DIRECTORY. +Feed the output to a *cvs* buffer and run `cvs-mode' on it. +With a prefix argument, prompt for a directory and cvs FLAGS to use. +A prefix arg >8 (ex: \\[universal-argument] \\[universal-argument]), + prevents reuse of an existing *cvs* buffer. +Optional argument NOSHOW if non-nil means not to display the buffer. + +\(fn DIRECTORY FLAGS &optional NOSHOW)" t nil) + +(defvar cvs-dired-action 'cvs-quickdir "\ +The action to be performed when opening a CVS directory. +Sensible values are `cvs-examine', `cvs-status' and `cvs-quickdir'.") + +(custom-autoload 'cvs-dired-action "pcvs" t) + +(defvar cvs-dired-use-hook '(4) "\ +Whether or not opening a CVS directory should run PCL-CVS. +A value of nil means never do it. +`always' means to always do it unless a prefix argument is given to the + command that prompted the opening of the directory. +Anything else means to do it only if the prefix arg is equal to this value.") + +(custom-autoload 'cvs-dired-use-hook "pcvs" t) + +(defun cvs-dired-noselect (dir) "\ +Run `cvs-examine' if DIR is a CVS administrative directory. +The exact behavior is determined also by `cvs-dired-use-hook'." (when (stringp dir) (setq dir (directory-file-name dir)) (when (and (string= "CVS" (file-name-nondirectory dir)) (file-readable-p (expand-file-name "Entries" dir)) cvs-dired-use-hook (if (eq cvs-dired-use-hook (quote always)) (not current-prefix-arg) (equal current-prefix-arg cvs-dired-use-hook))) (save-excursion (funcall cvs-dired-action (file-name-directory dir) t t))))) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pcvs" '("cvs-" "defun-cvs-mode"))) + +;;;*** + +;;;### (autoloads nil "pcvs-defs" "vc/pcvs-defs.el" (0 0 0 0)) +;;; Generated autoloads from vc/pcvs-defs.el + +(defvar cvs-global-menu (let ((m (make-sparse-keymap "PCL-CVS"))) (define-key m [status] `(menu-item ,(purecopy "Directory Status") cvs-status :help ,(purecopy "A more verbose status of a workarea"))) (define-key m [checkout] `(menu-item ,(purecopy "Checkout Module") cvs-checkout :help ,(purecopy "Check out a module from the repository"))) (define-key m [update] `(menu-item ,(purecopy "Update Directory") cvs-update :help ,(purecopy "Fetch updates from the repository"))) (define-key m [examine] `(menu-item ,(purecopy "Examine Directory") cvs-examine :help ,(purecopy "Examine the current state of a workarea"))) (fset 'cvs-global-menu m)) "\ +Global menu used by PCL-CVS.") + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pcvs-defs" '("cvs-"))) + +;;;*** + +;;;### (autoloads nil "pcvs-info" "vc/pcvs-info.el" (0 0 0 0)) +;;; Generated autoloads from vc/pcvs-info.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pcvs-info" '("cvs-"))) + +;;;*** + +;;;### (autoloads nil "pcvs-parse" "vc/pcvs-parse.el" (0 0 0 0)) +;;; Generated autoloads from vc/pcvs-parse.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pcvs-parse" '("cvs-"))) + +;;;*** + +;;;### (autoloads nil "pcvs-util" "vc/pcvs-util.el" (0 0 0 0)) +;;; Generated autoloads from vc/pcvs-util.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pcvs-util" '("cvs-"))) + +;;;*** + +;;;### (autoloads nil "perl-mode" "progmodes/perl-mode.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from progmodes/perl-mode.el +(put 'perl-indent-level 'safe-local-variable 'integerp) +(put 'perl-continued-statement-offset 'safe-local-variable 'integerp) +(put 'perl-continued-brace-offset 'safe-local-variable 'integerp) +(put 'perl-brace-offset 'safe-local-variable 'integerp) +(put 'perl-brace-imaginary-offset 'safe-local-variable 'integerp) +(put 'perl-label-offset 'safe-local-variable 'integerp) + +(autoload 'perl-mode "perl-mode" "\ +Major mode for editing Perl code. +Expression and list commands understand all Perl brackets. +Tab indents for Perl code. +Comments are delimited with # ... \\n. +Paragraphs are separated by blank lines only. +Delete converts tabs to spaces as it moves back. +\\{perl-mode-map} +Variables controlling indentation style: + `perl-tab-always-indent' + Non-nil means TAB in Perl mode should always indent the current line, + regardless of where in the line point is when the TAB command is used. + `perl-tab-to-comment' + Non-nil means that for lines which don't need indenting, TAB will + either delete an empty comment, indent an existing comment, move + to end-of-line, or if at end-of-line already, create a new comment. + `perl-nochange' + Lines starting with this regular expression are not auto-indented. + `perl-indent-level' + Indentation of Perl statements within surrounding block. + The surrounding block's indentation is the indentation + of the line on which the open-brace appears. + `perl-continued-statement-offset' + Extra indentation given to a substatement, such as the + then-clause of an if or body of a while. + `perl-continued-brace-offset' + Extra indentation given to a brace that starts a substatement. + This is in addition to `perl-continued-statement-offset'. + `perl-brace-offset' + Extra indentation for line if it starts with an open brace. + `perl-brace-imaginary-offset' + An open brace following other text is treated as if it were + this far to the right of the start of its line. + `perl-label-offset' + Extra indentation for line that is a label. + `perl-indent-continued-arguments' + Offset of argument lines relative to usual indentation. + +Various indentation styles: K&R BSD BLK GNU LW + perl-indent-level 5 8 0 2 4 + perl-continued-statement-offset 5 8 4 2 4 + perl-continued-brace-offset 0 0 0 0 -4 + perl-brace-offset -5 -8 0 0 0 + perl-brace-imaginary-offset 0 0 4 0 0 + perl-label-offset -5 -8 -2 -2 -2 + +Turning on Perl mode runs the normal hook `perl-mode-hook'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "perl-mode" '("perl-" "mark-perl-function" "indent-perl-exp"))) + +;;;*** + +;;;### (autoloads nil "picture" "textmodes/picture.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/picture.el + +(autoload 'picture-mode "picture" "\ +Switch to Picture mode, in which a quarter-plane screen model is used. +\\<picture-mode-map> +Printing characters replace instead of inserting themselves with motion +afterwards settable by these commands: + + Move left after insertion: \\[picture-movement-left] + Move right after insertion: \\[picture-movement-right] + Move up after insertion: \\[picture-movement-up] + Move down after insertion: \\[picture-movement-down] + + Move northwest (nw) after insertion: \\[picture-movement-nw] + Move northeast (ne) after insertion: \\[picture-movement-ne] + Move southwest (sw) after insertion: \\[picture-movement-sw] + Move southeast (se) after insertion: \\[picture-movement-se] + + Move westnorthwest (wnw) after insertion: C-u \\[picture-movement-nw] + Move eastnortheast (ene) after insertion: C-u \\[picture-movement-ne] + Move westsouthwest (wsw) after insertion: C-u \\[picture-movement-sw] + Move eastsoutheast (ese) after insertion: C-u \\[picture-movement-se] + +The current direction is displayed in the mode line. The initial +direction is right. Whitespace is inserted and tabs are changed to +spaces when required by movement. You can move around in the buffer +with these commands: + + Move vertically to SAME column in previous line: \\[picture-move-down] + Move vertically to SAME column in next line: \\[picture-move-up] + Move to column following last + non-whitespace character: \\[picture-end-of-line] + Move right, inserting spaces if required: \\[picture-forward-column] + Move left changing tabs to spaces if required: \\[picture-backward-column] + Move in direction of current picture motion: \\[picture-motion] + Move opposite to current picture motion: \\[picture-motion-reverse] + Move to beginning of next line: \\[next-line] + +You can edit tabular text with these commands: + + Move to column beneath (or at) next interesting + character (see variable `picture-tab-chars'): \\[picture-tab-search] + Move to next stop in tab stop list: \\[picture-tab] + Set tab stops according to context of this line: \\[picture-set-tab-stops] + (With ARG, resets tab stops to default value.) + Change the tab stop list: \\[edit-tab-stops] + +You can manipulate text with these commands: + Clear ARG columns after point without moving: \\[picture-clear-column] + Delete char at point: \\[picture-delete-char] + Clear ARG columns backward: \\[picture-backward-clear-column] + Clear ARG lines, advancing over them: \\[picture-clear-line] + (the cleared text is saved in the kill ring) + Open blank line(s) beneath current line: \\[picture-open-line] + +You can manipulate rectangles with these commands: + Clear a rectangle and save it: \\[picture-clear-rectangle] + Clear a rectangle, saving in a named register: \\[picture-clear-rectangle-to-register] + Insert currently saved rectangle at point: \\[picture-yank-rectangle] + Insert rectangle from named register: \\[picture-yank-rectangle-from-register] + Draw a rectangular box around mark and point: \\[picture-draw-rectangle] + Copies a rectangle to a register: \\[copy-rectangle-to-register] + Undo effects of rectangle overlay commands: \\[undo] + +You can return to the previous mode with \\[picture-mode-exit], which +also strips trailing whitespace from every line. Stripping is suppressed +by supplying an argument. + +Entry to this mode calls the value of `picture-mode-hook' if non-nil. + +Note that Picture mode commands will work outside of Picture mode, but +they are not by default assigned to keys. + +\(fn)" t nil) + +(defalias 'edit-picture 'picture-mode) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "picture" '("picture-"))) + +;;;*** + +;;;### (autoloads nil "pinentry" "net/pinentry.el" (0 0 0 0)) +;;; Generated autoloads from net/pinentry.el +(push (purecopy '(pinentry 0 1)) package--builtin-versions) + +(autoload 'pinentry-start "pinentry" "\ +Start a Pinentry service. + +Once the environment is properly set, subsequent invocations of +the gpg command will interact with Emacs for passphrase input. + +If the optional QUIET argument is non-nil, messages at startup +will not be shown. + +\(fn &optional QUIET)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pinentry" '("pinentry-"))) + +;;;*** + +;;;### (autoloads nil "pixel-scroll" "pixel-scroll.el" (0 0 0 0)) +;;; Generated autoloads from pixel-scroll.el + +(defvar pixel-scroll-mode nil "\ +Non-nil if Pixel-Scroll mode is enabled. +See the `pixel-scroll-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `pixel-scroll-mode'.") + +(custom-autoload 'pixel-scroll-mode "pixel-scroll" nil) + +(autoload 'pixel-scroll-mode "pixel-scroll" "\ +A minor mode to scroll text pixel-by-pixel. +With a prefix argument ARG, enable Pixel Scroll mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable Pixel Scroll mode +if ARG is omitted or nil. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pixel-scroll" '("pixel-"))) + +;;;*** + +;;;### (autoloads nil "plstore" "plstore.el" (0 0 0 0)) +;;; Generated autoloads from plstore.el + +(autoload 'plstore-open "plstore" "\ +Create a plstore instance associated with FILE. + +\(fn FILE)" nil nil) + +(autoload 'plstore-mode "plstore" "\ +Major mode for editing PLSTORE files. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "plstore" '("plstore-"))) + +;;;*** + +;;;### (autoloads nil "po" "textmodes/po.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/po.el + +(autoload 'po-find-file-coding-system "po" "\ +Return a (DECODING . ENCODING) pair, according to PO file's charset. +Called through `file-coding-system-alist', before the file is visited for real. + +\(fn ARG-LIST)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "po" '("po-"))) + +;;;*** + +;;;### (autoloads nil "pong" "play/pong.el" (0 0 0 0)) +;;; Generated autoloads from play/pong.el + +(autoload 'pong "pong" "\ +Play pong and waste time. +This is an implementation of the classical game pong. +Move left and right bats and try to bounce the ball to your opponent. + +pong-mode keybindings:\\<pong-mode-map> + +\\{pong-mode-map} + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pong" '("pong-"))) + +;;;*** + +;;;### (autoloads nil "pop3" "net/pop3.el" (0 0 0 0)) +;;; Generated autoloads from net/pop3.el + +(autoload 'pop3-movemail "pop3" "\ +Transfer contents of a maildrop to the specified FILE. +Use streaming commands. + +\(fn FILE)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pop3" '("pop3-"))) + +;;;*** + +;;;### (autoloads nil "pp" "emacs-lisp/pp.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/pp.el + +(autoload 'pp-to-string "pp" "\ +Return a string containing the pretty-printed representation of OBJECT. +OBJECT can be any Lisp object. Quoting characters are used as needed +to make output that `read' can handle, whenever this is possible. + +\(fn OBJECT)" nil nil) + +(autoload 'pp-buffer "pp" "\ +Prettify the current buffer with printed representation of a Lisp object. + +\(fn)" nil nil) + +(autoload 'pp "pp" "\ +Output the pretty-printed representation of OBJECT, any Lisp object. +Quoting characters are printed as needed to make output that `read' +can handle, whenever this is possible. +Output stream is STREAM, or value of `standard-output' (which see). + +\(fn OBJECT &optional STREAM)" nil nil) + +(autoload 'pp-eval-expression "pp" "\ +Evaluate EXPRESSION and pretty-print its value. +Also add the value to the front of the list in the variable `values'. + +\(fn EXPRESSION)" t nil) + +(autoload 'pp-macroexpand-expression "pp" "\ +Macroexpand EXPRESSION and pretty-print its value. + +\(fn EXPRESSION)" t nil) + +(autoload 'pp-eval-last-sexp "pp" "\ +Run `pp-eval-expression' on sexp before point. +With argument, pretty-print output into current buffer. +Ignores leading comment characters. + +\(fn ARG)" t nil) + +(autoload 'pp-macroexpand-last-sexp "pp" "\ +Run `pp-macroexpand-expression' on sexp before point. +With argument, pretty-print output into current buffer. +Ignores leading comment characters. + +\(fn ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pp" '("pp-"))) + +;;;*** + +;;;### (autoloads nil "printing" "printing.el" (0 0 0 0)) +;;; Generated autoloads from printing.el +(push (purecopy '(printing 6 9 3)) package--builtin-versions) + +(autoload 'pr-interface "printing" "\ +Activate the printing interface buffer. + +If BUFFER is nil, the current buffer is used for printing. + +For more information, type \\[pr-interface-help]. + +\(fn &optional BUFFER)" t nil) + +(autoload 'pr-ps-directory-preview "printing" "\ +Preview directory using ghostview. + +Interactively, the command prompts for N-UP printing number, a directory, a +file name regexp for matching and, when you use a prefix argument (C-u), the +command prompts the user for a file name, and saves the PostScript image in +that file instead of saving it in a temporary file. + +Noninteractively, if N-UP is nil, prompts for N-UP printing number. If DIR is +nil, prompts for DIRectory. If FILE-REGEXP is nil, prompts for +FILE(name)-REGEXP. The argument FILENAME is treated as follows: if it's nil, +save the image in a temporary file. If FILENAME is a string, save the +PostScript image in a file with that name. If FILENAME is t, prompts for a +file name. + +See also documentation for `pr-list-directory'. + +\(fn N-UP DIR FILE-REGEXP &optional FILENAME)" t nil) + +(autoload 'pr-ps-directory-using-ghostscript "printing" "\ +Print directory using PostScript through ghostscript. + +Interactively, the command prompts for N-UP printing number, a directory, a +file name regexp for matching and, when you use a prefix argument (C-u), the +command prompts the user for a file name, and saves the PostScript image in +that file instead of saving it in a temporary file. + +Noninteractively, if N-UP is nil, prompts for N-UP printing number. If DIR is +nil, prompts for DIRectory. If FILE-REGEXP is nil, prompts for +FILE(name)-REGEXP. The argument FILENAME is treated as follows: if it's nil, +save the image in a temporary file. If FILENAME is a string, save the +PostScript image in a file with that name. If FILENAME is t, prompts for a +file name. + +See also documentation for `pr-list-directory'. + +\(fn N-UP DIR FILE-REGEXP &optional FILENAME)" t nil) + +(autoload 'pr-ps-directory-print "printing" "\ +Print directory using PostScript printer. + +Interactively, the command prompts for N-UP printing number, a directory, a +file name regexp for matching and, when you use a prefix argument (C-u), the +command prompts the user for a file name, and saves the PostScript image in +that file instead of saving it in a temporary file. + +Noninteractively, if N-UP is nil, prompts for N-UP printing number. If DIR is +nil, prompts for DIRectory. If FILE-REGEXP is nil, prompts for +FILE(name)-REGEXP. The argument FILENAME is treated as follows: if it's nil, +save the image in a temporary file. If FILENAME is a string, save the +PostScript image in a file with that name. If FILENAME is t, prompts for a +file name. + +See also documentation for `pr-list-directory'. + +\(fn N-UP DIR FILE-REGEXP &optional FILENAME)" t nil) + +(autoload 'pr-ps-directory-ps-print "printing" "\ +Print directory using PostScript printer or through ghostscript. + +It depends on `pr-print-using-ghostscript'. + +Interactively, the command prompts for N-UP printing number, a directory, a +file name regexp for matching and, when you use a prefix argument (C-u), the +command prompts the user for a file name, and saves the PostScript image in +that file instead of saving it in a temporary file. + +Noninteractively, if N-UP is nil, prompts for N-UP printing number. If DIR is +nil, prompts for DIRectory. If FILE-REGEXP is nil, prompts for +FILE(name)-REGEXP. The argument FILENAME is treated as follows: if it's nil, +save the image in a temporary file. If FILENAME is a string, save the +PostScript image in a file with that name. If FILENAME is t, prompts for a +file name. + +See also documentation for `pr-list-directory'. + +\(fn N-UP DIR FILE-REGEXP &optional FILENAME)" t nil) + +(autoload 'pr-ps-buffer-preview "printing" "\ +Preview buffer using ghostview. + +Interactively, the command prompts for N-UP printing number and, when you use a +prefix argument (C-u), the command prompts the user for a file name, and saves +the PostScript image in that file instead of saving it in a temporary file. + +Noninteractively, if N-UP is nil, prompts for N-UP printing number. The +argument FILENAME is treated as follows: if it's nil, save the image in a +temporary file. If FILENAME is a string, save the PostScript image in a file +with that name. If FILENAME is t, prompts for a file name. + +\(fn N-UP &optional FILENAME)" t nil) + +(autoload 'pr-ps-buffer-using-ghostscript "printing" "\ +Print buffer using PostScript through ghostscript. + +Interactively, the command prompts for N-UP printing number and, when you use a +prefix argument (C-u), the command prompts the user for a file name, and saves +the PostScript image in that file instead of sending it to the printer. + +Noninteractively, if N-UP is nil, prompts for N-UP printing number. The +argument FILENAME is treated as follows: if it's nil, send the image to the +printer. If FILENAME is a string, save the PostScript image in a file with +that name. If FILENAME is t, prompts for a file name. + +\(fn N-UP &optional FILENAME)" t nil) + +(autoload 'pr-ps-buffer-print "printing" "\ +Print buffer using PostScript printer. + +Interactively, the command prompts for N-UP printing number and, when you use a +prefix argument (C-u), the command prompts the user for a file name, and saves +the PostScript image in that file instead of sending it to the printer. + +Noninteractively, if N-UP is nil, prompts for N-UP printing number. The +argument FILENAME is treated as follows: if it's nil, send the image to the +printer. If FILENAME is a string, save the PostScript image in a file with +that name. If FILENAME is t, prompts for a file name. + +\(fn N-UP &optional FILENAME)" t nil) + +(autoload 'pr-ps-buffer-ps-print "printing" "\ +Print buffer using PostScript printer or through ghostscript. + +It depends on `pr-print-using-ghostscript'. + +Interactively, the command prompts for N-UP printing number and, when you use a +prefix argument (C-u), the command prompts the user for a file name, and saves +the PostScript image in that file instead of sending it to the printer. + +Noninteractively, if N-UP is nil, prompts for N-UP printing number. The +argument FILENAME is treated as follows: if it's nil, send the image to the +printer. If FILENAME is a string, save the PostScript image in a file with +that name. If FILENAME is t, prompts for a file name. + +\(fn N-UP &optional FILENAME)" t nil) + +(autoload 'pr-ps-region-preview "printing" "\ +Preview region using ghostview. + +See also `pr-ps-buffer-preview'. + +\(fn N-UP &optional FILENAME)" t nil) + +(autoload 'pr-ps-region-using-ghostscript "printing" "\ +Print region using PostScript through ghostscript. + +See also `pr-ps-buffer-using-ghostscript'. + +\(fn N-UP &optional FILENAME)" t nil) + +(autoload 'pr-ps-region-print "printing" "\ +Print region using PostScript printer. + +See also `pr-ps-buffer-print'. + +\(fn N-UP &optional FILENAME)" t nil) + +(autoload 'pr-ps-region-ps-print "printing" "\ +Print region using PostScript printer or through ghostscript. + +See also `pr-ps-buffer-ps-print'. + +\(fn N-UP &optional FILENAME)" t nil) + +(autoload 'pr-ps-mode-preview "printing" "\ +Preview major mode using ghostview. + +See also `pr-ps-buffer-preview'. + +\(fn N-UP &optional FILENAME)" t nil) + +(autoload 'pr-ps-mode-using-ghostscript "printing" "\ +Print major mode using PostScript through ghostscript. + +See also `pr-ps-buffer-using-ghostscript'. + +\(fn N-UP &optional FILENAME)" t nil) + +(autoload 'pr-ps-mode-print "printing" "\ +Print major mode using PostScript printer. + +See also `pr-ps-buffer-print'. + +\(fn N-UP &optional FILENAME)" t nil) + +(autoload 'pr-ps-mode-ps-print "printing" "\ +Print major mode using PostScript or through ghostscript. + +See also `pr-ps-buffer-ps-print'. + +\(fn N-UP &optional FILENAME)" t nil) + +(autoload 'pr-printify-directory "printing" "\ +Replace nonprinting characters in directory with printable representations. +The printable representations use ^ (for ASCII control characters) or hex. +The characters tab, linefeed, space, return and formfeed are not affected. + +Interactively, the command prompts for a directory and a file name regexp for +matching. + +Noninteractively, if DIR is nil, prompts for DIRectory. If FILE-REGEXP is nil, +prompts for FILE(name)-REGEXP. + +See also documentation for `pr-list-directory'. + +\(fn &optional DIR FILE-REGEXP)" t nil) + +(autoload 'pr-printify-buffer "printing" "\ +Replace nonprinting characters in buffer with printable representations. +The printable representations use ^ (for ASCII control characters) or hex. +The characters tab, linefeed, space, return and formfeed are not affected. + +\(fn)" t nil) + +(autoload 'pr-printify-region "printing" "\ +Replace nonprinting characters in region with printable representations. +The printable representations use ^ (for ASCII control characters) or hex. +The characters tab, linefeed, space, return and formfeed are not affected. + +\(fn)" t nil) + +(autoload 'pr-txt-directory "printing" "\ +Print directory using text printer. + +Interactively, the command prompts for a directory and a file name regexp for +matching. + +Noninteractively, if DIR is nil, prompts for DIRectory. If FILE-REGEXP is nil, +prompts for FILE(name)-REGEXP. + +See also documentation for `pr-list-directory'. + +\(fn &optional DIR FILE-REGEXP)" t nil) + +(autoload 'pr-txt-buffer "printing" "\ +Print buffer using text printer. + +\(fn)" t nil) + +(autoload 'pr-txt-region "printing" "\ +Print region using text printer. + +\(fn)" t nil) + +(autoload 'pr-txt-mode "printing" "\ +Print major mode using text printer. + +\(fn)" t nil) + +(autoload 'pr-despool-preview "printing" "\ +Preview spooled PostScript. + +Interactively, when you use a prefix argument (C-u), the command prompts the +user for a file name, and saves the spooled PostScript image in that file +instead of saving it in a temporary file. + +Noninteractively, the argument FILENAME is treated as follows: if it is nil, +save the image in a temporary file. If FILENAME is a string, save the +PostScript image in a file with that name. + +\(fn &optional FILENAME)" t nil) + +(autoload 'pr-despool-using-ghostscript "printing" "\ +Print spooled PostScript using ghostscript. + +Interactively, when you use a prefix argument (C-u), the command prompts the +user for a file name, and saves the spooled PostScript image in that file +instead of sending it to the printer. + +Noninteractively, the argument FILENAME is treated as follows: if it is nil, +send the image to the printer. If FILENAME is a string, save the PostScript +image in a file with that name. + +\(fn &optional FILENAME)" t nil) + +(autoload 'pr-despool-print "printing" "\ +Send the spooled PostScript to the printer. + +Interactively, when you use a prefix argument (C-u), the command prompts the +user for a file name, and saves the spooled PostScript image in that file +instead of sending it to the printer. + +Noninteractively, the argument FILENAME is treated as follows: if it is nil, +send the image to the printer. If FILENAME is a string, save the PostScript +image in a file with that name. + +\(fn &optional FILENAME)" t nil) + +(autoload 'pr-despool-ps-print "printing" "\ +Send the spooled PostScript to the printer or use ghostscript to print it. + +Interactively, when you use a prefix argument (C-u), the command prompts the +user for a file name, and saves the spooled PostScript image in that file +instead of sending it to the printer. + +Noninteractively, the argument FILENAME is treated as follows: if it is nil, +send the image to the printer. If FILENAME is a string, save the PostScript +image in a file with that name. + +\(fn &optional FILENAME)" t nil) + +(autoload 'pr-ps-file-preview "printing" "\ +Preview PostScript file FILENAME. + +\(fn FILENAME)" t nil) + +(autoload 'pr-ps-file-up-preview "printing" "\ +Preview PostScript file FILENAME. + +\(fn N-UP IFILENAME &optional OFILENAME)" t nil) + +(autoload 'pr-ps-file-using-ghostscript "printing" "\ +Print PostScript file FILENAME using ghostscript. + +\(fn FILENAME)" t nil) + +(autoload 'pr-ps-file-print "printing" "\ +Print PostScript file FILENAME. + +\(fn FILENAME)" t nil) + +(autoload 'pr-ps-file-ps-print "printing" "\ +Send PostScript file FILENAME to printer or use ghostscript to print it. + +\(fn FILENAME)" t nil) + +(autoload 'pr-ps-file-up-ps-print "printing" "\ +Process a PostScript file IFILENAME and send it to printer. + +Interactively, the command prompts for N-UP printing number, for an input +PostScript file IFILENAME and, when you use a prefix argument (C-u), the +command prompts the user for an output PostScript file name OFILENAME, and +saves the PostScript image in that file instead of sending it to the printer. + +Noninteractively, if N-UP is nil, prompts for N-UP printing number. The +argument IFILENAME is treated as follows: if it's t, prompts for an input +PostScript file name; otherwise, it *must* be a string that it's an input +PostScript file name. The argument OFILENAME is treated as follows: if it's +nil, send the image to the printer. If OFILENAME is a string, save the +PostScript image in a file with that name. If OFILENAME is t, prompts for a +file name. + +\(fn N-UP IFILENAME &optional OFILENAME)" t nil) + +(autoload 'pr-toggle-file-duplex "printing" "\ +Toggle duplex for PostScript file. + +\(fn)" t nil) + +(autoload 'pr-toggle-file-tumble "printing" "\ +Toggle tumble for PostScript file. + +If tumble is off, produces a printing suitable for binding on the left or +right. +If tumble is on, produces a printing suitable for binding at the top or +bottom. + +\(fn)" t nil) + +(autoload 'pr-toggle-file-landscape "printing" "\ +Toggle landscape for PostScript file. + +\(fn)" t nil) + +(autoload 'pr-toggle-ghostscript "printing" "\ +Toggle printing using ghostscript. + +\(fn)" t nil) + +(autoload 'pr-toggle-faces "printing" "\ +Toggle printing with faces. + +\(fn)" t nil) + +(autoload 'pr-toggle-spool "printing" "\ +Toggle spooling. + +\(fn)" t nil) + +(autoload 'pr-toggle-duplex "printing" "\ +Toggle duplex. + +\(fn)" t nil) + +(autoload 'pr-toggle-tumble "printing" "\ +Toggle tumble. + +If tumble is off, produces a printing suitable for binding on the left or +right. +If tumble is on, produces a printing suitable for binding at the top or +bottom. + +\(fn)" t nil) + +(autoload 'pr-toggle-landscape "printing" "\ +Toggle landscape. + +\(fn)" t nil) + +(autoload 'pr-toggle-upside-down "printing" "\ +Toggle upside-down. + +\(fn)" t nil) + +(autoload 'pr-toggle-line "printing" "\ +Toggle line number. + +\(fn)" t nil) + +(autoload 'pr-toggle-zebra "printing" "\ +Toggle zebra stripes. + +\(fn)" t nil) + +(autoload 'pr-toggle-header "printing" "\ +Toggle printing header. + +\(fn)" t nil) + +(autoload 'pr-toggle-header-frame "printing" "\ +Toggle printing header frame. + +\(fn)" t nil) + +(autoload 'pr-toggle-lock "printing" "\ +Toggle menu lock. + +\(fn)" t nil) + +(autoload 'pr-toggle-region "printing" "\ +Toggle whether the region is automagically detected. + +\(fn)" t nil) + +(autoload 'pr-toggle-mode "printing" "\ +Toggle auto mode. + +\(fn)" t nil) + +(autoload 'pr-customize "printing" "\ +Customization of the `printing' group. + +\(fn &rest IGNORE)" t nil) + +(autoload 'lpr-customize "printing" "\ +Customization of the `lpr' group. + +\(fn &rest IGNORE)" t nil) + +(autoload 'pr-help "printing" "\ +Help for the printing package. + +\(fn &rest IGNORE)" t nil) + +(autoload 'pr-ps-name "printing" "\ +Interactively select a PostScript printer. + +\(fn)" t nil) + +(autoload 'pr-txt-name "printing" "\ +Interactively select a text printer. + +\(fn)" t nil) + +(autoload 'pr-ps-utility "printing" "\ +Interactively select a PostScript utility. + +\(fn)" t nil) + +(autoload 'pr-show-ps-setup "printing" "\ +Show current ps-print settings. + +\(fn &rest IGNORE)" t nil) + +(autoload 'pr-show-pr-setup "printing" "\ +Show current printing settings. + +\(fn &rest IGNORE)" t nil) + +(autoload 'pr-show-lpr-setup "printing" "\ +Show current lpr settings. + +\(fn &rest IGNORE)" t nil) + +(autoload 'pr-ps-fast-fire "printing" "\ +Fast fire function for PostScript printing. + +If a region is active, the region will be printed instead of the whole buffer. +Also if the current major-mode is defined in `pr-mode-alist', the settings in +`pr-mode-alist' will be used, that is, the current buffer or region will be +printed using `pr-ps-mode-ps-print'. + + +Interactively, you have the following situations: + + M-x pr-ps-fast-fire RET + The command prompts the user for a N-UP value and printing will + immediately be done using the current active printer. + + C-u M-x pr-ps-fast-fire RET + C-u 0 M-x pr-ps-fast-fire RET + The command prompts the user for a N-UP value and also for a current + PostScript printer, then printing will immediately be done using the new + current active printer. + + C-u 1 M-x pr-ps-fast-fire RET + The command prompts the user for a N-UP value and also for a file name, + and saves the PostScript image in that file instead of sending it to the + printer. + + C-u 2 M-x pr-ps-fast-fire RET + The command prompts the user for a N-UP value, then for a current + PostScript printer and, finally, for a file name. Then change the active + printer to that chosen by user and saves the PostScript image in + that file instead of sending it to the printer. + + +Noninteractively, the argument N-UP should be a positive integer greater than +zero and the argument SELECT is treated as follows: + + If it's nil, send the image to the printer. + + If it's a list or an integer lesser or equal to zero, the command prompts + the user for a current PostScript printer, then printing will immediately + be done using the new current active printer. + + If it's an integer equal to 1, the command prompts the user for a file name + and saves the PostScript image in that file instead of sending it to the + printer. + + If it's an integer greater or equal to 2, the command prompts the user for a + current PostScript printer and for a file name. Then change the active + printer to that chosen by user and saves the PostScript image in that file + instead of sending it to the printer. + + If it's a symbol which it's defined in `pr-ps-printer-alist', it's the new + active printer and printing will immediately be done using the new active + printer. + + Otherwise, send the image to the printer. + + +Note that this command always behaves as if `pr-auto-region' and `pr-auto-mode' +are both set to t. + +\(fn N-UP &optional SELECT)" t nil) + +(autoload 'pr-txt-fast-fire "printing" "\ +Fast fire function for text printing. + +If a region is active, the region will be printed instead of the whole buffer. +Also if the current major-mode is defined in `pr-mode-alist', the settings in +`pr-mode-alist' will be used, that is, the current buffer or region will be +printed using `pr-txt-mode'. + +Interactively, when you use a prefix argument (C-u), the command prompts the +user for a new active text printer. + +Noninteractively, the argument SELECT-PRINTER is treated as follows: + + If it's nil, the printing is sent to the current active text printer. + + If it's a symbol which it's defined in `pr-txt-printer-alist', it's the new + active printer and printing will immediately be done using the new active + printer. + + If it's non-nil, the command prompts the user for a new active text printer. + +Note that this command always behaves as if `pr-auto-region' and `pr-auto-mode' +are both set to t. + +\(fn &optional SELECT-PRINTER)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "printing" '("pr-" "lpr-setup"))) + +;;;*** + +;;;### (autoloads nil "proced" "proced.el" (0 0 0 0)) +;;; Generated autoloads from proced.el + +(autoload 'proced "proced" "\ +Generate a listing of UNIX system processes. +\\<proced-mode-map> +If invoked with optional ARG, do not select the window displaying +the process information. + +This function runs the normal hook `proced-post-display-hook'. + +See `proced-mode' for a description of features available in +Proced buffers. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proced" '("proced-"))) + +;;;*** + +;;;### (autoloads nil "profiler" "profiler.el" (0 0 0 0)) +;;; Generated autoloads from profiler.el + +(autoload 'profiler-start "profiler" "\ +Start/restart profilers. +MODE can be one of `cpu', `mem', or `cpu+mem'. +If MODE is `cpu' or `cpu+mem', time-based profiler will be started. +Also, if MODE is `mem' or `cpu+mem', then memory profiler will be started. + +\(fn MODE)" t nil) + +(autoload 'profiler-find-profile "profiler" "\ +Open profile FILENAME. + +\(fn FILENAME)" t nil) + +(autoload 'profiler-find-profile-other-window "profiler" "\ +Open profile FILENAME. + +\(fn FILENAME)" t nil) + +(autoload 'profiler-find-profile-other-frame "profiler" "\ +Open profile FILENAME. + +\(fn FILENAME)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "profiler" '("profiler-"))) + +;;;*** + +;;;### (autoloads nil "project" "progmodes/project.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/project.el + +(autoload 'project-current "project" "\ +Return the project instance in DIR or `default-directory'. +When no project found in DIR, and MAYBE-PROMPT is non-nil, ask +the user for a different directory to look in. If that directory +is not a part of a detectable project either, return a +`transient' project instance rooted in it. + +\(fn &optional MAYBE-PROMPT DIR)" nil nil) + +(autoload 'project-find-regexp "project" "\ +Find all matches for REGEXP in the current project's roots. +With \\[universal-argument] prefix, you can specify the directory +to search in, and the file name pattern to search for. + +\(fn REGEXP)" t nil) + +(autoload 'project-or-external-find-regexp "project" "\ +Find all matches for REGEXP in the project roots or external roots. +With \\[universal-argument] prefix, you can specify the file name +pattern to search for. + +\(fn REGEXP)" t nil) + +(autoload 'project-find-file "project" "\ +Visit a file (with completion) in the current project's roots. +The completion default is the filename at point, if one is +recognized. + +\(fn)" t nil) + +(autoload 'project-or-external-find-file "project" "\ +Visit a file (with completion) in the current project's roots or external roots. +The completion default is the filename at point, if one is +recognized. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "project" '("project-"))) + +;;;*** + +;;;### (autoloads nil "prolog" "progmodes/prolog.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/prolog.el + +(autoload 'prolog-mode "prolog" "\ +Major mode for editing Prolog code. + +Blank lines and `%%...' separate paragraphs. `%'s starts a comment +line and comments can also be enclosed in /* ... */. + +If an optional argument SYSTEM is non-nil, set up mode for the given system. + +To find out what version of Prolog mode you are running, enter +`\\[prolog-mode-version]'. + +Commands: +\\{prolog-mode-map} + +\(fn)" t nil) + +(autoload 'mercury-mode "prolog" "\ +Major mode for editing Mercury programs. +Actually this is just customized `prolog-mode'. + +\(fn)" t nil) + +(autoload 'run-prolog "prolog" "\ +Run an inferior Prolog process, input and output via buffer *prolog*. +With prefix argument ARG, restart the Prolog process if running before. + +\(fn ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "prolog" '("prolog-" "mercury-mode-map"))) + +;;;*** + +;;;### (autoloads nil "ps-bdf" "ps-bdf.el" (0 0 0 0)) +;;; Generated autoloads from ps-bdf.el + +(defvar bdf-directory-list (if (memq system-type '(ms-dos windows-nt)) (list (expand-file-name "fonts/bdf" installation-directory)) '("/usr/local/share/emacs/fonts/bdf")) "\ +List of directories to search for `BDF' font files. +The default value is (\"/usr/local/share/emacs/fonts/bdf\").") + +(custom-autoload 'bdf-directory-list "ps-bdf" t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ps-bdf" '("bdf-"))) + +;;;*** + +;;;### (autoloads nil "ps-mode" "progmodes/ps-mode.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/ps-mode.el +(push (purecopy '(ps-mode 1 1 9)) package--builtin-versions) + +(autoload 'ps-mode "ps-mode" "\ +Major mode for editing PostScript with GNU Emacs. + +Entry to this mode calls `ps-mode-hook'. + +The following variables hold user options, and can +be set through the `customize' command: + + `ps-mode-tab' + `ps-mode-paper-size' + `ps-mode-print-function' + `ps-run-prompt' + `ps-run-font-lock-keywords-2' + `ps-run-x' + `ps-run-dumb' + `ps-run-init' + `ps-run-error-line-numbers' + `ps-run-tmp-dir' + +Type \\[describe-variable] for documentation on these options. + + +\\{ps-mode-map} + + +When starting an interactive PostScript process with \\[ps-run-start], +a second window will be displayed, and `ps-run-mode-hook' will be called. +The keymap for this second window is: + +\\{ps-run-mode-map} + + +When Ghostscript encounters an error it displays an error message +with a file position. Clicking mouse-2 on this number will bring +point to the corresponding spot in the PostScript window, if input +to the interpreter was sent from that window. +Typing \\<ps-run-mode-map>\\[ps-run-goto-error] when the cursor is at the number has the same effect. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ps-mode" '("ps-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "ps-mule" "ps-mule.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from ps-mule.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ps-mule" '("ps-mule-"))) + +;;;*** + +;;;### (autoloads nil "ps-print" "ps-print.el" (0 0 0 0)) +;;; Generated autoloads from ps-print.el +(push (purecopy '(ps-print 7 3 5)) package--builtin-versions) + +(defvar ps-page-dimensions-database (purecopy (list (list 'a4 (/ (* 72 21.0) 2.54) (/ (* 72 29.7) 2.54) "A4") (list 'a3 (/ (* 72 29.7) 2.54) (/ (* 72 42.0) 2.54) "A3") (list 'letter (* 72 8.5) (* 72 11.0) "Letter") (list 'legal (* 72 8.5) (* 72 14.0) "Legal") (list 'letter-small (* 72 7.68) (* 72 10.16) "LetterSmall") (list 'tabloid (* 72 11.0) (* 72 17.0) "Tabloid") (list 'ledger (* 72 17.0) (* 72 11.0) "Ledger") (list 'statement (* 72 5.5) (* 72 8.5) "Statement") (list 'executive (* 72 7.5) (* 72 10.0) "Executive") (list 'a4small (* 72 7.47) (* 72 10.85) "A4Small") (list 'b4 (* 72 10.125) (* 72 14.33) "B4") (list 'b5 (* 72 7.16) (* 72 10.125) "B5") '(addresslarge 236.0 99.0 "AddressLarge") '(addresssmall 236.0 68.0 "AddressSmall") '(cuthanging13 90.0 222.0 "CutHanging13") '(cuthanging15 90.0 114.0 "CutHanging15") '(diskette 181.0 136.0 "Diskette") '(eurofilefolder 139.0 112.0 "EuropeanFilefolder") '(eurofoldernarrow 526.0 107.0 "EuroFolderNarrow") '(eurofolderwide 526.0 136.0 "EuroFolderWide") '(euronamebadge 189.0 108.0 "EuroNameBadge") '(euronamebadgelarge 223.0 136.0 "EuroNameBadgeLarge") '(filefolder 230.0 37.0 "FileFolder") '(jewelry 76.0 136.0 "Jewelry") '(mediabadge 180.0 136.0 "MediaBadge") '(multipurpose 126.0 68.0 "MultiPurpose") '(retaillabel 90.0 104.0 "RetailLabel") '(shipping 271.0 136.0 "Shipping") '(slide35mm 26.0 104.0 "Slide35mm") '(spine8mm 187.0 26.0 "Spine8mm") '(topcoated 425.19685 136.0 "TopCoatedPaper") '(topcoatedpaper 396.0 136.0 "TopcoatedPaper150") '(vhsface 205.0 127.0 "VHSFace") '(vhsspine 400.0 50.0 "VHSSpine") '(zipdisk 156.0 136.0 "ZipDisk"))) "\ +List associating a symbolic paper type to its width, height and doc media. +See `ps-paper-type'.") + +(custom-autoload 'ps-page-dimensions-database "ps-print" t) + +(defvar ps-paper-type 'letter "\ +Specify the size of paper to format for. +Should be one of the paper types defined in `ps-page-dimensions-database', for +example `letter', `legal' or `a4'.") + +(custom-autoload 'ps-paper-type "ps-print" t) + +(defvar ps-print-color-p (or (fboundp 'x-color-values) (fboundp 'color-instance-rgb-components)) "\ +Specify how buffer's text color is printed. + +Valid values are: + + nil Do not print colors. + + t Print colors. + + black-white Print colors on black/white printer. + See also `ps-black-white-faces'. + +Any other value is treated as t.") + +(custom-autoload 'ps-print-color-p "ps-print" t) + +(autoload 'ps-print-customize "ps-print" "\ +Customization of ps-print group. + +\(fn)" t nil) + +(autoload 'ps-print-buffer "ps-print" "\ +Generate and print a PostScript image of the buffer. + +Interactively, when you use a prefix argument (\\[universal-argument]), the command prompts the +user for a file name, and saves the PostScript image in that file instead of +sending it to the printer. + +Noninteractively, the argument FILENAME is treated as follows: if it is nil, +send the image to the printer. If FILENAME is a string, save the PostScript +image in a file with that name. + +\(fn &optional FILENAME)" t nil) + +(autoload 'ps-print-buffer-with-faces "ps-print" "\ +Generate and print a PostScript image of the buffer. +Like `ps-print-buffer', but includes font, color, and underline information in +the generated image. This command works only if you are using a window system, +so it has a way to determine color values. + +\(fn &optional FILENAME)" t nil) + +(autoload 'ps-print-region "ps-print" "\ +Generate and print a PostScript image of the region. +Like `ps-print-buffer', but prints just the current region. + +\(fn FROM TO &optional FILENAME)" t nil) + +(autoload 'ps-print-region-with-faces "ps-print" "\ +Generate and print a PostScript image of the region. +Like `ps-print-region', but includes font, color, and underline information in +the generated image. This command works only if you are using a window system, +so it has a way to determine color values. + +\(fn FROM TO &optional FILENAME)" t nil) + +(autoload 'ps-spool-buffer "ps-print" "\ +Generate and spool a PostScript image of the buffer. +Like `ps-print-buffer' except that the PostScript image is saved in a local +buffer to be sent to the printer later. + +Use the command `ps-despool' to send the spooled images to the printer. + +\(fn)" t nil) + +(autoload 'ps-spool-buffer-with-faces "ps-print" "\ +Generate and spool a PostScript image of the buffer. +Like the command `ps-spool-buffer', but includes font, color, and underline +information in the generated image. This command works only if you are using +a window system, so it has a way to determine color values. + +Use the command `ps-despool' to send the spooled images to the printer. + +\(fn)" t nil) + +(autoload 'ps-spool-region "ps-print" "\ +Generate a PostScript image of the region and spool locally. +Like `ps-spool-buffer', but spools just the current region. + +Use the command `ps-despool' to send the spooled images to the printer. + +\(fn FROM TO)" t nil) + +(autoload 'ps-spool-region-with-faces "ps-print" "\ +Generate a PostScript image of the region and spool locally. +Like `ps-spool-region', but includes font, color, and underline information in +the generated image. This command works only if you are using a window system, +so it has a way to determine color values. + +Use the command `ps-despool' to send the spooled images to the printer. + +\(fn FROM TO)" t nil) + +(autoload 'ps-despool "ps-print" "\ +Send the spooled PostScript to the printer. + +Interactively, when you use a prefix argument (\\[universal-argument]), the command prompts the +user for a file name, and saves the spooled PostScript image in that file +instead of sending it to the printer. + +Noninteractively, the argument FILENAME is treated as follows: if it is nil, +send the image to the printer. If FILENAME is a string, save the PostScript +image in a file with that name. + +\(fn &optional FILENAME)" t nil) + +(autoload 'ps-line-lengths "ps-print" "\ +Display the correspondence between a line length and a font size. +Done using the current ps-print setup. +Try: pr -t file | awk \\='{printf \"%3d %s +\", length($0), $0}\\=' | sort -r | head + +\(fn)" t nil) + +(autoload 'ps-nb-pages-buffer "ps-print" "\ +Display number of pages to print this buffer, for various font heights. +The table depends on the current ps-print setup. + +\(fn NB-LINES)" t nil) + +(autoload 'ps-nb-pages-region "ps-print" "\ +Display number of pages to print the region, for various font heights. +The table depends on the current ps-print setup. + +\(fn NB-LINES)" t nil) + +(autoload 'ps-setup "ps-print" "\ +Return the current PostScript-generation setup. + +\(fn)" nil nil) + +(autoload 'ps-extend-face-list "ps-print" "\ +Extend face in ALIST-SYM. + +If optional MERGE-P is non-nil, extensions in FACE-EXTENSION-LIST are merged +with face extension in ALIST-SYM; otherwise, overrides. + +If optional ALIST-SYM is nil, `ps-print-face-extension-alist' is used; +otherwise, it should be an alist symbol. + +The elements in FACE-EXTENSION-LIST are like those for `ps-extend-face'. + +See `ps-extend-face' for documentation. + +\(fn FACE-EXTENSION-LIST &optional MERGE-P ALIST-SYM)" nil nil) + +(autoload 'ps-extend-face "ps-print" "\ +Extend face in ALIST-SYM. + +If optional MERGE-P is non-nil, extensions in FACE-EXTENSION list are merged +with face extensions in ALIST-SYM; otherwise, overrides. + +If optional ALIST-SYM is nil, `ps-print-face-extension-alist' is used; +otherwise, it should be an alist symbol. + +The elements of FACE-EXTENSION list have the form: + + (FACE-NAME FOREGROUND BACKGROUND EXTENSION...) + +FACE-NAME is a face name symbol. + +FOREGROUND and BACKGROUND may be nil or a string that denotes the +foreground and background colors respectively. + +EXTENSION is one of the following symbols: + bold - use bold font. + italic - use italic font. + underline - put a line under text. + strikeout - like underline, but the line is in middle of text. + overline - like underline, but the line is over the text. + shadow - text will have a shadow. + box - text will be surrounded by a box. + outline - print characters as hollow outlines. + +If EXTENSION is any other symbol, it is ignored. + +\(fn FACE-EXTENSION &optional MERGE-P ALIST-SYM)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ps-print" '("ps-"))) + +;;;*** + +;;;### (autoloads nil "ps-samp" "ps-samp.el" (0 0 0 0)) +;;; Generated autoloads from ps-samp.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ps-samp" '("ps-"))) + +;;;*** + +;;;### (autoloads nil "pulse" "cedet/pulse.el" (0 0 0 0)) +;;; Generated autoloads from cedet/pulse.el +(push (purecopy '(pulse 1 0)) package--builtin-versions) + +(autoload 'pulse-momentary-highlight-one-line "pulse" "\ +Highlight the line around POINT, unhighlighting before next command. +Optional argument FACE specifies the face to do the highlighting. + +\(fn POINT &optional FACE)" nil nil) + +(autoload 'pulse-momentary-highlight-region "pulse" "\ +Highlight between START and END, unhighlighting before next command. +Optional argument FACE specifies the face to do the highlighting. + +\(fn START END &optional FACE)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pulse" '("pulse-"))) + +;;;*** + +;;;### (autoloads nil "puny" "net/puny.el" (0 0 0 0)) +;;; Generated autoloads from net/puny.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "puny" '("puny-"))) + +;;;*** + +;;;### (autoloads nil "python" "progmodes/python.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/python.el +(push (purecopy '(python 0 25 2)) package--builtin-versions) + +(add-to-list 'auto-mode-alist (cons (purecopy "\\.pyw?\\'") 'python-mode)) + +(add-to-list 'interpreter-mode-alist (cons (purecopy "python[0-9.]*") 'python-mode)) + +(autoload 'run-python "python" "\ +Run an inferior Python process. + +Argument CMD defaults to `python-shell-calculate-command' return +value. When called interactively with `prefix-arg', it allows +the user to edit such value and choose whether the interpreter +should be DEDICATED for the current buffer. When numeric prefix +arg is other than 0 or 4 do not SHOW. + +For a given buffer and same values of DEDICATED, if a process is +already running for it, it will do nothing. This means that if +the current buffer is using a global process, the user is still +able to switch it to use a dedicated one. + +Runs the hook `inferior-python-mode-hook' after +`comint-mode-hook' is run. (Type \\[describe-mode] in the +process buffer for a list of commands.) + +\(fn &optional CMD DEDICATED SHOW)" t nil) + +(autoload 'python-mode "python" "\ +Major mode for editing Python files. + +\\{python-mode-map} + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "python" '("python-" "run-python-internal" "inferior-python-mode"))) + +;;;*** + +;;;### (autoloads nil "qp" "mail/qp.el" (0 0 0 0)) +;;; Generated autoloads from mail/qp.el + +(autoload 'quoted-printable-decode-region "qp" "\ +Decode quoted-printable in the region between FROM and TO, per RFC 2045. +If CODING-SYSTEM is non-nil, decode bytes into characters with that +coding-system. + +Interactively, you can supply the CODING-SYSTEM argument +with \\[universal-coding-system-argument]. + +The CODING-SYSTEM argument is a historical hangover and is deprecated. +QP encodes raw bytes and should be decoded into raw bytes. Decoding +them into characters should be done separately. + +\(fn FROM TO &optional CODING-SYSTEM)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "qp" '("quoted-printable-"))) + +;;;*** + +;;;### (autoloads nil "quail" "international/quail.el" (0 0 0 0)) +;;; Generated autoloads from international/quail.el + +(autoload 'quail-title "quail" "\ +Return the title of the current Quail package. + +\(fn)" nil nil) + +(autoload 'quail-use-package "quail" "\ +Start using Quail package PACKAGE-NAME. +The remaining arguments are LIBRARIES to be loaded before using the package. + +This activates input method defined by PACKAGE-NAME by running +`quail-activate', which see. + +\(fn PACKAGE-NAME &rest LIBRARIES)" nil nil) + +(autoload 'quail-define-package "quail" "\ +Define NAME as a new Quail package for input LANGUAGE. +TITLE is a string to be displayed at mode-line to indicate this package. +Optional arguments are GUIDANCE, DOCSTRING, TRANSLATION-KEYS, + FORGET-LAST-SELECTION, DETERMINISTIC, KBD-TRANSLATE, SHOW-LAYOUT, + CREATE-DECODE-MAP, MAXIMUM-SHORTEST, OVERLAY-PLIST, + UPDATE-TRANSLATION-FUNCTION, CONVERSION-KEYS and SIMPLE. + +GUIDANCE specifies how a guidance string is shown in echo area. +If it is t, list of all possible translations for the current key is shown + with the currently selected translation being highlighted. +If it is an alist, the element has the form (CHAR . STRING). Each character + in the current key is searched in the list and the corresponding string is + shown. +If it is nil, the current key is shown. + +DOCSTRING is the documentation string of this package. The command +`describe-input-method' shows this string while replacing the form +\\=\\<VAR> in the string by the value of VAR. That value should be a +string. For instance, the form \\=\\<quail-translation-docstring> is +replaced by a description about how to select a translation from a +list of candidates. + +TRANSLATION-KEYS specifies additional key bindings used while translation +region is active. It is an alist of single key character vs. corresponding +command to be called. + +FORGET-LAST-SELECTION non-nil means a selected translation is not kept +for the future to translate the same key. If this flag is nil, a +translation selected for a key is remembered so that it can be the +first candidate when the same key is entered later. + +DETERMINISTIC non-nil means the first candidate of translation is +selected automatically without allowing users to select another +translation for a key. In this case, unselected translations are of +no use for an interactive use of Quail but can be used by some other +programs. If this flag is non-nil, FORGET-LAST-SELECTION is also set +to t. + +KBD-TRANSLATE non-nil means input characters are translated from a +user's keyboard layout to the standard keyboard layout. See the +documentation of `quail-keyboard-layout' and +`quail-keyboard-layout-standard' for more detail. + +SHOW-LAYOUT non-nil means the function `quail-help' (as used by +the command `describe-input-method') should show the user's keyboard +layout visually with translated characters. If KBD-TRANSLATE is +set, it is desirable to also set this flag, unless this package +defines no translations for single character keys. + +CREATE-DECODE-MAP non-nil means decode map is also created. A decode +map is an alist of translations and corresponding original keys. +Although this map is not used by Quail itself, it can be used by some +other programs. For instance, Vietnamese supporting needs this map to +convert Vietnamese text to VIQR format which uses only ASCII +characters to represent Vietnamese characters. + +MAXIMUM-SHORTEST non-nil means break key sequence to get maximum +length of the shortest sequence. When we don't have a translation of +key \"..ABCD\" but have translations of \"..AB\" and \"CD..\", break +the key at \"..AB\" and start translation of \"CD..\". Hangul +packages, for instance, use this facility. If this flag is nil, we +break the key just at \"..ABC\" and start translation of \"D..\". + +OVERLAY-PLIST if non-nil is a property list put on an overlay which +covers Quail translation region. + +UPDATE-TRANSLATION-FUNCTION if non-nil is a function to call to update +the current translation region according to a new translation data. By +default, a translated text or a user's key sequence (if no translation +for it) is inserted. + +CONVERSION-KEYS specifies additional key bindings used while +conversion region is active. It is an alist of single key character +vs. corresponding command to be called. + +If SIMPLE is non-nil, then we do not alter the meanings of +commands such as C-f, C-b, C-n, C-p and TAB; they are treated as +non-Quail commands. + +\(fn NAME LANGUAGE TITLE &optional GUIDANCE DOCSTRING TRANSLATION-KEYS FORGET-LAST-SELECTION DETERMINISTIC KBD-TRANSLATE SHOW-LAYOUT CREATE-DECODE-MAP MAXIMUM-SHORTEST OVERLAY-PLIST UPDATE-TRANSLATION-FUNCTION CONVERSION-KEYS SIMPLE)" nil nil) + +(autoload 'quail-set-keyboard-layout "quail" "\ +Set the current keyboard layout to the same as keyboard KBD-TYPE. + +Since some Quail packages depends on a physical layout of keys (not +characters generated by them), those are created by assuming the +standard layout defined in `quail-keyboard-layout-standard'. This +function tells Quail system the layout of your keyboard so that what +you type is correctly handled. + +\(fn KBD-TYPE)" t nil) + +(autoload 'quail-show-keyboard-layout "quail" "\ +Show the physical layout of the keyboard type KEYBOARD-TYPE. + +The variable `quail-keyboard-layout-type' holds the currently selected +keyboard type. + +\(fn &optional KEYBOARD-TYPE)" t nil) + +(autoload 'quail-define-rules "quail" "\ +Define translation rules of the current Quail package. +Each argument is a list of KEY and TRANSLATION. +KEY is a string meaning a sequence of keystrokes to be translated. +TRANSLATION is a character, a string, a vector, a Quail map, or a function. +If it is a character, it is the sole translation of KEY. +If it is a string, each character is a candidate for the translation. +If it is a vector, each element (string or character) is a candidate + for the translation. +In these cases, a key specific Quail map is generated and assigned to KEY. + +If TRANSLATION is a Quail map or a function symbol which returns a Quail map, + it is used to handle KEY. + +The first argument may be an alist of annotations for the following +rules. Each element has the form (ANNOTATION . VALUE), where +ANNOTATION is a symbol indicating the annotation type. Currently +the following annotation types are supported. + + append -- the value non-nil means that the following rules should + be appended to the rules of the current Quail package. + + face -- the value is a face to use for displaying TRANSLATIONs in + candidate list. + + advice -- the value is a function to call after one of RULES is + selected. The function is called with one argument, the + selected TRANSLATION string, after the TRANSLATION is + inserted. + + no-decode-map --- the value non-nil means that decoding map is not + generated for the following translations. + +\(fn &rest RULES)" nil t) + +(autoload 'quail-install-map "quail" "\ +Install the Quail map MAP in the current Quail package. + +Optional 2nd arg NAME, if non-nil, is a name of Quail package for +which to install MAP. + +The installed map can be referred by the function `quail-map'. + +\(fn MAP &optional NAME)" nil nil) + +(autoload 'quail-install-decode-map "quail" "\ +Install the Quail decode map DECODE-MAP in the current Quail package. + +Optional 2nd arg NAME, if non-nil, is a name of Quail package for +which to install MAP. + +The installed decode map can be referred by the function `quail-decode-map'. + +\(fn DECODE-MAP &optional NAME)" nil nil) + +(autoload 'quail-defrule "quail" "\ +Add one translation rule, KEY to TRANSLATION, in the current Quail package. +KEY is a string meaning a sequence of keystrokes to be translated. +TRANSLATION is a character, a string, a vector, a Quail map, + a function, or a cons. +It it is a character, it is the sole translation of KEY. +If it is a string, each character is a candidate for the translation. +If it is a vector, each element (string or character) is a candidate + for the translation. +If it is a cons, the car is one of the above and the cdr is a function + to call when translating KEY (the return value is assigned to the + variable `quail-current-data'). If the cdr part is not a function, + the value itself is assigned to `quail-current-data'. +In these cases, a key specific Quail map is generated and assigned to KEY. + +If TRANSLATION is a Quail map or a function symbol which returns a Quail map, + it is used to handle KEY. + +Optional 3rd argument NAME, if specified, says which Quail package +to define this translation rule in. The default is to define it in the +current Quail package. + +Optional 4th argument APPEND, if non-nil, appends TRANSLATION +to the current translations for KEY instead of replacing them. + +\(fn KEY TRANSLATION &optional NAME APPEND)" nil nil) + +(autoload 'quail-defrule-internal "quail" "\ +Define KEY as TRANS in a Quail map MAP. + +If Optional 4th arg APPEND is non-nil, TRANS is appended to the +current translations for KEY instead of replacing them. + +Optional 5th arg DECODE-MAP is a Quail decode map. + +Optional 6th arg PROPS is a property list annotating TRANS. See the +function `quail-define-rules' for the detail. + +\(fn KEY TRANS MAP &optional APPEND DECODE-MAP PROPS)" nil nil) + +(autoload 'quail-update-leim-list-file "quail" "\ +Update entries for Quail packages in `LEIM' list file in directory DIRNAME. +DIRNAME is a directory containing Emacs input methods; +normally, it should specify the `leim' subdirectory +of the Emacs source tree. + +It searches for Quail packages under `quail' subdirectory of DIRNAME, +and update the file \"leim-list.el\" in DIRNAME. + +When called from a program, the remaining arguments are additional +directory names to search for Quail packages under `quail' subdirectory +of each directory. + +\(fn DIRNAME &rest DIRNAMES)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "quail" '("quail-"))) + +;;;*** + +;;;### (autoloads nil "quail/ethiopic" "leim/quail/ethiopic.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from leim/quail/ethiopic.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "quail/ethiopic" '("ethio-select-a-translation"))) + +;;;*** + +;;;### (autoloads nil "quail/hangul" "leim/quail/hangul.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from leim/quail/hangul.el + +(autoload 'hangul-input-method-activate "quail/hangul" "\ +Activate Hangul input method INPUT-METHOD. +FUNC is a function to handle input key. +HELP-TEXT is a text set in `hangul-input-method-help-text'. + +\(fn INPUT-METHOD FUNC HELP-TEXT &rest ARGS)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "quail/hangul" '("hangul" "alphabetp" "notzerop"))) + +;;;*** + +;;;### (autoloads nil "quail/indian" "leim/quail/indian.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from leim/quail/indian.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "quail/indian" '("inscript-" "quail-"))) + +;;;*** + +;;;### (autoloads nil "quail/ipa" "leim/quail/ipa.el" (0 0 0 0)) +;;; Generated autoloads from leim/quail/ipa.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "quail/ipa" '("ipa-x-sampa-"))) + +;;;*** + +;;;### (autoloads nil "quail/japanese" "leim/quail/japanese.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from leim/quail/japanese.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "quail/japanese" '("quail-japanese-"))) + +;;;*** + +;;;### (autoloads nil "quail/lao" "leim/quail/lao.el" (0 0 0 0)) +;;; Generated autoloads from leim/quail/lao.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "quail/lao" '("lao-" "quail-lao-update-translation"))) + +;;;*** + +;;;### (autoloads nil "quail/lrt" "leim/quail/lrt.el" (0 0 0 0)) +;;; Generated autoloads from leim/quail/lrt.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "quail/lrt" '("quail-lrt-update-translation"))) + +;;;*** + +;;;### (autoloads nil "quail/sisheng" "leim/quail/sisheng.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from leim/quail/sisheng.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "quail/sisheng" '("quail-make-sisheng-rules" "sisheng-"))) + +;;;*** + +;;;### (autoloads nil "quail/thai" "leim/quail/thai.el" (0 0 0 0)) +;;; Generated autoloads from leim/quail/thai.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "quail/thai" '("thai-generate-quail-map"))) + +;;;*** + +;;;### (autoloads nil "quail/tibetan" "leim/quail/tibetan.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from leim/quail/tibetan.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "quail/tibetan" '("quail-tib" "tibetan-"))) + +;;;*** + +;;;### (autoloads nil "quail/uni-input" "leim/quail/uni-input.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from leim/quail/uni-input.el + +(autoload 'ucs-input-activate "quail/uni-input" "\ +Activate UCS input method. +With ARG, activate UCS input method if and only if ARG is positive. + +While this input method is active, the variable +`input-method-function' is bound to the function `ucs-input-method'. + +\(fn &optional ARG)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "quail/uni-input" '("ucs-input-"))) + +;;;*** + +;;;### (autoloads nil "quail/viqr" "leim/quail/viqr.el" (0 0 0 0)) +;;; Generated autoloads from leim/quail/viqr.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "quail/viqr" '("viet-quail-define-rules"))) + +;;;*** + +;;;### (autoloads nil "quickurl" "net/quickurl.el" (0 0 0 0)) +;;; Generated autoloads from net/quickurl.el + +(defconst quickurl-reread-hook-postfix "\n;; Local Variables:\n;; eval: (progn (require 'quickurl) (add-hook 'local-write-file-hooks (lambda () (quickurl-read) nil)))\n;; End:\n" "\ +Example `quickurl-postfix' text that adds a local variable to the +`quickurl-url-file' so that if you edit it by hand it will ensure that +`quickurl-urls' is updated with the new URL list. + +To make use of this do something like: + + (setq quickurl-postfix quickurl-reread-hook-postfix) + +in your init file (after loading/requiring quickurl).") + +(autoload 'quickurl "quickurl" "\ +Insert a URL based on LOOKUP. + +If not supplied LOOKUP is taken to be the word at point in the current +buffer, this default action can be modified via +`quickurl-grab-lookup-function'. + +\(fn &optional LOOKUP)" t nil) + +(autoload 'quickurl-ask "quickurl" "\ +Insert a URL, with `completing-read' prompt, based on LOOKUP. + +\(fn LOOKUP)" t nil) + +(autoload 'quickurl-add-url "quickurl" "\ +Allow the user to interactively add a new URL associated with WORD. + +See `quickurl-grab-url' for details on how the default word/URL combination +is decided. + +\(fn WORD URL COMMENT)" t nil) + +(autoload 'quickurl-browse-url "quickurl" "\ +Browse the URL associated with LOOKUP. + +If not supplied LOOKUP is taken to be the word at point in the +current buffer, this default action can be modified via +`quickurl-grab-lookup-function'. + +\(fn &optional LOOKUP)" t nil) + +(autoload 'quickurl-browse-url-ask "quickurl" "\ +Browse the URL, with `completing-read' prompt, associated with LOOKUP. + +\(fn LOOKUP)" t nil) + +(autoload 'quickurl-edit-urls "quickurl" "\ +Pull `quickurl-url-file' into a buffer for hand editing. + +\(fn)" t nil) + +(autoload 'quickurl-list-mode "quickurl" "\ +A mode for browsing the quickurl URL list. + +The key bindings for `quickurl-list-mode' are: + +\\{quickurl-list-mode-map} + +\(fn)" t nil) + +(autoload 'quickurl-list "quickurl" "\ +Display `quickurl-list' as a formatted list using `quickurl-list-mode'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "quickurl" '("quickurl-"))) + +;;;*** + +;;;### (autoloads nil "radix-tree" "emacs-lisp/radix-tree.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from emacs-lisp/radix-tree.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "radix-tree" '("radix-tree-"))) + +;;;*** + +;;;### (autoloads nil "rcirc" "net/rcirc.el" (0 0 0 0)) +;;; Generated autoloads from net/rcirc.el + +(autoload 'rcirc "rcirc" "\ +Connect to all servers in `rcirc-server-alist'. + +Do not connect to a server if it is already connected. + +If ARG is non-nil, instead prompt for connection parameters. + +\(fn ARG)" t nil) + +(defalias 'irc 'rcirc) + +(autoload 'rcirc-connect "rcirc" "\ + + +\(fn SERVER &optional PORT NICK USER-NAME FULL-NAME STARTUP-CHANNELS PASSWORD ENCRYPTION SERVER-ALIAS)" nil nil) + +(defvar rcirc-track-minor-mode nil "\ +Non-nil if Rcirc-Track minor mode is enabled. +See the `rcirc-track-minor-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `rcirc-track-minor-mode'.") + +(custom-autoload 'rcirc-track-minor-mode "rcirc" nil) + +(autoload 'rcirc-track-minor-mode "rcirc" "\ +Global minor mode for tracking activity in rcirc buffers. +With a prefix argument ARG, enable the mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode +if ARG is omitted or nil. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rcirc" '("rcirc-" "defun-rcirc-command" "set-rcirc-" "with-rcirc-"))) + +;;;*** + +;;;### (autoloads nil "re-builder" "emacs-lisp/re-builder.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from emacs-lisp/re-builder.el + +(defalias 'regexp-builder 're-builder) + +(autoload 're-builder "re-builder" "\ +Construct a regexp interactively. +This command makes the current buffer the \"target\" buffer of +the regexp builder. It displays a buffer named \"*RE-Builder*\" +in another window, initially containing an empty regexp. + +As you edit the regexp in the \"*RE-Builder*\" buffer, the +matching parts of the target buffer will be highlighted. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "re-builder" '("reb-" "re-builder-unload-function"))) + +;;;*** + +;;;### (autoloads nil "recentf" "recentf.el" (0 0 0 0)) +;;; Generated autoloads from recentf.el + +(defvar recentf-mode nil "\ +Non-nil if Recentf mode is enabled. +See the `recentf-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `recentf-mode'.") + +(custom-autoload 'recentf-mode "recentf" nil) + +(autoload 'recentf-mode "recentf" "\ +Toggle \"Open Recent\" menu (Recentf mode). +With a prefix argument ARG, enable Recentf mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +Recentf mode if ARG is omitted or nil. + +When Recentf mode is enabled, a \"Open Recent\" submenu is +displayed in the \"File\" menu, containing a list of files that +were operated on recently. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "recentf" '("recentf-"))) + +;;;*** + +;;;### (autoloads nil "rect" "rect.el" (0 0 0 0)) +;;; Generated autoloads from rect.el + +(autoload 'delete-rectangle "rect" "\ +Delete (don't save) text in the region-rectangle. +The same range of columns is deleted in each line starting with the +line where the region begins and ending with the line where the region +ends. + +When called from a program the rectangle's corners are START and END. +With a prefix (or a FILL) argument, also fill lines where nothing has +to be deleted. + +\(fn START END &optional FILL)" t nil) + +(autoload 'delete-extract-rectangle "rect" "\ +Delete the contents of the rectangle with corners at START and END. +Return it as a list of strings, one for each line of the rectangle. + +When called from a program the rectangle's corners are START and END. +With an optional FILL argument, also fill lines where nothing has to be +deleted. + +\(fn START END &optional FILL)" nil nil) + +(autoload 'extract-rectangle "rect" "\ +Return the contents of the rectangle with corners at START and END. +Return it as a list of strings, one for each line of the rectangle. + +\(fn START END)" nil nil) + +(autoload 'kill-rectangle "rect" "\ +Delete the region-rectangle and save it as the last killed one. + +When called from a program the rectangle's corners are START and END. +You might prefer to use `delete-extract-rectangle' from a program. + +With a prefix (or a FILL) argument, also fill lines where nothing has to be +deleted. + +If the buffer is read-only, Emacs will beep and refrain from deleting +the rectangle, but put it in `killed-rectangle' anyway. This means that +you can use this command to copy text from a read-only buffer. +\(If the variable `kill-read-only-ok' is non-nil, then this won't +even beep.) + +\(fn START END &optional FILL)" t nil) + +(autoload 'copy-rectangle-as-kill "rect" "\ +Copy the region-rectangle and save it as the last killed one. + +\(fn START END)" t nil) + +(autoload 'yank-rectangle "rect" "\ +Yank the last killed rectangle with upper left corner at point. + +\(fn)" t nil) + +(autoload 'insert-rectangle "rect" "\ +Insert text of RECTANGLE with upper left corner at point. +RECTANGLE's first line is inserted at point, its second +line is inserted at a point vertically under point, etc. +RECTANGLE should be a list of strings. +After this command, the mark is at the upper left corner +and point is at the lower right corner. + +\(fn RECTANGLE)" nil nil) + +(autoload 'open-rectangle "rect" "\ +Blank out the region-rectangle, shifting text right. + +The text previously in the region is not overwritten by the blanks, +but instead winds up to the right of the rectangle. + +When called from a program the rectangle's corners are START and END. +With a prefix (or a FILL) argument, fill with blanks even if there is +no text on the right side of the rectangle. + +\(fn START END &optional FILL)" t nil) + +(defalias 'close-rectangle 'delete-whitespace-rectangle) + +(autoload 'delete-whitespace-rectangle "rect" "\ +Delete all whitespace following a specified column in each line. +The left edge of the rectangle specifies the position in each line +at which whitespace deletion should begin. On each line in the +rectangle, all contiguous whitespace starting at that column is deleted. + +When called from a program the rectangle's corners are START and END. +With a prefix (or a FILL) argument, also fill too short lines. + +\(fn START END &optional FILL)" t nil) + +(autoload 'string-rectangle "rect" "\ +Replace rectangle contents with STRING on each line. +The length of STRING need not be the same as the rectangle width. + +Called from a program, takes three args; START, END and STRING. + +\(fn START END STRING)" t nil) + +(defalias 'replace-rectangle 'string-rectangle) + +(autoload 'string-insert-rectangle "rect" "\ +Insert STRING on each line of region-rectangle, shifting text right. + +When called from a program, the rectangle's corners are START and END. +The left edge of the rectangle specifies the column for insertion. +This command does not delete or overwrite any existing text. + +\(fn START END STRING)" t nil) + +(autoload 'clear-rectangle "rect" "\ +Blank out the region-rectangle. +The text previously in the region is overwritten with blanks. + +When called from a program the rectangle's corners are START and END. +With a prefix (or a FILL) argument, also fill with blanks the parts of the +rectangle which were empty. + +\(fn START END &optional FILL)" t nil) + +(autoload 'rectangle-number-lines "rect" "\ +Insert numbers in front of the region-rectangle. + +START-AT, if non-nil, should be a number from which to begin +counting. FORMAT, if non-nil, should be a format string to pass +to `format' along with the line count. When called interactively +with a prefix argument, prompt for START-AT and FORMAT. + +\(fn START END START-AT &optional FORMAT)" t nil) + +(autoload 'rectangle-mark-mode "rect" "\ +Toggle the region as rectangular. +Activates the region if needed. Only lasts until the region is deactivated. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rect" '("rectangle-" "clear-rectangle-line" "spaces-string" "string-rectangle-" "delete-" "ope" "killed-rectangle" "extract-rectangle-" "apply-on-rectangle"))) + +;;;*** + +;;;### (autoloads nil "refbib" "textmodes/refbib.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/refbib.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "refbib" '("r2b-"))) + +;;;*** + +;;;### (autoloads nil "refer" "textmodes/refer.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/refer.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "refer" '("refer-"))) + +;;;*** + +;;;### (autoloads nil "refill" "textmodes/refill.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/refill.el + +(autoload 'refill-mode "refill" "\ +Toggle automatic refilling (Refill mode). +With a prefix argument ARG, enable Refill mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Refill mode is a buffer-local minor mode. When enabled, the +current paragraph is refilled as you edit. Self-inserting +characters only cause refilling if they would cause +auto-filling. + +For true \"word wrap\" behavior, use `visual-line-mode' instead. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "refill" '("refill-"))) + +;;;*** + +;;;### (autoloads nil "reftex" "textmodes/reftex.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/reftex.el +(autoload 'reftex-citation "reftex-cite" nil t) +(autoload 'reftex-all-document-files "reftex-parse") +(autoload 'reftex-isearch-minor-mode "reftex-global" nil t) +(autoload 'reftex-index-phrases-mode "reftex-index" nil t) + +(autoload 'turn-on-reftex "reftex" "\ +Turn on RefTeX mode. + +\(fn)" nil nil) + +(autoload 'reftex-mode "reftex" "\ +Minor mode with distinct support for \\label, \\ref and \\cite in LaTeX. + +\\<reftex-mode-map>A Table of Contents of the entire (multifile) document with browsing +capabilities is available with `\\[reftex-toc]'. + +Labels can be created with `\\[reftex-label]' and referenced with `\\[reftex-reference]'. +When referencing, you get a menu with all labels of a given type and +context of the label definition. The selected label is inserted as a +\\ref macro. + +Citations can be made with `\\[reftex-citation]' which will use a regular expression +to pull out a *formatted* list of articles from your BibTeX +database. The selected citation is inserted as a \\cite macro. + +Index entries can be made with `\\[reftex-index-selection-or-word]' which indexes the word at point +or the current selection. More general index entries are created with +`\\[reftex-index]'. `\\[reftex-display-index]' displays the compiled index. + +Most command have help available on the fly. This help is accessed by +pressing `?' to any prompt mentioning this feature. + +Extensive documentation about RefTeX is available in Info format. +You can view this information with `\\[reftex-info]'. + +\\{reftex-mode-map} +Under X, these and other functions will also be available as `Ref' menu +on the menu bar. + +------------------------------------------------------------------------------ + +\(fn &optional ARG)" t nil) + +(autoload 'reftex-reset-scanning-information "reftex" "\ +Reset the symbols containing information from buffer scanning. +This enforces rescanning the buffer on next use. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "reftex" '("reftex-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "reftex-auc" "textmodes/reftex-auc.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from textmodes/reftex-auc.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "reftex-auc" '("reftex-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "reftex-cite" +;;;;;; "textmodes/reftex-cite.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/reftex-cite.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "reftex-cite" '("reftex-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "reftex-dcr" "textmodes/reftex-dcr.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from textmodes/reftex-dcr.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "reftex-dcr" '("reftex-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "reftex-global" +;;;;;; "textmodes/reftex-global.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/reftex-global.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "reftex-global" '("reftex-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "reftex-index" +;;;;;; "textmodes/reftex-index.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/reftex-index.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "reftex-index" '("reftex-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "reftex-parse" +;;;;;; "textmodes/reftex-parse.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/reftex-parse.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "reftex-parse" '("reftex-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "reftex-ref" "textmodes/reftex-ref.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from textmodes/reftex-ref.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "reftex-ref" '("reftex-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "reftex-sel" "textmodes/reftex-sel.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from textmodes/reftex-sel.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "reftex-sel" '("reftex-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "reftex-toc" "textmodes/reftex-toc.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from textmodes/reftex-toc.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "reftex-toc" '("reftex-"))) + +;;;*** + +;;;### (autoloads nil "reftex-vars" "textmodes/reftex-vars.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from textmodes/reftex-vars.el +(put 'reftex-vref-is-default 'safe-local-variable (lambda (x) (or (stringp x) (symbolp x)))) +(put 'reftex-fref-is-default 'safe-local-variable (lambda (x) (or (stringp x) (symbolp x)))) +(put 'reftex-level-indent 'safe-local-variable 'integerp) +(put 'reftex-guess-label-type 'safe-local-variable (lambda (x) (memq x '(nil t)))) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "reftex-vars" '("reftex-"))) + +;;;*** + +;;;### (autoloads nil "regexp-opt" "emacs-lisp/regexp-opt.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from emacs-lisp/regexp-opt.el + +(autoload 'regexp-opt "regexp-opt" "\ +Return a regexp to match a string in the list STRINGS. +Each string should be unique in STRINGS and should not contain +any regexps, quoted or not. Optional PAREN specifies how the +returned regexp is surrounded by grouping constructs. + +The optional argument PAREN can be any of the following: + +a string + the resulting regexp is preceded by PAREN and followed by + \\), e.g. use \"\\\\(?1:\" to produce an explicitly numbered + group. + +`words' + the resulting regexp is surrounded by \\=\\<\\( and \\)\\>. + +`symbols' + the resulting regexp is surrounded by \\_<\\( and \\)\\_>. + +non-nil + the resulting regexp is surrounded by \\( and \\). + +nil + the resulting regexp is surrounded by \\(?: and \\), if it is + necessary to ensure that a postfix operator appended to it will + apply to the whole expression. + +The resulting regexp is equivalent to but usually more efficient +than that of a simplified version: + + (defun simplified-regexp-opt (strings &optional paren) + (let ((parens + (cond ((stringp paren) (cons paren \"\\\\)\")) + ((eq paren 'words) '(\"\\\\\\=<\\\\(\" . \"\\\\)\\\\>\")) + ((eq paren 'symbols) '(\"\\\\_<\\\\(\" . \"\\\\)\\\\_>\")) + ((null paren) '(\"\\\\(?:\" . \"\\\\)\")) + (t '(\"\\\\(\" . \"\\\\)\"))))) + (concat (car paren) + (mapconcat 'regexp-quote strings \"\\\\|\") + (cdr paren)))) + +\(fn STRINGS &optional PAREN)" nil nil) + +(autoload 'regexp-opt-depth "regexp-opt" "\ +Return the depth of REGEXP. +This means the number of non-shy regexp grouping constructs +\(parenthesized expressions) in REGEXP. + +\(fn REGEXP)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "regexp-opt" '("regexp-opt-"))) + +;;;*** + +;;;### (autoloads nil "regi" "emacs-lisp/regi.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/regi.el +(push (purecopy '(regi 1 8)) package--builtin-versions) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "regi" '("regi-"))) + +;;;*** + +;;;### (autoloads nil "registry" "registry.el" (0 0 0 0)) +;;; Generated autoloads from registry.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "registry" '("registry-"))) + +;;;*** + +;;;### (autoloads nil "remember" "textmodes/remember.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/remember.el +(push (purecopy '(remember 2 0)) package--builtin-versions) + +(autoload 'remember "remember" "\ +Remember an arbitrary piece of data. +INITIAL is the text to initially place in the *Remember* buffer, +or nil to bring up a blank *Remember* buffer. + +With a prefix or a visible region, use the region as INITIAL. + +\(fn &optional INITIAL)" t nil) + +(autoload 'remember-other-frame "remember" "\ +Call `remember' in another frame. + +\(fn &optional INITIAL)" t nil) + +(autoload 'remember-clipboard "remember" "\ +Remember the contents of the current clipboard. +Most useful for remembering things from other applications. + +\(fn)" t nil) + +(autoload 'remember-diary-extract-entries "remember" "\ +Extract diary entries from the region. + +\(fn)" nil nil) + +(autoload 'remember-notes "remember" "\ +Return the notes buffer, creating it if needed, and maybe switch to it. +This buffer is for notes that you want to preserve across Emacs sessions. +The notes are saved in `remember-data-file'. + +If a buffer is already visiting that file, just return it. + +Otherwise, create the buffer, and rename it to `remember-notes-buffer-name', +unless a buffer of that name already exists. Set the major mode according +to `remember-notes-initial-major-mode', and enable `remember-notes-mode' +minor mode. + +Use \\<remember-notes-mode-map>\\[remember-notes-save-and-bury-buffer] to save and bury the notes buffer. + +Interactively, or if SWITCH-TO is non-nil, switch to the buffer. +Return the buffer. + +Set `initial-buffer-choice' to `remember-notes' to visit your notes buffer +when Emacs starts. Set `remember-notes-buffer-name' to \"*scratch*\" +to turn the *scratch* buffer into your notes buffer. + +\(fn &optional SWITCH-TO)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "remember" '("remember-"))) + +;;;*** + +;;;### (autoloads nil "repeat" "repeat.el" (0 0 0 0)) +;;; Generated autoloads from repeat.el +(push (purecopy '(repeat 0 51)) package--builtin-versions) + +(autoload 'repeat "repeat" "\ +Repeat most recently executed command. +If REPEAT-ARG is non-nil (interactively, with a prefix argument), +supply a prefix argument to that command. Otherwise, give the +command the same prefix argument it was given before, if any. + +If this command is invoked by a multi-character key sequence, it +can then be repeated by repeating the final character of that +sequence. This behavior can be modified by the global variable +`repeat-on-final-keystroke'. + +`repeat' ignores commands bound to input events. Hence the term +\"most recently executed command\" shall be read as \"most +recently executed command not bound to an input event\". + +\(fn REPEAT-ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "repeat" '("repeat-"))) + +;;;*** + +;;;### (autoloads nil "reporter" "mail/reporter.el" (0 0 0 0)) +;;; Generated autoloads from mail/reporter.el + +(autoload 'reporter-submit-bug-report "reporter" "\ +Begin submitting a bug report via email. + +ADDRESS is the email address for the package's maintainer. PKGNAME is +the name of the package (if you want to include version numbers, +you must put them into PKGNAME before calling this function). +Optional PRE-HOOKS and POST-HOOKS are passed to `reporter-dump-state'. +Optional SALUTATION is inserted at the top of the mail buffer, +and point is left after the salutation. + +VARLIST is the list of variables to dump (see `reporter-dump-state' +for details). The optional argument PRE-HOOKS and POST-HOOKS are +passed to `reporter-dump-state'. Optional argument SALUTATION is text +to be inserted at the top of the mail buffer; in that case, point is +left after that text. + +This function prompts for a summary if `reporter-prompt-for-summary-p' +is non-nil. + +This function does not send a message; it uses the given information +to initialize a message, which the user can then edit and finally send +\(or decline to send). The variable `mail-user-agent' controls which +mail-sending package is used for editing and sending the message. + +\(fn ADDRESS PKGNAME VARLIST &optional PRE-HOOKS POST-HOOKS SALUTATION)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "reporter" '("reporter-"))) + +;;;*** + +;;;### (autoloads nil "reposition" "reposition.el" (0 0 0 0)) +;;; Generated autoloads from reposition.el + +(autoload 'reposition-window "reposition" "\ +Make the current definition and/or comment visible. +Further invocations move it to the top of the window or toggle the +visibility of comments that precede it. + Point is left unchanged unless prefix ARG is supplied. + If the definition is fully onscreen, it is moved to the top of the +window. If it is partly offscreen, the window is scrolled to get the +definition (or as much as will fit) onscreen, unless point is in a comment +which is also partly offscreen, in which case the scrolling attempts to get +as much of the comment onscreen as possible. + Initially `reposition-window' attempts to make both the definition and +preceding comments visible. Further invocations toggle the visibility of +the comment lines. + If ARG is non-nil, point may move in order to make the whole defun +visible (if only part could otherwise be made so), to make the defun line +visible (if point is in code and it could not be made so, or if only +comments, including the first comment line, are visible), or to make the +first comment line visible (if point is in a comment). + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "reposition" '("repos-count-screen-lines"))) + +;;;*** + +;;;### (autoloads nil "reveal" "reveal.el" (0 0 0 0)) +;;; Generated autoloads from reveal.el + +(autoload 'reveal-mode "reveal" "\ +Toggle uncloaking of invisible text near point (Reveal mode). +With a prefix argument ARG, enable Reveal mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +Reveal mode if ARG is omitted or nil. + +Reveal mode is a buffer-local minor mode. When enabled, it +reveals invisible text around point. + +\(fn &optional ARG)" t nil) + +(defvar global-reveal-mode nil "\ +Non-nil if Global Reveal mode is enabled. +See the `global-reveal-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `global-reveal-mode'.") + +(custom-autoload 'global-reveal-mode "reveal" nil) + +(autoload 'global-reveal-mode "reveal" "\ +Toggle Reveal mode in all buffers (Global Reveal mode). +Reveal mode renders invisible text around point visible again. + +With a prefix argument ARG, enable Global Reveal mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "reveal" '("reveal-"))) + +;;;*** + +;;;### (autoloads nil "rfc1843" "international/rfc1843.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from international/rfc1843.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rfc1843" '("rfc1843-"))) + +;;;*** + +;;;### (autoloads nil "rfc2045" "mail/rfc2045.el" (0 0 0 0)) +;;; Generated autoloads from mail/rfc2045.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rfc2045" '("rfc2045-encode-string"))) + +;;;*** + +;;;### (autoloads nil "rfc2047" "mail/rfc2047.el" (0 0 0 0)) +;;; Generated autoloads from mail/rfc2047.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rfc2047" '("rfc2047-"))) + +;;;*** + +;;;### (autoloads nil "rfc2104" "net/rfc2104.el" (0 0 0 0)) +;;; Generated autoloads from net/rfc2104.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rfc2104" '("rfc2104-"))) + +;;;*** + +;;;### (autoloads nil "rfc2231" "mail/rfc2231.el" (0 0 0 0)) +;;; Generated autoloads from mail/rfc2231.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rfc2231" '("rfc2231-"))) + +;;;*** + +;;;### (autoloads nil "rfc2368" "mail/rfc2368.el" (0 0 0 0)) +;;; Generated autoloads from mail/rfc2368.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rfc2368" '("rfc2368-"))) + +;;;*** + +;;;### (autoloads nil "rfc822" "mail/rfc822.el" (0 0 0 0)) +;;; Generated autoloads from mail/rfc822.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rfc822" '("rfc822-"))) + +;;;*** + +;;;### (autoloads nil "ring" "emacs-lisp/ring.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/ring.el + +(autoload 'ring-p "ring" "\ +Return t if X is a ring; nil otherwise. + +\(fn X)" nil nil) + +(autoload 'make-ring "ring" "\ +Make a ring that can contain SIZE elements. + +\(fn SIZE)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ring" '("ring-"))) + +;;;*** + +;;;### (autoloads nil "rlogin" "net/rlogin.el" (0 0 0 0)) +;;; Generated autoloads from net/rlogin.el + +(autoload 'rlogin "rlogin" "\ +Open a network login connection via `rlogin' with args INPUT-ARGS. +INPUT-ARGS should start with a host name; it may also contain +other arguments for `rlogin'. + +Input is sent line-at-a-time to the remote connection. + +Communication with the remote host is recorded in a buffer `*rlogin-HOST*' +\(or `*rlogin-USER@HOST*' if the remote username differs). +If a prefix argument is given and the buffer `*rlogin-HOST*' already exists, +a new buffer with a different connection will be made. + +When called from a program, if the optional second argument BUFFER is +a string or buffer, it specifies the buffer to use. + +The variable `rlogin-program' contains the name of the actual program to +run. It can be a relative or absolute path. + +The variable `rlogin-explicit-args' is a list of arguments to give to +the rlogin when starting. They are added after any arguments given in +INPUT-ARGS. + +If the default value of `rlogin-directory-tracking-mode' is t, then the +default directory in that buffer is set to a remote (FTP) file name to +access your home directory on the remote machine. Occasionally this causes +an error, if you cannot access the home directory on that machine. This +error is harmless as long as you don't try to use that default directory. + +If `rlogin-directory-tracking-mode' is neither t nor nil, then the default +directory is initially set up to your (local) home directory. +This is useful if the remote machine and your local machine +share the same files via NFS. This is the default. + +If you wish to change directory tracking styles during a session, use the +function `rlogin-directory-tracking-mode' rather than simply setting the +variable. + +\(fn INPUT-ARGS &optional BUFFER)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rlogin" '("rlogin-"))) + +;;;*** + +;;;### (autoloads nil "rmail" "mail/rmail.el" (0 0 0 0)) +;;; Generated autoloads from mail/rmail.el + +(defvar rmail-file-name (purecopy "~/RMAIL") "\ +Name of user's primary mail file.") + +(custom-autoload 'rmail-file-name "rmail" t) + +(put 'rmail-spool-directory 'standard-value '((cond ((file-exists-p "/var/mail") "/var/mail/") ((file-exists-p "/var/spool/mail") "/var/spool/mail/") ((memq system-type '(hpux usg-unix-v)) "/usr/mail/") (t "/usr/spool/mail/")))) + +(defvar rmail-spool-directory (purecopy (cond ((file-exists-p "/var/mail") "/var/mail/") ((file-exists-p "/var/spool/mail") "/var/spool/mail/") ((memq system-type '(hpux usg-unix-v)) "/usr/mail/") (t "/usr/spool/mail/"))) "\ +Name of directory used by system mailer for delivering new mail. +Its name should end with a slash.") + +(custom-autoload 'rmail-spool-directory "rmail" t) +(custom-initialize-delay 'rmail-spool-directory nil) + +(autoload 'rmail-movemail-variant-p "rmail" "\ +Return t if the current movemail variant is any of VARIANTS. +Currently known variants are `emacs' and `mailutils'. + +\(fn &rest VARIANTS)" nil nil) + +(defvar rmail-user-mail-address-regexp nil "\ +Regexp matching user mail addresses. +If non-nil, this variable is used to identify the correspondent +when receiving new mail. If it matches the address of the sender, +the recipient is taken as correspondent of a mail. +If nil (default value), your `user-login-name' and `user-mail-address' +are used to exclude yourself as correspondent. + +Usually you don't have to set this variable, except if you collect mails +sent by you under different user names. +Then it should be a regexp matching your mail addresses. + +Setting this variable has an effect only before reading a mail.") + +(custom-autoload 'rmail-user-mail-address-regexp "rmail" t) + +(define-obsolete-variable-alias 'rmail-dont-reply-to-names 'mail-dont-reply-to-names "24.1") + +(defvar rmail-default-dont-reply-to-names nil "\ +Regexp specifying part of the default value of `mail-dont-reply-to-names'. +This is used when the user does not set `mail-dont-reply-to-names' +explicitly.") + +(make-obsolete-variable 'rmail-default-dont-reply-to-names 'mail-dont-reply-to-names "24.1") + +(defvar rmail-ignored-headers (purecopy (concat "^via:\\|^mail-from:\\|^origin:\\|^references:\\|^sender:" "\\|^status:\\|^received:\\|^x400-originator:\\|^x400-recipients:" "\\|^x400-received:\\|^x400-mts-identifier:\\|^x400-content-type:" "\\|^\\(resent-\\|\\)message-id:\\|^summary-line:\\|^resent-date:" "\\|^nntp-posting-host:\\|^path:\\|^x-char.*:\\|^x-face:\\|^face:" "\\|^x-mailer:\\|^delivered-to:\\|^lines:" "\\|^content-transfer-encoding:\\|^x-coding-system:" "\\|^return-path:\\|^errors-to:\\|^return-receipt-to:" "\\|^precedence:\\|^mime-version:" "\\|^list-owner:\\|^list-help:\\|^list-post:\\|^list-subscribe:" "\\|^list-id:\\|^list-unsubscribe:\\|^list-archive:" "\\|^content-length:\\|^nntp-posting-date:\\|^user-agent" "\\|^importance:\\|^envelope-to:\\|^delivery-date\\|^openpgp:" "\\|^mbox-line:\\|^cancel-lock:" "\\|^DomainKey-Signature:\\|^dkim-signature:" "\\|^ARC-.*:" "\\|^Received-SPF:" "\\|^Authentication-Results:" "\\|^resent-face:\\|^resent-x.*:\\|^resent-organization:\\|^resent-openpgp:" "\\|^x-.*:")) "\ +Regexp to match header fields that Rmail should normally hide. +\(See also `rmail-nonignored-headers', which overrides this regexp.) +This variable is used for reformatting the message header, +which normally happens once for each message, +when you view the message for the first time in Rmail. +To make a change in this variable take effect +for a message that you have already viewed, +go to that message and type \\[rmail-toggle-header] twice.") + +(custom-autoload 'rmail-ignored-headers "rmail" t) + +(defvar rmail-displayed-headers nil "\ +Regexp to match Header fields that Rmail should display. +If nil, display all header fields except those matched by +`rmail-ignored-headers'.") + +(custom-autoload 'rmail-displayed-headers "rmail" t) + +(defvar rmail-retry-ignored-headers (purecopy "^x-authentication-warning:\\|^x-detected-operating-system:\\|^x-spam[-a-z]*:\\|content-type:\\|content-transfer-encoding:\\|mime-version:\\|message-id:") "\ +Headers that should be stripped when retrying a failed message.") + +(custom-autoload 'rmail-retry-ignored-headers "rmail" t) + +(defvar rmail-highlighted-headers (purecopy "^From:\\|^Subject:") "\ +Regexp to match Header fields that Rmail should normally highlight. +A value of nil means don't highlight. Uses the face `rmail-highlight'.") + +(custom-autoload 'rmail-highlighted-headers "rmail" t) + +(defvar rmail-primary-inbox-list nil "\ +List of files that are inboxes for your primary mail file `rmail-file-name'. +If this is nil, uses the environment variable MAIL. If that is +unset, uses a file named by the function `user-login-name' in the +directory `rmail-spool-directory' (whose value depends on the +operating system). For example, \"/var/mail/USER\".") + +(custom-autoload 'rmail-primary-inbox-list "rmail" t) + +(defvar rmail-secondary-file-directory (purecopy "~/") "\ +Directory for additional secondary Rmail files.") + +(custom-autoload 'rmail-secondary-file-directory "rmail" t) + +(defvar rmail-secondary-file-regexp (purecopy "\\.xmail$") "\ +Regexp for which files are secondary Rmail files.") + +(custom-autoload 'rmail-secondary-file-regexp "rmail" t) + +(defvar rmail-mode-hook nil "\ +List of functions to call when Rmail is invoked.") + +(defvar rmail-show-message-hook nil "\ +List of functions to call when Rmail displays a message.") + +(custom-autoload 'rmail-show-message-hook "rmail" t) + +(defvar rmail-file-coding-system nil "\ +Coding system used in RMAIL file. + +This is set to nil by default.") + +(defvar rmail-insert-mime-forwarded-message-function nil "\ +Function to insert a message in MIME format so it can be forwarded. +This function is called if `rmail-enable-mime' and +`rmail-enable-mime-composing' are non-nil. +It is called with one argument FORWARD-BUFFER, which is a +buffer containing the message to forward. The current buffer +is the outgoing mail buffer.") + +(autoload 'rmail "rmail" "\ +Read and edit incoming mail. +Moves messages into file named by `rmail-file-name' and edits that +file in RMAIL Mode. +Type \\[describe-mode] once editing that file, for a list of RMAIL commands. + +May be called with file name as argument; then performs rmail editing on +that file, but does not copy any new mail into the file. +Interactively, if you supply a prefix argument, then you +have a chance to specify a file name with the minibuffer. + +If `rmail-display-summary' is non-nil, make a summary for this RMAIL file. + +\(fn &optional FILE-NAME-ARG)" t nil) + +(autoload 'rmail-mode "rmail" "\ +Rmail Mode is used by \\<rmail-mode-map>\\[rmail] for editing Rmail files. +All normal editing commands are turned off. +Instead, these commands are available: + +\\[rmail-beginning-of-message] Move point to front of this message. +\\[rmail-end-of-message] Move point to bottom of this message. +\\[scroll-up] Scroll to next screen of this message. +\\[scroll-down] Scroll to previous screen of this message. +\\[rmail-next-undeleted-message] Move to Next non-deleted message. +\\[rmail-previous-undeleted-message] Move to Previous non-deleted message. +\\[rmail-next-message] Move to Next message whether deleted or not. +\\[rmail-previous-message] Move to Previous message whether deleted or not. +\\[rmail-first-message] Move to the first message in Rmail file. +\\[rmail-last-message] Move to the last message in Rmail file. +\\[rmail-show-message] Jump to message specified by numeric position in file. +\\[rmail-search] Search for string and show message it is found in. +\\[rmail-delete-forward] Delete this message, move to next nondeleted. +\\[rmail-delete-backward] Delete this message, move to previous nondeleted. +\\[rmail-undelete-previous-message] Undelete message. Tries current message, then earlier messages + till a deleted message is found. +\\[rmail-edit-current-message] Edit the current message. \\[rmail-cease-edit] to return to Rmail. +\\[rmail-expunge] Expunge deleted messages. +\\[rmail-expunge-and-save] Expunge and save the file. +\\[rmail-quit] Quit Rmail: expunge, save, then switch to another buffer. +\\[save-buffer] Save without expunging. +\\[rmail-get-new-mail] Move new mail from system spool directory into this file. +\\[rmail-mail] Mail a message (same as \\[mail-other-window]). +\\[rmail-continue] Continue composing outgoing message started before. +\\[rmail-reply] Reply to this message. Like \\[rmail-mail] but initializes some fields. +\\[rmail-retry-failure] Send this message again. Used on a mailer failure message. +\\[rmail-forward] Forward this message to another user. +\\[rmail-output] Output (append) this message to another mail file. +\\[rmail-output-as-seen] Output (append) this message to file as it's displayed. +\\[rmail-output-body-to-file] Save message body to a file. Default filename comes from Subject line. +\\[rmail-input] Input Rmail file. Run Rmail on that file. +\\[rmail-add-label] Add label to message. It will be displayed in the mode line. +\\[rmail-kill-label] Kill label. Remove a label from current message. +\\[rmail-next-labeled-message] Move to Next message with specified label + (label defaults to last one specified). + Standard labels: filed, unseen, answered, forwarded, deleted. + Any other label is present only if you add it with \\[rmail-add-label]. +\\[rmail-previous-labeled-message] Move to Previous message with specified label +\\[rmail-summary] Show headers buffer, with a one line summary of each message. +\\[rmail-summary-by-labels] Summarize only messages with particular label(s). +\\[rmail-summary-by-recipients] Summarize only messages with particular recipient(s). +\\[rmail-summary-by-regexp] Summarize only messages with particular regexp(s). +\\[rmail-summary-by-topic] Summarize only messages with subject line regexp(s). +\\[rmail-toggle-header] Toggle display of complete header. + +\(fn)" t nil) + +(autoload 'rmail-input "rmail" "\ +Run Rmail on file FILENAME. + +\(fn FILENAME)" t nil) + +(autoload 'rmail-set-remote-password "rmail" "\ +Set PASSWORD to be used for retrieving mail from a POP or IMAP server. + +\(fn PASSWORD)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rmail" '("rmail-" "mail-"))) + +;;;*** + +;;;### (autoloads nil "rmail-spam-filter" "mail/rmail-spam-filter.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from mail/rmail-spam-filter.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rmail-spam-filter" '("rmail-" "rsf-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "rmailedit" "mail/rmailedit.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from mail/rmailedit.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rmailedit" '("rmail-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "rmailkwd" "mail/rmailkwd.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from mail/rmailkwd.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rmailkwd" '("rmail-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "rmailmm" "mail/rmailmm.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from mail/rmailmm.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rmailmm" '("rmail-"))) + +;;;*** + +;;;### (autoloads nil "rmailout" "mail/rmailout.el" (0 0 0 0)) +;;; Generated autoloads from mail/rmailout.el +(put 'rmail-output-file-alist 'risky-local-variable t) + +(autoload 'rmail-output "rmailout" "\ +Append this message to mail file FILE-NAME. +Writes mbox format, unless FILE-NAME exists and is Babyl format, in which +case it writes Babyl. + +Interactively, the default file name comes from `rmail-default-file', +which is updated to the name you use in this command. In all uses, if +FILE-NAME is not absolute, it is expanded with the directory part of +`rmail-default-file'. + +If a buffer is visiting FILE-NAME, adds the text to that buffer +rather than saving the file directly. If the buffer is an Rmail +buffer, updates it accordingly. + +This command always outputs the complete message header, even if +the header display is currently pruned. + +Optional prefix argument COUNT (default 1) says to output that +many consecutive messages, starting with the current one (ignoring +deleted messages). If `rmail-delete-after-output' is non-nil, deletes +messages after output. + +The optional third argument NOATTRIBUTE, if non-nil, says not to +set the `filed' attribute, and not to display a \"Wrote file\" +message (if writing a file directly). + +Set the optional fourth argument NOT-RMAIL non-nil if you call this +from a non-Rmail buffer. In this case, COUNT is ignored. + +\(fn FILE-NAME &optional COUNT NOATTRIBUTE NOT-RMAIL)" t nil) + +(autoload 'rmail-output-as-seen "rmailout" "\ +Append this message to mbox file named FILE-NAME. +The details are as for `rmail-output', except that: + i) the header is output as currently seen + ii) this function cannot write to Babyl files +iii) an Rmail buffer cannot be visiting FILE-NAME + +Note that if NOT-RMAIL is non-nil, there is no difference between this +function and `rmail-output'. This argument may be removed in future, +so you should call `rmail-output' directly in that case. + +\(fn FILE-NAME &optional COUNT NOATTRIBUTE NOT-RMAIL)" t nil) + +(autoload 'rmail-output-body-to-file "rmailout" "\ +Write this message body to the file FILE-NAME. +Interactively, the default file name comes from either the message +\"Subject\" header, or from `rmail-default-body-file'. Updates the value +of `rmail-default-body-file' accordingly. In all uses, if FILE-NAME +is not absolute, it is expanded with the directory part of +`rmail-default-body-file'. + +Note that this overwrites FILE-NAME (after confirmation), rather +than appending to it. Deletes the message after writing if +`rmail-delete-after-output' is non-nil. + +\(fn FILE-NAME)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rmailout" '("rmail-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "rmailsort" "mail/rmailsort.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from mail/rmailsort.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rmailsort" '("rmail-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "rmailsum" "mail/rmailsum.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from mail/rmailsum.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rmailsum" '("rmail-"))) + +;;;*** + +;;;### (autoloads nil "rng-cmpct" "nxml/rng-cmpct.el" (0 0 0 0)) +;;; Generated autoloads from nxml/rng-cmpct.el + +(autoload 'rng-c-load-schema "rng-cmpct" "\ +Load a schema in RELAX NG compact syntax from FILENAME. +Return a pattern. + +\(fn FILENAME)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rng-cmpct" '("rng-"))) + +;;;*** + +;;;### (autoloads nil "rng-dt" "nxml/rng-dt.el" (0 0 0 0)) +;;; Generated autoloads from nxml/rng-dt.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rng-dt" '("rng-dt-"))) + +;;;*** + +;;;### (autoloads nil "rng-loc" "nxml/rng-loc.el" (0 0 0 0)) +;;; Generated autoloads from nxml/rng-loc.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rng-loc" '("rng-"))) + +;;;*** + +;;;### (autoloads nil "rng-maint" "nxml/rng-maint.el" (0 0 0 0)) +;;; Generated autoloads from nxml/rng-maint.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rng-maint" '("rng-"))) + +;;;*** + +;;;### (autoloads nil "rng-match" "nxml/rng-match.el" (0 0 0 0)) +;;; Generated autoloads from nxml/rng-match.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rng-match" '("rng-"))) + +;;;*** + +;;;### (autoloads nil "rng-nxml" "nxml/rng-nxml.el" (0 0 0 0)) +;;; Generated autoloads from nxml/rng-nxml.el + +(autoload 'rng-nxml-mode-init "rng-nxml" "\ +Initialize `nxml-mode' to take advantage of `rng-validate-mode'. +This is typically called from `nxml-mode-hook'. +Validation will be enabled if `rng-nxml-auto-validate-flag' is non-nil. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rng-nxml" '("rng-"))) + +;;;*** + +;;;### (autoloads nil "rng-parse" "nxml/rng-parse.el" (0 0 0 0)) +;;; Generated autoloads from nxml/rng-parse.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rng-parse" '("rng-parse-"))) + +;;;*** + +;;;### (autoloads nil "rng-pttrn" "nxml/rng-pttrn.el" (0 0 0 0)) +;;; Generated autoloads from nxml/rng-pttrn.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rng-pttrn" '("rng-"))) + +;;;*** + +;;;### (autoloads nil "rng-uri" "nxml/rng-uri.el" (0 0 0 0)) +;;; Generated autoloads from nxml/rng-uri.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rng-uri" '("rng-"))) + +;;;*** + +;;;### (autoloads nil "rng-util" "nxml/rng-util.el" (0 0 0 0)) +;;; Generated autoloads from nxml/rng-util.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rng-util" '("rng-"))) + +;;;*** + +;;;### (autoloads nil "rng-valid" "nxml/rng-valid.el" (0 0 0 0)) +;;; Generated autoloads from nxml/rng-valid.el + +(autoload 'rng-validate-mode "rng-valid" "\ +Minor mode performing continual validation against a RELAX NG schema. + +Checks whether the buffer is a well-formed XML 1.0 document, +conforming to the XML Namespaces Recommendation and valid against a +RELAX NG schema. The mode-line indicates whether it is or not. Any +parts of the buffer that cause it not to be are considered errors and +are highlighted with face `rng-error'. A description of each error is +available as a tooltip. \\[rng-next-error] goes to the next error +after point. Clicking mouse-1 on the word `Invalid' in the mode-line +goes to the first error in the buffer. If the buffer changes, then it +will be automatically rechecked when Emacs becomes idle; the +rechecking will be paused whenever there is input pending. + +By default, uses a vacuous schema that allows any well-formed XML +document. A schema can be specified explicitly using +\\[rng-set-schema-file-and-validate], or implicitly based on the buffer's +file name or on the root element name. In each case the schema must +be a RELAX NG schema using the compact schema (such schemas +conventionally have a suffix of `.rnc'). The variable +`rng-schema-locating-files' specifies files containing rules +to use for finding the schema. + +\(fn &optional ARG NO-CHANGE-SCHEMA)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rng-valid" '("rng-"))) + +;;;*** + +;;;### (autoloads nil "rng-xsd" "nxml/rng-xsd.el" (0 0 0 0)) +;;; Generated autoloads from nxml/rng-xsd.el + +(put 'http://www\.w3\.org/2001/XMLSchema-datatypes 'rng-dt-compile #'rng-xsd-compile) + +(autoload 'rng-xsd-compile "rng-xsd" "\ +Provides W3C XML Schema as a RELAX NG datatypes library. +NAME is a symbol giving the local name of the datatype. PARAMS is a +list of pairs (PARAM-NAME . PARAM-VALUE) where PARAM-NAME is a symbol +giving the name of the parameter and PARAM-VALUE is a string giving +its value. If NAME or PARAMS are invalid, it calls `rng-dt-error' +passing it arguments in the same style as format; the value from +`rng-dt-error' will be returned. Otherwise, it returns a list. The +first member of the list is t if any string is a legal value for the +datatype and nil otherwise. The second argument is a symbol; this +symbol will be called as a function passing it a string followed by +the remaining members of the list. The function must return an object +representing the value of the datatype that was represented by the +string, or nil if the string is not a representation of any value. +The object returned can be any convenient non-nil value, provided +that, if two strings represent the same value, the returned objects +must be equal. + +\(fn NAME PARAMS)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rng-xsd" '("rng-xsd-" "xsd-duration-reference-dates"))) + +;;;*** + +;;;### (autoloads nil "robin" "international/robin.el" (0 0 0 0)) +;;; Generated autoloads from international/robin.el + +(autoload 'robin-define-package "robin" "\ +Define a robin package. + +NAME is the string of this robin package. +DOCSTRING is the documentation string of this robin package. +Each RULE is of the form (INPUT OUTPUT) where INPUT is a string and +OUTPUT is either a character or a string. RULES are not evaluated. + +If there already exists a robin package whose name is NAME, the new +one replaces the old one. + +\(fn NAME DOCSTRING &rest RULES)" nil t) + +(autoload 'robin-modify-package "robin" "\ +Change a rule in an already defined robin package. + +NAME is the string specifying a robin package. +INPUT is a string that specifies the input pattern. +OUTPUT is either a character or a string to be generated. + +\(fn NAME INPUT OUTPUT)" nil nil) + +(autoload 'robin-use-package "robin" "\ +Start using robin package NAME, which is a string. + +\(fn NAME)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "robin" '("robin-"))) + +;;;*** + +;;;### (autoloads nil "rot13" "rot13.el" (0 0 0 0)) +;;; Generated autoloads from rot13.el + +(autoload 'rot13 "rot13" "\ +ROT13 encrypt OBJECT, a buffer or string. +If OBJECT is a buffer, encrypt the region between START and END. +If OBJECT is a string, encrypt it in its entirety, ignoring START +and END, and return the encrypted string. + +\(fn OBJECT &optional START END)" nil nil) + +(autoload 'rot13-string "rot13" "\ +Return ROT13 encryption of STRING. + +\(fn STRING)" nil nil) + +(autoload 'rot13-region "rot13" "\ +ROT13 encrypt the region between START and END in current buffer. + +\(fn START END)" t nil) + +(autoload 'rot13-other-window "rot13" "\ +Display current buffer in ROT13 in another window. +The text itself is not modified, only the way it is displayed is affected. + +To terminate the ROT13 display, delete that window. As long as that window +is not deleted, any buffer displayed in it will become instantly encoded +in ROT13. + +See also `toggle-rot13-mode'. + +\(fn)" t nil) + +(autoload 'toggle-rot13-mode "rot13" "\ +Toggle the use of ROT13 encoding for the current window. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rot13" '("rot13-"))) + +;;;*** + +;;;### (autoloads nil "rst" "textmodes/rst.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/rst.el + (add-to-list 'auto-mode-alist (purecopy '("\\.re?st\\'" . rst-mode))) + +(autoload 'rst-mode "rst" "\ +Major mode for editing reStructuredText documents. +\\<rst-mode-map> + +Turning on `rst-mode' calls the normal hooks `text-mode-hook' +and `rst-mode-hook'. This mode also supports font-lock +highlighting. + +\\{rst-mode-map} + +\(fn)" t nil) + +(autoload 'rst-minor-mode "rst" "\ +Toggle ReST minor mode. +With a prefix argument ARG, enable ReST minor mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +When ReST minor mode is enabled, the ReST mode keybindings +are installed on top of the major mode bindings. Use this +for modes derived from Text mode, like Mail mode. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rst" '("rst-"))) + +;;;*** + +;;;### (autoloads nil "rtree" "rtree.el" (0 0 0 0)) +;;; Generated autoloads from rtree.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rtree" '("rtree-"))) + +;;;*** + +;;;### (autoloads nil "ruby-mode" "progmodes/ruby-mode.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from progmodes/ruby-mode.el +(push (purecopy '(ruby-mode 1 2)) package--builtin-versions) + +(autoload 'ruby-mode "ruby-mode" "\ +Major mode for editing Ruby code. + +\(fn)" t nil) + +(add-to-list 'auto-mode-alist (cons (purecopy (concat "\\(?:\\.\\(?:" "rbw?\\|ru\\|rake\\|thor" "\\|jbuilder\\|rabl\\|gemspec\\|podspec" "\\)" "\\|/" "\\(?:Gem\\|Rake\\|Cap\\|Thor" "\\|Puppet\\|Berks" "\\|Vagrant\\|Guard\\|Pod\\)file" "\\)\\'")) 'ruby-mode)) + +(dolist (name (list "ruby" "rbx" "jruby" "ruby1.9" "ruby1.8")) (add-to-list 'interpreter-mode-alist (cons (purecopy name) 'ruby-mode))) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ruby-mode" '("ruby-"))) + +;;;*** + +;;;### (autoloads nil "ruler-mode" "ruler-mode.el" (0 0 0 0)) +;;; Generated autoloads from ruler-mode.el +(push (purecopy '(ruler-mode 1 6)) package--builtin-versions) + +(defvar ruler-mode nil "\ +Non-nil if Ruler mode is enabled. +Use the command `ruler-mode' to change this variable.") + +(autoload 'ruler-mode "ruler-mode" "\ +Toggle display of ruler in header line (Ruler mode). +With a prefix argument ARG, enable Ruler mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode +if ARG is omitted or nil. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ruler-mode" '("ruler-"))) + +;;;*** + +;;;### (autoloads nil "rx" "emacs-lisp/rx.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/rx.el + +(autoload 'rx-to-string "rx" "\ +Parse and produce code for regular expression FORM. +FORM is a regular expression in sexp form. +NO-GROUP non-nil means don't put shy groups around the result. + +\(fn FORM &optional NO-GROUP)" nil nil) + +(autoload 'rx "rx" "\ +Translate regular expressions REGEXPS in sexp form to a regexp string. +REGEXPS is a non-empty sequence of forms of the sort listed below. + +Note that `rx' is a Lisp macro; when used in a Lisp program being +compiled, the translation is performed by the compiler. +See `rx-to-string' for how to do such a translation at run-time. + +The following are valid subforms of regular expressions in sexp +notation. + +STRING + matches string STRING literally. + +CHAR + matches character CHAR literally. + +`not-newline', `nonl' + matches any character except a newline. + +`anything' + matches any character + +`(any SET ...)' +`(in SET ...)' +`(char SET ...)' + matches any character in SET .... SET may be a character or string. + Ranges of characters can be specified as `A-Z' in strings. + Ranges may also be specified as conses like `(?A . ?Z)'. + + SET may also be the name of a character class: `digit', + `control', `hex-digit', `blank', `graph', `print', `alnum', + `alpha', `ascii', `nonascii', `lower', `punct', `space', `upper', + `word', or one of their synonyms. + +`(not (any SET ...))' + matches any character not in SET ... + +`line-start', `bol' + matches the empty string, but only at the beginning of a line + in the text being matched + +`line-end', `eol' + is similar to `line-start' but matches only at the end of a line + +`string-start', `bos', `bot' + matches the empty string, but only at the beginning of the + string being matched against. + +`string-end', `eos', `eot' + matches the empty string, but only at the end of the + string being matched against. + +`buffer-start' + matches the empty string, but only at the beginning of the + buffer being matched against. Actually equivalent to `string-start'. + +`buffer-end' + matches the empty string, but only at the end of the + buffer being matched against. Actually equivalent to `string-end'. + +`point' + matches the empty string, but only at point. + +`word-start', `bow' + matches the empty string, but only at the beginning of a word. + +`word-end', `eow' + matches the empty string, but only at the end of a word. + +`word-boundary' + matches the empty string, but only at the beginning or end of a + word. + +`(not word-boundary)' +`not-word-boundary' + matches the empty string, but not at the beginning or end of a + word. + +`symbol-start' + matches the empty string, but only at the beginning of a symbol. + +`symbol-end' + matches the empty string, but only at the end of a symbol. + +`digit', `numeric', `num' + matches 0 through 9. + +`control', `cntrl' + matches ASCII control characters. + +`hex-digit', `hex', `xdigit' + matches 0 through 9, a through f and A through F. + +`blank' + matches space and tab only. + +`graphic', `graph' + matches graphic characters--everything except whitespace, ASCII + and non-ASCII control characters, surrogates, and codepoints + unassigned by Unicode. + +`printing', `print' + matches whitespace and graphic characters. + +`alphanumeric', `alnum' + matches alphabetic characters and digits. (For multibyte characters, + it matches according to Unicode character properties.) + +`letter', `alphabetic', `alpha' + matches alphabetic characters. (For multibyte characters, + it matches according to Unicode character properties.) + +`ascii' + matches ASCII (unibyte) characters. + +`nonascii' + matches non-ASCII (multibyte) characters. + +`lower', `lower-case' + matches anything lower-case. + +`upper', `upper-case' + matches anything upper-case. + +`punctuation', `punct' + matches punctuation. (But at present, for multibyte characters, + it matches anything that has non-word syntax.) + +`space', `whitespace', `white' + matches anything that has whitespace syntax. + +`word', `wordchar' + matches anything that has word syntax. + +`not-wordchar' + matches anything that has non-word syntax. + +`(syntax SYNTAX)' + matches a character with syntax SYNTAX. SYNTAX must be one + of the following symbols, or a symbol corresponding to the syntax + character, e.g. `\\.' for `\\s.'. + + `whitespace' (\\s- in string notation) + `punctuation' (\\s.) + `word' (\\sw) + `symbol' (\\s_) + `open-parenthesis' (\\s() + `close-parenthesis' (\\s)) + `expression-prefix' (\\s') + `string-quote' (\\s\") + `paired-delimiter' (\\s$) + `escape' (\\s\\) + `character-quote' (\\s/) + `comment-start' (\\s<) + `comment-end' (\\s>) + `string-delimiter' (\\s|) + `comment-delimiter' (\\s!) + +`(not (syntax SYNTAX))' + matches a character that doesn't have syntax SYNTAX. + +`(category CATEGORY)' + matches a character with category CATEGORY. CATEGORY must be + either a character to use for C, or one of the following symbols. + + `consonant' (\\c0 in string notation) + `base-vowel' (\\c1) + `upper-diacritical-mark' (\\c2) + `lower-diacritical-mark' (\\c3) + `tone-mark' (\\c4) + `symbol' (\\c5) + `digit' (\\c6) + `vowel-modifying-diacritical-mark' (\\c7) + `vowel-sign' (\\c8) + `semivowel-lower' (\\c9) + `not-at-end-of-line' (\\c<) + `not-at-beginning-of-line' (\\c>) + `alpha-numeric-two-byte' (\\cA) + `chinese-two-byte' (\\cC) + `greek-two-byte' (\\cG) + `japanese-hiragana-two-byte' (\\cH) + `indian-tow-byte' (\\cI) + `japanese-katakana-two-byte' (\\cK) + `korean-hangul-two-byte' (\\cN) + `cyrillic-two-byte' (\\cY) + `combining-diacritic' (\\c^) + `ascii' (\\ca) + `arabic' (\\cb) + `chinese' (\\cc) + `ethiopic' (\\ce) + `greek' (\\cg) + `korean' (\\ch) + `indian' (\\ci) + `japanese' (\\cj) + `japanese-katakana' (\\ck) + `latin' (\\cl) + `lao' (\\co) + `tibetan' (\\cq) + `japanese-roman' (\\cr) + `thai' (\\ct) + `vietnamese' (\\cv) + `hebrew' (\\cw) + `cyrillic' (\\cy) + `can-break' (\\c|) + +`(not (category CATEGORY))' + matches a character that doesn't have category CATEGORY. + +`(and SEXP1 SEXP2 ...)' +`(: SEXP1 SEXP2 ...)' +`(seq SEXP1 SEXP2 ...)' +`(sequence SEXP1 SEXP2 ...)' + matches what SEXP1 matches, followed by what SEXP2 matches, etc. + +`(submatch SEXP1 SEXP2 ...)' +`(group SEXP1 SEXP2 ...)' + like `and', but makes the match accessible with `match-end', + `match-beginning', and `match-string'. + +`(submatch-n N SEXP1 SEXP2 ...)' +`(group-n N SEXP1 SEXP2 ...)' + like `group', but make it an explicitly-numbered group with + group number N. + +`(or SEXP1 SEXP2 ...)' +`(| SEXP1 SEXP2 ...)' + matches anything that matches SEXP1 or SEXP2, etc. If all + args are strings, use `regexp-opt' to optimize the resulting + regular expression. + +`(minimal-match SEXP)' + produce a non-greedy regexp for SEXP. Normally, regexps matching + zero or more occurrences of something are \"greedy\" in that they + match as much as they can, as long as the overall regexp can + still match. A non-greedy regexp matches as little as possible. + +`(maximal-match SEXP)' + produce a greedy regexp for SEXP. This is the default. + +Below, `SEXP ...' represents a sequence of regexp forms, treated as if +enclosed in `(and ...)'. + +`(zero-or-more SEXP ...)' +`(0+ SEXP ...)' + matches zero or more occurrences of what SEXP ... matches. + +`(* SEXP ...)' + like `zero-or-more', but always produces a greedy regexp, independent + of `rx-greedy-flag'. + +`(*? SEXP ...)' + like `zero-or-more', but always produces a non-greedy regexp, + independent of `rx-greedy-flag'. + +`(one-or-more SEXP ...)' +`(1+ SEXP ...)' + matches one or more occurrences of SEXP ... + +`(+ SEXP ...)' + like `one-or-more', but always produces a greedy regexp. + +`(+? SEXP ...)' + like `one-or-more', but always produces a non-greedy regexp. + +`(zero-or-one SEXP ...)' +`(optional SEXP ...)' +`(opt SEXP ...)' + matches zero or one occurrences of A. + +`(? SEXP ...)' + like `zero-or-one', but always produces a greedy regexp. + +`(?? SEXP ...)' + like `zero-or-one', but always produces a non-greedy regexp. + +`(repeat N SEXP)' +`(= N SEXP ...)' + matches N occurrences. + +`(>= N SEXP ...)' + matches N or more occurrences. + +`(repeat N M SEXP)' +`(** N M SEXP ...)' + matches N to M occurrences. + +`(backref N)' + matches what was matched previously by submatch N. + +`(eval FORM)' + evaluate FORM and insert result. If result is a string, + `regexp-quote' it. + +`(regexp REGEXP)' + include REGEXP in string notation in the result. + +\(fn &rest REGEXPS)" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rx" '("rx-"))) + +;;;*** + +;;;### (autoloads nil "sasl" "net/sasl.el" (0 0 0 0)) +;;; Generated autoloads from net/sasl.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sasl" '("sasl-"))) + +;;;*** + +;;;### (autoloads nil "sasl-cram" "net/sasl-cram.el" (0 0 0 0)) +;;; Generated autoloads from net/sasl-cram.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sasl-cram" '("sasl-cram-md5-"))) + +;;;*** + +;;;### (autoloads nil "sasl-digest" "net/sasl-digest.el" (0 0 0 0)) +;;; Generated autoloads from net/sasl-digest.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sasl-digest" '("sasl-digest-md5-"))) + +;;;*** + +;;;### (autoloads nil "sasl-ntlm" "net/sasl-ntlm.el" (0 0 0 0)) +;;; Generated autoloads from net/sasl-ntlm.el +(push (purecopy '(sasl 1 0)) package--builtin-versions) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sasl-ntlm" '("sasl-ntlm-"))) + +;;;*** + +;;;### (autoloads nil "sasl-scram-rfc" "net/sasl-scram-rfc.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from net/sasl-scram-rfc.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sasl-scram-rfc" '("sasl-scram-"))) + +;;;*** + +;;;### (autoloads nil "savehist" "savehist.el" (0 0 0 0)) +;;; Generated autoloads from savehist.el +(push (purecopy '(savehist 24)) package--builtin-versions) + +(defvar savehist-mode nil "\ +Non-nil if Savehist mode is enabled. +See the `savehist-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `savehist-mode'.") + +(custom-autoload 'savehist-mode "savehist" nil) + +(autoload 'savehist-mode "savehist" "\ +Toggle saving of minibuffer history (Savehist mode). +With a prefix argument ARG, enable Savehist mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +When Savehist mode is enabled, minibuffer history is saved +periodically and when exiting Emacs. When Savehist mode is +enabled for the first time in an Emacs session, it loads the +previous minibuffer history from `savehist-file'. + +This mode should normally be turned on from your Emacs init file. +Calling it at any other time replaces your current minibuffer +histories, which is probably undesirable. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "savehist" '("savehist-"))) + +;;;*** + +;;;### (autoloads nil "saveplace" "saveplace.el" (0 0 0 0)) +;;; Generated autoloads from saveplace.el + +(defvar save-place-mode nil "\ +Non-nil if Save-Place mode is enabled. +See the `save-place-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `save-place-mode'.") + +(custom-autoload 'save-place-mode "saveplace" nil) + +(autoload 'save-place-mode "saveplace" "\ +Non-nil means automatically save place in each file. +This means when you visit a file, point goes to the last place +where it was when you previously visited the same file. + +\(fn &optional ARG)" t nil) + +(autoload 'save-place-local-mode "saveplace" "\ +Toggle whether to save your place in this file between sessions. +If this mode is enabled, point is recorded when you kill the buffer +or exit Emacs. Visiting this file again will go to that position, +even in a later Emacs session. + +If called with a prefix arg, the mode is enabled if and only if +the argument is positive. + +To save places automatically in all files, put this in your init +file: + +\(save-place-mode 1) + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "saveplace" '("save-place" "load-save-place-alist-from-file"))) + +;;;*** + +;;;### (autoloads nil "sb-image" "sb-image.el" (0 0 0 0)) +;;; Generated autoloads from sb-image.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sb-image" '("speedbar-" "defimage-speedbar"))) + +;;;*** + +;;;### (autoloads nil "scheme" "progmodes/scheme.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/scheme.el + +(autoload 'scheme-mode "scheme" "\ +Major mode for editing Scheme code. +Editing commands are similar to those of `lisp-mode'. + +In addition, if an inferior Scheme process is running, some additional +commands will be defined, for evaluating expressions and controlling +the interpreter, and the state of the process will be displayed in the +mode line of all Scheme buffers. The names of commands that interact +with the Scheme process start with \"xscheme-\" if you use the MIT +Scheme-specific `xscheme' package; for more information see the +documentation for `xscheme-interaction-mode'. Use \\[run-scheme] to +start an inferior Scheme using the more general `cmuscheme' package. + +Commands: +Delete converts tabs to spaces as it moves back. +Blank lines separate paragraphs. Semicolons start comments. +\\{scheme-mode-map} + +\(fn)" t nil) + +(autoload 'dsssl-mode "scheme" "\ +Major mode for editing DSSSL code. +Editing commands are similar to those of `lisp-mode'. + +Commands: +Delete converts tabs to spaces as it moves back. +Blank lines separate paragraphs. Semicolons start comments. +\\{scheme-mode-map} +Entering this mode runs the hooks `scheme-mode-hook' and then +`dsssl-mode-hook' and inserts the value of `dsssl-sgml-declaration' if +that variable's value is a string. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "scheme" '("scheme-" "dsssl-"))) + +;;;*** + +;;;### (autoloads nil "score-mode" "gnus/score-mode.el" (0 0 0 0)) +;;; Generated autoloads from gnus/score-mode.el + +(autoload 'gnus-score-mode "score-mode" "\ +Mode for editing Gnus score files. +This mode is an extended emacs-lisp mode. + +\\{gnus-score-mode-map} + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "score-mode" '("gnus-score-" "score-mode-"))) + +;;;*** + +;;;### (autoloads nil "scroll-all" "scroll-all.el" (0 0 0 0)) +;;; Generated autoloads from scroll-all.el + +(defvar scroll-all-mode nil "\ +Non-nil if Scroll-All mode is enabled. +See the `scroll-all-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `scroll-all-mode'.") + +(custom-autoload 'scroll-all-mode "scroll-all" nil) + +(autoload 'scroll-all-mode "scroll-all" "\ +Toggle shared scrolling in same-frame windows (Scroll-All mode). +With a prefix argument ARG, enable Scroll-All mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +When Scroll-All mode is enabled, scrolling commands invoked in +one window apply to all visible windows in the same frame. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "scroll-all" '("scroll-all-"))) + +;;;*** + +;;;### (autoloads nil "scroll-bar" "scroll-bar.el" (0 0 0 0)) +;;; Generated autoloads from scroll-bar.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "scroll-bar" '("set-scroll-bar-mode" "scroll-bar-" "toggle-" "horizontal-scroll-bar" "get-scroll-bar-mode" "previous-scroll-bar-mode"))) + +;;;*** + +;;;### (autoloads nil "scroll-lock" "scroll-lock.el" (0 0 0 0)) +;;; Generated autoloads from scroll-lock.el + +(autoload 'scroll-lock-mode "scroll-lock" "\ +Buffer-local minor mode for pager-like scrolling. +With a prefix argument ARG, enable the mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode +if ARG is omitted or nil. When enabled, keys that normally move +point by line or paragraph will scroll the buffer by the +respective amount of lines instead and point will be kept +vertically fixed relative to window boundaries during scrolling. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "scroll-lock" '("scroll-lock-"))) + +;;;*** + +;;;### (autoloads nil "secrets" "net/secrets.el" (0 0 0 0)) +;;; Generated autoloads from net/secrets.el +(when (featurep 'dbusbind) + (autoload 'secrets-show-secrets "secrets" nil t)) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "secrets" '("secrets-"))) + +;;;*** + +;;;### (autoloads nil "semantic" "cedet/semantic.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic.el +(push (purecopy '(semantic 2 2)) package--builtin-versions) + +(defvar semantic-default-submodes '(global-semantic-idle-scheduler-mode global-semanticdb-minor-mode) "\ +List of auxiliary Semantic minor modes enabled by `semantic-mode'. +The possible elements of this list include the following: + + `global-semanticdb-minor-mode' - Maintain tag database. + `global-semantic-idle-scheduler-mode' - Reparse buffer when idle. + `global-semantic-idle-summary-mode' - Show summary of tag at point. + `global-semantic-idle-completions-mode' - Show completions when idle. + `global-semantic-decoration-mode' - Additional tag decorations. + `global-semantic-highlight-func-mode' - Highlight the current tag. + `global-semantic-stickyfunc-mode' - Show current fun in header line. + `global-semantic-mru-bookmark-mode' - Provide `switch-to-buffer'-like + keybinding for tag names. + `global-cedet-m3-minor-mode' - A mouse 3 context menu. + `global-semantic-idle-local-symbol-highlight-mode' - Highlight references + of the symbol under point. +The following modes are more targeted at people who want to see + some internal information of the semantic parser in action: + `global-semantic-highlight-edits-mode' - Visualize incremental parser by + highlighting not-yet parsed changes. + `global-semantic-show-unmatched-syntax-mode' - Highlight unmatched lexical + syntax tokens. + `global-semantic-show-parser-state-mode' - Display the parser cache state.") + +(custom-autoload 'semantic-default-submodes "semantic" t) + +(defvar semantic-mode nil "\ +Non-nil if Semantic mode is enabled. +See the `semantic-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `semantic-mode'.") + +(custom-autoload 'semantic-mode "semantic" nil) + +(autoload 'semantic-mode "semantic" "\ +Toggle parser features (Semantic mode). +With a prefix argument ARG, enable Semantic mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +Semantic mode if ARG is omitted or nil. + +In Semantic mode, Emacs parses the buffers you visit for their +semantic content. This information is used by a variety of +auxiliary minor modes, listed in `semantic-default-submodes'; +all the minor modes in this list are also enabled when you enable +Semantic mode. + +\\{semantic-mode-map} + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic" '("semantic-" "bovinate"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/analyze" +;;;;;; "cedet/semantic/analyze.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/analyze.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/analyze" '("semantic-a"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/analyze/complete" +;;;;;; "cedet/semantic/analyze/complete.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/analyze/complete.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/analyze/complete" '("semantic-analyze-"))) + +;;;*** + +;;;### (autoloads nil "semantic/analyze/debug" "cedet/semantic/analyze/debug.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/analyze/debug.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/analyze/debug" '("semantic-analyze"))) + +;;;*** + +;;;### (autoloads nil "semantic/analyze/fcn" "cedet/semantic/analyze/fcn.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/analyze/fcn.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/analyze/fcn" '("semantic-analyze-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/analyze/refs" +;;;;;; "cedet/semantic/analyze/refs.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/analyze/refs.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/analyze/refs" '("semantic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/bovine" +;;;;;; "cedet/semantic/bovine.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/bovine.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/bovine" '("semantic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/bovine/c" +;;;;;; "cedet/semantic/bovine/c.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/bovine/c.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/bovine/c" '("semantic" "c++-mode" "c-mode"))) + +;;;*** + +;;;### (autoloads nil "semantic/bovine/debug" "cedet/semantic/bovine/debug.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/bovine/debug.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/bovine/debug" '("semantic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/bovine/el" +;;;;;; "cedet/semantic/bovine/el.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/bovine/el.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/bovine/el" '("lisp-mode" "emacs-lisp-mode" "semantic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/bovine/gcc" +;;;;;; "cedet/semantic/bovine/gcc.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/bovine/gcc.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/bovine/gcc" '("semantic-"))) + +;;;*** + +;;;### (autoloads nil "semantic/bovine/grammar" "cedet/semantic/bovine/grammar.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/bovine/grammar.el + +(autoload 'bovine-grammar-mode "semantic/bovine/grammar" "\ +Major mode for editing Bovine grammars. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/bovine/grammar" '("bovine-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/bovine/make" +;;;;;; "cedet/semantic/bovine/make.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/bovine/make.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/bovine/make" '("semantic-" "makefile-mode"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/bovine/scm" +;;;;;; "cedet/semantic/bovine/scm.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/bovine/scm.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/bovine/scm" '("semantic-"))) + +;;;*** + +;;;### (autoloads nil "semantic/chart" "cedet/semantic/chart.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/chart.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/chart" '("semantic-chart-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/complete" +;;;;;; "cedet/semantic/complete.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/complete.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/complete" '("semantic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/ctxt" +;;;;;; "cedet/semantic/ctxt.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/ctxt.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/ctxt" '("semantic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/db" +;;;;;; "cedet/semantic/db.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/db.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/db" '("semanticdb-"))) + +;;;*** + +;;;### (autoloads nil "semantic/db-debug" "cedet/semantic/db-debug.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/db-debug.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/db-debug" '("semanticdb-"))) + +;;;*** + +;;;### (autoloads nil "semantic/db-ebrowse" "cedet/semantic/db-ebrowse.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/db-ebrowse.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/db-ebrowse" '("semanticdb-" "c++-mode"))) + +;;;*** + +;;;### (autoloads nil "semantic/db-el" "cedet/semantic/db-el.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/db-el.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/db-el" '("semanticdb-" "emacs-lisp-mode"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/db-file" +;;;;;; "cedet/semantic/db-file.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/db-file.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/db-file" '("semanticdb-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/db-find" +;;;;;; "cedet/semantic/db-find.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/db-find.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/db-find" '("semanticdb-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/db-global" +;;;;;; "cedet/semantic/db-global.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/db-global.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/db-global" '("semanticdb-"))) + +;;;*** + +;;;### (autoloads nil "semantic/db-javascript" "cedet/semantic/db-javascript.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/db-javascript.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/db-javascript" '("semanticdb-" "javascript-mode"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/db-mode" +;;;;;; "cedet/semantic/db-mode.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/db-mode.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/db-mode" '("semanticdb-"))) + +;;;*** + +;;;### (autoloads nil "semantic/db-ref" "cedet/semantic/db-ref.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/db-ref.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/db-ref" '("semanticdb-ref-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/db-typecache" +;;;;;; "cedet/semantic/db-typecache.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/db-typecache.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/db-typecache" '("semanticdb-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/debug" +;;;;;; "cedet/semantic/debug.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/debug.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/debug" '("semantic-debug-"))) + +;;;*** + +;;;### (autoloads nil "semantic/decorate" "cedet/semantic/decorate.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/decorate.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/decorate" '("semantic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/decorate/include" +;;;;;; "cedet/semantic/decorate/include.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/decorate/include.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/decorate/include" '("semantic-decoration-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/decorate/mode" +;;;;;; "cedet/semantic/decorate/mode.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/decorate/mode.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/decorate/mode" '("semantic-" "define-semantic-decoration-style"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/dep" +;;;;;; "cedet/semantic/dep.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/dep.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/dep" '("semantic-" "defcustom-mode-local-semantic-dependency-system-include-path"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/doc" +;;;;;; "cedet/semantic/doc.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/doc.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/doc" '("semantic-doc"))) + +;;;*** + +;;;### (autoloads nil "semantic/ede-grammar" "cedet/semantic/ede-grammar.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/ede-grammar.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/ede-grammar" '("semantic-ede-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/edit" +;;;;;; "cedet/semantic/edit.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/edit.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/edit" '("semantic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/find" +;;;;;; "cedet/semantic/find.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/find.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/find" '("semantic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/format" +;;;;;; "cedet/semantic/format.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/format.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/format" '("semantic-"))) + +;;;*** + +;;;### (autoloads nil "semantic/fw" "cedet/semantic/fw.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from cedet/semantic/fw.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/fw" '("semantic"))) + +;;;*** + +;;;### (autoloads nil "semantic/grammar" "cedet/semantic/grammar.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/grammar.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/grammar" '("semantic-"))) + +;;;*** + +;;;### (autoloads nil "semantic/grammar-wy" "cedet/semantic/grammar-wy.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/grammar-wy.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/grammar-wy" '("semantic-grammar-wy--"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/html" +;;;;;; "cedet/semantic/html.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/html.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/html" '("html-helper-mode" "semantic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/ia" +;;;;;; "cedet/semantic/ia.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/ia.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/ia" '("semantic-ia-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/ia-sb" +;;;;;; "cedet/semantic/ia-sb.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/ia-sb.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/ia-sb" '("semantic-ia-s"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/idle" +;;;;;; "cedet/semantic/idle.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/idle.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/idle" '("semantic-" "global-semantic-idle-summary-mode" "define-semantic-idle-service"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/imenu" +;;;;;; "cedet/semantic/imenu.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/imenu.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/imenu" '("semantic-"))) + +;;;*** + +;;;### (autoloads nil "semantic/java" "cedet/semantic/java.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from cedet/semantic/java.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/java" '("semantic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/lex" +;;;;;; "cedet/semantic/lex.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/lex.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/lex" '("semantic-" "define-lex"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/lex-spp" +;;;;;; "cedet/semantic/lex-spp.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/lex-spp.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/lex-spp" '("semantic-lex-" "define-lex-spp-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/mru-bookmark" +;;;;;; "cedet/semantic/mru-bookmark.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/mru-bookmark.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/mru-bookmark" '("semantic-" "global-semantic-mru-bookmark-mode"))) + +;;;*** + +;;;### (autoloads nil "semantic/sb" "cedet/semantic/sb.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from cedet/semantic/sb.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/sb" '("semantic-sb-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/scope" +;;;;;; "cedet/semantic/scope.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/scope.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/scope" '("semantic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/senator" +;;;;;; "cedet/semantic/senator.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/senator.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/senator" '("semantic-up-reference" "senator-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/sort" +;;;;;; "cedet/semantic/sort.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/sort.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/sort" '("semantic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/symref" +;;;;;; "cedet/semantic/symref.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/symref.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/symref" '("semantic-symref-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/symref/cscope" +;;;;;; "cedet/semantic/symref/cscope.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/symref/cscope.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/symref/cscope" '("semantic-symref-cscope--line-re"))) + +;;;*** + +;;;### (autoloads nil "semantic/symref/filter" "cedet/semantic/symref/filter.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/symref/filter.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/symref/filter" '("semantic-symref-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/symref/global" +;;;;;; "cedet/semantic/symref/global.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/symref/global.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/symref/global" '("semantic-symref-global--line-re"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/symref/grep" +;;;;;; "cedet/semantic/symref/grep.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/symref/grep.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/symref/grep" '("semantic-symref-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/symref/idutils" +;;;;;; "cedet/semantic/symref/idutils.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/symref/idutils.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/symref/idutils" '("semantic-symref-idutils--line-re"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/symref/list" +;;;;;; "cedet/semantic/symref/list.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/symref/list.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/symref/list" '("semantic-symref-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/tag" +;;;;;; "cedet/semantic/tag.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/tag.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/tag" '("semantic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/tag-file" +;;;;;; "cedet/semantic/tag-file.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/tag-file.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/tag-file" '("semantic-prototype-file"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/tag-ls" +;;;;;; "cedet/semantic/tag-ls.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/tag-ls.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/tag-ls" '("semantic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/tag-write" +;;;;;; "cedet/semantic/tag-write.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/tag-write.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/tag-write" '("semantic-tag-write-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/texi" +;;;;;; "cedet/semantic/texi.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/texi.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/texi" '("semantic-"))) + +;;;*** + +;;;### (autoloads nil "semantic/util" "cedet/semantic/util.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from cedet/semantic/util.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/util" '("semantic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/util-modes" +;;;;;; "cedet/semantic/util-modes.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/util-modes.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/util-modes" '("semantic-"))) + +;;;*** + +;;;### (autoloads nil "semantic/wisent" "cedet/semantic/wisent.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/wisent.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/wisent" '("wisent-" "define-wisent-lexer"))) + +;;;*** + +;;;### (autoloads nil "semantic/wisent/comp" "cedet/semantic/wisent/comp.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/wisent/comp.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/wisent/comp" '("wisent-"))) + +;;;*** + +;;;### (autoloads nil "semantic/wisent/grammar" "cedet/semantic/wisent/grammar.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/wisent/grammar.el + +(autoload 'wisent-grammar-mode "semantic/wisent/grammar" "\ +Major mode for editing Wisent grammars. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/wisent/grammar" '("wisent-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/wisent/java-tags" +;;;;;; "cedet/semantic/wisent/java-tags.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/wisent/java-tags.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/wisent/java-tags" '("semantic-" "wisent-java-parse-error"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/wisent/javascript" +;;;;;; "cedet/semantic/wisent/javascript.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/wisent/javascript.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/wisent/javascript" '("js-mode" "semantic-" "wisent-javascript-jv-expand-tag"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "semantic/wisent/python" +;;;;;; "cedet/semantic/wisent/python.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/wisent/python.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/wisent/python" '("wisent-python-" "semantic-" "python-"))) + +;;;*** + +;;;### (autoloads nil "semantic/wisent/wisent" "cedet/semantic/wisent/wisent.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/wisent/wisent.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "semantic/wisent/wisent" '("wisent-" "$region" "$nterm" "$action"))) + +;;;*** + +;;;### (autoloads nil "sendmail" "mail/sendmail.el" (0 0 0 0)) +;;; Generated autoloads from mail/sendmail.el + +(defvar mail-from-style 'default "\ +Specifies how \"From:\" fields look. + +If nil, they contain just the return address like: + king@grassland.com +If `parens', they look like: + king@grassland.com (Elvis Parsley) +If `angles', they look like: + Elvis Parsley <king@grassland.com> + +Otherwise, most addresses look like `angles', but they look like +`parens' if `angles' would need quoting and `parens' would not.") + +(custom-autoload 'mail-from-style "sendmail" t) + +(defvar mail-specify-envelope-from nil "\ +If non-nil, specify the envelope-from address when sending mail. +The value used to specify it is whatever is found in +the variable `mail-envelope-from', with `user-mail-address' as fallback. + +On most systems, specifying the envelope-from address is a +privileged operation. This variable affects sendmail and +smtpmail -- if you use feedmail to send mail, see instead the +variable `feedmail-deduce-envelope-from'.") + +(custom-autoload 'mail-specify-envelope-from "sendmail" t) + +(defvar mail-self-blind nil "\ +Non-nil means insert BCC to self in messages to be sent. +This is done when the message is initialized, +so you can remove or alter the BCC field to override the default.") + +(custom-autoload 'mail-self-blind "sendmail" t) + +(defvar mail-interactive t "\ +Non-nil means when sending a message wait for and display errors. +Otherwise, let mailer send back a message to report errors.") + +(custom-autoload 'mail-interactive "sendmail" t) + +(defvar send-mail-function (if (and (boundp 'smtpmail-smtp-server) smtpmail-smtp-server) 'smtpmail-send-it 'sendmail-query-once) "\ +Function to call to send the current buffer as mail. +The headers should be delimited by a line which is +not a valid RFC822 header or continuation line, +that matches the variable `mail-header-separator'. +This is used by the default mail-sending commands. See also +`message-send-mail-function' for use with the Message package.") + +(custom-autoload 'send-mail-function "sendmail" t) + +(defvar mail-header-separator (purecopy "--text follows this line--") "\ +Line used to separate headers from text in messages being composed.") + +(custom-autoload 'mail-header-separator "sendmail" t) + +(defvar mail-archive-file-name nil "\ +Name of file to write all outgoing messages in, or nil for none. +This is normally an mbox file, but for backwards compatibility may also +be a Babyl file.") + +(custom-autoload 'mail-archive-file-name "sendmail" t) + +(defvar mail-default-reply-to nil "\ +Address to insert as default Reply-to field of outgoing messages. +If nil, it will be initialized from the REPLYTO environment variable +when you first send mail.") + +(custom-autoload 'mail-default-reply-to "sendmail" t) + +(defvar mail-personal-alias-file (purecopy "~/.mailrc") "\ +If non-nil, the name of the user's personal mail alias file. +This file typically should be in same format as the `.mailrc' file used by +the `Mail' or `mailx' program. +This file need not actually exist.") + +(custom-autoload 'mail-personal-alias-file "sendmail" t) + +(defvar mail-setup-hook nil "\ +Normal hook, run each time a new outgoing message is initialized.") + +(custom-autoload 'mail-setup-hook "sendmail" t) + +(defvar mail-aliases t "\ +Alist of mail address aliases, +or t meaning should be initialized from your mail aliases file. +\(The file's name is normally `~/.mailrc', but `mail-personal-alias-file' +can specify a different file name.) +The alias definitions in the file have this form: + alias ALIAS MEANING") + +(defvar mail-yank-prefix "> " "\ +Prefix insert on lines of yanked message being replied to. +If this is nil, use indentation, as specified by `mail-indentation-spaces'.") + +(custom-autoload 'mail-yank-prefix "sendmail" t) + +(defvar mail-indentation-spaces 3 "\ +Number of spaces to insert at the beginning of each cited line. +Used by `mail-yank-original' via `mail-indent-citation'.") + +(custom-autoload 'mail-indentation-spaces "sendmail" t) + +(defvar mail-citation-hook nil "\ +Hook for modifying a citation just inserted in the mail buffer. +Each hook function can find the citation between (point) and (mark t), +and should leave point and mark around the citation text as modified. +The hook functions can find the header of the cited message +in the variable `mail-citation-header', whether or not this is included +in the cited portion of the message. + +If this hook is entirely empty (nil), a default action is taken +instead of no action.") + +(custom-autoload 'mail-citation-hook "sendmail" t) + +(defvar mail-citation-prefix-regexp (purecopy "\\([ ]*\\(\\w\\|[_.]\\)+>+\\|[ ]*[]>|]\\)+") "\ +Regular expression to match a citation prefix plus whitespace. +It should match whatever sort of citation prefixes you want to handle, +with whitespace before and after; it should also match just whitespace. +The default value matches citations like `foo-bar>' plus whitespace.") + +(custom-autoload 'mail-citation-prefix-regexp "sendmail" t) + +(defvar mail-signature t "\ +Text inserted at end of mail buffer when a message is initialized. +If t, it means to insert the contents of the file `mail-signature-file'. +If a string, that string is inserted. + (To make a proper signature, the string should begin with \\n\\n-- \\n, + which is the standard way to delimit a signature in a message.) +Otherwise, it should be an expression; it is evaluated +and should insert whatever you want to insert.") + +(custom-autoload 'mail-signature "sendmail" t) + +(defvar mail-signature-file (purecopy "~/.signature") "\ +File containing the text inserted at end of mail buffer.") + +(custom-autoload 'mail-signature-file "sendmail" t) + +(defvar mail-default-directory (purecopy "~/") "\ +Value of `default-directory' for Mail mode buffers. +This directory is used for auto-save files of Mail mode buffers. + +Note that Message mode does not use this variable; it auto-saves +in `message-auto-save-directory'.") + +(custom-autoload 'mail-default-directory "sendmail" t) + +(defvar mail-default-headers nil "\ +A string containing header lines, to be inserted in outgoing messages. +It can contain newlines, and should end in one. It is inserted +before you edit the message, so you can edit or delete the lines.") + +(custom-autoload 'mail-default-headers "sendmail" t) + +(autoload 'sendmail-query-once "sendmail" "\ +Query for `send-mail-function' and send mail with it. +This also saves the value of `send-mail-function' via Customize. + +\(fn)" nil nil) + +(define-mail-user-agent 'sendmail-user-agent 'sendmail-user-agent-compose 'mail-send-and-exit) + +(autoload 'sendmail-user-agent-compose "sendmail" "\ + + +\(fn &optional TO SUBJECT OTHER-HEADERS CONTINUE SWITCH-FUNCTION YANK-ACTION SEND-ACTIONS RETURN-ACTION &rest IGNORED)" nil nil) + +(autoload 'mail-mode "sendmail" "\ +Major mode for editing mail to be sent. +Like Text Mode but with these additional commands: + +\\[mail-send] mail-send (send the message) +\\[mail-send-and-exit] mail-send-and-exit (send the message and exit) + +Here are commands that move to a header field (and create it if there isn't): + \\[mail-to] move to To: \\[mail-subject] move to Subj: + \\[mail-bcc] move to BCC: \\[mail-cc] move to CC: + \\[mail-fcc] move to FCC: \\[mail-reply-to] move to Reply-To: + \\[mail-mail-reply-to] move to Mail-Reply-To: + \\[mail-mail-followup-to] move to Mail-Followup-To: +\\[mail-text] move to message text. +\\[mail-signature] mail-signature (insert `mail-signature-file' file). +\\[mail-yank-original] mail-yank-original (insert current message, in Rmail). +\\[mail-fill-yanked-message] mail-fill-yanked-message (fill what was yanked). +\\[mail-insert-file] insert a text file into the message. +\\[mail-add-attachment] attach to the message a file as binary attachment. +Turning on Mail mode runs the normal hooks `text-mode-hook' and +`mail-mode-hook' (in that order). + +\(fn)" t nil) + +(defvar mail-mailing-lists nil "\ +List of mailing list addresses the user is subscribed to. +The variable is used to trigger insertion of the \"Mail-Followup-To\" +header when sending a message to a mailing list.") + +(custom-autoload 'mail-mailing-lists "sendmail" t) + +(defvar sendmail-coding-system nil "\ +Coding system for encoding the outgoing mail. +This has higher priority than the default `buffer-file-coding-system' +and `default-sendmail-coding-system', +but lower priority than the local value of `buffer-file-coding-system'. +See also the function `select-message-coding-system'.") + +(defvar default-sendmail-coding-system 'iso-latin-1 "\ +Default coding system for encoding the outgoing mail. +This variable is used only when `sendmail-coding-system' is nil. + +This variable is set/changed by the command `set-language-environment'. +User should not set this variable manually, +instead use `sendmail-coding-system' to get a constant encoding +of outgoing mails regardless of the current language environment. +See also the function `select-message-coding-system'.") + +(autoload 'mail "sendmail" "\ +Edit a message to be sent. Prefix arg means resume editing (don't erase). +When this function returns, the buffer `*mail*' is selected. +The value is t if the message was newly initialized; otherwise, nil. + +Optionally, the signature file `mail-signature-file' can be inserted at the +end; see the variable `mail-signature'. + +\\<mail-mode-map> +While editing message, type \\[mail-send-and-exit] to send the message and exit. + +Various special commands starting with C-c are available in sendmail mode +to move to message header fields: +\\{mail-mode-map} + +If `mail-self-blind' is non-nil, a BCC to yourself is inserted +when the message is initialized. + +If `mail-default-reply-to' is non-nil, it should be an address (a string); +a Reply-to: field with that address is inserted. + +If `mail-archive-file-name' is non-nil, an FCC field with that file name +is inserted. + +The normal hook `mail-setup-hook' is run after the message is +initialized. It can add more default fields to the message. + +The first argument, NOERASE, determines what to do when there is +an existing modified `*mail*' buffer. If NOERASE is nil, the +existing mail buffer is used, and the user is prompted whether to +keep the old contents or to erase them. If NOERASE has the value +`new', a new mail buffer will be created instead of using the old +one. Any other non-nil value means to always select the old +buffer without erasing the contents. + +The second through fifth arguments, + TO, SUBJECT, IN-REPLY-TO and CC, specify if non-nil + the initial contents of those header fields. + These arguments should not have final newlines. +The sixth argument REPLYBUFFER is a buffer which contains an + original message being replied to, or else an action + of the form (FUNCTION . ARGS) which says how to insert the original. + Or it can be nil, if not replying to anything. +The seventh argument ACTIONS is a list of actions to take + if/when the message is sent. Each action looks like (FUNCTION . ARGS); + when the message is sent, we apply FUNCTION to ARGS. + This is how Rmail arranges to mark messages `answered'. + +\(fn &optional NOERASE TO SUBJECT IN-REPLY-TO CC REPLYBUFFER ACTIONS RETURN-ACTION)" t nil) + +(autoload 'mail-other-window "sendmail" "\ +Like `mail' command, but display mail buffer in another window. + +\(fn &optional NOERASE TO SUBJECT IN-REPLY-TO CC REPLYBUFFER SENDACTIONS)" t nil) + +(autoload 'mail-other-frame "sendmail" "\ +Like `mail' command, but display mail buffer in another frame. + +\(fn &optional NOERASE TO SUBJECT IN-REPLY-TO CC REPLYBUFFER SENDACTIONS)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sendmail" '("mail-" "sendmail-"))) + +;;;*** + +;;;### (autoloads nil "seq" "emacs-lisp/seq.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/seq.el +(push (purecopy '(seq 2 20)) package--builtin-versions) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "seq" '("seq-"))) + +;;;*** + +;;;### (autoloads nil "server" "server.el" (0 0 0 0)) +;;; Generated autoloads from server.el + +(put 'server-host 'risky-local-variable t) + +(put 'server-port 'risky-local-variable t) + +(put 'server-auth-dir 'risky-local-variable t) + +(defvar server-name "server" "\ +The name of the Emacs server, if this Emacs process creates one. +The command `server-start' makes use of this. It should not be +changed while a server is running.") + +(custom-autoload 'server-name "server" t) + +(autoload 'server-start "server" "\ +Allow this Emacs process to be a server for client processes. +This starts a server communications subprocess through which client +\"editors\" can send your editing commands to this Emacs job. +To use the server, set up the program `emacsclient' in the Emacs +distribution as your standard \"editor\". + +Optional argument LEAVE-DEAD (interactively, a prefix arg) means just +kill any existing server communications subprocess. + +If a server is already running, restart it. If clients are +running, ask the user for confirmation first, unless optional +argument INHIBIT-PROMPT is non-nil. + +To force-start a server, do \\[server-force-delete] and then +\\[server-start]. + +\(fn &optional LEAVE-DEAD INHIBIT-PROMPT)" t nil) + +(autoload 'server-force-delete "server" "\ +Unconditionally delete connection file for server NAME. +If server is running, it is first stopped. +NAME defaults to `server-name'. With argument, ask for NAME. + +\(fn &optional NAME)" t nil) + +(defvar server-mode nil "\ +Non-nil if Server mode is enabled. +See the `server-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `server-mode'.") + +(custom-autoload 'server-mode "server" nil) + +(autoload 'server-mode "server" "\ +Toggle Server mode. +With a prefix argument ARG, enable Server mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +Server mode if ARG is omitted or nil. + +Server mode runs a process that accepts commands from the +`emacsclient' program. See Info node `Emacs server' and +`server-start' for details. + +\(fn &optional ARG)" t nil) + +(autoload 'server-save-buffers-kill-terminal "server" "\ +Offer to save each buffer, then kill the current client. +With ARG non-nil, silently save all file-visiting buffers, then kill. + +If emacsclient was started with a list of filenames to edit, then +only these files will be asked to be saved. + +\(fn ARG)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "server" '("server-"))) + +;;;*** + +;;;### (autoloads nil "ses" "ses.el" (0 0 0 0)) +;;; Generated autoloads from ses.el + +(autoload 'ses-mode "ses" "\ +Major mode for Simple Emacs Spreadsheet. + +When you invoke SES in a new buffer, it is divided into cells +that you can enter data into. You can navigate the cells with +the arrow keys and add more cells with the tab key. The contents +of these cells can be numbers, text, or Lisp expressions. (To +enter text, enclose it in double quotes.) + +In an expression, you can use cell coordinates to refer to the +contents of another cell. For example, you can sum a range of +cells with `(+ A1 A2 A3)'. There are specialized functions like +`ses+' (addition for ranges with empty cells), `ses-average' (for +performing calculations on cells), and `ses-range' and `ses-select' +\(for extracting ranges of cells). + +Each cell also has a print function that controls how it is +displayed. + +Each SES buffer is divided into a print area and a data area. +Normally, you can simply use SES to look at and manipulate the print +area, and let SES manage the data area outside the visible region. + +See \"ses-example.ses\" (in `data-directory') for an example +spreadsheet, and the Info node `(ses)Top.' + +In the following, note the separate keymaps for cell editing mode +and print mode specifications. Key definitions: + +\\{ses-mode-map} +These key definitions are active only in the print area (the visible +part): +\\{ses-mode-print-map} +These are active only in the minibuffer, when entering or editing a +formula: +\\{ses-mode-edit-map} + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ses" '("ses" "noreturn" "1value"))) + +;;;*** + +;;;### (autoloads nil "sgml-mode" "textmodes/sgml-mode.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from textmodes/sgml-mode.el + +(autoload 'sgml-mode "sgml-mode" "\ +Major mode for editing SGML documents. +Makes > match <. +Keys <, &, SPC within <>, \", / and \\=' can be electric depending on +`sgml-quick-keys'. + +An argument of N to a tag-inserting command means to wrap it around +the next N words. In Transient Mark mode, when the mark is active, +N defaults to -1, which means to wrap it around the current region. + +If you like upcased tags, put (setq sgml-transformation-function \\='upcase) +in your init file. + +Use \\[sgml-validate] to validate your document with an SGML parser. + +Do \\[describe-variable] sgml- SPC to see available variables. +Do \\[describe-key] on the following bindings to discover what they do. +\\{sgml-mode-map} + +\(fn)" t nil) + +(autoload 'html-mode "sgml-mode" "\ +Major mode based on SGML mode for editing HTML documents. +This allows inserting skeleton constructs used in hypertext documents with +completion. See below for an introduction to HTML. Use +\\[browse-url-of-buffer] to see how this comes out. See also `sgml-mode' on +which this is based. + +Do \\[describe-variable] html- SPC and \\[describe-variable] sgml- SPC to see available variables. + +To write fairly well formatted pages you only need to know few things. Most +browsers have a function to read the source code of the page being seen, so +you can imitate various tricks. Here's a very short HTML primer which you +can also view with a browser to see what happens: + +<title>A Title Describing Contents should be on every page. Pages can +have

Very Major Headlines

through
Very Minor Headlines
+
Parts can be separated with horizontal rules. + +

Paragraphs only need an opening tag. Line breaks and multiple spaces are +ignored unless the text is

preformatted.
Text can be marked as +bold, italic or underlined using the normal M-o or +Edit/Text Properties/Face commands. + +Pages can have named points and can link other points +to them with see also somename. In the same way see also URL where URL is a filename relative to current +directory, or absolute as in `http://www.cs.indiana.edu/elisp/w3/docs.html'. + +Images in many formats can be inlined with . + +If you mainly create your own documents, `sgml-specials' might be +interesting. But note that some HTML 2 browsers can't handle `''. +To work around that, do: + (eval-after-load \"sgml-mode\" \\='(aset sgml-char-names ?\\=' nil)) + +\\{html-mode-map} + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sgml-mode" '("html-" "sgml-"))) + +;;;*** + +;;;### (autoloads nil "sh-script" "progmodes/sh-script.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from progmodes/sh-script.el +(push (purecopy '(sh-script 2 0 6)) package--builtin-versions) +(put 'sh-shell 'safe-local-variable 'symbolp) + +(autoload 'sh-mode "sh-script" "\ +Major mode for editing shell scripts. +This mode works for many shells, since they all have roughly the same syntax, +as far as commands, arguments, variables, pipes, comments etc. are concerned. +Unless the file's magic number indicates the shell, your usual shell is +assumed. Since filenames rarely give a clue, they are not further analyzed. + +This mode adapts to the variations between shells (see `sh-set-shell') by +means of an inheritance based feature lookup (see `sh-feature'). This +mechanism applies to all variables (including skeletons) that pertain to +shell-specific features. Shell script files can use the `sh-shell' local +variable to indicate the shell variant to be used for the file. + +The default style of this mode is that of Rosenblatt's Korn shell book. +The syntax of the statements varies with the shell being used. The +following commands are available, based on the current shell's syntax: +\\ +\\[sh-case] case statement +\\[sh-for] for loop +\\[sh-function] function definition +\\[sh-if] if statement +\\[sh-indexed-loop] indexed loop from 1 to n +\\[sh-while-getopts] while getopts loop +\\[sh-repeat] repeat loop +\\[sh-select] select loop +\\[sh-until] until loop +\\[sh-while] while loop + +For sh and rc shells indentation commands are: +\\[sh-show-indent] Show the variable controlling this line's indentation. +\\[sh-set-indent] Set then variable controlling this line's indentation. +\\[sh-learn-line-indent] Change the indentation variable so this line +would indent to the way it currently is. +\\[sh-learn-buffer-indent] Set the indentation variables so the +buffer indents as it currently is indented. + + +\\[backward-delete-char-untabify] Delete backward one position, even if it was a tab. +\\[sh-end-of-command] Go to end of successive commands. +\\[sh-beginning-of-command] Go to beginning of successive commands. +\\[sh-set-shell] Set this buffer's shell, and maybe its magic number. +\\[sh-execute-region] Have optional header and region be executed in a subshell. + +`sh-electric-here-document-mode' controls whether insertion of two +unquoted < insert a here document. You can control this behavior by +modifying `sh-mode-hook'. + +If you generally program a shell different from your login shell you can +set `sh-shell-file' accordingly. If your shell's file name doesn't correctly +indicate what shell it is use `sh-alias-alist' to translate. + +If your shell gives error messages with line numbers, you can use \\[executable-interpret] +with your script for an edit-interpret-debug cycle. + +\(fn)" t nil) + +(defalias 'shell-script-mode 'sh-mode) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sh-script" '("sh-"))) + +;;;*** + +;;;### (autoloads nil "shadow" "emacs-lisp/shadow.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/shadow.el + +(autoload 'list-load-path-shadows "shadow" "\ +Display a list of Emacs Lisp files that shadow other files. + +If STRINGP is non-nil, returns any shadows as a string. +Otherwise, if interactive shows any shadows in a `*Shadows*' buffer; +else prints messages listing any shadows. + +This function lists potential load path problems. Directories in +the `load-path' variable are searched, in order, for Emacs Lisp +files. When a previously encountered file name is found again, a +message is displayed indicating that the later file is \"hidden\" by +the earlier. + +For example, suppose `load-path' is set to + +\(\"/usr/share/emacs/site-lisp\" \"/usr/share/emacs/24.3/lisp\") + +and that each of these directories contains a file called XXX.el. Then +XXX.el in the site-lisp directory is referred to by all of: +\(require \\='XXX), (autoload .... \"XXX\"), (load-library \"XXX\") etc. + +The first XXX.el file prevents Emacs from seeing the second (unless +the second is loaded explicitly via `load-file'). + +When not intended, such shadowings can be the source of subtle +problems. For example, the above situation may have arisen because the +XXX package was not distributed with versions of Emacs prior to +24.3. A system administrator downloaded XXX from elsewhere and installed +it. Later, XXX was updated and included in the Emacs distribution. +Unless the system administrator checks for this, the new version of XXX +will be hidden behind the old (which may no longer work with the new +Emacs version). + +This function performs these checks and flags all possible +shadowings. Because a .el file may exist without a corresponding .elc +\(or vice-versa), these suffixes are essentially ignored. A file +XXX.elc in an early directory (that does not contain XXX.el) is +considered to shadow a later file XXX.el, and vice-versa. + +Shadowings are located by calling the (non-interactive) companion +function, `load-path-shadows-find'. + +\(fn &optional STRINGP)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "shadow" '("load-path-shadows-"))) + +;;;*** + +;;;### (autoloads nil "shadowfile" "shadowfile.el" (0 0 0 0)) +;;; Generated autoloads from shadowfile.el + +(autoload 'shadow-define-cluster "shadowfile" "\ +Edit (or create) the definition of a cluster NAME. +This is a group of hosts that share directories, so that copying to or from +one of them is sufficient to update the file on all of them. Clusters are +defined by a name, the network address of a primary host (the one we copy +files to), and a regular expression that matches the hostnames of all the +sites in the cluster. + +\(fn NAME)" t nil) + +(autoload 'shadow-define-literal-group "shadowfile" "\ +Declare a single file to be shared between sites. +It may have different filenames on each site. When this file is edited, the +new version will be copied to each of the other locations. Sites can be +specific hostnames, or names of clusters (see `shadow-define-cluster'). + +\(fn)" t nil) + +(autoload 'shadow-define-regexp-group "shadowfile" "\ +Make each of a group of files be shared between hosts. +Prompts for regular expression; files matching this are shared between a list +of sites, which are also prompted for. The filenames must be identical on all +hosts (if they aren't, use `shadow-define-literal-group' instead of this +function). Each site can be either a hostname or the name of a cluster (see +`shadow-define-cluster'). + +\(fn)" t nil) + +(autoload 'shadow-initialize "shadowfile" "\ +Set up file shadowing. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "shadowfile" '("shadow"))) + +;;;*** + +;;;### (autoloads nil "shell" "shell.el" (0 0 0 0)) +;;; Generated autoloads from shell.el + +(defvar shell-dumb-shell-regexp (purecopy "cmd\\(proxy\\)?\\.exe") "\ +Regexp to match shells that don't save their command history, and +don't handle the backslash as a quote character. For shells that +match this regexp, Emacs will write out the command history when the +shell finishes, and won't remove backslashes when it unquotes shell +arguments.") + +(custom-autoload 'shell-dumb-shell-regexp "shell" t) + +(autoload 'shell "shell" "\ +Run an inferior shell, with I/O through BUFFER (which defaults to `*shell*'). +Interactively, a prefix arg means to prompt for BUFFER. +If `default-directory' is a remote file name, it is also prompted +to change if called with a prefix arg. + +If BUFFER exists but shell process is not running, make new shell. +If BUFFER exists and shell process is running, just switch to BUFFER. +Program used comes from variable `explicit-shell-file-name', + or (if that is nil) from the ESHELL environment variable, + or (if that is nil) from `shell-file-name'. +If a file `~/.emacs_SHELLNAME' exists, or `~/.emacs.d/init_SHELLNAME.sh', +it is given as initial input (but this may be lost, due to a timing +error, if the shell discards input when it starts up). +The buffer is put in Shell mode, giving commands for sending input +and controlling the subjobs of the shell. See `shell-mode'. +See also the variable `shell-prompt-pattern'. + +To specify a coding system for converting non-ASCII characters +in the input and output to the shell, use \\[universal-coding-system-argument] +before \\[shell]. You can also specify this with \\[set-buffer-process-coding-system] +in the shell buffer, after you start the shell. +The default comes from `process-coding-system-alist' and +`default-process-coding-system'. + +The shell file name (sans directories) is used to make a symbol name +such as `explicit-csh-args'. If that symbol is a variable, +its value is used as a list of arguments when invoking the shell. +Otherwise, one argument `-i' is passed to the shell. + +\(Type \\[describe-mode] in the shell buffer for a list of commands.) + +\(fn &optional BUFFER)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "shell" '("shell-" "dirs" "explicit-"))) + +;;;*** + +;;;### (autoloads nil "shr" "net/shr.el" (0 0 0 0)) +;;; Generated autoloads from net/shr.el + +(autoload 'shr-render-region "shr" "\ +Display the HTML rendering of the region between BEGIN and END. + +\(fn BEGIN END &optional BUFFER)" t nil) + +(autoload 'shr-insert-document "shr" "\ +Render the parsed document DOM into the current buffer. +DOM should be a parse tree as generated by +`libxml-parse-html-region' or similar. + +\(fn DOM)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "shr" '("shr-"))) + +;;;*** + +;;;### (autoloads nil "shr-color" "net/shr-color.el" (0 0 0 0)) +;;; Generated autoloads from net/shr-color.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "shr-color" '("shr-color-"))) + +;;;*** + +;;;### (autoloads nil "sieve" "net/sieve.el" (0 0 0 0)) +;;; Generated autoloads from net/sieve.el + +(autoload 'sieve-manage "sieve" "\ + + +\(fn SERVER &optional PORT)" t nil) + +(autoload 'sieve-upload "sieve" "\ + + +\(fn &optional NAME)" t nil) + +(autoload 'sieve-upload-and-bury "sieve" "\ + + +\(fn &optional NAME)" t nil) + +(autoload 'sieve-upload-and-kill "sieve" "\ + + +\(fn &optional NAME)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sieve" '("sieve-"))) + +;;;*** + +;;;### (autoloads nil "sieve-manage" "net/sieve-manage.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from net/sieve-manage.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sieve-manage" '("sieve-"))) + +;;;*** + +;;;### (autoloads nil "sieve-mode" "net/sieve-mode.el" (0 0 0 0)) +;;; Generated autoloads from net/sieve-mode.el + +(autoload 'sieve-mode "sieve-mode" "\ +Major mode for editing Sieve code. +This is much like C mode except for the syntax of comments. Its keymap +inherits from C mode's and it has the same variables for customizing +indentation. It has its own abbrev table and its own syntax table. + +Turning on Sieve mode runs `sieve-mode-hook'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sieve-mode" '("sieve-"))) + +;;;*** + +;;;### (autoloads nil "simula" "progmodes/simula.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/simula.el + +(autoload 'simula-mode "simula" "\ +Major mode for editing SIMULA code. +\\{simula-mode-map} +Variables controlling indentation style: + `simula-tab-always-indent' + Non-nil means TAB in SIMULA mode should always reindent the current line, + regardless of where in the line point is when the TAB command is used. + `simula-indent-level' + Indentation of SIMULA statements with respect to containing block. + `simula-substatement-offset' + Extra indentation after DO, THEN, ELSE, WHEN and OTHERWISE. + `simula-continued-statement-offset' 3 + Extra indentation for lines not starting a statement or substatement, + e.g. a nested FOR-loop. If value is a list, each line in a multiple- + line continued statement will have the car of the list extra indentation + with respect to the previous line of the statement. + `simula-label-offset' -4711 + Offset of SIMULA label lines relative to usual indentation. + `simula-if-indent' (0 . 0) + Extra indentation of THEN and ELSE with respect to the starting IF. + Value is a cons cell, the car is extra THEN indentation and the cdr + extra ELSE indentation. IF after ELSE is indented as the starting IF. + `simula-inspect-indent' (0 . 0) + Extra indentation of WHEN and OTHERWISE with respect to the + corresponding INSPECT. Value is a cons cell, the car is + extra WHEN indentation and the cdr extra OTHERWISE indentation. + `simula-electric-indent' nil + If this variable is non-nil, `simula-indent-line' + will check the previous line to see if it has to be reindented. + `simula-abbrev-keyword' `upcase' + Determine how SIMULA keywords will be expanded. Value is one of + the symbols `upcase', `downcase', `capitalize', (as in) `abbrev-table', + or nil if they should not be changed. + `simula-abbrev-stdproc' `abbrev-table' + Determine how standard SIMULA procedure and class names will be + expanded. Value is one of the symbols `upcase', `downcase', `capitalize', + (as in) `abbrev-table', or nil if they should not be changed. + +Turning on SIMULA mode calls the value of the variable simula-mode-hook +with no arguments, if that value is non-nil. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "simula" '("simula-"))) + +;;;*** + +;;;### (autoloads nil "skeleton" "skeleton.el" (0 0 0 0)) +;;; Generated autoloads from skeleton.el + +(defvar skeleton-filter-function 'identity "\ +Function for transforming a skeleton proxy's aliases' variable value.") + +(autoload 'define-skeleton "skeleton" "\ +Define a user-configurable COMMAND that enters a statement skeleton. +DOCUMENTATION is that of the command. +SKELETON is as defined under `skeleton-insert'. + +\(fn COMMAND DOCUMENTATION &rest SKELETON)" nil t) + +(function-put 'define-skeleton 'doc-string-elt '2) + +(autoload 'skeleton-proxy-new "skeleton" "\ +Insert SKELETON. +Prefix ARG allows wrapping around words or regions (see `skeleton-insert'). +If no ARG was given, but the region is visible, ARG defaults to -1 depending +on `skeleton-autowrap'. An ARG of M-0 will prevent this just for once. +This command can also be an abbrev expansion (3rd and 4th columns in +\\[edit-abbrevs] buffer: \"\" command-name). + +Optional second argument STR may also be a string which will be the value +of `str' whereas the skeleton's interactor is then ignored. + +\(fn SKELETON &optional STR ARG)" nil nil) + +(autoload 'skeleton-insert "skeleton" "\ +Insert the complex statement skeleton SKELETON describes very concisely. + +With optional second argument REGIONS, wrap first interesting point +\(`_') in skeleton around next REGIONS words, if REGIONS is positive. +If REGIONS is negative, wrap REGIONS preceding interregions into first +REGIONS interesting positions (successive `_'s) in skeleton. + +An interregion is the stretch of text between two contiguous marked +points. If you marked A B C [] (where [] is the cursor) in +alphabetical order, the 3 interregions are simply the last 3 regions. +But if you marked B A [] C, the interregions are B-A, A-[], []-C. + +The optional third argument STR, if specified, is the value for the +variable `str' within the skeleton. When this is non-nil, the +interactor gets ignored, and this should be a valid skeleton element. + +When done with skeleton, but before going back to `_'-point, add +a newline (unless `skeleton-end-newline' is nil) and run the hook +`skeleton-end-hook'. + +SKELETON is made up as (INTERACTOR ELEMENT ...). INTERACTOR may be nil if +not needed, a prompt-string or an expression for complex read functions. + +If ELEMENT is a string or a character it gets inserted (see also +`skeleton-transformation-function'). Other possibilities are: + + \\n go to next line and indent according to mode, unless + this is the first/last element of a skeleton and point + is at bol/eol + _ interesting point, interregion here + - interesting point, no interregion interaction, overrides + interesting point set by _ + > indent line (or interregion if > _) according to major mode + @ add position to `skeleton-positions' + & do next ELEMENT if previous moved point + | do next ELEMENT if previous didn't move point + -NUM delete NUM preceding characters (see `skeleton-untabify') + resume: skipped, continue here if quit is signaled + nil skipped + +After termination, point will be positioned at the last occurrence of - +or at the first occurrence of _ or at the end of the inserted text. + +Note that \\n as the last element of the skeleton only inserts a +newline if not at eol. If you want to unconditionally insert a newline +at the end of the skeleton, use \"\\n\" instead. Likewise with \\n +as the first element when at bol. + +Further elements can be defined via `skeleton-further-elements'. +ELEMENT may itself be a SKELETON with an INTERACTOR. The user is prompted +repeatedly for different inputs. The SKELETON is processed as often as +the user enters a non-empty string. \\[keyboard-quit] terminates skeleton insertion, but +continues after `resume:' and positions at `_' if any. If INTERACTOR in +such a subskeleton is a prompt-string which contains a \".. %s ..\" it is +formatted with `skeleton-subprompt'. Such an INTERACTOR may also be a list +of strings with the subskeleton being repeated once for each string. + +Quoted Lisp expressions are evaluated for their side-effects. +Other Lisp expressions are evaluated and the value treated as above. +Note that expressions may not return t since this implies an +endless loop. Modes can define other symbols by locally setting them +to any valid skeleton element. The following local variables are +available: + + str first time: read a string according to INTERACTOR + then: insert previously read string once more + help help-form during interaction with the user or nil + input initial input (string or cons with index) while reading str + v1, v2 local variables for memorizing anything you want + +\(fn SKELETON &optional REGIONS STR)" nil nil) + +(autoload 'skeleton-pair-insert-maybe "skeleton" "\ +Insert the character you type ARG times. + +With no ARG, if `skeleton-pair' is non-nil, pairing can occur. If the region +is visible the pair is wrapped around it depending on `skeleton-autowrap'. +Else, if `skeleton-pair-on-word' is non-nil or we are not before or inside a +word, and if `skeleton-pair-filter-function' returns nil, pairing is performed. +Pairing is also prohibited if we are right after a quoting character +such as backslash. + +If a match is found in `skeleton-pair-alist', that is inserted, else +the defaults are used. These are (), [], {}, <> and (grave +accent, apostrophe) for the paired ones, and the same character +twice for the others. + +\(fn ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "skeleton" '("skeleton-"))) + +;;;*** + +;;;### (autoloads nil "smerge-mode" "vc/smerge-mode.el" (0 0 0 0)) +;;; Generated autoloads from vc/smerge-mode.el + +(autoload 'smerge-refine-regions "smerge-mode" "\ +Show fine differences in the two regions BEG1..END1 and BEG2..END2. +PROPS-C is an alist of properties to put (via overlays) on the changes. +PROPS-R is an alist of properties to put on removed characters. +PROPS-A is an alist of properties to put on added characters. +If PROPS-R and PROPS-A are nil, put PROPS-C on all changes. +If PROPS-C is nil, but PROPS-R and PROPS-A are non-nil, +put PROPS-A on added characters, PROPS-R on removed characters. +If PROPS-C, PROPS-R and PROPS-A are non-nil, put PROPS-C on changed characters, +PROPS-A on added characters, and PROPS-R on removed characters. + +If non-nil, PREPROC is called with no argument in a buffer that contains +a copy of a region, just before preparing it to for `diff'. It can be +used to replace chars to try and eliminate some spurious differences. + +\(fn BEG1 END1 BEG2 END2 PROPS-C &optional PREPROC PROPS-R PROPS-A)" nil nil) + +(autoload 'smerge-ediff "smerge-mode" "\ +Invoke ediff to resolve the conflicts. +NAME-UPPER, NAME-LOWER, and NAME-BASE, if non-nil, are used for the +buffer names. + +\(fn &optional NAME-UPPER NAME-LOWER NAME-BASE)" t nil) + +(autoload 'smerge-mode "smerge-mode" "\ +Minor mode to simplify editing output from the diff3 program. +With a prefix argument ARG, enable the mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode +if ARG is omitted or nil. +\\{smerge-mode-map} + +\(fn &optional ARG)" t nil) + +(autoload 'smerge-start-session "smerge-mode" "\ +Turn on `smerge-mode' and move point to first conflict marker. +If no conflict maker is found, turn off `smerge-mode'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "smerge-mode" '("smerge-"))) + +;;;*** + +;;;### (autoloads nil "smie" "emacs-lisp/smie.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/smie.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "smie" '("smie-"))) + +;;;*** + +;;;### (autoloads nil "smiley" "gnus/smiley.el" (0 0 0 0)) +;;; Generated autoloads from gnus/smiley.el + +(autoload 'smiley-region "smiley" "\ +Replace in the region `smiley-regexp-alist' matches with corresponding images. +A list of images is returned. + +\(fn START END)" t nil) + +(autoload 'smiley-buffer "smiley" "\ +Run `smiley-region' at the BUFFER, specified in the argument or +interactively. If there's no argument, do it at the current buffer. + +\(fn &optional BUFFER)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "smiley" '("smiley-" "gnus-smiley-file-types"))) + +;;;*** + +;;;### (autoloads nil "smime" "gnus/smime.el" (0 0 0 0)) +;;; Generated autoloads from gnus/smime.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "smime" '("smime"))) + +;;;*** + +;;;### (autoloads nil "smtpmail" "mail/smtpmail.el" (0 0 0 0)) +;;; Generated autoloads from mail/smtpmail.el + +(autoload 'smtpmail-send-it "smtpmail" "\ + + +\(fn)" nil nil) + +(autoload 'smtpmail-send-queued-mail "smtpmail" "\ +Send mail that was queued as a result of setting `smtpmail-queue-mail'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "smtpmail" '("smtpmail-"))) + +;;;*** + +;;;### (autoloads nil "snake" "play/snake.el" (0 0 0 0)) +;;; Generated autoloads from play/snake.el + +(autoload 'snake "snake" "\ +Play the Snake game. +Move the snake around without colliding with its tail or with the border. + +Eating dots causes the snake to get longer. + +Snake mode keybindings: + \\ +\\[snake-start-game] Starts a new game of Snake +\\[snake-end-game] Terminates the current game +\\[snake-pause-game] Pauses (or resumes) the current game +\\[snake-move-left] Makes the snake move left +\\[snake-move-right] Makes the snake move right +\\[snake-move-up] Makes the snake move up +\\[snake-move-down] Makes the snake move down + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "snake" '("snake-"))) + +;;;*** + +;;;### (autoloads nil "snmp-mode" "net/snmp-mode.el" (0 0 0 0)) +;;; Generated autoloads from net/snmp-mode.el + +(autoload 'snmp-mode "snmp-mode" "\ +Major mode for editing SNMP MIBs. +Expression and list commands understand all C brackets. +Tab indents for C code. +Comments start with -- and end with newline or another --. +Delete converts tabs to spaces as it moves back. +\\{snmp-mode-map} +Turning on snmp-mode runs the hooks in `snmp-common-mode-hook', then +`snmp-mode-hook'. + +\(fn)" t nil) + +(autoload 'snmpv2-mode "snmp-mode" "\ +Major mode for editing SNMPv2 MIBs. +Expression and list commands understand all C brackets. +Tab indents for C code. +Comments start with -- and end with newline or another --. +Delete converts tabs to spaces as it moves back. +\\{snmp-mode-map} +Turning on snmp-mode runs the hooks in `snmp-common-mode-hook', +then `snmpv2-mode-hook'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "snmp-mode" '("snmp"))) + +;;;*** + +;;;### (autoloads nil "soap-client" "net/soap-client.el" (0 0 0 0)) +;;; Generated autoloads from net/soap-client.el +(push (purecopy '(soap-client 3 1 3)) package--builtin-versions) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "soap-client" '("soap-"))) + +;;;*** + +;;;### (autoloads nil "soap-inspect" "net/soap-inspect.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from net/soap-inspect.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "soap-inspect" '("soap-"))) + +;;;*** + +;;;### (autoloads nil "socks" "net/socks.el" (0 0 0 0)) +;;; Generated autoloads from net/socks.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "socks" '("socks-"))) + +;;;*** + +;;;### (autoloads nil "solar" "calendar/solar.el" (0 0 0 0)) +;;; Generated autoloads from calendar/solar.el + +(autoload 'sunrise-sunset "solar" "\ +Local time of sunrise and sunset for today. Accurate to a few seconds. +If called with an optional prefix argument ARG, prompt for date. +If called with an optional double prefix argument, prompt for +longitude, latitude, time zone, and date, and always use standard time. + +This function is suitable for execution in an init file. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "solar" '("solar-" "diary-sunrise-sunset" "calendar-"))) + +;;;*** + +;;;### (autoloads nil "solitaire" "play/solitaire.el" (0 0 0 0)) +;;; Generated autoloads from play/solitaire.el + +(autoload 'solitaire "solitaire" "\ +Play Solitaire. + +To play Solitaire, type \\[solitaire]. +\\ +Move around the board using the cursor keys. +Move stones using \\[solitaire-move] followed by a direction key. +Undo moves using \\[solitaire-undo]. +Check for possible moves using \\[solitaire-do-check]. +\(The variable `solitaire-auto-eval' controls whether to automatically +check after each move or undo.) + +What is Solitaire? + +I don't know who invented this game, but it seems to be rather old and +its origin seems to be northern Africa. Here's how to play: +Initially, the board will look similar to this: + + Le Solitaire + ============ + + o o o + + o o o + + o o o o o o o + + o o o . o o o + + o o o o o o o + + o o o + + o o o + +Let's call the o's stones and the .'s holes. One stone fits into one +hole. As you can see, all holes but one are occupied by stones. The +aim of the game is to get rid of all but one stone, leaving that last +one in the middle of the board if you're cool. + +A stone can be moved if there is another stone next to it, and a hole +after that one. Thus there must be three fields in a row, either +horizontally or vertically, up, down, left or right, which look like +this: o o . + +Then the first stone is moved to the hole, jumping over the second, +which therefore is taken away. The above thus `evaluates' to: . . o + +That's all. Here's the board after two moves: + + o o o + + . o o + + o o . o o o o + + o . o o o o o + + o o o o o o o + + o o o + + o o o + +Pick your favorite shortcuts: + +\\{solitaire-mode-map} + +\(fn ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "solitaire" '("solitaire-"))) + +;;;*** + +;;;### (autoloads nil "sort" "sort.el" (0 0 0 0)) +;;; Generated autoloads from sort.el +(put 'sort-fold-case 'safe-local-variable 'booleanp) + +(autoload 'sort-subr "sort" "\ +General text sorting routine to divide buffer into records and sort them. + +We divide the accessible portion of the buffer into disjoint pieces +called sort records. A portion of each sort record (perhaps all of +it) is designated as the sort key. The records are rearranged in the +buffer in order by their sort keys. The records may or may not be +contiguous. + +Usually the records are rearranged in order of ascending sort key. +If REVERSE is non-nil, they are rearranged in order of descending sort key. +The variable `sort-fold-case' determines whether alphabetic case affects +the sort order. + +The next four arguments are functions to be called to move point +across a sort record. They will be called many times from within sort-subr. + +NEXTRECFUN is called with point at the end of the previous record. +It moves point to the start of the next record. +It should move point to the end of the buffer if there are no more records. +The first record is assumed to start at the position of point when sort-subr +is called. + +ENDRECFUN is called with point within the record. +It should move point to the end of the record. + +STARTKEYFUN moves from the start of the record to the start of the key. +It may return either a non-nil value to be used as the key, or +else the key is the substring between the values of point after +STARTKEYFUN and ENDKEYFUN are called. If STARTKEYFUN is nil, the key +starts at the beginning of the record. + +ENDKEYFUN moves from the start of the sort key to the end of the sort key. +ENDKEYFUN may be nil if STARTKEYFUN returns a value or if it would be the +same as ENDRECFUN. + +PREDICATE, if non-nil, is the predicate function for comparing +keys; it is called with two arguments, the keys to compare, and +should return non-nil if the first key should sort before the +second key. If PREDICATE is nil, comparison is done with `<' if +the keys are numbers, with `compare-buffer-substrings' if the +keys are cons cells (the car and cdr of each cons cell are taken +as start and end positions), and with `string<' otherwise. + +\(fn REVERSE NEXTRECFUN ENDRECFUN &optional STARTKEYFUN ENDKEYFUN PREDICATE)" nil nil) + +(autoload 'sort-lines "sort" "\ +Sort lines in region alphabetically; argument means descending order. +Called from a program, there are three arguments: +REVERSE (non-nil means reverse order), BEG and END (region to sort). +The variable `sort-fold-case' determines whether alphabetic case affects +the sort order. + +\(fn REVERSE BEG END)" t nil) + +(autoload 'sort-paragraphs "sort" "\ +Sort paragraphs in region alphabetically; argument means descending order. +Called from a program, there are three arguments: +REVERSE (non-nil means reverse order), BEG and END (region to sort). +The variable `sort-fold-case' determines whether alphabetic case affects +the sort order. + +\(fn REVERSE BEG END)" t nil) + +(autoload 'sort-pages "sort" "\ +Sort pages in region alphabetically; argument means descending order. +Called from a program, there are three arguments: +REVERSE (non-nil means reverse order), BEG and END (region to sort). +The variable `sort-fold-case' determines whether alphabetic case affects +the sort order. + +\(fn REVERSE BEG END)" t nil) +(put 'sort-numeric-base 'safe-local-variable 'integerp) + +(autoload 'sort-numeric-fields "sort" "\ +Sort lines in region numerically by the ARGth field of each line. +Fields are separated by whitespace and numbered from 1 up. +Specified field must contain a number in each line of the region, +which may begin with \"0x\" or \"0\" for hexadecimal and octal values. +Otherwise, the number is interpreted according to sort-numeric-base. +With a negative arg, sorts by the ARGth field counted from the right. +Called from a program, there are three arguments: +FIELD, BEG and END. BEG and END specify region to sort. + +\(fn FIELD BEG END)" t nil) + +(autoload 'sort-fields "sort" "\ +Sort lines in region lexicographically by the ARGth field of each line. +Fields are separated by whitespace and numbered from 1 up. +With a negative arg, sorts by the ARGth field counted from the right. +Called from a program, there are three arguments: +FIELD, BEG and END. BEG and END specify region to sort. +The variable `sort-fold-case' determines whether alphabetic case affects +the sort order. + +\(fn FIELD BEG END)" t nil) + +(autoload 'sort-regexp-fields "sort" "\ +Sort the text in the region region lexicographically. +If called interactively, prompt for two regular expressions, +RECORD-REGEXP and KEY-REGEXP. + +RECORD-REGEXP specifies the textual units to be sorted. + For example, to sort lines, RECORD-REGEXP would be \"^.*$\". + +KEY-REGEXP specifies the part of each record (i.e. each match for + RECORD-REGEXP) to be used for sorting. + If it is \"\\\\digit\", use the digit'th \"\\\\(...\\\\)\" + match field specified by RECORD-REGEXP. + If it is \"\\\\&\", use the whole record. + Otherwise, KEY-REGEXP should be a regular expression with which + to search within the record. If a match for KEY-REGEXP is not + found within a record, that record is ignored. + +With a negative prefix arg, sort in reverse order. + +The variable `sort-fold-case' determines whether alphabetic case affects +the sort order. + +For example: to sort lines in the region by the first word on each line + starting with the letter \"f\", + RECORD-REGEXP would be \"^.*$\" and KEY would be \"\\\\=\\\" + +\(fn REVERSE RECORD-REGEXP KEY-REGEXP BEG END)" t nil) + +(autoload 'sort-columns "sort" "\ +Sort lines in region alphabetically by a certain range of columns. +For the purpose of this command, the region BEG...END includes +the entire line that point is in and the entire line the mark is in. +The column positions of point and mark bound the range of columns to sort on. +A prefix argument means sort into REVERSE order. +The variable `sort-fold-case' determines whether alphabetic case affects +the sort order. + +Note that `sort-columns' rejects text that contains tabs, +because tabs could be split across the specified columns +and it doesn't know how to handle that. Also, when possible, +it uses the `sort' utility program, which doesn't understand tabs. +Use \\[untabify] to convert tabs to spaces before sorting. + +\(fn REVERSE &optional BEG END)" t nil) + +(autoload 'reverse-region "sort" "\ +Reverse the order of lines in a region. +From a program takes two point or marker arguments, BEG and END. + +\(fn BEG END)" t nil) + +(autoload 'delete-duplicate-lines "sort" "\ +Delete all but one copy of any identical lines in the region. +Non-interactively, arguments BEG and END delimit the region. +Normally it searches forwards, keeping the first instance of +each identical line. If REVERSE is non-nil (interactively, with +a C-u prefix), it searches backwards and keeps the last instance of +each repeated line. + +Identical lines need not be adjacent, unless the argument +ADJACENT is non-nil (interactively, with a C-u C-u prefix). +This is a more efficient mode of operation, and may be useful +on large regions that have already been sorted. + +If the argument KEEP-BLANKS is non-nil (interactively, with a +C-u C-u C-u prefix), it retains repeated blank lines. + +Returns the number of deleted lines. Interactively, or if INTERACTIVE +is non-nil, it also prints a message describing the number of deletions. + +\(fn BEG END &optional REVERSE ADJACENT KEEP-BLANKS INTERACTIVE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sort" '("sort-"))) + +;;;*** + +;;;### (autoloads nil "soundex" "soundex.el" (0 0 0 0)) +;;; Generated autoloads from soundex.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "soundex" '("soundex"))) + +;;;*** + +;;;### (autoloads nil "spam" "gnus/spam.el" (0 0 0 0)) +;;; Generated autoloads from gnus/spam.el + +(autoload 'spam-initialize "spam" "\ +Install the spam.el hooks and do other initialization. +When SYMBOLS is given, set those variables to t. This is so you +can call `spam-initialize' before you set spam-use-* variables on +explicitly, and matters only if you need the extra headers +installed through `spam-necessary-extra-headers'. + +\(fn &rest SYMBOLS)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "spam" '("spam-"))) + +;;;*** + +;;;### (autoloads nil "spam-report" "gnus/spam-report.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from gnus/spam-report.el + +(autoload 'spam-report-process-queue "spam-report" "\ +Report all queued requests from `spam-report-requests-file'. + +If FILE is given, use it instead of `spam-report-requests-file'. +If KEEP is t, leave old requests in the file. If KEEP is the +symbol `ask', query before flushing the queue file. + +\(fn &optional FILE KEEP)" t nil) + +(autoload 'spam-report-url-ping-mm-url "spam-report" "\ +Ping a host through HTTP, addressing a specific GET resource. Use +the external program specified in `mm-url-program' to connect to +server. + +\(fn HOST REPORT)" nil nil) + +(autoload 'spam-report-url-to-file "spam-report" "\ +Collect spam report requests in `spam-report-requests-file'. +Customize `spam-report-url-ping-function' to use this function. + +\(fn HOST REPORT)" nil nil) + +(autoload 'spam-report-agentize "spam-report" "\ +Add spam-report support to the Agent. +Spam reports will be queued with \\[spam-report-url-to-file] when +the Agent is unplugged, and will be submitted in a batch when the +Agent is plugged. + +\(fn)" t nil) + +(autoload 'spam-report-deagentize "spam-report" "\ +Remove spam-report support from the Agent. +Spam reports will be queued with the method used when +\\[spam-report-agentize] was run. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "spam-report" '("spam-report-"))) + +;;;*** + +;;;### (autoloads nil "spam-stat" "gnus/spam-stat.el" (0 0 0 0)) +;;; Generated autoloads from gnus/spam-stat.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "spam-stat" '("spam-stat" "with-spam-stat-max-buffer-size"))) + +;;;*** + +;;;### (autoloads nil "spam-wash" "gnus/spam-wash.el" (0 0 0 0)) +;;; Generated autoloads from gnus/spam-wash.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "spam-wash" '("spam-"))) + +;;;*** + +;;;### (autoloads nil "speedbar" "speedbar.el" (0 0 0 0)) +;;; Generated autoloads from speedbar.el + +(defalias 'speedbar 'speedbar-frame-mode) + +(autoload 'speedbar-frame-mode "speedbar" "\ +Enable or disable speedbar. Positive ARG means turn on, negative turn off. +A nil ARG means toggle. Once the speedbar frame is activated, a buffer in +`speedbar-mode' will be displayed. Currently, only one speedbar is +supported at a time. +`speedbar-before-popup-hook' is called before popping up the speedbar frame. +`speedbar-before-delete-hook' is called before the frame is deleted. + +\(fn &optional ARG)" t nil) + +(autoload 'speedbar-get-focus "speedbar" "\ +Change frame focus to or from the speedbar frame. +If the selected frame is not speedbar, then speedbar frame is +selected. If the speedbar frame is active, then select the attached frame. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "speedbar" '("speedbar-"))) + +;;;*** + +;;;### (autoloads nil "spook" "play/spook.el" (0 0 0 0)) +;;; Generated autoloads from play/spook.el + +(autoload 'spook "spook" "\ +Adds that special touch of class to your outgoing mail. + +\(fn)" t nil) + +(autoload 'snarf-spooks "spook" "\ +Return a vector containing the lines from `spook-phrases-file'. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "spook" '("spook-phrase"))) + +;;;*** + +;;;### (autoloads nil "sql" "progmodes/sql.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/sql.el +(push (purecopy '(sql 3 5)) package--builtin-versions) + +(autoload 'sql-add-product-keywords "sql" "\ +Add highlighting KEYWORDS for SQL PRODUCT. + +PRODUCT should be a symbol, the name of a SQL product, such as +`oracle'. KEYWORDS should be a list; see the variable +`font-lock-keywords'. By default they are added at the beginning +of the current highlighting list. If optional argument APPEND is +`set', they are used to replace the current highlighting list. +If APPEND is any other non-nil value, they are added at the end +of the current highlighting list. + +For example: + + (sql-add-product-keywords \\='ms + \\='((\"\\\\b\\\\w+_t\\\\b\" . font-lock-type-face))) + +adds a fontification pattern to fontify identifiers ending in +`_t' as data types. + +\(fn PRODUCT KEYWORDS &optional APPEND)" nil nil) + +(autoload 'sql-mode "sql" "\ +Major mode to edit SQL. + +You can send SQL statements to the SQLi buffer using +\\[sql-send-region]. Such a buffer must exist before you can do this. +See `sql-help' on how to create SQLi buffers. + +\\{sql-mode-map} +Customization: Entry to this mode runs the `sql-mode-hook'. + +When you put a buffer in SQL mode, the buffer stores the last SQLi +buffer created as its destination in the variable `sql-buffer'. This +will be the buffer \\[sql-send-region] sends the region to. If this +SQLi buffer is killed, \\[sql-send-region] is no longer able to +determine where the strings should be sent to. You can set the +value of `sql-buffer' using \\[sql-set-sqli-buffer]. + +For information on how to create multiple SQLi buffers, see +`sql-interactive-mode'. + +Note that SQL doesn't have an escape character unless you specify +one. If you specify backslash as escape character in SQL, you +must tell Emacs. Here's how to do that in your init file: + +\(add-hook \\='sql-mode-hook + (lambda () + (modify-syntax-entry ?\\\\ \".\" sql-mode-syntax-table))) + +\(fn)" t nil) + +(autoload 'sql-connect "sql" "\ +Connect to an interactive session using CONNECTION settings. + +See `sql-connection-alist' to see how to define connections and +their settings. + +The user will not be prompted for any login parameters if a value +is specified in the connection settings. + +\(fn CONNECTION &optional NEW-NAME)" t nil) + +(autoload 'sql-product-interactive "sql" "\ +Run PRODUCT interpreter as an inferior process. + +If buffer `*SQL*' exists but no process is running, make a new process. +If buffer exists and a process is running, just switch to buffer `*SQL*'. + +To specify the SQL product, prefix the call with +\\[universal-argument]. To set the buffer name as well, prefix +the call to \\[sql-product-interactive] with +\\[universal-argument] \\[universal-argument]. + +\(Type \\[describe-mode] in the SQL buffer for a list of commands.) + +\(fn &optional PRODUCT NEW-NAME)" t nil) + +(autoload 'sql-oracle "sql" "\ +Run sqlplus by Oracle as an inferior process. + +If buffer `*SQL*' exists but no process is running, make a new process. +If buffer exists and a process is running, just switch to buffer +`*SQL*'. + +Interpreter used comes from variable `sql-oracle-program'. Login uses +the variables `sql-user', `sql-password', and `sql-database' as +defaults, if set. Additional command line parameters can be stored in +the list `sql-oracle-options'. + +The buffer is put in SQL interactive mode, giving commands for sending +input. See `sql-interactive-mode'. + +To set the buffer name directly, use \\[universal-argument] +before \\[sql-oracle]. Once session has started, +\\[sql-rename-buffer] can be called separately to rename the +buffer. + +To specify a coding system for converting non-ASCII characters +in the input and output to the process, use \\[universal-coding-system-argument] +before \\[sql-oracle]. You can also specify this with \\[set-buffer-process-coding-system] +in the SQL buffer, after you start the process. +The default comes from `process-coding-system-alist' and +`default-process-coding-system'. + +\(Type \\[describe-mode] in the SQL buffer for a list of commands.) + +\(fn &optional BUFFER)" t nil) + +(autoload 'sql-sybase "sql" "\ +Run isql by Sybase as an inferior process. + +If buffer `*SQL*' exists but no process is running, make a new process. +If buffer exists and a process is running, just switch to buffer +`*SQL*'. + +Interpreter used comes from variable `sql-sybase-program'. Login uses +the variables `sql-server', `sql-user', `sql-password', and +`sql-database' as defaults, if set. Additional command line parameters +can be stored in the list `sql-sybase-options'. + +The buffer is put in SQL interactive mode, giving commands for sending +input. See `sql-interactive-mode'. + +To set the buffer name directly, use \\[universal-argument] +before \\[sql-sybase]. Once session has started, +\\[sql-rename-buffer] can be called separately to rename the +buffer. + +To specify a coding system for converting non-ASCII characters +in the input and output to the process, use \\[universal-coding-system-argument] +before \\[sql-sybase]. You can also specify this with \\[set-buffer-process-coding-system] +in the SQL buffer, after you start the process. +The default comes from `process-coding-system-alist' and +`default-process-coding-system'. + +\(Type \\[describe-mode] in the SQL buffer for a list of commands.) + +\(fn &optional BUFFER)" t nil) + +(autoload 'sql-informix "sql" "\ +Run dbaccess by Informix as an inferior process. + +If buffer `*SQL*' exists but no process is running, make a new process. +If buffer exists and a process is running, just switch to buffer +`*SQL*'. + +Interpreter used comes from variable `sql-informix-program'. Login uses +the variable `sql-database' as default, if set. + +The buffer is put in SQL interactive mode, giving commands for sending +input. See `sql-interactive-mode'. + +To set the buffer name directly, use \\[universal-argument] +before \\[sql-informix]. Once session has started, +\\[sql-rename-buffer] can be called separately to rename the +buffer. + +To specify a coding system for converting non-ASCII characters +in the input and output to the process, use \\[universal-coding-system-argument] +before \\[sql-informix]. You can also specify this with \\[set-buffer-process-coding-system] +in the SQL buffer, after you start the process. +The default comes from `process-coding-system-alist' and +`default-process-coding-system'. + +\(Type \\[describe-mode] in the SQL buffer for a list of commands.) + +\(fn &optional BUFFER)" t nil) + +(autoload 'sql-sqlite "sql" "\ +Run sqlite as an inferior process. + +SQLite is free software. + +If buffer `*SQL*' exists but no process is running, make a new process. +If buffer exists and a process is running, just switch to buffer +`*SQL*'. + +Interpreter used comes from variable `sql-sqlite-program'. Login uses +the variables `sql-user', `sql-password', `sql-database', and +`sql-server' as defaults, if set. Additional command line parameters +can be stored in the list `sql-sqlite-options'. + +The buffer is put in SQL interactive mode, giving commands for sending +input. See `sql-interactive-mode'. + +To set the buffer name directly, use \\[universal-argument] +before \\[sql-sqlite]. Once session has started, +\\[sql-rename-buffer] can be called separately to rename the +buffer. + +To specify a coding system for converting non-ASCII characters +in the input and output to the process, use \\[universal-coding-system-argument] +before \\[sql-sqlite]. You can also specify this with \\[set-buffer-process-coding-system] +in the SQL buffer, after you start the process. +The default comes from `process-coding-system-alist' and +`default-process-coding-system'. + +\(Type \\[describe-mode] in the SQL buffer for a list of commands.) + +\(fn &optional BUFFER)" t nil) + +(autoload 'sql-mysql "sql" "\ +Run mysql by TcX as an inferior process. + +Mysql versions 3.23 and up are free software. + +If buffer `*SQL*' exists but no process is running, make a new process. +If buffer exists and a process is running, just switch to buffer +`*SQL*'. + +Interpreter used comes from variable `sql-mysql-program'. Login uses +the variables `sql-user', `sql-password', `sql-database', and +`sql-server' as defaults, if set. Additional command line parameters +can be stored in the list `sql-mysql-options'. + +The buffer is put in SQL interactive mode, giving commands for sending +input. See `sql-interactive-mode'. + +To set the buffer name directly, use \\[universal-argument] +before \\[sql-mysql]. Once session has started, +\\[sql-rename-buffer] can be called separately to rename the +buffer. + +To specify a coding system for converting non-ASCII characters +in the input and output to the process, use \\[universal-coding-system-argument] +before \\[sql-mysql]. You can also specify this with \\[set-buffer-process-coding-system] +in the SQL buffer, after you start the process. +The default comes from `process-coding-system-alist' and +`default-process-coding-system'. + +\(Type \\[describe-mode] in the SQL buffer for a list of commands.) + +\(fn &optional BUFFER)" t nil) + +(autoload 'sql-solid "sql" "\ +Run solsql by Solid as an inferior process. + +If buffer `*SQL*' exists but no process is running, make a new process. +If buffer exists and a process is running, just switch to buffer +`*SQL*'. + +Interpreter used comes from variable `sql-solid-program'. Login uses +the variables `sql-user', `sql-password', and `sql-server' as +defaults, if set. + +The buffer is put in SQL interactive mode, giving commands for sending +input. See `sql-interactive-mode'. + +To set the buffer name directly, use \\[universal-argument] +before \\[sql-solid]. Once session has started, +\\[sql-rename-buffer] can be called separately to rename the +buffer. + +To specify a coding system for converting non-ASCII characters +in the input and output to the process, use \\[universal-coding-system-argument] +before \\[sql-solid]. You can also specify this with \\[set-buffer-process-coding-system] +in the SQL buffer, after you start the process. +The default comes from `process-coding-system-alist' and +`default-process-coding-system'. + +\(Type \\[describe-mode] in the SQL buffer for a list of commands.) + +\(fn &optional BUFFER)" t nil) + +(autoload 'sql-ingres "sql" "\ +Run sql by Ingres as an inferior process. + +If buffer `*SQL*' exists but no process is running, make a new process. +If buffer exists and a process is running, just switch to buffer +`*SQL*'. + +Interpreter used comes from variable `sql-ingres-program'. Login uses +the variable `sql-database' as default, if set. + +The buffer is put in SQL interactive mode, giving commands for sending +input. See `sql-interactive-mode'. + +To set the buffer name directly, use \\[universal-argument] +before \\[sql-ingres]. Once session has started, +\\[sql-rename-buffer] can be called separately to rename the +buffer. + +To specify a coding system for converting non-ASCII characters +in the input and output to the process, use \\[universal-coding-system-argument] +before \\[sql-ingres]. You can also specify this with \\[set-buffer-process-coding-system] +in the SQL buffer, after you start the process. +The default comes from `process-coding-system-alist' and +`default-process-coding-system'. + +\(Type \\[describe-mode] in the SQL buffer for a list of commands.) + +\(fn &optional BUFFER)" t nil) + +(autoload 'sql-ms "sql" "\ +Run osql by Microsoft as an inferior process. + +If buffer `*SQL*' exists but no process is running, make a new process. +If buffer exists and a process is running, just switch to buffer +`*SQL*'. + +Interpreter used comes from variable `sql-ms-program'. Login uses the +variables `sql-user', `sql-password', `sql-database', and `sql-server' +as defaults, if set. Additional command line parameters can be stored +in the list `sql-ms-options'. + +The buffer is put in SQL interactive mode, giving commands for sending +input. See `sql-interactive-mode'. + +To set the buffer name directly, use \\[universal-argument] +before \\[sql-ms]. Once session has started, +\\[sql-rename-buffer] can be called separately to rename the +buffer. + +To specify a coding system for converting non-ASCII characters +in the input and output to the process, use \\[universal-coding-system-argument] +before \\[sql-ms]. You can also specify this with \\[set-buffer-process-coding-system] +in the SQL buffer, after you start the process. +The default comes from `process-coding-system-alist' and +`default-process-coding-system'. + +\(Type \\[describe-mode] in the SQL buffer for a list of commands.) + +\(fn &optional BUFFER)" t nil) + +(autoload 'sql-postgres "sql" "\ +Run psql by Postgres as an inferior process. + +If buffer `*SQL*' exists but no process is running, make a new process. +If buffer exists and a process is running, just switch to buffer +`*SQL*'. + +Interpreter used comes from variable `sql-postgres-program'. Login uses +the variables `sql-database' and `sql-server' as default, if set. +Additional command line parameters can be stored in the list +`sql-postgres-options'. + +The buffer is put in SQL interactive mode, giving commands for sending +input. See `sql-interactive-mode'. + +To set the buffer name directly, use \\[universal-argument] +before \\[sql-postgres]. Once session has started, +\\[sql-rename-buffer] can be called separately to rename the +buffer. + +To specify a coding system for converting non-ASCII characters +in the input and output to the process, use \\[universal-coding-system-argument] +before \\[sql-postgres]. You can also specify this with \\[set-buffer-process-coding-system] +in the SQL buffer, after you start the process. +The default comes from `process-coding-system-alist' and +`default-process-coding-system'. If your output lines end with ^M, +your might try undecided-dos as a coding system. If this doesn't help, +Try to set `comint-output-filter-functions' like this: + +\(setq comint-output-filter-functions (append comint-output-filter-functions + \\='(comint-strip-ctrl-m))) + +\(Type \\[describe-mode] in the SQL buffer for a list of commands.) + +\(fn &optional BUFFER)" t nil) + +(autoload 'sql-interbase "sql" "\ +Run isql by Interbase as an inferior process. + +If buffer `*SQL*' exists but no process is running, make a new process. +If buffer exists and a process is running, just switch to buffer +`*SQL*'. + +Interpreter used comes from variable `sql-interbase-program'. Login +uses the variables `sql-user', `sql-password', and `sql-database' as +defaults, if set. + +The buffer is put in SQL interactive mode, giving commands for sending +input. See `sql-interactive-mode'. + +To set the buffer name directly, use \\[universal-argument] +before \\[sql-interbase]. Once session has started, +\\[sql-rename-buffer] can be called separately to rename the +buffer. + +To specify a coding system for converting non-ASCII characters +in the input and output to the process, use \\[universal-coding-system-argument] +before \\[sql-interbase]. You can also specify this with \\[set-buffer-process-coding-system] +in the SQL buffer, after you start the process. +The default comes from `process-coding-system-alist' and +`default-process-coding-system'. + +\(Type \\[describe-mode] in the SQL buffer for a list of commands.) + +\(fn &optional BUFFER)" t nil) + +(autoload 'sql-db2 "sql" "\ +Run db2 by IBM as an inferior process. + +If buffer `*SQL*' exists but no process is running, make a new process. +If buffer exists and a process is running, just switch to buffer +`*SQL*'. + +Interpreter used comes from variable `sql-db2-program'. There is not +automatic login. + +The buffer is put in SQL interactive mode, giving commands for sending +input. See `sql-interactive-mode'. + +If you use \\[sql-accumulate-and-indent] to send multiline commands to +db2, newlines will be escaped if necessary. If you don't want that, set +`comint-input-sender' back to `comint-simple-send' by writing an after +advice. See the elisp manual for more information. + +To set the buffer name directly, use \\[universal-argument] +before \\[sql-db2]. Once session has started, +\\[sql-rename-buffer] can be called separately to rename the +buffer. + +To specify a coding system for converting non-ASCII characters +in the input and output to the process, use \\[universal-coding-system-argument] +before \\[sql-db2]. You can also specify this with \\[set-buffer-process-coding-system] +in the SQL buffer, after you start the process. +The default comes from `process-coding-system-alist' and +`default-process-coding-system'. + +\(Type \\[describe-mode] in the SQL buffer for a list of commands.) + +\(fn &optional BUFFER)" t nil) + +(autoload 'sql-linter "sql" "\ +Run inl by RELEX as an inferior process. + +If buffer `*SQL*' exists but no process is running, make a new process. +If buffer exists and a process is running, just switch to buffer +`*SQL*'. + +Interpreter used comes from variable `sql-linter-program' - usually `inl'. +Login uses the variables `sql-user', `sql-password', `sql-database' and +`sql-server' as defaults, if set. Additional command line parameters +can be stored in the list `sql-linter-options'. Run inl -h to get help on +parameters. + +`sql-database' is used to set the LINTER_MBX environment variable for +local connections, `sql-server' refers to the server name from the +`nodetab' file for the network connection (dbc_tcp or friends must run +for this to work). If `sql-password' is an empty string, inl will use +an empty password. + +The buffer is put in SQL interactive mode, giving commands for sending +input. See `sql-interactive-mode'. + +To set the buffer name directly, use \\[universal-argument] +before \\[sql-linter]. Once session has started, +\\[sql-rename-buffer] can be called separately to rename the +buffer. + +\(Type \\[describe-mode] in the SQL buffer for a list of commands.) + +\(fn &optional BUFFER)" t nil) + +(autoload 'sql-vertica "sql" "\ +Run vsql as an inferior process. + +\(fn &optional BUFFER)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sql" '("sql-"))) + +;;;*** + +;;;### (autoloads nil "srecode" "cedet/srecode.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode.el +(push (purecopy '(srecode 1 2)) package--builtin-versions) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode" '("srecode-version"))) + +;;;*** + +;;;### (autoloads nil "srecode/args" "cedet/srecode/args.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from cedet/srecode/args.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/args" '("srecode-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "srecode/compile" +;;;;;; "cedet/srecode/compile.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/compile.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/compile" '("srecode-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "srecode/cpp" +;;;;;; "cedet/srecode/cpp.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/cpp.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/cpp" '("srecode-"))) + +;;;*** + +;;;### (autoloads nil "srecode/ctxt" "cedet/srecode/ctxt.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from cedet/srecode/ctxt.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/ctxt" '("srecode-"))) + +;;;*** + +;;;### (autoloads nil "srecode/dictionary" "cedet/srecode/dictionary.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/dictionary.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/dictionary" '("srecode-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "srecode/document" +;;;;;; "cedet/srecode/document.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/document.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/document" '("srecode-document-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "srecode/el" "cedet/srecode/el.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/el.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/el" '("srecode-semantic-apply-tag-to-dict"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "srecode/expandproto" +;;;;;; "cedet/srecode/expandproto.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/expandproto.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/expandproto" '("srecode-"))) + +;;;*** + +;;;### (autoloads nil "srecode/extract" "cedet/srecode/extract.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/extract.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/extract" '("srecode-extract"))) + +;;;*** + +;;;### (autoloads nil "srecode/fields" "cedet/srecode/fields.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/fields.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/fields" '("srecode-"))) + +;;;*** + +;;;### (autoloads nil "srecode/filters" "cedet/srecode/filters.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/filters.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/filters" '("srecode-comment-prefix"))) + +;;;*** + +;;;### (autoloads nil "srecode/find" "cedet/srecode/find.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from cedet/srecode/find.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/find" '("srecode-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "srecode/getset" +;;;;;; "cedet/srecode/getset.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/getset.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/getset" '("srecode-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "srecode/insert" +;;;;;; "cedet/srecode/insert.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/insert.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/insert" '("srecode-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "srecode/map" +;;;;;; "cedet/srecode/map.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/map.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/map" '("srecode-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "srecode/mode" +;;;;;; "cedet/srecode/mode.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/mode.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/mode" '("srecode-"))) + +;;;*** + +;;;### (autoloads nil "srecode/semantic" "cedet/srecode/semantic.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/semantic.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/semantic" '("srecode-semantic-"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "srecode/srt" +;;;;;; "cedet/srecode/srt.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/srt.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/srt" '("srecode-read-"))) + +;;;*** + +;;;### (autoloads nil "srecode/srt-mode" "cedet/srecode/srt-mode.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/srt-mode.el + +(autoload 'srecode-template-mode "srecode/srt-mode" "\ +Major-mode for writing SRecode macros. + +\(fn)" t nil) + +(defalias 'srt-mode 'srecode-template-mode) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/srt-mode" '("semantic-" "srecode-"))) + +;;;*** + +;;;### (autoloads nil "srecode/table" "cedet/srecode/table.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from cedet/srecode/table.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/table" '("srecode-" "object-sort-list"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "srecode/template" +;;;;;; "cedet/srecode/template.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/template.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/template" '("semantic-tag-components"))) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "srecode/texi" +;;;;;; "cedet/srecode/texi.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/texi.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "srecode/texi" '("semantic-insert-foreign-tag" "srecode-texi-"))) + +;;;*** + +;;;### (autoloads nil "starttls" "net/starttls.el" (0 0 0 0)) +;;; Generated autoloads from net/starttls.el + +(autoload 'starttls-open-stream "starttls" "\ +Open a TLS connection for a port to a host. +Returns a subprocess object to represent the connection. +Input and output work as for subprocesses; `delete-process' closes it. +Args are NAME BUFFER HOST PORT. +NAME is name for process. It is modified if necessary to make it unique. +BUFFER is the buffer (or `buffer-name') to associate with the process. + Process output goes at end of that buffer, unless you specify + an output stream or filter function to handle the output. + BUFFER may be also nil, meaning that this process is not associated + with any buffer +Third arg is name of the host to connect to, or its IP address. +Fourth arg PORT is an integer specifying a port to connect to. +If `starttls-use-gnutls' is nil, this may also be a service name, but +GnuTLS requires a port number. + +\(fn NAME BUFFER HOST PORT)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "starttls" '("starttls-"))) + +;;;*** + +;;;### (autoloads nil "strokes" "strokes.el" (0 0 0 0)) +;;; Generated autoloads from strokes.el + +(autoload 'strokes-global-set-stroke "strokes" "\ +Interactively give STROKE the global binding as COMMAND. +Works just like `global-set-key', except for strokes. COMMAND is +a symbol naming an interactively-callable function. STROKE is a +list of sampled positions on the stroke grid as described in the +documentation for the `strokes-define-stroke' function. + +See also `strokes-global-set-stroke-string'. + +\(fn STROKE COMMAND)" t nil) + +(autoload 'strokes-read-stroke "strokes" "\ +Read a simple stroke (interactively) and return the stroke. +Optional PROMPT in minibuffer displays before and during stroke reading. +This function will display the stroke interactively as it is being +entered in the strokes buffer if the variable +`strokes-use-strokes-buffer' is non-nil. +Optional EVENT is acceptable as the starting event of the stroke. + +\(fn &optional PROMPT EVENT)" nil nil) + +(autoload 'strokes-read-complex-stroke "strokes" "\ +Read a complex stroke (interactively) and return the stroke. +Optional PROMPT in minibuffer displays before and during stroke reading. +Note that a complex stroke allows the user to pen-up and pen-down. This +is implemented by allowing the user to paint with button 1 or button 2 and +then complete the stroke with button 3. +Optional EVENT is acceptable as the starting event of the stroke. + +\(fn &optional PROMPT EVENT)" nil nil) + +(autoload 'strokes-do-stroke "strokes" "\ +Read a simple stroke from the user and then execute its command. +This must be bound to a mouse event. + +\(fn EVENT)" t nil) + +(autoload 'strokes-do-complex-stroke "strokes" "\ +Read a complex stroke from the user and then execute its command. +This must be bound to a mouse event. + +\(fn EVENT)" t nil) + +(autoload 'strokes-describe-stroke "strokes" "\ +Displays the command which STROKE maps to, reading STROKE interactively. + +\(fn STROKE)" t nil) + +(autoload 'strokes-help "strokes" "\ +Get instruction on using the Strokes package. + +\(fn)" t nil) + +(autoload 'strokes-load-user-strokes "strokes" "\ +Load user-defined strokes from file named by `strokes-file'. + +\(fn)" t nil) + +(autoload 'strokes-list-strokes "strokes" "\ +Pop up a buffer containing an alphabetical listing of strokes in STROKES-MAP. +With CHRONOLOGICAL prefix arg (\\[universal-argument]) list strokes chronologically +by command name. +If STROKES-MAP is not given, `strokes-global-map' will be used instead. + +\(fn &optional CHRONOLOGICAL STROKES-MAP)" t nil) + +(defvar strokes-mode nil "\ +Non-nil if Strokes mode is enabled. +See the `strokes-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `strokes-mode'.") + +(custom-autoload 'strokes-mode "strokes" nil) + +(autoload 'strokes-mode "strokes" "\ +Toggle Strokes mode, a global minor mode. +With a prefix argument ARG, enable Strokes mode if ARG is +positive, and disable it otherwise. If called from Lisp, +enable the mode if ARG is omitted or nil. + +\\ +Strokes are pictographic mouse gestures which invoke commands. +Strokes are invoked with \\[strokes-do-stroke]. You can define +new strokes with \\[strokes-global-set-stroke]. See also +\\[strokes-do-complex-stroke] for `complex' strokes. + +To use strokes for pictographic editing, such as Chinese/Japanese, use +\\[strokes-compose-complex-stroke], which draws strokes and inserts them. +Encode/decode your strokes with \\[strokes-encode-buffer], +\\[strokes-decode-buffer]. + +\\{strokes-mode-map} + +\(fn &optional ARG)" t nil) + +(autoload 'strokes-decode-buffer "strokes" "\ +Decode stroke strings in BUFFER and display their corresponding glyphs. +Optional BUFFER defaults to the current buffer. +Optional FORCE non-nil will ignore the buffer's read-only status. + +\(fn &optional BUFFER FORCE)" t nil) + +(autoload 'strokes-compose-complex-stroke "strokes" "\ +Read a complex stroke and insert its glyph into the current buffer. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "strokes" '("strokes-"))) + +;;;*** + +;;;### (autoloads nil "studly" "play/studly.el" (0 0 0 0)) +;;; Generated autoloads from play/studly.el + +(autoload 'studlify-region "studly" "\ +Studlify-case the region. + +\(fn BEGIN END)" t nil) + +(autoload 'studlify-word "studly" "\ +Studlify-case the current word, or COUNT words if given an argument. + +\(fn COUNT)" t nil) + +(autoload 'studlify-buffer "studly" "\ +Studlify-case the current buffer. + +\(fn)" t nil) + +;;;*** + +;;;### (autoloads nil "subr-x" "emacs-lisp/subr-x.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/subr-x.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "subr-x" '("read-multiple-choice" "string-" "hash-table-" "and-let*" "when-let" "internal--" "if-let" "thread-"))) + +;;;*** + +;;;### (autoloads nil "subword" "progmodes/subword.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/subword.el + +(define-obsolete-function-alias 'capitalized-words-mode 'subword-mode "25.1") + +(autoload 'subword-mode "subword" "\ +Toggle subword movement and editing (Subword mode). +With a prefix argument ARG, enable Subword mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Subword mode is a buffer-local minor mode. Enabling it changes +the definition of a word so that word-based commands stop inside +symbols with mixed uppercase and lowercase letters, +e.g. \"GtkWidget\", \"EmacsFrameClass\", \"NSGraphicsContext\". + +Here we call these mixed case symbols `nomenclatures'. Each +capitalized (or completely uppercase) part of a nomenclature is +called a `subword'. Here are some examples: + + Nomenclature Subwords + =========================================================== + GtkWindow => \"Gtk\" and \"Window\" + EmacsFrameClass => \"Emacs\", \"Frame\" and \"Class\" + NSGraphicsContext => \"NS\", \"Graphics\" and \"Context\" + +This mode changes the definition of a word so that word commands +treat nomenclature boundaries as word boundaries. + +\\{subword-mode-map} + +\(fn &optional ARG)" t nil) + +(defvar global-subword-mode nil "\ +Non-nil if Global Subword mode is enabled. +See the `global-subword-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `global-subword-mode'.") + +(custom-autoload 'global-subword-mode "subword" nil) + +(autoload 'global-subword-mode "subword" "\ +Toggle Subword mode in all buffers. +With prefix ARG, enable Global Subword mode if ARG is positive; +otherwise, disable it. If called from Lisp, enable the mode if +ARG is omitted or nil. + +Subword mode is enabled in all buffers where +`(lambda nil (subword-mode 1))' would do it. +See `subword-mode' for more information on Subword mode. + +\(fn &optional ARG)" t nil) + +(autoload 'superword-mode "subword" "\ +Toggle superword movement and editing (Superword mode). +With a prefix argument ARG, enable Superword mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Superword mode is a buffer-local minor mode. Enabling it changes +the definition of words such that symbols characters are treated +as parts of words: e.g., in `superword-mode', +\"this_is_a_symbol\" counts as one word. + +\\{superword-mode-map} + +\(fn &optional ARG)" t nil) + +(defvar global-superword-mode nil "\ +Non-nil if Global Superword mode is enabled. +See the `global-superword-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `global-superword-mode'.") + +(custom-autoload 'global-superword-mode "subword" nil) + +(autoload 'global-superword-mode "subword" "\ +Toggle Superword mode in all buffers. +With prefix ARG, enable Global Superword mode if ARG is positive; +otherwise, disable it. If called from Lisp, enable the mode if +ARG is omitted or nil. + +Superword mode is enabled in all buffers where +`(lambda nil (superword-mode 1))' would do it. +See `superword-mode' for more information on Superword mode. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "subword" '("superword-mode-map" "subword-"))) + +;;;*** + +;;;### (autoloads nil "supercite" "mail/supercite.el" (0 0 0 0)) +;;; Generated autoloads from mail/supercite.el + +(autoload 'sc-cite-original "supercite" "\ +Workhorse citing function which performs the initial citation. +This is callable from the various mail and news readers' reply +function according to the agreed upon standard. See the associated +info node `(SC)Top' for more details. +`sc-cite-original' does not do any yanking of the +original message but it does require a few things: + + 1) The reply buffer is the current buffer. + + 2) The original message has been yanked and inserted into the + reply buffer. + + 3) Verbose mail headers from the original message have been + inserted into the reply buffer directly before the text of the + original message. + + 4) Point is at the beginning of the verbose headers. + + 5) Mark is at the end of the body of text to be cited. + +The region need not be active (and typically isn't when this +function is called). Also, the hook `sc-pre-hook' is run before, +and `sc-post-hook' is run after the guts of this function. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "supercite" '("sc-"))) + +;;;*** + +;;;### (autoloads nil "svg" "svg.el" (0 0 0 0)) +;;; Generated autoloads from svg.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "svg" '("svg-"))) + +;;;*** + +;;;### (autoloads nil "t-mouse" "t-mouse.el" (0 0 0 0)) +;;; Generated autoloads from t-mouse.el + +(define-obsolete-function-alias 't-mouse-mode 'gpm-mouse-mode "23.1") + +(defvar gpm-mouse-mode t "\ +Non-nil if Gpm-Mouse mode is enabled. +See the `gpm-mouse-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `gpm-mouse-mode'.") + +(custom-autoload 'gpm-mouse-mode "t-mouse" nil) + +(autoload 'gpm-mouse-mode "t-mouse" "\ +Toggle mouse support in GNU/Linux consoles (GPM Mouse mode). +With a prefix argument ARG, enable GPM Mouse mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +This allows the use of the mouse when operating on a GNU/Linux console, +in the same way as you can use the mouse under X11. +It relies on the `gpm' daemon being activated. + +Note that when `gpm-mouse-mode' is enabled, you cannot use the +mouse to transfer text between Emacs and other programs which use +GPM. This is due to limitations in GPM and the Linux kernel. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "t-mouse" '("gpm-mouse-"))) + +;;;*** + +;;;### (autoloads nil "tabify" "tabify.el" (0 0 0 0)) +;;; Generated autoloads from tabify.el + +(autoload 'untabify "tabify" "\ +Convert all tabs in region to multiple spaces, preserving columns. +If called interactively with prefix ARG, convert for the entire +buffer. + +Called non-interactively, the region is specified by arguments +START and END, rather than by the position of point and mark. +The variable `tab-width' controls the spacing of tab stops. + +\(fn START END &optional ARG)" t nil) + +(autoload 'tabify "tabify" "\ +Convert multiple spaces in region to tabs when possible. +A group of spaces is partially replaced by tabs +when this can be done without changing the column they end at. +If called interactively with prefix ARG, convert for the entire +buffer. + +Called non-interactively, the region is specified by arguments +START and END, rather than by the position of point and mark. +The variable `tab-width' controls the spacing of tab stops. + +\(fn START END &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tabify" '("tabify-regexp"))) + +;;;*** + +;;;### (autoloads nil "table" "textmodes/table.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/table.el + +(autoload 'table-insert "table" "\ +Insert an editable text table. +Insert a table of specified number of COLUMNS and ROWS. Optional +parameter CELL-WIDTH and CELL-HEIGHT can specify the size of each +cell. The cell size is uniform across the table if the specified size +is a number. They can be a list of numbers to specify different size +for each cell. When called interactively, the list of number is +entered by simply listing all the numbers with space characters +delimiting them. + +Examples: + +\\[table-insert] inserts a table at the current point location. + +Suppose we have the following situation where `-!-' indicates the +location of point. + + -!- + +Type \\[table-insert] and hit ENTER key. As it asks table +specification, provide 3 for number of columns, 1 for number of rows, +5 for cell width and 1 for cell height. Now you shall see the next +table and the point is automatically moved to the beginning of the +first cell. + + +-----+-----+-----+ + |-!- | | | + +-----+-----+-----+ + +Inside a table cell, there are special key bindings. \\ + +M-9 \\[table-widen-cell] (or \\[universal-argument] 9 \\[table-widen-cell]) widens the first cell by 9 character +width, which results as + + +--------------+-----+-----+ + |-!- | | | + +--------------+-----+-----+ + +Type TAB \\[table-widen-cell] then type TAB M-2 M-7 \\[table-widen-cell] (or \\[universal-argument] 2 7 \\[table-widen-cell]). Typing +TAB moves the point forward by a cell. The result now looks like this: + + +--------------+------+--------------------------------+ + | | |-!- | + +--------------+------+--------------------------------+ + +If you knew each width of the columns prior to the table creation, +what you could have done better was to have had given the complete +width information to `table-insert'. + +Cell width(s): 14 6 32 + +instead of + +Cell width(s): 5 + +This would have eliminated the previously mentioned width adjustment +work all together. + +If the point is in the last cell type S-TAB S-TAB to move it to the +first cell. Now type \\[table-heighten-cell] which heighten the row by a line. + + +--------------+------+--------------------------------+ + |-!- | | | + | | | | + +--------------+------+--------------------------------+ + +Type \\[table-insert-row-column] and tell it to insert a row. + + +--------------+------+--------------------------------+ + |-!- | | | + | | | | + +--------------+------+--------------------------------+ + | | | | + | | | | + +--------------+------+--------------------------------+ + +Move the point under the table as shown below. + + +--------------+------+--------------------------------+ + | | | | + | | | | + +--------------+------+--------------------------------+ + | | | | + | | | | + +--------------+------+--------------------------------+ + -!- + +Type M-x table-insert-row instead of \\[table-insert-row-column]. \\[table-insert-row-column] does not work +when the point is outside of the table. This insertion at +outside of the table effectively appends a row at the end. + + +--------------+------+--------------------------------+ + | | | | + | | | | + +--------------+------+--------------------------------+ + | | | | + | | | | + +--------------+------+--------------------------------+ + |-!- | | | + | | | | + +--------------+------+--------------------------------+ + +Text editing inside the table cell produces reasonably expected +results. + + +--------------+------+--------------------------------+ + | | | | + | | | | + +--------------+------+--------------------------------+ + | | |Text editing inside the table | + | | |cell produces reasonably | + | | |expected results.-!- | + +--------------+------+--------------------------------+ + | | | | + | | | | + +--------------+------+--------------------------------+ + +Inside a table cell has a special keymap. + +\\{table-cell-map} + +\(fn COLUMNS ROWS &optional CELL-WIDTH CELL-HEIGHT)" t nil) + +(autoload 'table-insert-row "table" "\ +Insert N table row(s). +When point is in a table the newly inserted row(s) are placed above +the current row. When point is outside of the table it must be below +the table within the table width range, then the newly created row(s) +are appended at the bottom of the table. + +\(fn N)" t nil) + +(autoload 'table-insert-column "table" "\ +Insert N table column(s). +When point is in a table the newly inserted column(s) are placed left +of the current column. When point is outside of the table it must be +right side of the table within the table height range, then the newly +created column(s) are appended at the right of the table. + +\(fn N)" t nil) + +(autoload 'table-insert-row-column "table" "\ +Insert row(s) or column(s). +See `table-insert-row' and `table-insert-column'. + +\(fn ROW-COLUMN N)" t nil) + +(autoload 'table-recognize "table" "\ +Recognize all tables within the current buffer and activate them. +Scans the entire buffer and recognizes valid table cells. If the +optional numeric prefix argument ARG is negative the tables in the +buffer become inactive, meaning the tables become plain text and loses +all the table specific features. + +\(fn &optional ARG)" t nil) + +(autoload 'table-unrecognize "table" "\ + + +\(fn)" t nil) + +(autoload 'table-recognize-region "table" "\ +Recognize all tables within region. +BEG and END specify the region to work on. If the optional numeric +prefix argument ARG is negative the tables in the region become +inactive, meaning the tables become plain text and lose all the table +specific features. + +\(fn BEG END &optional ARG)" t nil) + +(autoload 'table-unrecognize-region "table" "\ + + +\(fn BEG END)" t nil) + +(autoload 'table-recognize-table "table" "\ +Recognize a table at point. +If the optional numeric prefix argument ARG is negative the table +becomes inactive, meaning the table becomes plain text and loses all +the table specific features. + +\(fn &optional ARG)" t nil) + +(autoload 'table-unrecognize-table "table" "\ + + +\(fn)" t nil) + +(autoload 'table-recognize-cell "table" "\ +Recognize a table cell that contains current point. +Probe the cell dimension and prepare the cell information. The +optional two arguments FORCE and NO-COPY are for internal use only and +must not be specified. When the optional numeric prefix argument ARG +is negative the cell becomes inactive, meaning that the cell becomes +plain text and loses all the table specific features. + +\(fn &optional FORCE NO-COPY ARG)" t nil) + +(autoload 'table-unrecognize-cell "table" "\ + + +\(fn)" t nil) + +(autoload 'table-heighten-cell "table" "\ +Heighten the current cell by N lines by expanding the cell vertically. +Heightening is done by adding blank lines at the bottom of the current +cell. Other cells aligned horizontally with the current one are also +heightened in order to keep the rectangular table structure. The +optional argument NO-COPY is internal use only and must not be +specified. + +\(fn N &optional NO-COPY NO-UPDATE)" t nil) + +(autoload 'table-shorten-cell "table" "\ +Shorten the current cell by N lines by shrinking the cell vertically. +Shortening is done by removing blank lines from the bottom of the cell +and possibly from the top of the cell as well. Therefore, the cell +must have some bottom/top blank lines to be shorten effectively. This +is applicable to all the cells aligned horizontally with the current +one because they are also shortened in order to keep the rectangular +table structure. + +\(fn N)" t nil) + +(autoload 'table-widen-cell "table" "\ +Widen the current cell by N columns and expand the cell horizontally. +Some other cells in the same table are widen as well to keep the +table's rectangle structure. + +\(fn N &optional NO-COPY NO-UPDATE)" t nil) + +(autoload 'table-narrow-cell "table" "\ +Narrow the current cell by N columns and shrink the cell horizontally. +Some other cells in the same table are narrowed as well to keep the +table's rectangle structure. + +\(fn N)" t nil) + +(autoload 'table-forward-cell "table" "\ +Move point forward to the beginning of the next cell. +With argument ARG, do it ARG times; +a negative argument ARG = -N means move backward N cells. +Do not specify NO-RECOGNIZE and UNRECOGNIZE. They are for internal use only. + +Sample Cell Traveling Order (In Irregular Table Cases) + +You can actually try how it works in this buffer. Press +\\[table-recognize] and go to cells in the following tables and press +\\[table-forward-cell] or TAB key. + ++-----+--+ +--+-----+ +--+--+--+ +--+--+--+ +---------+ +--+---+--+ +|0 |1 | |0 |1 | |0 |1 |2 | |0 |1 |2 | |0 | |0 |1 |2 | ++--+--+ | | +--+--+ +--+ | | | | +--+ +----+----+ +--+-+-+--+ +|2 |3 | | | |2 |3 | |3 +--+ | | +--+3 | |1 |2 | |3 |4 | +| +--+--+ +--+--+ | +--+4 | | | |4 +--+ +--+-+-+--+ +----+----+ +| |4 | |4 | | |5 | | | | | |5 | |3 |4 |5 | |5 | ++--+-----+ +-----+--+ +--+--+--+ +--+--+--+ +--+---+--+ +---------+ + ++--+--+--+ +--+--+--+ +--+--+--+ +--+--+--+ +|0 |1 |2 | |0 |1 |2 | |0 |1 |2 | |0 |1 |2 | +| | | | | +--+ | | | | | +--+ +--+ ++--+ +--+ +--+3 +--+ | +--+ | |3 +--+4 | +|3 | |4 | |4 +--+5 | | |3 | | +--+5 +--+ +| | | | | |6 | | | | | | |6 | |7 | ++--+--+--+ +--+--+--+ +--+--+--+ +--+--+--+ + ++--+--+--+ +--+--+--+ +--+--+--+--+ +--+-----+--+ +--+--+--+--+ +|0 |1 |2 | |0 |1 |2 | |0 |1 |2 |3 | |0 |1 |2 | |0 |1 |2 |3 | +| +--+ | | +--+ | | +--+--+ | | | | | | +--+--+ | +| |3 +--+ +--+3 | | +--+4 +--+ +--+ +--+ +--+4 +--+ ++--+ |4 | |4 | +--+ |5 +--+--+6 | |3 +--+--+4 | |5 | |6 | +|5 +--+ | | +--+5 | | |7 |8 | | | |5 |6 | | | | | | +| |6 | | | |6 | | +--+--+--+--+ +--+--+--+--+ +--+-----+--+ ++--+--+--+ +--+--+--+ + +\(fn &optional ARG NO-RECOGNIZE UNRECOGNIZE)" t nil) + +(autoload 'table-backward-cell "table" "\ +Move backward to the beginning of the previous cell. +With argument ARG, do it ARG times; +a negative argument ARG = -N means move forward N cells. + +\(fn &optional ARG)" t nil) + +(autoload 'table-span-cell "table" "\ +Span current cell into adjacent cell in DIRECTION. +DIRECTION is one of symbols; right, left, above or below. + +\(fn DIRECTION)" t nil) + +(autoload 'table-split-cell-vertically "table" "\ +Split current cell vertically. +Creates a cell above and a cell below the current point location. + +\(fn)" t nil) + +(autoload 'table-split-cell-horizontally "table" "\ +Split current cell horizontally. +Creates a cell on the left and a cell on the right of the current point location. + +\(fn)" t nil) + +(autoload 'table-split-cell "table" "\ +Split current cell in ORIENTATION. +ORIENTATION is a symbol either horizontally or vertically. + +\(fn ORIENTATION)" t nil) + +(autoload 'table-justify "table" "\ +Justify contents of a cell, a row of cells or a column of cells. +WHAT is a symbol `cell', `row' or `column'. JUSTIFY is a symbol +`left', `center', `right', `top', `middle', `bottom' or `none'. + +\(fn WHAT JUSTIFY)" t nil) + +(autoload 'table-justify-cell "table" "\ +Justify cell contents. +JUSTIFY is a symbol `left', `center' or `right' for horizontal, or `top', +`middle', `bottom' or `none' for vertical. When optional PARAGRAPH is +non-nil the justify operation is limited to the current paragraph, +otherwise the entire cell contents is justified. + +\(fn JUSTIFY &optional PARAGRAPH)" t nil) + +(autoload 'table-justify-row "table" "\ +Justify cells of a row. +JUSTIFY is a symbol `left', `center' or `right' for horizontal, +or `top', `middle', `bottom' or `none' for vertical. + +\(fn JUSTIFY)" t nil) + +(autoload 'table-justify-column "table" "\ +Justify cells of a column. +JUSTIFY is a symbol `left', `center' or `right' for horizontal, +or `top', `middle', `bottom' or `none' for vertical. + +\(fn JUSTIFY)" t nil) + +(autoload 'table-fixed-width-mode "table" "\ +Cell width is fixed when this is non-nil. +Normally it should be nil for allowing automatic cell width expansion +that widens a cell when it is necessary. When non-nil, typing in a +cell does not automatically expand the cell width. A word that is too +long to fit in a cell is chopped into multiple lines. The chopped +location is indicated by `table-word-continuation-char'. This +variable's value can be toggled by \\[table-fixed-width-mode] at +run-time. + +\(fn &optional ARG)" t nil) + +(autoload 'table-query-dimension "table" "\ +Return the dimension of the current cell and the current table. +The result is a list (cw ch tw th c r cells) where cw is the cell +width, ch is the cell height, tw is the table width, th is the table +height, c is the number of columns, r is the number of rows and cells +is the total number of cells. The cell dimension excludes the cell +frame while the table dimension includes the table frame. The columns +and the rows are counted by the number of cell boundaries. Therefore +the number tends to be larger than it appears for the tables with +non-uniform cell structure (heavily spanned and split). When optional +WHERE is provided the cell and table at that location is reported. + +\(fn &optional WHERE)" t nil) + +(autoload 'table-generate-source "table" "\ +Generate source of the current table in the specified language. +LANGUAGE is a symbol that specifies the language to describe the +structure of the table. It must be either `html', `latex' or `cals'. +The resulted source text is inserted into DEST-BUFFER and the buffer +object is returned. When DEST-BUFFER is omitted or nil the default +buffer specified in `table-dest-buffer-name' is used. In this case +the content of the default buffer is erased prior to the generation. +When DEST-BUFFER is non-nil it is expected to be either a destination +buffer or a name of the destination buffer. In this case the +generated result is inserted at the current point in the destination +buffer and the previously existing contents in the buffer are +untouched. + +References used for this implementation: + +HTML: + URL `http://www.w3.org' + +LaTeX: + URL `http://www.maths.tcd.ie/~dwilkins/LaTeXPrimer/Tables.html' + +CALS (DocBook DTD): + URL `http://www.oasis-open.org/html/a502.htm' + URL `http://www.oreilly.com/catalog/docbook/chapter/book/table.html#AEN114751' + +\(fn LANGUAGE &optional DEST-BUFFER CAPTION)" t nil) + +(autoload 'table-insert-sequence "table" "\ +Travel cells forward while inserting a specified sequence string in each cell. +STR is the base string from which the sequence starts. When STR is an +empty string then each cell content is erased. When STR ends with +numerical characters (they may optionally be surrounded by a pair of +parentheses) they are incremented as a decimal number. Otherwise the +last character in STR is incremented in ASCII code order. N is the +number of sequence elements to insert. When N is negative the cell +traveling direction is backward. When N is zero it travels forward +entire table. INCREMENT is the increment between adjacent sequence +elements and can be a negative number for effectively decrementing. +INTERVAL is the number of cells to travel between sequence element +insertion which is normally 1. When zero or less is given for +INTERVAL it is interpreted as number of cells per row so that sequence +is placed straight down vertically as long as the table's cell +structure is uniform. JUSTIFY is a symbol `left', `center' or +`right' that specifies justification of the inserted string. + +Example: + + (progn + (table-insert 16 3 5 1) + (table-forward-cell 15) + (table-insert-sequence \"D0\" -16 1 1 \\='center) + (table-forward-cell 16) + (table-insert-sequence \"A[0]\" -16 1 1 \\='center) + (table-forward-cell 1) + (table-insert-sequence \"-\" 16 0 1 \\='center)) + + (progn + (table-insert 16 8 5 1) + (table-insert-sequence \"@\" 0 1 2 \\='right) + (table-forward-cell 1) + (table-insert-sequence \"64\" 0 1 2 \\='left)) + +\(fn STR N INCREMENT INTERVAL JUSTIFY)" t nil) + +(autoload 'table-delete-row "table" "\ +Delete N row(s) of cells. +Delete N rows of cells from current row. The current row is the row +contains the current cell where point is located. Each row must +consists from cells of same height. + +\(fn N)" t nil) + +(autoload 'table-delete-column "table" "\ +Delete N column(s) of cells. +Delete N columns of cells from current column. The current column is +the column contains the current cell where point is located. Each +column must consists from cells of same width. + +\(fn N)" t nil) + +(autoload 'table-capture "table" "\ +Convert plain text into a table by capturing the text in the region. +Create a table with the text in region as cell contents. BEG and END +specify the region. The text in the region is replaced with a table. +The removed text is inserted in the table. When optional +COL-DELIM-REGEXP and ROW-DELIM-REGEXP are provided the region contents +is parsed and separated into individual cell contents by using the +delimiter regular expressions. This parsing determines the number of +columns and rows of the table automatically. If COL-DELIM-REGEXP and +ROW-DELIM-REGEXP are omitted the result table has only one cell and +the entire region contents is placed in that cell. Optional JUSTIFY +is one of `left', `center' or `right', which specifies the cell +justification. Optional MIN-CELL-WIDTH specifies the minimum cell +width. Optional COLUMNS specify the number of columns when +ROW-DELIM-REGEXP is not specified. + + +Example 1: + +1, 2, 3, 4 +5, 6, 7, 8 +, 9, 10 + +Running `table-capture' on above 3 line region with COL-DELIM-REGEXP +\",\" and ROW-DELIM-REGEXP \"\\n\" creates the following table. In +this example the cells are centered and minimum cell width is +specified as 5. + ++-----+-----+-----+-----+ +| 1 | 2 | 3 | 4 | ++-----+-----+-----+-----+ +| 5 | 6 | 7 | 8 | ++-----+-----+-----+-----+ +| | 9 | 10 | | ++-----+-----+-----+-----+ + +Note: + +In case the function is called interactively user must use \\[quoted-insert] `quoted-insert' +in order to enter \"\\n\" successfully. COL-DELIM-REGEXP at the end +of each row is optional. + + +Example 2: + +This example shows how a table can be used for text layout editing. +Let `table-capture' capture the following region starting from +-!- and ending at -*-, that contains three paragraphs and two item +name headers. This time specify empty string for both +COL-DELIM-REGEXP and ROW-DELIM-REGEXP. + +-!-`table-capture' is a powerful command however mastering its power +requires some practice. Here is a list of items what it can do. + +Parse Cell Items By using column delimiter regular + expression and raw delimiter regular + expression, it parses the specified text + area and extracts cell items from + non-table text and then forms a table out + of them. + +Capture Text Area When no delimiters are specified it + creates a single cell table. The text in + the specified region is placed in that + cell.-*- + +Now the entire content is captured in a cell which is itself a table +like this. + ++-----------------------------------------------------------------+ +|`table-capture' is a powerful command however mastering its power| +|requires some practice. Here is a list of items what it can do. | +| | +|Parse Cell Items By using column delimiter regular | +| expression and raw delimiter regular | +| expression, it parses the specified text | +| area and extracts cell items from | +| non-table text and then forms a table out | +| of them. | +| | +|Capture Text Area When no delimiters are specified it | +| creates a single cell table. The text in | +| the specified region is placed in that | +| cell. | ++-----------------------------------------------------------------+ + +By splitting the cell appropriately we now have a table consisting of +paragraphs occupying its own cell. Each cell can now be edited +independently. + ++-----------------------------------------------------------------+ +|`table-capture' is a powerful command however mastering its power| +|requires some practice. Here is a list of items what it can do. | ++---------------------+-------------------------------------------+ +|Parse Cell Items |By using column delimiter regular | +| |expression and raw delimiter regular | +| |expression, it parses the specified text | +| |area and extracts cell items from | +| |non-table text and then forms a table out | +| |of them. | ++---------------------+-------------------------------------------+ +|Capture Text Area |When no delimiters are specified it | +| |creates a single cell table. The text in | +| |the specified region is placed in that | +| |cell. | ++---------------------+-------------------------------------------+ + +By applying `table-release', which does the opposite process, the +contents become once again plain text. `table-release' works as +companion command to `table-capture' this way. + +\(fn BEG END &optional COL-DELIM-REGEXP ROW-DELIM-REGEXP JUSTIFY MIN-CELL-WIDTH COLUMNS)" t nil) + +(autoload 'table-release "table" "\ +Convert a table into plain text by removing the frame from a table. +Remove the frame from a table and deactivate the table. This command +converts a table into plain text without frames. It is a companion to +`table-capture' which does the opposite process. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "table" '("table-" "*table--"))) + +;;;*** + +;;;### (autoloads nil "tabulated-list" "emacs-lisp/tabulated-list.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/tabulated-list.el +(push (purecopy '(tabulated-list 1 0)) package--builtin-versions) + +;;;*** + +;;;### (autoloads nil "talk" "talk.el" (0 0 0 0)) +;;; Generated autoloads from talk.el + +(autoload 'talk-connect "talk" "\ +Connect to display DISPLAY for the Emacs talk group. + +\(fn DISPLAY)" t nil) + +(autoload 'talk "talk" "\ +Connect to the Emacs talk group from the current X display or tty frame. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "talk" '("talk-"))) + +;;;*** + +;;;### (autoloads nil "tar-mode" "tar-mode.el" (0 0 0 0)) +;;; Generated autoloads from tar-mode.el + +(autoload 'tar-mode "tar-mode" "\ +Major mode for viewing a tar file as a dired-like listing of its contents. +You can move around using the usual cursor motion commands. +Letters no longer insert themselves. +Type `e' to pull a file out of the tar file and into its own buffer; +or click mouse-2 on the file's line in the Tar mode buffer. +Type `c' to copy an entry from the tar file into another file on disk. + +If you edit a sub-file of this archive (as with the `e' command) and +save it with \\[save-buffer], the contents of that buffer will be +saved back into the tar-file buffer; in this way you can edit a file +inside of a tar archive without extracting it and re-archiving it. + +See also: variables `tar-update-datestamp' and `tar-anal-blocksize'. +\\{tar-mode-map} + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tar-mode" '("tar-"))) + +;;;*** + +;;;### (autoloads nil "tcl" "progmodes/tcl.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/tcl.el + +(autoload 'tcl-mode "tcl" "\ +Major mode for editing Tcl code. +Expression and list commands understand all Tcl brackets. +Tab indents for Tcl code. +Paragraphs are separated by blank lines only. +Delete converts tabs to spaces as it moves back. + +Variables controlling indentation style: + `tcl-indent-level' + Indentation of Tcl statements within surrounding block. + `tcl-continued-indent-level' + Indentation of continuation line relative to first line of command. + +Variables controlling user interaction with mode (see variable +documentation for details): + `tcl-tab-always-indent' + Controls action of TAB key. + `tcl-auto-newline' + Non-nil means automatically newline before and after braces, brackets, + and semicolons inserted in Tcl code. + `tcl-use-smart-word-finder' + If not nil, use a smarter, Tcl-specific way to find the current + word when looking up help on a Tcl command. + +Turning on Tcl mode runs `tcl-mode-hook'. Read the documentation for +`tcl-mode-hook' to see what kinds of interesting hook functions +already exist. + +\(fn)" t nil) + +(autoload 'inferior-tcl "tcl" "\ +Run inferior Tcl process. +Prefix arg means enter program name interactively. +See documentation for function `inferior-tcl-mode' for more information. + +\(fn CMD)" t nil) + +(autoload 'tcl-help-on-word "tcl" "\ +Get help on Tcl command. Default is word at point. +Prefix argument means invert sense of `tcl-use-smart-word-finder'. + +\(fn COMMAND &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tcl" '("tcl-" "calculate-tcl-indent" "inferior-tcl-" "indent-tcl-exp" "add-log-tcl-defun" "run-tcl" "switch-to-tcl"))) + +;;;*** + +;;;### (autoloads nil "tcover-ses" "emacs-lisp/tcover-ses.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from emacs-lisp/tcover-ses.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tcover-ses" '("ses-exercise"))) + +;;;*** + +;;;### (autoloads nil "tcover-unsafep" "emacs-lisp/tcover-unsafep.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/tcover-unsafep.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tcover-unsafep" '("testcover-unsafep"))) + +;;;*** + +;;;### (autoloads nil "telnet" "net/telnet.el" (0 0 0 0)) +;;; Generated autoloads from net/telnet.el + +(autoload 'telnet "telnet" "\ +Open a network login connection to host named HOST (a string). +Optional arg PORT specifies alternative port to connect to. +Interactively, use \\[universal-argument] prefix to be prompted for port number. + +Communication with HOST is recorded in a buffer `*PROGRAM-HOST*' +where PROGRAM is the telnet program being used. This program +is controlled by the contents of the global variable `telnet-host-properties', +falling back on the value of the global variable `telnet-program'. +Normally input is edited in Emacs and sent a line at a time. + +\(fn HOST &optional PORT)" t nil) + +(autoload 'rsh "telnet" "\ +Open a network login connection to host named HOST (a string). +Communication with HOST is recorded in a buffer `*rsh-HOST*'. +Normally input is edited in Emacs and sent a line at a time. + +\(fn HOST)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "telnet" '("telnet-" "send-process-next-char"))) + +;;;*** + +;;;### (autoloads nil "tempo" "tempo.el" (0 0 0 0)) +;;; Generated autoloads from tempo.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tempo" '("tempo-"))) + +;;;*** + +;;;### (autoloads nil "term" "term.el" (0 0 0 0)) +;;; Generated autoloads from term.el + +(autoload 'make-term "term" "\ +Make a term process NAME in a buffer, running PROGRAM. +The name of the buffer is made by surrounding NAME with `*'s. +If there is already a running process in that buffer, it is not restarted. +Optional third arg STARTFILE is the name of a file to send the contents of to +the process. Any more args are arguments to PROGRAM. + +\(fn NAME PROGRAM &optional STARTFILE &rest SWITCHES)" nil nil) + +(autoload 'term "term" "\ +Start a terminal-emulator in a new buffer. +The buffer is in Term mode; see `term-mode' for the +commands to use in that buffer. + +\\Type \\[switch-to-buffer] to switch to another buffer. + +\(fn PROGRAM)" t nil) + +(autoload 'ansi-term "term" "\ +Start a terminal-emulator in a new buffer. + +\(fn PROGRAM &optional NEW-BUFFER-NAME)" t nil) + +(autoload 'serial-term "term" "\ +Start a terminal-emulator for a serial port in a new buffer. +PORT is the path or name of the serial port. For example, this +could be \"/dev/ttyS0\" on Unix. On Windows, this could be +\"COM1\" or \"\\\\.\\COM10\". +SPEED is the speed of the serial port in bits per second. 9600 +is a common value. SPEED can be nil, see +`serial-process-configure' for details. +The buffer is in Term mode; see `term-mode' for the commands to +use in that buffer. +\\Type \\[switch-to-buffer] to switch to another buffer. + +\(fn PORT SPEED)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "term" '("serial-" "term-" "ansi-term-color-vector" "explicit-shell-file-name"))) + +;;;*** + +;;;### (autoloads nil "testcover" "emacs-lisp/testcover.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from emacs-lisp/testcover.el + +(autoload 'testcover-start "testcover" "\ +Uses edebug to instrument all macros and functions in FILENAME, then +changes the instrumentation from edebug to testcover--much faster, no +problems with type-ahead or post-command-hook, etc. If BYTE-COMPILE is +non-nil, byte-compiles each function after instrumenting. + +\(fn FILENAME &optional BYTE-COMPILE)" t nil) + +(autoload 'testcover-this-defun "testcover" "\ +Start coverage on function under point. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "testcover" '("testcover-"))) + +;;;*** + +;;;### (autoloads nil "tetris" "play/tetris.el" (0 0 0 0)) +;;; Generated autoloads from play/tetris.el +(push (purecopy '(tetris 2 1)) package--builtin-versions) + +(autoload 'tetris "tetris" "\ +Play the Tetris game. +Shapes drop from the top of the screen, and the user has to move and +rotate the shape to fit in with those at the bottom of the screen so +as to form complete rows. + +tetris-mode keybindings: + \\ +\\[tetris-start-game] Starts a new game of Tetris +\\[tetris-end-game] Terminates the current game +\\[tetris-pause-game] Pauses (or resumes) the current game +\\[tetris-move-left] Moves the shape one square to the left +\\[tetris-move-right] Moves the shape one square to the right +\\[tetris-rotate-prev] Rotates the shape clockwise +\\[tetris-rotate-next] Rotates the shape anticlockwise +\\[tetris-move-bottom] Drops the shape to the bottom of the playing area + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tetris" '("tetris-"))) + +;;;*** + +;;;### (autoloads nil "tex-mode" "textmodes/tex-mode.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/tex-mode.el + +(defvar tex-shell-file-name nil "\ +If non-nil, the shell file name to run in the subshell used to run TeX.") + +(custom-autoload 'tex-shell-file-name "tex-mode" t) + +(defvar tex-directory (purecopy ".") "\ +Directory in which temporary files are written. +You can make this `/tmp' if your TEXINPUTS has no relative directories in it +and you don't try to apply \\[tex-region] or \\[tex-buffer] when there are +`\\input' commands with relative directories.") + +(custom-autoload 'tex-directory "tex-mode" t) + +(defvar tex-first-line-header-regexp nil "\ +Regexp for matching a first line which `tex-region' should include. +If this is non-nil, it should be a regular expression string; +if it matches the first line of the file, +`tex-region' always includes the first line in the TeX run.") + +(custom-autoload 'tex-first-line-header-regexp "tex-mode" t) + +(defvar tex-main-file nil "\ +The main TeX source file which includes this buffer's file. +The command `tex-file' runs TeX on the file specified by `tex-main-file' +if the variable is non-nil.") + +(custom-autoload 'tex-main-file "tex-mode" t) + +(defvar tex-offer-save t "\ +If non-nil, ask about saving modified buffers before \\[tex-file] is run.") + +(custom-autoload 'tex-offer-save "tex-mode" t) + +(defvar tex-run-command (purecopy "tex") "\ +Command used to run TeX subjob. +TeX Mode sets `tex-command' to this string. +See the documentation of that variable.") + +(custom-autoload 'tex-run-command "tex-mode" t) + +(defvar latex-run-command (purecopy "latex") "\ +Command used to run LaTeX subjob. +LaTeX Mode sets `tex-command' to this string. +See the documentation of that variable.") + +(custom-autoload 'latex-run-command "tex-mode" t) + +(defvar slitex-run-command (purecopy "slitex") "\ +Command used to run SliTeX subjob. +SliTeX Mode sets `tex-command' to this string. +See the documentation of that variable.") + +(custom-autoload 'slitex-run-command "tex-mode" t) + +(defvar tex-start-options (purecopy "") "\ +TeX options to use when starting TeX. +These immediately precede the commands in `tex-start-commands' +and the input file name, with no separating space and are not shell-quoted. +If nil, TeX runs with no options. See the documentation of `tex-command'.") + +(custom-autoload 'tex-start-options "tex-mode" t) + +(defvar tex-start-commands (purecopy "\\nonstopmode\\input") "\ +TeX commands to use when starting TeX. +They are shell-quoted and precede the input file name, with a separating space. +If nil, no commands are used. See the documentation of `tex-command'.") + +(custom-autoload 'tex-start-commands "tex-mode" t) + +(defvar latex-block-names nil "\ +User defined LaTeX block names. +Combined with `latex-standard-block-names' for minibuffer completion.") + +(custom-autoload 'latex-block-names "tex-mode" t) + +(defvar tex-bibtex-command (purecopy "bibtex") "\ +Command used by `tex-bibtex-file' to gather bibliographic data. +If this string contains an asterisk (`*'), that is replaced by the file name; +otherwise, the file name, preceded by blank, is added at the end.") + +(custom-autoload 'tex-bibtex-command "tex-mode" t) + +(defvar tex-dvi-print-command (purecopy "lpr -d") "\ +Command used by \\[tex-print] to print a .dvi file. +If this string contains an asterisk (`*'), that is replaced by the file name; +otherwise, the file name, preceded by blank, is added at the end.") + +(custom-autoload 'tex-dvi-print-command "tex-mode" t) + +(defvar tex-alt-dvi-print-command (purecopy "lpr -d") "\ +Command used by \\[tex-print] with a prefix arg to print a .dvi file. +If this string contains an asterisk (`*'), that is replaced by the file name; +otherwise, the file name, preceded by blank, is added at the end. + +If two printers are not enough of a choice, you can set the variable +`tex-alt-dvi-print-command' to an expression that asks what you want; +for example, + + (setq tex-alt-dvi-print-command + \\='(format \"lpr -P%s\" (read-string \"Use printer: \"))) + +would tell \\[tex-print] with a prefix argument to ask you which printer to +use.") + +(custom-autoload 'tex-alt-dvi-print-command "tex-mode" t) + +(defvar tex-dvi-view-command `(cond ((eq window-system 'x) ,(purecopy "xdvi")) ((eq window-system 'w32) ,(purecopy "yap")) (t ,(purecopy "dvi2tty * | cat -s"))) "\ +Command used by \\[tex-view] to display a `.dvi' file. +If it is a string, that specifies the command directly. +If this string contains an asterisk (`*'), that is replaced by the file name; +otherwise, the file name, preceded by a space, is added at the end. + +If the value is a form, it is evaluated to get the command to use.") + +(custom-autoload 'tex-dvi-view-command "tex-mode" t) + +(defvar tex-show-queue-command (purecopy "lpq") "\ +Command used by \\[tex-show-print-queue] to show the print queue. +Should show the queue(s) that \\[tex-print] puts jobs on.") + +(custom-autoload 'tex-show-queue-command "tex-mode" t) + +(defvar tex-default-mode 'latex-mode "\ +Mode to enter for a new file that might be either TeX or LaTeX. +This variable is used when it can't be determined whether the file +is plain TeX or LaTeX or what because the file contains no commands. +Normally set to either `plain-tex-mode' or `latex-mode'.") + +(custom-autoload 'tex-default-mode "tex-mode" t) + +(defvar tex-open-quote (purecopy "``") "\ +String inserted by typing \\[tex-insert-quote] to open a quotation.") + +(custom-autoload 'tex-open-quote "tex-mode" t) + +(defvar tex-close-quote (purecopy "''") "\ +String inserted by typing \\[tex-insert-quote] to close a quotation.") + +(custom-autoload 'tex-close-quote "tex-mode" t) + +(autoload 'tex-mode "tex-mode" "\ +Major mode for editing files of input for TeX, LaTeX, or SliTeX. +Tries to determine (by looking at the beginning of the file) whether +this file is for plain TeX, LaTeX, or SliTeX and calls `plain-tex-mode', +`latex-mode', or `slitex-mode', respectively. If it cannot be determined, +such as if there are no commands in the file, the value of `tex-default-mode' +says which mode to use. + +\(fn)" t nil) + +(defalias 'TeX-mode 'tex-mode) + +(defalias 'plain-TeX-mode 'plain-tex-mode) + +(defalias 'LaTeX-mode 'latex-mode) + +(autoload 'plain-tex-mode "tex-mode" "\ +Major mode for editing files of input for plain TeX. +Makes $ and } display the characters they match. +Makes \" insert \\=`\\=` when it seems to be the beginning of a quotation, +and \\='\\=' when it appears to be the end; it inserts \" only after a \\. + +Use \\[tex-region] to run TeX on the current region, plus a \"header\" +copied from the top of the file (containing macro definitions, etc.), +running TeX under a special subshell. \\[tex-buffer] does the whole buffer. +\\[tex-file] saves the buffer and then processes the file. +\\[tex-print] prints the .dvi file made by any of these. +\\[tex-view] previews the .dvi file made by any of these. +\\[tex-bibtex-file] runs bibtex on the file of the current buffer. + +Use \\[tex-validate-buffer] to check buffer for paragraphs containing +mismatched $'s or braces. + +Special commands: +\\{plain-tex-mode-map} + +Mode variables: +tex-run-command + Command string used by \\[tex-region] or \\[tex-buffer]. +tex-directory + Directory in which to create temporary files for TeX jobs + run by \\[tex-region] or \\[tex-buffer]. +tex-dvi-print-command + Command string used by \\[tex-print] to print a .dvi file. +tex-alt-dvi-print-command + Alternative command string used by \\[tex-print] (when given a prefix + argument) to print a .dvi file. +tex-dvi-view-command + Command string used by \\[tex-view] to preview a .dvi file. +tex-show-queue-command + Command string used by \\[tex-show-print-queue] to show the print + queue that \\[tex-print] put your job on. + +Entering Plain-tex mode runs the hook `text-mode-hook', then the hook +`tex-mode-hook', and finally the hook `plain-tex-mode-hook'. When the +special subshell is initiated, the hook `tex-shell-hook' is run. + +\(fn)" t nil) + +(autoload 'latex-mode "tex-mode" "\ +Major mode for editing files of input for LaTeX. +Makes $ and } display the characters they match. +Makes \" insert \\=`\\=` when it seems to be the beginning of a quotation, +and \\='\\=' when it appears to be the end; it inserts \" only after a \\. + +Use \\[tex-region] to run LaTeX on the current region, plus the preamble +copied from the top of the file (containing \\documentstyle, etc.), +running LaTeX under a special subshell. \\[tex-buffer] does the whole buffer. +\\[tex-file] saves the buffer and then processes the file. +\\[tex-print] prints the .dvi file made by any of these. +\\[tex-view] previews the .dvi file made by any of these. +\\[tex-bibtex-file] runs bibtex on the file of the current buffer. + +Use \\[tex-validate-buffer] to check buffer for paragraphs containing +mismatched $'s or braces. + +Special commands: +\\{latex-mode-map} + +Mode variables: +latex-run-command + Command string used by \\[tex-region] or \\[tex-buffer]. +tex-directory + Directory in which to create temporary files for LaTeX jobs + run by \\[tex-region] or \\[tex-buffer]. +tex-dvi-print-command + Command string used by \\[tex-print] to print a .dvi file. +tex-alt-dvi-print-command + Alternative command string used by \\[tex-print] (when given a prefix + argument) to print a .dvi file. +tex-dvi-view-command + Command string used by \\[tex-view] to preview a .dvi file. +tex-show-queue-command + Command string used by \\[tex-show-print-queue] to show the print + queue that \\[tex-print] put your job on. + +Entering Latex mode runs the hook `text-mode-hook', then +`tex-mode-hook', and finally `latex-mode-hook'. When the special +subshell is initiated, `tex-shell-hook' is run. + +\(fn)" t nil) + +(autoload 'slitex-mode "tex-mode" "\ +Major mode for editing files of input for SliTeX. +Makes $ and } display the characters they match. +Makes \" insert \\=`\\=` when it seems to be the beginning of a quotation, +and \\='\\=' when it appears to be the end; it inserts \" only after a \\. + +Use \\[tex-region] to run SliTeX on the current region, plus the preamble +copied from the top of the file (containing \\documentstyle, etc.), +running SliTeX under a special subshell. \\[tex-buffer] does the whole buffer. +\\[tex-file] saves the buffer and then processes the file. +\\[tex-print] prints the .dvi file made by any of these. +\\[tex-view] previews the .dvi file made by any of these. +\\[tex-bibtex-file] runs bibtex on the file of the current buffer. + +Use \\[tex-validate-buffer] to check buffer for paragraphs containing +mismatched $'s or braces. + +Special commands: +\\{slitex-mode-map} + +Mode variables: +slitex-run-command + Command string used by \\[tex-region] or \\[tex-buffer]. +tex-directory + Directory in which to create temporary files for SliTeX jobs + run by \\[tex-region] or \\[tex-buffer]. +tex-dvi-print-command + Command string used by \\[tex-print] to print a .dvi file. +tex-alt-dvi-print-command + Alternative command string used by \\[tex-print] (when given a prefix + argument) to print a .dvi file. +tex-dvi-view-command + Command string used by \\[tex-view] to preview a .dvi file. +tex-show-queue-command + Command string used by \\[tex-show-print-queue] to show the print + queue that \\[tex-print] put your job on. + +Entering SliTeX mode runs the hook `text-mode-hook', then the hook +`tex-mode-hook', then the hook `latex-mode-hook', and finally the hook +`slitex-mode-hook'. When the special subshell is initiated, the hook +`tex-shell-hook' is run. + +\(fn)" t nil) + +(autoload 'tex-start-shell "tex-mode" "\ + + +\(fn)" nil nil) + +(autoload 'doctex-mode "tex-mode" "\ +Major mode to edit DocTeX files. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tex-mode" '("tex-" "doctex-font-lock-" "latex-" "plain-tex-mode-map"))) + +;;;*** + +;;;### (autoloads nil "texinfmt" "textmodes/texinfmt.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/texinfmt.el + +(autoload 'texinfo-format-buffer "texinfmt" "\ +Process the current buffer as texinfo code, into an Info file. +The Info file output is generated in a buffer visiting the Info file +name specified in the @setfilename command. + +Non-nil argument (prefix, if interactive) means don't make tag table +and don't split the file if large. You can use `Info-tagify' and +`Info-split' to do these manually. + +\(fn &optional NOSPLIT)" t nil) + +(autoload 'texinfo-format-region "texinfmt" "\ +Convert the current region of the Texinfo file to Info format. +This lets you see what that part of the file will look like in Info. +The command is bound to \\[texinfo-format-region]. The text that is +converted to Info is stored in a temporary buffer. + +\(fn REGION-BEGINNING REGION-END)" t nil) + +(autoload 'texi2info "texinfmt" "\ +Convert the current buffer (written in Texinfo code) into an Info file. +The Info file output is generated in a buffer visiting the Info file +names specified in the @setfilename command. + +This function automatically updates all node pointers and menus, and +creates a master menu. This work is done on a temporary buffer that +is automatically removed when the Info file is created. The original +Texinfo source buffer is not changed. + +Non-nil argument (prefix, if interactive) means don't split the file +if large. You can use `Info-split' to do this manually. + +\(fn &optional NOSPLIT)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "texinfmt" '("batch-texinfo-format" "texinf"))) + +;;;*** + +;;;### (autoloads nil "texinfo" "textmodes/texinfo.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/texinfo.el + +(defvar texinfo-open-quote (purecopy "``") "\ +String inserted by typing \\[texinfo-insert-quote] to open a quotation.") + +(custom-autoload 'texinfo-open-quote "texinfo" t) + +(defvar texinfo-close-quote (purecopy "''") "\ +String inserted by typing \\[texinfo-insert-quote] to close a quotation.") + +(custom-autoload 'texinfo-close-quote "texinfo" t) + +(autoload 'texinfo-mode "texinfo" "\ +Major mode for editing Texinfo files. + + It has these extra commands: +\\{texinfo-mode-map} + + These are files that are used as input for TeX to make printed manuals +and also to be turned into Info files with \\[makeinfo-buffer] or +the `makeinfo' program. These files must be written in a very restricted and +modified version of TeX input format. + + Editing commands are like text-mode except that the syntax table is +set up so expression commands skip Texinfo bracket groups. To see +what the Info version of a region of the Texinfo file will look like, +use \\[makeinfo-region], which runs `makeinfo' on the current region. + + You can show the structure of a Texinfo file with \\[texinfo-show-structure]. +This command shows the structure of a Texinfo file by listing the +lines with the @-sign commands for @chapter, @section, and the like. +These lines are displayed in another window called the *Occur* window. +In that window, you can position the cursor over one of the lines and +use \\[occur-mode-goto-occurrence], to jump to the corresponding spot +in the Texinfo file. + + In addition, Texinfo mode provides commands that insert various +frequently used @-sign commands into the buffer. You can use these +commands to save keystrokes. And you can insert balanced braces with +\\[texinfo-insert-braces] and later use the command \\[up-list] to +move forward past the closing brace. + +Also, Texinfo mode provides functions for automatically creating or +updating menus and node pointers. These functions + + * insert the `Next', `Previous' and `Up' pointers of a node, + * insert or update the menu for a section, and + * create a master menu for a Texinfo source file. + +Here are the functions: + + texinfo-update-node \\[texinfo-update-node] + texinfo-every-node-update \\[texinfo-every-node-update] + texinfo-sequential-node-update + + texinfo-make-menu \\[texinfo-make-menu] + texinfo-all-menus-update \\[texinfo-all-menus-update] + texinfo-master-menu + + texinfo-indent-menu-description (column &optional region-p) + +The `texinfo-column-for-description' variable specifies the column to +which menu descriptions are indented. + +Passed an argument (a prefix argument, if interactive), the +`texinfo-update-node' and `texinfo-make-menu' functions do their jobs +in the region. + +To use the updating commands, you must structure your Texinfo file +hierarchically, such that each `@node' line, with the exception of the +Top node, is accompanied by some kind of section line, such as an +`@chapter' or `@section' line. + +If the file has a `top' node, it must be called `top' or `Top' and +be the first node in the file. + +Entering Texinfo mode calls the value of `text-mode-hook', and then the +value of `texinfo-mode-hook'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "texinfo" '("texinfo-"))) + +;;;*** + +;;;### (autoloads nil "texnfo-upd" "textmodes/texnfo-upd.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from textmodes/texnfo-upd.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "texnfo-upd" '("texinfo-"))) + +;;;*** + +;;;### (autoloads nil "thai-util" "language/thai-util.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from language/thai-util.el + +(autoload 'thai-compose-region "thai-util" "\ +Compose Thai characters in the region. +When called from a program, expects two arguments, +positions (integers or markers) specifying the region. + +\(fn BEG END)" t nil) + +(autoload 'thai-compose-string "thai-util" "\ +Compose Thai characters in STRING and return the resulting string. + +\(fn STRING)" nil nil) + +(autoload 'thai-compose-buffer "thai-util" "\ +Compose Thai characters in the current buffer. + +\(fn)" t nil) + +(autoload 'thai-composition-function "thai-util" "\ + + +\(fn GSTRING)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "thai-util" '("exit-thai-language-environment-internal" "setup-thai-language-environment-internal" "thai-"))) + +;;;*** + +;;;### (autoloads nil "thai-word" "language/thai-word.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from language/thai-word.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "thai-word" '("thai-"))) + +;;;*** + +;;;### (autoloads nil "thingatpt" "thingatpt.el" (0 0 0 0)) +;;; Generated autoloads from thingatpt.el + +(autoload 'forward-thing "thingatpt" "\ +Move forward to the end of the Nth next THING. +THING should be a symbol specifying a type of syntactic entity. +Possibilities include `symbol', `list', `sexp', `defun', +`filename', `url', `email', `word', `sentence', `whitespace', +`line', and `page'. + +\(fn THING &optional N)" nil nil) + +(autoload 'bounds-of-thing-at-point "thingatpt" "\ +Determine the start and end buffer locations for the THING at point. +THING should be a symbol specifying a type of syntactic entity. +Possibilities include `symbol', `list', `sexp', `defun', +`filename', `url', `email', `word', `sentence', `whitespace', +`line', and `page'. + +See the file `thingatpt.el' for documentation on how to define a +valid THING. + +Return a cons cell (START . END) giving the start and end +positions of the thing found. + +\(fn THING)" nil nil) + +(autoload 'thing-at-point "thingatpt" "\ +Return the THING at point. +THING should be a symbol specifying a type of syntactic entity. +Possibilities include `symbol', `list', `sexp', `defun', +`filename', `url', `email', `word', `sentence', `whitespace', +`line', `number', and `page'. + +When the optional argument NO-PROPERTIES is non-nil, +strip text properties from the return value. + +See the file `thingatpt.el' for documentation on how to define +a symbol as a valid THING. + +\(fn THING &optional NO-PROPERTIES)" nil nil) + +(autoload 'sexp-at-point "thingatpt" "\ +Return the sexp at point, or nil if none is found. + +\(fn)" nil nil) + +(autoload 'symbol-at-point "thingatpt" "\ +Return the symbol at point, or nil if none is found. + +\(fn)" nil nil) + +(autoload 'number-at-point "thingatpt" "\ +Return the number at point, or nil if none is found. + +\(fn)" nil nil) + +(autoload 'list-at-point "thingatpt" "\ +Return the Lisp list at point, or nil if none is found. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "thingatpt" '("form-at-point" "thing-at-point-" "sentence-at-point" "word-at-point" "in-string-p" "end-of-thing" "beginning-of-thing"))) + +;;;*** + +;;;### (autoloads nil "thumbs" "thumbs.el" (0 0 0 0)) +;;; Generated autoloads from thumbs.el + +(autoload 'thumbs-find-thumb "thumbs" "\ +Display the thumbnail for IMG. + +\(fn IMG)" t nil) + +(autoload 'thumbs-show-from-dir "thumbs" "\ +Make a preview buffer for all images in DIR. +Optional argument REG to select file matching a regexp, +and SAME-WINDOW to show thumbs in the same window. + +\(fn DIR &optional REG SAME-WINDOW)" t nil) + +(autoload 'thumbs-dired-show-marked "thumbs" "\ +In dired, make a thumbs buffer with marked files. + +\(fn)" t nil) + +(autoload 'thumbs-dired-show "thumbs" "\ +In dired, make a thumbs buffer with all files in current directory. + +\(fn)" t nil) + +(defalias 'thumbs 'thumbs-show-from-dir) + +(autoload 'thumbs-dired-setroot "thumbs" "\ +In dired, call the setroot program on the image at point. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "thumbs" '("thumbs-"))) + +;;;*** + +;;;### (autoloads nil "thunk" "emacs-lisp/thunk.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/thunk.el +(push (purecopy '(thunk 1 0)) package--builtin-versions) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "thunk" '("thunk-"))) + +;;;*** + +;;;### (autoloads nil "tibet-util" "language/tibet-util.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from language/tibet-util.el + +(autoload 'tibetan-char-p "tibet-util" "\ +Check if char CH is Tibetan character. +Returns non-nil if CH is Tibetan. Otherwise, returns nil. + +\(fn CH)" nil nil) + +(autoload 'tibetan-tibetan-to-transcription "tibet-util" "\ +Transcribe Tibetan string STR and return the corresponding Roman string. + +\(fn STR)" nil nil) + +(autoload 'tibetan-transcription-to-tibetan "tibet-util" "\ +Convert Tibetan Roman string STR to Tibetan character string. +The returned string has no composition information. + +\(fn STR)" nil nil) + +(autoload 'tibetan-compose-string "tibet-util" "\ +Compose Tibetan string STR. + +\(fn STR)" nil nil) + +(autoload 'tibetan-compose-region "tibet-util" "\ +Compose Tibetan text the region BEG and END. + +\(fn BEG END)" t nil) + +(autoload 'tibetan-decompose-region "tibet-util" "\ +Decompose Tibetan text in the region FROM and TO. +This is different from decompose-region because precomposed Tibetan characters +are decomposed into normal Tibetan character sequences. + +\(fn FROM TO)" t nil) + +(autoload 'tibetan-decompose-string "tibet-util" "\ +Decompose Tibetan string STR. +This is different from decompose-string because precomposed Tibetan characters +are decomposed into normal Tibetan character sequences. + +\(fn STR)" nil nil) + +(autoload 'tibetan-decompose-buffer "tibet-util" "\ +Decomposes Tibetan characters in the buffer into their components. +See also the documentation of the function `tibetan-decompose-region'. + +\(fn)" t nil) + +(autoload 'tibetan-compose-buffer "tibet-util" "\ +Composes Tibetan character components in the buffer. +See also docstring of the function tibetan-compose-region. + +\(fn)" t nil) + +(autoload 'tibetan-post-read-conversion "tibet-util" "\ + + +\(fn LEN)" nil nil) + +(autoload 'tibetan-pre-write-conversion "tibet-util" "\ + + +\(fn FROM TO)" nil nil) + +(autoload 'tibetan-pre-write-canonicalize-for-unicode "tibet-util" "\ + + +\(fn FROM TO)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tibet-util" '("tibetan-"))) + +;;;*** + +;;;### (autoloads nil "tildify" "textmodes/tildify.el" (0 0 0 0)) +;;; Generated autoloads from textmodes/tildify.el +(push (purecopy '(tildify 4 6 1)) package--builtin-versions) + +(autoload 'tildify-region "tildify" "\ +Add hard spaces in the region between BEG and END. +See variables `tildify-pattern', `tildify-space-string', and +`tildify-ignored-environments-alist' for information about configuration +parameters. +This function performs no refilling of the changed text. +If DONT-ASK is set, or called interactively with prefix argument, user +won't be prompted for confirmation of each substitution. + +\(fn BEG END &optional DONT-ASK)" t nil) + +(autoload 'tildify-buffer "tildify" "\ +Add hard spaces in the current buffer. +See variables `tildify-pattern', `tildify-space-string', and +`tildify-ignored-environments-alist' for information about configuration +parameters. +This function performs no refilling of the changed text. +If DONT-ASK is set, or called interactively with prefix argument, user +won't be prompted for confirmation of each substitution. + +\(fn &optional DONT-ASK)" t nil) + +(autoload 'tildify-space "tildify" "\ +Convert space before point into a hard space if the context is right. + +If + * character before point is a space character, + * character before that has \"w\" character syntax (i.e. it's a word + constituent), + * `tildify-space-pattern' matches when `looking-back' (no more than 10 + characters) from before the space character, and + * all predicates in `tildify-space-predicates' return non-nil, +replace the space character with value of `tildify-space-string' and +return t. + +Otherwise, if + * `tildify-double-space-undos' variable is non-nil, + * character before point is a space character, and + * text before that is a hard space as defined by + `tildify-space-string' variable, +remove the hard space and leave only the space character. + +This function is meant to be used as a `post-self-insert-hook'. + +\(fn)" t nil) + +(autoload 'tildify-mode "tildify" "\ +Adds electric behavior to space character. + +When space is inserted into a buffer in a position where hard space is required +instead (determined by `tildify-space-pattern' and `tildify-space-predicates'), +that space character is replaced by a hard space specified by +`tildify-space-string'. Converting of the space is done by `tildify-space'. + +When `tildify-mode' is enabled, if `tildify-string-alist' specifies a hard space +representation for current major mode, the `tildify-space-string' buffer-local +variable will be set to the representation. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tildify" '("tildify-"))) + +;;;*** + +;;;### (autoloads nil "time" "time.el" (0 0 0 0)) +;;; Generated autoloads from time.el + +(defvar display-time-day-and-date nil "\ +Non-nil means \\[display-time] should display day and date as well as time.") + +(custom-autoload 'display-time-day-and-date "time" t) +(put 'display-time-string 'risky-local-variable t) + +(autoload 'display-time "time" "\ +Enable display of time, load level, and mail flag in mode lines. +This display updates automatically every minute. +If `display-time-day-and-date' is non-nil, the current day and date +are displayed as well. +This runs the normal hook `display-time-hook' after each update. + +\(fn)" t nil) + +(defvar display-time-mode nil "\ +Non-nil if Display-Time mode is enabled. +See the `display-time-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `display-time-mode'.") + +(custom-autoload 'display-time-mode "time" nil) + +(autoload 'display-time-mode "time" "\ +Toggle display of time, load level, and mail flag in mode lines. +With a prefix argument ARG, enable Display Time mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +it if ARG is omitted or nil. + +When Display Time mode is enabled, it updates every minute (you +can control the number of seconds between updates by customizing +`display-time-interval'). If `display-time-day-and-date' is +non-nil, the current day and date are displayed as well. This +runs the normal hook `display-time-hook' after each update. + +\(fn &optional ARG)" t nil) + +(autoload 'display-time-world "time" "\ +Enable updating display of times in various time zones. +`display-time-world-list' specifies the zones. +To turn off the world time display, go to that window and type `q'. + +\(fn)" t nil) + +(autoload 'emacs-uptime "time" "\ +Return a string giving the uptime of this instance of Emacs. +FORMAT is a string to format the result, using `format-seconds'. +For example, the Unix uptime command format is \"%D, %z%2h:%.2m\". + +\(fn &optional FORMAT)" t nil) + +(autoload 'emacs-init-time "time" "\ +Return a string giving the duration of the Emacs initialization. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "time" '("display-time-" "legacy-style-world-list" "zoneinfo-style-world-list"))) + +;;;*** + +;;;### (autoloads nil "time-date" "calendar/time-date.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from calendar/time-date.el + +(autoload 'date-to-time "time-date" "\ +Parse a string DATE that represents a date-time and return a time value. +If DATE lacks timezone information, GMT is assumed. + +\(fn DATE)" nil nil) + +(defalias 'time-to-seconds 'float-time) + +(autoload 'seconds-to-time "time-date" "\ +Convert SECONDS to a time value. + +\(fn SECONDS)" nil nil) + +(autoload 'days-to-time "time-date" "\ +Convert DAYS into a time value. + +\(fn DAYS)" nil nil) + +(autoload 'time-since "time-date" "\ +Return the time elapsed since TIME. +TIME should be either a time value or a date-time string. + +\(fn TIME)" nil nil) + +(define-obsolete-function-alias 'subtract-time 'time-subtract "26.1") + +(autoload 'date-to-day "time-date" "\ +Return the number of days between year 1 and DATE. +DATE should be a date-time string. + +\(fn DATE)" nil nil) + +(autoload 'days-between "time-date" "\ +Return the number of days between DATE1 and DATE2. +DATE1 and DATE2 should be date-time strings. + +\(fn DATE1 DATE2)" nil nil) + +(autoload 'date-leap-year-p "time-date" "\ +Return t if YEAR is a leap year. + +\(fn YEAR)" nil nil) + +(autoload 'time-to-day-in-year "time-date" "\ +Return the day number within the year corresponding to TIME. + +\(fn TIME)" nil nil) + +(autoload 'time-to-days "time-date" "\ +The number of days between the Gregorian date 0001-12-31bce and TIME. +TIME should be a time value. +The Gregorian date Sunday, December 31, 1bce is imaginary. + +\(fn TIME)" nil nil) + +(autoload 'safe-date-to-time "time-date" "\ +Parse a string DATE that represents a date-time and return a time value. +If DATE is malformed, return a time value of zeros. + +\(fn DATE)" nil nil) + +(autoload 'format-seconds "time-date" "\ +Use format control STRING to format the number SECONDS. +The valid format specifiers are: +%y is the number of (365-day) years. +%d is the number of days. +%h is the number of hours. +%m is the number of minutes. +%s is the number of seconds. +%z is a non-printing control flag (see below). +%% is a literal \"%\". + +Upper-case specifiers are followed by the unit-name (e.g. \"years\"). +Lower-case specifiers return only the unit. + +\"%\" may be followed by a number specifying a width, with an +optional leading \".\" for zero-padding. For example, \"%.3Y\" will +return something of the form \"001 year\". + +The \"%z\" specifier does not print anything. When it is used, specifiers +must be given in order of decreasing size. To the left of \"%z\", nothing +is output until the first non-zero unit is encountered. + +This function does not work for SECONDS greater than `most-positive-fixnum'. + +\(fn STRING SECONDS)" nil nil) + +(autoload 'seconds-to-string "time-date" "\ +Convert the time interval in seconds to a short string. + +\(fn DELAY)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "time-date" '("seconds-to-string" "time-" "encode-time-value" "with-decoded-time-value"))) + +;;;*** + +;;;### (autoloads nil "time-stamp" "time-stamp.el" (0 0 0 0)) +;;; Generated autoloads from time-stamp.el +(put 'time-stamp-format 'safe-local-variable 'stringp) +(put 'time-stamp-time-zone 'safe-local-variable 'string-or-null-p) +(put 'time-stamp-line-limit 'safe-local-variable 'integerp) +(put 'time-stamp-start 'safe-local-variable 'stringp) +(put 'time-stamp-end 'safe-local-variable 'stringp) +(put 'time-stamp-inserts-lines 'safe-local-variable 'symbolp) +(put 'time-stamp-count 'safe-local-variable 'integerp) +(put 'time-stamp-pattern 'safe-local-variable 'stringp) + +(autoload 'time-stamp "time-stamp" "\ +Update the time stamp string(s) in the buffer. +A template in a file can be automatically updated with a new time stamp +every time you save the file. Add this line to your init file: + (add-hook \\='before-save-hook \\='time-stamp) +or customize `before-save-hook' through Custom. +Normally the template must appear in the first 8 lines of a file and +look like one of the following: + Time-stamp: <> + Time-stamp: \" \" +The time stamp is written between the brackets or quotes: + Time-stamp: <2001-02-18 10:20:51 gildea> +The time stamp is updated only if the variable `time-stamp-active' is non-nil. +The format of the time stamp is set by the variable `time-stamp-pattern' or +`time-stamp-format'. The variables `time-stamp-pattern', +`time-stamp-line-limit', `time-stamp-start', `time-stamp-end', +`time-stamp-count', and `time-stamp-inserts-lines' control finding +the template. + +\(fn)" t nil) + +(autoload 'time-stamp-toggle-active "time-stamp" "\ +Toggle `time-stamp-active', setting whether \\[time-stamp] updates a buffer. +With ARG, turn time stamping on if and only if arg is positive. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "time-stamp" '("time-stamp-"))) + +;;;*** + +;;;### (autoloads nil "timeclock" "calendar/timeclock.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from calendar/timeclock.el +(push (purecopy '(timeclock 2 6 1)) package--builtin-versions) + +(defvar timeclock-mode-line-display nil "\ +Non-nil if Timeclock-Mode-Line-Display mode is enabled. +See the `timeclock-mode-line-display' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `timeclock-mode-line-display'.") + +(custom-autoload 'timeclock-mode-line-display "timeclock" nil) + +(autoload 'timeclock-mode-line-display "timeclock" "\ +Toggle display of the amount of time left today in the mode line. +If `timeclock-use-display-time' is non-nil (the default), then +the function `display-time-mode' must be active, and the mode line +will be updated whenever the time display is updated. Otherwise, +the timeclock will use its own sixty second timer to do its +updating. With prefix ARG, turn mode line display on if and only +if ARG is positive. Returns the new status of timeclock mode line +display (non-nil means on). + +\(fn &optional ARG)" t nil) + +(autoload 'timeclock-in "timeclock" "\ +Clock in, recording the current time moment in the timelog. +With a numeric prefix ARG, record the fact that today has only that +many hours in it to be worked. If ARG is a non-numeric prefix argument +\(non-nil, but not a number), 0 is assumed (working on a holiday or +weekend). *If not called interactively, ARG should be the number of +_seconds_ worked today*. This feature only has effect the first time +this function is called within a day. + +PROJECT is the project being clocked into. If PROJECT is nil, and +FIND-PROJECT is non-nil -- or the user calls `timeclock-in' +interactively -- call the function `timeclock-get-project-function' to +discover the name of the project. + +\(fn &optional ARG PROJECT FIND-PROJECT)" t nil) + +(autoload 'timeclock-out "timeclock" "\ +Clock out, recording the current time moment in the timelog. +If a prefix ARG is given, the user has completed the project that was +begun during the last time segment. + +REASON is the user's reason for clocking out. If REASON is nil, and +FIND-REASON is non-nil -- or the user calls `timeclock-out' +interactively -- call the function `timeclock-get-reason-function' to +discover the reason. + +\(fn &optional ARG REASON FIND-REASON)" t nil) + +(autoload 'timeclock-status-string "timeclock" "\ +Report the overall timeclock status at the present moment. +If SHOW-SECONDS is non-nil, display second resolution. +If TODAY-ONLY is non-nil, the display will be relative only to time +worked today, ignoring the time worked on previous days. + +\(fn &optional SHOW-SECONDS TODAY-ONLY)" t nil) + +(autoload 'timeclock-change "timeclock" "\ +Change to working on a different project. +This clocks out of the current project, then clocks in on a new one. +With a prefix ARG, consider the previous project as finished at the +time of changeover. PROJECT is the name of the last project you were +working on. + +\(fn &optional ARG PROJECT)" t nil) + +(autoload 'timeclock-query-out "timeclock" "\ +Ask the user whether to clock out. +This is a useful function for adding to `kill-emacs-query-functions'. + +\(fn)" nil nil) + +(autoload 'timeclock-reread-log "timeclock" "\ +Re-read the timeclock, to account for external changes. +Returns the new value of `timeclock-discrepancy'. + +\(fn)" t nil) + +(autoload 'timeclock-workday-remaining-string "timeclock" "\ +Return a string representing the amount of time left today. +Display second resolution if SHOW-SECONDS is non-nil. If TODAY-ONLY +is non-nil, the display will be relative only to time worked today. +See `timeclock-relative' for more information about the meaning of +\"relative to today\". + +\(fn &optional SHOW-SECONDS TODAY-ONLY)" t nil) + +(autoload 'timeclock-workday-elapsed-string "timeclock" "\ +Return a string representing the amount of time worked today. +Display seconds resolution if SHOW-SECONDS is non-nil. If RELATIVE is +non-nil, the amount returned will be relative to past time worked. + +\(fn &optional SHOW-SECONDS)" t nil) + +(autoload 'timeclock-when-to-leave-string "timeclock" "\ +Return a string representing the end of today's workday. +This string is relative to the value of `timeclock-workday'. If +SHOW-SECONDS is non-nil, the value printed/returned will include +seconds. If TODAY-ONLY is non-nil, the value returned will be +relative only to the time worked today, and not to past time. + +\(fn &optional SHOW-SECONDS TODAY-ONLY)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "timeclock" '("timeclock-"))) + +;;;*** + +;;;### (autoloads nil "timer-list" "emacs-lisp/timer-list.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from emacs-lisp/timer-list.el + +(autoload 'timer-list "timer-list" "\ +List all timers in a buffer. + +\(fn &optional IGNORE-AUTO NONCONFIRM)" t nil) + (put 'timer-list 'disabled "Beware: manually canceling timers can ruin your Emacs session.") + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "timer-list" '("timer-list-"))) + +;;;*** + +;;;### (autoloads nil "timezone" "timezone.el" (0 0 0 0)) +;;; Generated autoloads from timezone.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "timezone" '("timezone-"))) + +;;;*** + +;;;### (autoloads nil "titdic-cnv" "international/titdic-cnv.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from international/titdic-cnv.el + +(autoload 'titdic-convert "titdic-cnv" "\ +Convert a TIT dictionary of FILENAME into a Quail package. +Optional argument DIRNAME if specified is the directory name under which +the generated Quail package is saved. + +\(fn FILENAME &optional DIRNAME)" t nil) + +(autoload 'batch-titdic-convert "titdic-cnv" "\ +Run `titdic-convert' on the files remaining on the command line. +Use this from the command line, with `-batch'; +it won't work in an interactive Emacs. +For example, invoke \"emacs -batch -f batch-titdic-convert XXX.tit\" to + generate Quail package file \"xxx.el\" from TIT dictionary file \"XXX.tit\". +To get complete usage, invoke \"emacs -batch -f batch-titdic-convert -h\". + +\(fn &optional FORCE)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "titdic-cnv" '("batch-miscdic-convert" "miscdic-convert" "ctlau-" "ziranma-converter" "py-converter" "quail-" "quick-" "tit-" "tsang-"))) + +;;;*** + +;;;### (autoloads nil "tls" "net/tls.el" (0 0 0 0)) +;;; Generated autoloads from net/tls.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tls" '("open-tls-stream" "tls-"))) + +;;;*** + +;;;### (autoloads nil "tmm" "tmm.el" (0 0 0 0)) +;;; Generated autoloads from tmm.el + (define-key global-map "\M-`" 'tmm-menubar) + (define-key global-map [menu-bar mouse-1] 'tmm-menubar-mouse) + +(autoload 'tmm-menubar "tmm" "\ +Text-mode emulation of looking and choosing from a menubar. +See the documentation for `tmm-prompt'. +X-POSITION, if non-nil, specifies a horizontal position within the menu bar; +we make that menu bar item (the one at that position) the default choice. + +Note that \\[menu-bar-open] by default drops down TTY menus; if you want it +to invoke `tmm-menubar' instead, customize the variable +`tty-menu-open-use-tmm' to a non-nil value. + +\(fn &optional X-POSITION)" t nil) + +(autoload 'tmm-menubar-mouse "tmm" "\ +Text-mode emulation of looking and choosing from a menubar. +This command is used when you click the mouse in the menubar +on a console which has no window system but does have a mouse. +See the documentation for `tmm-prompt'. + +\(fn EVENT)" t nil) + +(autoload 'tmm-prompt "tmm" "\ +Text-mode emulation of calling the bindings in keymap. +Creates a text-mode menu of possible choices. You can access the elements +in the menu in two ways: + *) via history mechanism from minibuffer; + *) Or via completion-buffer that is automatically shown. +The last alternative is currently a hack, you cannot use mouse reliably. + +MENU is like the MENU argument to `x-popup-menu': either a +keymap or an alist of alists. +DEFAULT-ITEM, if non-nil, specifies an initial default choice. +Its value should be an event that has a binding in MENU. + +\(fn MENU &optional IN-POPUP DEFAULT-ITEM)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tmm" '("tmm-"))) + +;;;*** + +;;;### (autoloads nil "todo-mode" "calendar/todo-mode.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from calendar/todo-mode.el + +(autoload 'todo-show "todo-mode" "\ +Visit a todo file and display one of its categories. + +When invoked in Todo mode, Todo Archive mode or Todo Filtered +Items mode, or when invoked anywhere else with a prefix argument, +prompt for which todo file to visit. When invoked outside of a +Todo mode buffer without a prefix argument, visit +`todo-default-todo-file'. Subsequent invocations from outside of +Todo mode revisit this file or, with option +`todo-show-current-file' non-nil (the default), whichever todo +file was last visited. + +If you call this command before you have created any todo file in +the current format, and you have an todo file in old format, it +will ask you whether to convert that file and show it. +Otherwise, calling this command before any todo file exists +prompts for a file name and an initial category (defaulting to +`todo-initial-file' and `todo-initial-category'), creates both of +these, visits the file and displays the category, and if option +`todo-add-item-if-new-category' is non-nil (the default), prompts +for the first item. + +The first invocation of this command on an existing todo file +interacts with the option `todo-show-first': if its value is +`first' (the default), show the first category in the file; if +its value is `table', show the table of categories in the file; +if its value is one of `top', `diary' or `regexp', show the +corresponding saved top priorities, diary items, or regexp items +file, if any. Subsequent invocations always show the file's +current (i.e., last displayed) category. + +In Todo mode just the category's unfinished todo items are shown +by default. The done items are hidden, but typing +`\\[todo-toggle-view-done-items]' displays them below the todo +items. With non-nil user option `todo-show-with-done' both todo +and done items are always shown on visiting a category. + +\(fn &optional SOLICIT-FILE INTERACTIVE)" t nil) + +(autoload 'todo-mode "todo-mode" "\ +Major mode for displaying, navigating and editing todo lists. + +\\{todo-mode-map} + +\(fn)" t nil) + +(autoload 'todo-archive-mode "todo-mode" "\ +Major mode for archived todo categories. + +\\{todo-archive-mode-map} + +\(fn)" t nil) + +(autoload 'todo-filtered-items-mode "todo-mode" "\ +Mode for displaying and reprioritizing top priority Todo. + +\\{todo-filtered-items-mode-map} + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "todo-mode" '("todo-"))) + +;;;*** + +;;;### (autoloads nil "tool-bar" "tool-bar.el" (0 0 0 0)) +;;; Generated autoloads from tool-bar.el + +(autoload 'toggle-tool-bar-mode-from-frame "tool-bar" "\ +Toggle tool bar on or off, based on the status of the current frame. +See `tool-bar-mode' for more information. + +\(fn &optional ARG)" t nil) + +(autoload 'tool-bar-add-item "tool-bar" "\ +Add an item to the tool bar. +ICON names the image, DEF is the key definition and KEY is a symbol +for the fake function key in the menu keymap. Remaining arguments +PROPS are additional items to add to the menu item specification. See +Info node `(elisp)Tool Bar'. Items are added from left to right. + +ICON is the base name of a file containing the image to use. The +function will first try to use low-color/ICON.xpm if `display-color-cells' +is less or equal to 256, then ICON.xpm, then ICON.pbm, and finally +ICON.xbm, using `find-image'. + +Use this function only to make bindings in the global value of `tool-bar-map'. +To define items in any other map, use `tool-bar-local-item'. + +\(fn ICON DEF KEY &rest PROPS)" nil nil) + +(autoload 'tool-bar-local-item "tool-bar" "\ +Add an item to the tool bar in map MAP. +ICON names the image, DEF is the key definition and KEY is a symbol +for the fake function key in the menu keymap. Remaining arguments +PROPS are additional items to add to the menu item specification. See +Info node `(elisp)Tool Bar'. Items are added from left to right. + +ICON is the base name of a file containing the image to use. The +function will first try to use low-color/ICON.xpm if `display-color-cells' +is less or equal to 256, then ICON.xpm, then ICON.pbm, and finally +ICON.xbm, using `find-image'. + +\(fn ICON DEF KEY MAP &rest PROPS)" nil nil) + +(autoload 'tool-bar-add-item-from-menu "tool-bar" "\ +Define tool bar binding for COMMAND in keymap MAP using the given ICON. +This makes a binding for COMMAND in `tool-bar-map', copying its +binding from the menu bar in MAP (which defaults to `global-map'), but +modifies the binding by adding an image specification for ICON. It +finds ICON just like `tool-bar-add-item'. PROPS are additional +properties to add to the binding. + +MAP must contain appropriate binding for `[menu-bar]' which holds a keymap. + +Use this function only to make bindings in the global value of `tool-bar-map'. +To define items in any other map, use `tool-bar-local-item-from-menu'. + +\(fn COMMAND ICON &optional MAP &rest PROPS)" nil nil) + +(autoload 'tool-bar-local-item-from-menu "tool-bar" "\ +Define local tool bar binding for COMMAND using the given ICON. +This makes a binding for COMMAND in IN-MAP, copying its binding from +the menu bar in FROM-MAP (which defaults to `global-map'), but +modifies the binding by adding an image specification for ICON. It +finds ICON just like `tool-bar-add-item'. PROPS are additional +properties to add to the binding. + +FROM-MAP must contain appropriate binding for `[menu-bar]' which +holds a keymap. + +\(fn COMMAND ICON IN-MAP &optional FROM-MAP &rest PROPS)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tool-bar" '("tool-bar-"))) + +;;;*** + +;;;### (autoloads nil "tooltip" "tooltip.el" (0 0 0 0)) +;;; Generated autoloads from tooltip.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tooltip" '("tooltip-"))) + +;;;*** + +;;;### (autoloads nil "tq" "emacs-lisp/tq.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/tq.el + +(autoload 'tq-create "tq" "\ +Create and return a transaction queue communicating with PROCESS. +PROCESS should be a subprocess capable of sending and receiving +streams of bytes. It may be a local process, or it may be connected +to a tcp server on another machine. + +\(fn PROCESS)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tq" '("tq-"))) + +;;;*** + +;;;### (autoloads nil "trace" "emacs-lisp/trace.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/trace.el + +(defvar trace-buffer "*trace-output*" "\ +Trace output will by default go to that buffer.") + +(custom-autoload 'trace-buffer "trace" t) + +(autoload 'trace-values "trace" "\ +Helper function to get internal values. +You can call this function to add internal values in the trace buffer. + +\(fn &rest VALUES)" nil nil) + +(autoload 'trace-function-foreground "trace" "\ +Trace calls to function FUNCTION. +With a prefix argument, also prompt for the trace buffer (default +`trace-buffer'), and a Lisp expression CONTEXT. + +Tracing a function causes every call to that function to insert +into BUFFER Lisp-style trace messages that display the function's +arguments and return values. It also evaluates CONTEXT, if that is +non-nil, and inserts its value too. For example, you can use this +to track the current buffer, or position of point. + +This function creates BUFFER if it does not exist. This buffer will +popup whenever FUNCTION is called. Do not use this function to trace +functions that switch buffers, or do any other display-oriented +stuff - use `trace-function-background' instead. + +To stop tracing a function, use `untrace-function' or `untrace-all'. + +\(fn FUNCTION &optional BUFFER CONTEXT)" t nil) + +(autoload 'trace-function-background "trace" "\ +Trace calls to function FUNCTION, quietly. +This is like `trace-function-foreground', but without popping up +the output buffer or changing the window configuration. + +\(fn FUNCTION &optional BUFFER CONTEXT)" t nil) + +(defalias 'trace-function 'trace-function-foreground) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "trace" '("untrace-" "trace-" "inhibit-trace"))) + +;;;*** + +;;;### (autoloads nil "tramp" "net/tramp.el" (0 0 0 0)) +;;; Generated autoloads from net/tramp.el + +(defvar tramp-mode t "\ +Whether Tramp is enabled. +If it is set to nil, all remote file names are used literally.") + +(custom-autoload 'tramp-mode "tramp" t) + +(defvar tramp-syntax 'default "\ +Tramp filename syntax to be used. + +It can have the following values: + + `default' -- Default syntax + `simplified' -- Ange-FTP like syntax + `separate' -- Syntax as defined for XEmacs originally + +Do not change the value by `setq', it must be changed only by +`custom-set-variables'. See also `tramp-change-syntax'.") + +(custom-autoload 'tramp-syntax "tramp" nil) + +(defconst tramp-initial-file-name-regexp "\\`/.+:.*:" "\ +Value for `tramp-file-name-regexp' for autoload. +It must match the initial `tramp-syntax' settings.") + +(defvar tramp-file-name-regexp tramp-initial-file-name-regexp "\ +Value for `tramp-file-name-regexp' for autoload. +It must match the initial `tramp-syntax' settings.") + +(defconst tramp-completion-file-name-regexp-default (concat "\\`/\\(" "\\([^/|:]+:[^/|:]*|\\)*" (if (memq system-type '(cygwin windows-nt)) "\\(-\\|[^/|:]\\{2,\\}\\)" "[^/|:]+") "\\(:[^/|:]*\\)?" "\\)?\\'") "\ +Value for `tramp-completion-file-name-regexp' for default remoting. +See `tramp-file-name-structure' for more explanations. + +On W32 systems, the volume letter must be ignored.") + +(defconst tramp-initial-completion-file-name-regexp tramp-completion-file-name-regexp-default "\ +Value for `tramp-completion-file-name-regexp' for autoload. +It must match the initial `tramp-syntax' settings.") + +(defconst tramp-completion-file-name-handler-alist '((file-name-all-completions . tramp-completion-handle-file-name-all-completions) (file-name-completion . tramp-completion-handle-file-name-completion)) "\ +Alist of completion handler functions. +Used for file names matching `tramp-completion-file-name-regexp'. +Operations not mentioned here will be handled by Tramp's file +name handler functions, or the normal Emacs functions.") + +(autoload 'tramp-completion-file-name-handler "tramp" "\ +Invoke Tramp file name completion handler. +Falls back to normal file name handler if no Tramp file name handler exists. + +\(fn OPERATION &rest ARGS)" nil nil) + +(defun tramp-autoload-file-name-handler (operation &rest args) "\ +Load Tramp file name handler, and perform OPERATION." (let ((default-directory temporary-file-directory)) (load "tramp" (quote noerror) (quote nomessage))) (apply operation args)) + +(defun tramp-register-autoload-file-name-handlers nil "\ +Add Tramp file name handlers to `file-name-handler-alist' during autoload." (add-to-list (quote file-name-handler-alist) (cons tramp-initial-file-name-regexp (quote tramp-autoload-file-name-handler))) (put (quote tramp-autoload-file-name-handler) (quote safe-magic) t) (add-to-list (quote file-name-handler-alist) (cons tramp-initial-completion-file-name-regexp (quote tramp-completion-file-name-handler))) (put (quote tramp-completion-file-name-handler) (quote safe-magic) t) (put (quote tramp-completion-file-name-handler) (quote operations) (mapcar (quote car) tramp-completion-file-name-handler-alist))) + +(tramp-register-autoload-file-name-handlers) + +(autoload 'tramp-unload-file-name-handlers "tramp" "\ +Unload Tramp file name handlers from `file-name-handler-alist'. + +\(fn)" nil nil) + +(defvar tramp-completion-mode nil "\ +If non-nil, external packages signal that they are in file name completion.") + +(autoload 'tramp-unload-tramp "tramp" "\ +Discard Tramp from loading remote files. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tramp" '("tramp-" "with-"))) + +;;;*** + +;;;### (autoloads nil "tramp-adb" "net/tramp-adb.el" (0 0 0 0)) +;;; Generated autoloads from net/tramp-adb.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tramp-adb" '("tramp-"))) + +;;;*** + +;;;### (autoloads nil "tramp-cache" "net/tramp-cache.el" (0 0 0 0)) +;;; Generated autoloads from net/tramp-cache.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tramp-cache" '("tramp-"))) + +;;;*** + +;;;### (autoloads nil "tramp-cmds" "net/tramp-cmds.el" (0 0 0 0)) +;;; Generated autoloads from net/tramp-cmds.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tramp-cmds" '("tramp-"))) + +;;;*** + +;;;### (autoloads nil "tramp-compat" "net/tramp-compat.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from net/tramp-compat.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tramp-compat" '("tramp-"))) + +;;;*** + +;;;### (autoloads nil "tramp-ftp" "net/tramp-ftp.el" (0 0 0 0)) +;;; Generated autoloads from net/tramp-ftp.el + +(autoload 'tramp-ftp-enable-ange-ftp "tramp-ftp" "\ +Reenable Ange-FTP, when Tramp is unloaded. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tramp-ftp" '("tramp-"))) + +;;;*** + +;;;### (autoloads nil "tramp-gvfs" "net/tramp-gvfs.el" (0 0 0 0)) +;;; Generated autoloads from net/tramp-gvfs.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tramp-gvfs" '("tramp-" "with-tramp-dbus-call-method"))) + +;;;*** + +;;;### (autoloads nil "tramp-sh" "net/tramp-sh.el" (0 0 0 0)) +;;; Generated autoloads from net/tramp-sh.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tramp-sh" '("tramp-"))) + +;;;*** + +;;;### (autoloads nil "tramp-smb" "net/tramp-smb.el" (0 0 0 0)) +;;; Generated autoloads from net/tramp-smb.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tramp-smb" '("tramp-smb-"))) + +;;;*** + +;;;### (autoloads nil "tramp-uu" "net/tramp-uu.el" (0 0 0 0)) +;;; Generated autoloads from net/tramp-uu.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tramp-uu" '("tramp-uu"))) + +;;;*** + +;;;### (autoloads nil "trampver" "net/trampver.el" (0 0 0 0)) +;;; Generated autoloads from net/trampver.el +(push (purecopy '(tramp 2 3 2)) package--builtin-versions) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "trampver" '("tramp-"))) + +;;;*** + +;;;### (autoloads nil "tree-widget" "tree-widget.el" (0 0 0 0)) +;;; Generated autoloads from tree-widget.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tree-widget" '("tree-widget-"))) + +;;;*** + +;;;### (autoloads nil "tutorial" "tutorial.el" (0 0 0 0)) +;;; Generated autoloads from tutorial.el + +(autoload 'help-with-tutorial "tutorial" "\ +Select the Emacs learn-by-doing tutorial. +If there is a tutorial version written in the language +of the selected language environment, that version is used. +If there's no tutorial in that language, `TUTORIAL' is selected. +With ARG, you are asked to choose which language. +If DONT-ASK-FOR-REVERT is non-nil the buffer is reverted without +any question when restarting the tutorial. + +If any of the standard Emacs key bindings that are used in the +tutorial have been changed then an explanatory note about this is +shown in the beginning of the tutorial buffer. + +When the tutorial buffer is killed the content and the point +position in the buffer is saved so that the tutorial may be +resumed later. + +\(fn &optional ARG DONT-ASK-FOR-REVERT)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tutorial" '("get-lang-string" "lang-strings" "tutorial--"))) + +;;;*** + +;;;### (autoloads nil "tv-util" "language/tv-util.el" (0 0 0 0)) +;;; Generated autoloads from language/tv-util.el + +(autoload 'tai-viet-composition-function "tv-util" "\ + + +\(fn FROM TO FONT-OBJECT STRING)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tv-util" '("tai-viet-"))) + +;;;*** + +;;;### (autoloads nil "two-column" "textmodes/two-column.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from textmodes/two-column.el + (autoload '2C-command "two-column" () t 'keymap) + (global-set-key "\C-x6" '2C-command) + (global-set-key [f2] '2C-command) + +(autoload '2C-two-columns "two-column" "\ +Split current window vertically for two-column editing. +\\When called the first time, associates a buffer with the current +buffer in two-column minor mode (use \\[describe-mode] once in the mode, +for details.). It runs `2C-other-buffer-hook' in the new buffer. +When called again, restores the screen layout with the current buffer +first and the associated buffer to its right. + +\(fn &optional BUFFER)" t nil) + +(autoload '2C-associate-buffer "two-column" "\ +Associate another buffer with this one in two-column minor mode. +Can also be used to associate a just previously visited file, by +accepting the proposed default buffer. + +\(See \\[describe-mode] .) + +\(fn)" t nil) + +(autoload '2C-split "two-column" "\ +Split a two-column text at point, into two buffers in two-column minor mode. +Point becomes the local value of `2C-window-width'. Only lines that +have the ARG same preceding characters at that column get split. The +ARG preceding characters without any leading whitespace become the local +value for `2C-separator'. This way lines that continue across both +columns remain untouched in the first buffer. + +This function can be used with a prototype line, to set up things. You +write the first line of each column and then split that line. E.g.: + +First column's text sSs Second column's text + \\___/\\ + / \\ + 5 character Separator You type M-5 \\[2C-split] with the point here. + +\(See \\[describe-mode] .) + +\(fn ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "two-column" '("2C-"))) + +;;;*** + +;;;### (autoloads nil "type-break" "type-break.el" (0 0 0 0)) +;;; Generated autoloads from type-break.el + +(defvar type-break-mode nil "\ +Non-nil if Type-Break mode is enabled. +See the `type-break-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `type-break-mode'.") + +(custom-autoload 'type-break-mode "type-break" nil) + +(autoload 'type-break-mode "type-break" "\ +Enable or disable typing-break mode. +This is a minor mode, but it is global to all buffers by default. + +When this mode is enabled, the user is encouraged to take typing breaks at +appropriate intervals; either after a specified amount of time or when the +user has exceeded a keystroke threshold. When the time arrives, the user +is asked to take a break. If the user refuses at that time, Emacs will ask +again in a short period of time. The idea is to give the user enough time +to find a good breaking point in his or her work, but be sufficiently +annoying to discourage putting typing breaks off indefinitely. + +A negative prefix argument disables this mode. +No argument or any non-negative argument enables it. + +The user may enable or disable this mode by setting the variable of the +same name, though setting it in that way doesn't reschedule a break or +reset the keystroke counter. + +If the mode was previously disabled and is enabled as a consequence of +calling this function, it schedules a break with `type-break-schedule' to +make sure one occurs (the user can call that command to reschedule the +break at any time). It also initializes the keystroke counter. + +The variable `type-break-interval' specifies the number of seconds to +schedule between regular typing breaks. This variable doesn't directly +affect the time schedule; it simply provides a default for the +`type-break-schedule' command. + +If set, the variable `type-break-good-rest-interval' specifies the minimum +amount of time which is considered a reasonable typing break. Whenever +that time has elapsed, typing breaks are automatically rescheduled for +later even if Emacs didn't prompt you to take one first. Also, if a break +is ended before this much time has elapsed, the user will be asked whether +or not to continue. A nil value for this variable prevents automatic +break rescheduling, making `type-break-interval' an upper bound on the time +between breaks. In this case breaks will be prompted for as usual before +the upper bound if the keystroke threshold is reached. + +If `type-break-good-rest-interval' is nil and +`type-break-good-break-interval' is set, then confirmation is required to +interrupt a break before `type-break-good-break-interval' seconds +have passed. This provides for an upper bound on the time between breaks +together with confirmation of interruptions to these breaks. + +The variable `type-break-keystroke-threshold' is used to determine the +thresholds at which typing breaks should be considered. You can use +the command `type-break-guesstimate-keystroke-threshold' to try to +approximate good values for this. + +There are several variables that affect how or when warning messages about +imminent typing breaks are displayed. They include: + + `type-break-mode-line-message-mode' + `type-break-time-warning-intervals' + `type-break-keystroke-warning-intervals' + `type-break-warning-repeat' + `type-break-warning-countdown-string' + `type-break-warning-countdown-string-type' + +There are several variables that affect if, how, and when queries to begin +a typing break occur. They include: + + `type-break-query-mode' + `type-break-query-function' + `type-break-query-interval' + +The command `type-break-statistics' prints interesting things. + +Finally, a file (named `type-break-file-name') is used to store information +across Emacs sessions. This provides recovery of the break status between +sessions and after a crash. Manual changes to the file may result in +problems. + +\(fn &optional ARG)" t nil) + +(autoload 'type-break "type-break" "\ +Take a typing break. + +During the break, a demo selected from the functions listed in +`type-break-demo-functions' is run. + +After the typing break is finished, the next break is scheduled +as per the function `type-break-schedule'. + +\(fn)" t nil) + +(autoload 'type-break-statistics "type-break" "\ +Print statistics about typing breaks in a temporary buffer. +This includes the last time a typing break was taken, when the next one is +scheduled, the keystroke thresholds and the current keystroke count, etc. + +\(fn)" t nil) + +(autoload 'type-break-guesstimate-keystroke-threshold "type-break" "\ +Guess values for the minimum/maximum keystroke threshold for typing breaks. + +If called interactively, the user is prompted for their guess as to how +many words per minute they usually type. This value should not be your +maximum WPM, but your average. Of course, this is harder to gauge since it +can vary considerably depending on what you are doing. For example, one +tends to type less when debugging a program as opposed to writing +documentation. (Perhaps a separate program should be written to estimate +average typing speed.) + +From that, this command sets the values in `type-break-keystroke-threshold' +based on a fairly simple algorithm involving assumptions about the average +length of words (5). For the minimum threshold, it uses about a fifth of +the computed maximum threshold. + +When called from Lisp programs, the optional args WORDLEN and FRAC can be +used to override the default assumption about average word length and the +fraction of the maximum threshold to which to set the minimum threshold. +FRAC should be the inverse of the fractional value; for example, a value of +2 would mean to use one half, a value of 4 would mean to use one quarter, etc. + +\(fn WPM &optional WORDLEN FRAC)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "type-break" '("timep" "type-break-"))) + +;;;*** + +;;;### (autoloads nil "uce" "mail/uce.el" (0 0 0 0)) +;;; Generated autoloads from mail/uce.el + +(autoload 'uce-reply-to-uce "uce" "\ +Compose a reply to unsolicited commercial email (UCE). +Sets up a reply buffer addressed to: the sender, his postmaster, +his abuse@ address, and the postmaster of the mail relay used. +You might need to set `uce-mail-reader' before using this. + +\(fn &optional IGNORED)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "uce" '("uce-"))) + +;;;*** + +;;;### (autoloads nil "ucs-normalize" "international/ucs-normalize.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from international/ucs-normalize.el + +(autoload 'ucs-normalize-NFD-region "ucs-normalize" "\ +Normalize the current region by the Unicode NFD. + +\(fn FROM TO)" t nil) + +(autoload 'ucs-normalize-NFD-string "ucs-normalize" "\ +Normalize the string STR by the Unicode NFD. + +\(fn STR)" nil nil) + +(autoload 'ucs-normalize-NFC-region "ucs-normalize" "\ +Normalize the current region by the Unicode NFC. + +\(fn FROM TO)" t nil) + +(autoload 'ucs-normalize-NFC-string "ucs-normalize" "\ +Normalize the string STR by the Unicode NFC. + +\(fn STR)" nil nil) + +(autoload 'ucs-normalize-NFKD-region "ucs-normalize" "\ +Normalize the current region by the Unicode NFKD. + +\(fn FROM TO)" t nil) + +(autoload 'ucs-normalize-NFKD-string "ucs-normalize" "\ +Normalize the string STR by the Unicode NFKD. + +\(fn STR)" nil nil) + +(autoload 'ucs-normalize-NFKC-region "ucs-normalize" "\ +Normalize the current region by the Unicode NFKC. + +\(fn FROM TO)" t nil) + +(autoload 'ucs-normalize-NFKC-string "ucs-normalize" "\ +Normalize the string STR by the Unicode NFKC. + +\(fn STR)" nil nil) + +(autoload 'ucs-normalize-HFS-NFD-region "ucs-normalize" "\ +Normalize the current region by the Unicode NFD and Mac OS's HFS Plus. + +\(fn FROM TO)" t nil) + +(autoload 'ucs-normalize-HFS-NFD-string "ucs-normalize" "\ +Normalize the string STR by the Unicode NFD and Mac OS's HFS Plus. + +\(fn STR)" nil nil) + +(autoload 'ucs-normalize-HFS-NFC-region "ucs-normalize" "\ +Normalize the current region by the Unicode NFC and Mac OS's HFS Plus. + +\(fn FROM TO)" t nil) + +(autoload 'ucs-normalize-HFS-NFC-string "ucs-normalize" "\ +Normalize the string STR by the Unicode NFC and Mac OS's HFS Plus. + +\(fn STR)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ucs-normalize" '("ucs-normalize-" "utf-8-hfs"))) + +;;;*** + +;;;### (autoloads nil "underline" "textmodes/underline.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from textmodes/underline.el + +(autoload 'underline-region "underline" "\ +Underline all nonblank characters in the region. +Works by overstriking underscores. +Called from program, takes two arguments START and END +which specify the range to operate on. + +\(fn START END)" t nil) + +(autoload 'ununderline-region "underline" "\ +Remove all underlining (overstruck underscores) in the region. +Called from program, takes two arguments START and END +which specify the range to operate on. + +\(fn START END)" t nil) + +;;;*** + +;;;### (autoloads "actual autoloads are elsewhere" "undigest" "mail/undigest.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from mail/undigest.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "undigest" '("rmail-"))) + +;;;*** + +;;;### (autoloads nil "unrmail" "mail/unrmail.el" (0 0 0 0)) +;;; Generated autoloads from mail/unrmail.el + +(autoload 'batch-unrmail "unrmail" "\ +Convert old-style Rmail Babyl files to mbox format. +Specify the input Rmail Babyl file names as command line arguments. +For each Rmail file, the corresponding output file name +is made by adding `.mail' at the end. +For example, invoke `emacs -batch -f batch-unrmail RMAIL'. + +\(fn)" nil nil) + +(autoload 'unrmail "unrmail" "\ +Convert old-style Rmail Babyl file FILE to mbox format file TO-FILE. +The variable `unrmail-mbox-format' controls which mbox format to use. + +\(fn FILE TO-FILE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "unrmail" '("unrmail-mbox-format"))) + +;;;*** + +;;;### (autoloads nil "unsafep" "emacs-lisp/unsafep.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/unsafep.el + +(autoload 'unsafep "unsafep" "\ +Return nil if evaluating FORM couldn't possibly do any harm. +Otherwise result is a reason why FORM is unsafe. +UNSAFEP-VARS is a list of symbols with local bindings. + +\(fn FORM &optional UNSAFEP-VARS)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "unsafep" '("unsafep-" "safe-functions"))) + +;;;*** + +;;;### (autoloads nil "url" "url/url.el" (0 0 0 0)) +;;; Generated autoloads from url/url.el + +(autoload 'url-retrieve "url" "\ +Retrieve URL asynchronously and call CALLBACK with CBARGS when finished. +URL is either a string or a parsed URL. If it is a string +containing characters that are not valid in a URI, those +characters are percent-encoded; see `url-encode-url'. + +CALLBACK is called when the object has been completely retrieved, with +the current buffer containing the object, and any MIME headers associated +with it. It is called as (apply CALLBACK STATUS CBARGS). +STATUS is a plist representing what happened during the request, +with most recent events first, or an empty list if no events have +occurred. Each pair is one of: + +\(:redirect REDIRECTED-TO) - the request was redirected to this URL +\(:error (ERROR-SYMBOL . DATA)) - an error occurred. The error can be +signaled with (signal ERROR-SYMBOL DATA). + +Return the buffer URL will load into, or nil if the process has +already completed (i.e. URL was a mailto URL or similar; in this case +the callback is not called). + +The variables `url-request-data', `url-request-method' and +`url-request-extra-headers' can be dynamically bound around the +request; dynamic binding of other variables doesn't necessarily +take effect. + +If SILENT, then don't message progress reports and the like. +If INHIBIT-COOKIES, cookies will neither be stored nor sent to +the server. +If URL is a multibyte string, it will be encoded as utf-8 and +URL-encoded before it's used. + +\(fn URL CALLBACK &optional CBARGS SILENT INHIBIT-COOKIES)" nil nil) + +(autoload 'url-retrieve-synchronously "url" "\ +Retrieve URL synchronously. +Return the buffer containing the data, or nil if there are no data +associated with it (the case for dired, info, or mailto URLs that need +no further processing). URL is either a string or a parsed URL. + +If SILENT is non-nil, don't do any messaging while retrieving. +If INHIBIT-COOKIES is non-nil, refuse to store cookies. If +TIMEOUT is passed, it should be a number that says (in seconds) +how long to wait for a response before giving up. + +\(fn URL &optional SILENT INHIBIT-COOKIES TIMEOUT)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url" '("url-"))) + +;;;*** + +;;;### (autoloads nil "url-about" "url/url-about.el" (0 0 0 0)) +;;; Generated autoloads from url/url-about.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-about" '("url-"))) + +;;;*** + +;;;### (autoloads nil "url-auth" "url/url-auth.el" (0 0 0 0)) +;;; Generated autoloads from url/url-auth.el + +(autoload 'url-get-authentication "url-auth" "\ +Return an authorization string suitable for use in the WWW-Authenticate +header in an HTTP/1.0 request. + +URL is the url you are requesting authorization to. This can be either a + string representing the URL, or the parsed representation returned by + `url-generic-parse-url' +REALM is the realm at a specific site we are looking for. This should be a + string specifying the exact realm, or nil or the symbol `any' to + specify that the filename portion of the URL should be used as the + realm +TYPE is the type of authentication to be returned. This is either a string + representing the type (basic, digest, etc), or nil or the symbol `any' + to specify that any authentication is acceptable. If requesting `any' + the strongest matching authentication will be returned. If this is + wrong, it's no big deal, the error from the server will specify exactly + what type of auth to use +PROMPT is boolean - specifies whether to ask the user for a username/password + if one cannot be found in the cache + +\(fn URL REALM TYPE PROMPT &optional ARGS)" nil nil) + +(autoload 'url-register-auth-scheme "url-auth" "\ +Register an HTTP authentication method. + +TYPE is a string or symbol specifying the name of the method. + This should be the same thing you expect to get returned in + an Authenticate header in HTTP/1.0 - it will be downcased. +FUNCTION is the function to call to get the authorization information. + This defaults to `url-?-auth', where ? is TYPE. +RATING a rating between 1 and 10 of the strength of the authentication. + This is used when asking for the best authentication for a specific + URL. The item with the highest rating is returned. + +\(fn TYPE &optional FUNCTION RATING)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-auth" '("url-"))) + +;;;*** + +;;;### (autoloads nil "url-cache" "url/url-cache.el" (0 0 0 0)) +;;; Generated autoloads from url/url-cache.el + +(autoload 'url-store-in-cache "url-cache" "\ +Store buffer BUFF in the cache. + +\(fn &optional BUFF)" nil nil) + +(autoload 'url-is-cached "url-cache" "\ +Return non-nil if the URL is cached. +The actual return value is the last modification time of the cache file. + +\(fn URL)" nil nil) + +(autoload 'url-cache-extract "url-cache" "\ +Extract FNAM from the local disk cache. + +\(fn FNAM)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-cache" '("url-"))) + +;;;*** + +;;;### (autoloads nil "url-cid" "url/url-cid.el" (0 0 0 0)) +;;; Generated autoloads from url/url-cid.el + +(autoload 'url-cid "url-cid" "\ + + +\(fn URL)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-cid" '("url-cid-gnus"))) + +;;;*** + +;;;### (autoloads nil "url-cookie" "url/url-cookie.el" (0 0 0 0)) +;;; Generated autoloads from url/url-cookie.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-cookie" '("url-cookie"))) + +;;;*** + +;;;### (autoloads nil "url-dav" "url/url-dav.el" (0 0 0 0)) +;;; Generated autoloads from url/url-dav.el + +(autoload 'url-dav-supported-p "url-dav" "\ +Return WebDAV protocol version supported by URL. +Returns nil if WebDAV is not supported. + +\(fn URL)" nil nil) + +(autoload 'url-dav-request "url-dav" "\ +Perform WebDAV operation METHOD on URL. Return the parsed responses. +Automatically creates an XML request body if TAG is non-nil. +BODY is the XML document fragment to be enclosed by . + +DEPTH is how deep the request should propagate. Default is 0, meaning +it should apply only to URL. A negative number means to use +`Infinity' for the depth. Not all WebDAV servers support this depth +though. + +HEADERS is an assoc list of extra headers to send in the request. + +NAMESPACES is an assoc list of (NAMESPACE . EXPANSION), and these are +added to the element. The DAV=DAV: namespace is automatically +added to this list, so most requests can just pass in nil. + +\(fn URL METHOD TAG BODY &optional DEPTH HEADERS NAMESPACES)" nil nil) + +(autoload 'url-dav-vc-registered "url-dav" "\ + + +\(fn URL)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-dav" '("url-"))) + +;;;*** + +;;;### (autoloads nil "url-dired" "url/url-dired.el" (0 0 0 0)) +;;; Generated autoloads from url/url-dired.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-dired" '("url-"))) + +;;;*** + +;;;### (autoloads nil "url-domsuf" "url/url-domsuf.el" (0 0 0 0)) +;;; Generated autoloads from url/url-domsuf.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-domsuf" '("url-domsuf-"))) + +;;;*** + +;;;### (autoloads nil "url-expand" "url/url-expand.el" (0 0 0 0)) +;;; Generated autoloads from url/url-expand.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-expand" '("url-"))) + +;;;*** + +;;;### (autoloads nil "url-file" "url/url-file.el" (0 0 0 0)) +;;; Generated autoloads from url/url-file.el + +(autoload 'url-file "url-file" "\ +Handle file: and ftp: URLs. + +\(fn URL CALLBACK CBARGS)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-file" '("url-file-"))) + +;;;*** + +;;;### (autoloads nil "url-ftp" "url/url-ftp.el" (0 0 0 0)) +;;; Generated autoloads from url/url-ftp.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-ftp" '("url-ftp"))) + +;;;*** + +;;;### (autoloads nil "url-future" "url/url-future.el" (0 0 0 0)) +;;; Generated autoloads from url/url-future.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-future" '("url-future-"))) + +;;;*** + +;;;### (autoloads nil "url-gw" "url/url-gw.el" (0 0 0 0)) +;;; Generated autoloads from url/url-gw.el + +(autoload 'url-gateway-nslookup-host "url-gw" "\ +Attempt to resolve the given HOST using nslookup if possible. + +\(fn HOST)" t nil) + +(autoload 'url-open-stream "url-gw" "\ +Open a stream to HOST, possibly via a gateway. +Args per `open-network-stream'. +Will not make a connection if `url-gateway-unplugged' is non-nil. +Might do a non-blocking connection; use `process-status' to check. + +Optional arg GATEWAY-METHOD specifies the gateway to be used, +overriding the value of `url-gateway-method'. + +\(fn NAME BUFFER HOST SERVICE &optional GATEWAY-METHOD)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-gw" '("url-"))) + +;;;*** + +;;;### (autoloads nil "url-handlers" "url/url-handlers.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from url/url-handlers.el + +(defvar url-handler-mode nil "\ +Non-nil if Url-Handler mode is enabled. +See the `url-handler-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `url-handler-mode'.") + +(custom-autoload 'url-handler-mode "url-handlers" nil) + +(autoload 'url-handler-mode "url-handlers" "\ +Toggle using `url' library for URL filenames (URL Handler mode). +With a prefix argument ARG, enable URL Handler mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +\(fn &optional ARG)" t nil) + +(autoload 'url-file-handler "url-handlers" "\ +Function called from the `file-name-handler-alist' routines. +OPERATION is what needs to be done (`file-exists-p', etc). ARGS are +the arguments that would have been passed to OPERATION. + +\(fn OPERATION &rest ARGS)" nil nil) + +(autoload 'url-copy-file "url-handlers" "\ +Copy URL to NEWNAME. Both args must be strings. +Signals a `file-already-exists' error if file NEWNAME already exists, +unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil. +A number as third arg means request confirmation if NEWNAME already exists. +This is what happens in interactive use with M-x. +Fourth arg KEEP-TIME non-nil means give the new file the same +last-modified time as the old one. (This works on only some systems.) +Fifth arg PRESERVE-UID-GID is ignored. +A prefix arg makes KEEP-TIME non-nil. + +\(fn URL NEWNAME &optional OK-IF-ALREADY-EXISTS KEEP-TIME PRESERVE-UID-GID)" nil nil) + +(autoload 'url-file-local-copy "url-handlers" "\ +Copy URL into a temporary file on this machine. +Returns the name of the local copy, or nil, if FILE is directly +accessible. + +\(fn URL &rest IGNORED)" nil nil) + +(autoload 'url-insert-buffer-contents "url-handlers" "\ +Insert the contents of BUFFER into current buffer. +This is like `url-insert', but also decodes the current buffer as +if it had been inserted from a file named URL. + +\(fn BUFFER URL &optional VISIT BEG END REPLACE)" nil nil) + +(autoload 'url-insert-file-contents "url-handlers" "\ + + +\(fn URL &optional VISIT BEG END REPLACE)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-handlers" '("url-"))) + +;;;*** + +;;;### (autoloads nil "url-history" "url/url-history.el" (0 0 0 0)) +;;; Generated autoloads from url/url-history.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-history" '("url-"))) + +;;;*** + +;;;### (autoloads nil "url-http" "url/url-http.el" (0 0 0 0)) +;;; Generated autoloads from url/url-http.el + (autoload 'url-default-expander "url-expand") + +(defalias 'url-https-expand-file-name 'url-default-expander) + (autoload 'url-https "url-http") + (autoload 'url-https-file-exists-p "url-http") + (autoload 'url-https-file-readable-p "url-http") + (autoload 'url-https-file-attributes "url-http") + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-http" '("url-h"))) + +;;;*** + +;;;### (autoloads nil "url-imap" "url/url-imap.el" (0 0 0 0)) +;;; Generated autoloads from url/url-imap.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-imap" '("url-imap"))) + +;;;*** + +;;;### (autoloads nil "url-irc" "url/url-irc.el" (0 0 0 0)) +;;; Generated autoloads from url/url-irc.el + +(autoload 'url-irc "url-irc" "\ + + +\(fn URL)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-irc" '("url-irc-"))) + +;;;*** + +;;;### (autoloads nil "url-ldap" "url/url-ldap.el" (0 0 0 0)) +;;; Generated autoloads from url/url-ldap.el + +(autoload 'url-ldap "url-ldap" "\ +Perform an LDAP search specified by URL. +The return value is a buffer displaying the search results in HTML. +URL can be a URL string, or a URL record of the type returned by +`url-generic-parse-url'. + +\(fn URL)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-ldap" '("url-ldap-"))) + +;;;*** + +;;;### (autoloads nil "url-mailto" "url/url-mailto.el" (0 0 0 0)) +;;; Generated autoloads from url/url-mailto.el + +(autoload 'url-mail "url-mailto" "\ + + +\(fn &rest ARGS)" t nil) + +(autoload 'url-mailto "url-mailto" "\ +Handle the mailto: URL syntax. + +\(fn URL)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-mailto" '("url-mail-goto-field"))) + +;;;*** + +;;;### (autoloads nil "url-methods" "url/url-methods.el" (0 0 0 0)) +;;; Generated autoloads from url/url-methods.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-methods" '("url-scheme-"))) + +;;;*** + +;;;### (autoloads nil "url-misc" "url/url-misc.el" (0 0 0 0)) +;;; Generated autoloads from url/url-misc.el + +(autoload 'url-man "url-misc" "\ +Fetch a Unix manual page URL. + +\(fn URL)" nil nil) + +(autoload 'url-info "url-misc" "\ +Fetch a GNU Info URL. + +\(fn URL)" nil nil) + +(autoload 'url-generic-emulator-loader "url-misc" "\ + + +\(fn URL)" nil nil) + +(defalias 'url-rlogin 'url-generic-emulator-loader) + +(defalias 'url-telnet 'url-generic-emulator-loader) + +(defalias 'url-tn3270 'url-generic-emulator-loader) + +(autoload 'url-data "url-misc" "\ +Fetch a data URL (RFC 2397). + +\(fn URL)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-misc" '("url-do-terminal-emulator"))) + +;;;*** + +;;;### (autoloads nil "url-news" "url/url-news.el" (0 0 0 0)) +;;; Generated autoloads from url/url-news.el + +(autoload 'url-news "url-news" "\ + + +\(fn URL)" nil nil) + +(autoload 'url-snews "url-news" "\ + + +\(fn URL)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-news" '("url-news-"))) + +;;;*** + +;;;### (autoloads nil "url-nfs" "url/url-nfs.el" (0 0 0 0)) +;;; Generated autoloads from url/url-nfs.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-nfs" '("url-nfs"))) + +;;;*** + +;;;### (autoloads nil "url-ns" "url/url-ns.el" (0 0 0 0)) +;;; Generated autoloads from url/url-ns.el + +(autoload 'isPlainHostName "url-ns" "\ + + +\(fn HOST)" nil nil) + +(autoload 'dnsDomainIs "url-ns" "\ + + +\(fn HOST DOM)" nil nil) + +(autoload 'dnsResolve "url-ns" "\ + + +\(fn HOST)" nil nil) + +(autoload 'isResolvable "url-ns" "\ + + +\(fn HOST)" nil nil) + +(autoload 'isInNet "url-ns" "\ + + +\(fn IP NET MASK)" nil nil) + +(autoload 'url-ns-prefs "url-ns" "\ + + +\(fn &optional FILE)" nil nil) + +(autoload 'url-ns-user-pref "url-ns" "\ + + +\(fn KEY &optional DEFAULT)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-ns" '("url-ns-"))) + +;;;*** + +;;;### (autoloads nil "url-parse" "url/url-parse.el" (0 0 0 0)) +;;; Generated autoloads from url/url-parse.el + +(autoload 'url-recreate-url "url-parse" "\ +Recreate a URL string from the parsed URLOBJ. + +\(fn URLOBJ)" nil nil) + +(autoload 'url-generic-parse-url "url-parse" "\ +Return an URL-struct of the parts of URL. +The CL-style struct contains the following fields: + +TYPE is the URI scheme (string or nil). +USER is the user name (string or nil). +PASSWORD is the password (string [deprecated] or nil). +HOST is the host (a registered name, IP literal in square + brackets, or IPv4 address in dotted-decimal form). +PORTSPEC is the specified port (a number), or nil. +FILENAME is the path AND the query component of the URI. +TARGET is the fragment identifier component (used to refer to a + subordinate resource, e.g. a part of a webpage). +ATTRIBUTES is nil; this slot originally stored the attribute and + value alists for IMAP URIs, but this feature was removed + since it conflicts with RFC 3986. +FULLNESS is non-nil if the hierarchical sequence component of + the URL starts with two slashes, \"//\". + +The parser follows RFC 3986, except that it also tries to handle +URIs that are not fully specified (e.g. lacking TYPE), and it +does not check for or perform %-encoding. + +Here is an example. The URL + + foo://bob:pass@example.com:42/a/b/c.dtb?type=animal&name=narwhal#nose + +parses to + + TYPE = \"foo\" + USER = \"bob\" + PASSWORD = \"pass\" + HOST = \"example.com\" + PORTSPEC = 42 + FILENAME = \"/a/b/c.dtb?type=animal&name=narwhal\" + TARGET = \"nose\" + ATTRIBUTES = nil + FULLNESS = t + +\(fn URL)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-parse" '("url-"))) + +;;;*** + +;;;### (autoloads nil "url-privacy" "url/url-privacy.el" (0 0 0 0)) +;;; Generated autoloads from url/url-privacy.el + +(autoload 'url-setup-privacy-info "url-privacy" "\ +Setup variables that expose info about you and your system. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-privacy" '("url-device-type"))) + +;;;*** + +;;;### (autoloads nil "url-proxy" "url/url-proxy.el" (0 0 0 0)) +;;; Generated autoloads from url/url-proxy.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-proxy" '("url-"))) + +;;;*** + +;;;### (autoloads nil "url-queue" "url/url-queue.el" (0 0 0 0)) +;;; Generated autoloads from url/url-queue.el + +(autoload 'url-queue-retrieve "url-queue" "\ +Retrieve URL asynchronously and call CALLBACK with CBARGS when finished. +This is like `url-retrieve' (which see for details of the arguments), +but with limits on the degree of parallelism. The variable +`url-queue-parallel-processes' sets the number of concurrent processes. +The variable `url-queue-timeout' sets a timeout. + +\(fn URL CALLBACK &optional CBARGS SILENT INHIBIT-COOKIES)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-queue" '("url-queue"))) + +;;;*** + +;;;### (autoloads nil "url-tramp" "url/url-tramp.el" (0 0 0 0)) +;;; Generated autoloads from url/url-tramp.el + +(defvar url-tramp-protocols '("ftp" "ssh" "scp" "rsync" "telnet") "\ +List of URL protocols for which the work is handled by Tramp. +They must also be covered by `url-handler-regexp'.") + +(custom-autoload 'url-tramp-protocols "url-tramp" t) + +(autoload 'url-tramp-file-handler "url-tramp" "\ +Function called from the `file-name-handler-alist' routines. +OPERATION is what needs to be done. ARGS are the arguments that +would have been passed to OPERATION. + +\(fn OPERATION &rest ARGS)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-tramp" '("url-tramp-convert-"))) + +;;;*** + +;;;### (autoloads nil "url-util" "url/url-util.el" (0 0 0 0)) +;;; Generated autoloads from url/url-util.el + +(defvar url-debug nil "\ +What types of debug messages from the URL library to show. +Debug messages are logged to the *URL-DEBUG* buffer. + +If t, all messages will be logged. +If a number, all messages will be logged, as well shown via `message'. +If a list, it is a list of the types of messages to be logged.") + +(custom-autoload 'url-debug "url-util" t) + +(autoload 'url-debug "url-util" "\ + + +\(fn TAG &rest ARGS)" nil nil) + +(autoload 'url-parse-args "url-util" "\ + + +\(fn STR &optional NODOWNCASE)" nil nil) + +(autoload 'url-insert-entities-in-string "url-util" "\ +Convert HTML markup-start characters to entity references in STRING. +Also replaces the \" character, so that the result may be safely used as +an attribute value in a tag. Returns a new string with the result of the +conversion. Replaces these characters as follows: + & ==> & + < ==> < + > ==> > + \" ==> " + +\(fn STRING)" nil nil) + +(autoload 'url-normalize-url "url-util" "\ +Return a \"normalized\" version of URL. +Strips out default port numbers, etc. + +\(fn URL)" nil nil) + +(autoload 'url-lazy-message "url-util" "\ +Just like `message', but is a no-op if called more than once a second. +Will not do anything if `url-show-status' is nil. + +\(fn &rest ARGS)" nil nil) + +(autoload 'url-get-normalized-date "url-util" "\ +Return a date string that most HTTP servers can understand. + +\(fn &optional SPECIFIED-TIME)" nil nil) + +(autoload 'url-eat-trailing-space "url-util" "\ +Remove spaces/tabs at the end of a string. + +\(fn X)" nil nil) + +(autoload 'url-strip-leading-spaces "url-util" "\ +Remove spaces at the front of a string. + +\(fn X)" nil nil) + +(autoload 'url-display-percentage "url-util" "\ + + +\(fn FMT PERC &rest ARGS)" nil nil) + +(autoload 'url-percentage "url-util" "\ + + +\(fn X Y)" nil nil) + +(defalias 'url-basepath 'url-file-directory) + +(autoload 'url-file-directory "url-util" "\ +Return the directory part of FILE, for a URL. + +\(fn FILE)" nil nil) + +(autoload 'url-file-nondirectory "url-util" "\ +Return the nondirectory part of FILE, for a URL. + +\(fn FILE)" nil nil) + +(autoload 'url-parse-query-string "url-util" "\ + + +\(fn QUERY &optional DOWNCASE ALLOW-NEWLINES)" nil nil) + +(autoload 'url-build-query-string "url-util" "\ +Build a query-string. + +Given a QUERY in the form: + ((key1 val1) + (key2 val2) + (key3 val1 val2) + (key4) + (key5 \"\")) + +\(This is the same format as produced by `url-parse-query-string') + +This will return a string +\"key1=val1&key2=val2&key3=val1&key3=val2&key4&key5\". Keys may +be strings or symbols; if they are symbols, the symbol name will +be used. + +When SEMICOLONS is given, the separator will be \";\". + +When KEEP-EMPTY is given, empty values will show as \"key=\" +instead of just \"key\" as in the example above. + +\(fn QUERY &optional SEMICOLONS KEEP-EMPTY)" nil nil) + +(autoload 'url-unhex-string "url-util" "\ +Remove %XX embedded spaces, etc in a URL. +If optional second argument ALLOW-NEWLINES is non-nil, then allow the +decoding of carriage returns and line feeds in the string, which is normally +forbidden in URL encoding. + +\(fn STR &optional ALLOW-NEWLINES)" nil nil) + +(autoload 'url-hexify-string "url-util" "\ +URI-encode STRING and return the result. +If STRING is multibyte, it is first converted to a utf-8 byte +string. Each byte corresponding to an allowed character is left +as-is, while all other bytes are converted to a three-character +string: \"%\" followed by two upper-case hex digits. + +The allowed characters are specified by ALLOWED-CHARS. If this +argument is nil, the list `url-unreserved-chars' determines the +allowed characters. Otherwise, ALLOWED-CHARS should be a vector +whose Nth element is non-nil if character N is allowed. + +\(fn STRING &optional ALLOWED-CHARS)" nil nil) + +(autoload 'url-encode-url "url-util" "\ +Return a properly URI-encoded version of URL. +This function also performs URI normalization, e.g. converting +the scheme to lowercase if it is uppercase. Apart from +normalization, if URL is already URI-encoded, this function +should return it unchanged. + +\(fn URL)" nil nil) + +(autoload 'url-file-extension "url-util" "\ +Return the filename extension of FNAME. +If optional argument X is t, then return the basename +of the file with the extension stripped off. + +\(fn FNAME &optional X)" nil nil) + +(autoload 'url-truncate-url-for-viewing "url-util" "\ +Return a shortened version of URL that is WIDTH characters wide or less. +WIDTH defaults to the current frame width. + +\(fn URL &optional WIDTH)" nil nil) + +(autoload 'url-view-url "url-util" "\ +View the current document's URL. +Optional argument NO-SHOW means just return the URL, don't show it in +the minibuffer. + +This uses `url-current-object', set locally to the buffer. + +\(fn &optional NO-SHOW)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-util" '("url-"))) + +;;;*** + +;;;### (autoloads nil "url-vars" "url/url-vars.el" (0 0 0 0)) +;;; Generated autoloads from url/url-vars.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "url-vars" '("url-"))) + +;;;*** + +;;;### (autoloads nil "userlock" "userlock.el" (0 0 0 0)) +;;; Generated autoloads from userlock.el + +(autoload 'ask-user-about-lock "userlock" "\ +Ask user what to do when he wants to edit FILE but it is locked by OPPONENT. +This function has a choice of three things to do: + do (signal \\='file-locked (list FILE OPPONENT)) + to refrain from editing the file + return t (grab the lock on the file) + return nil (edit the file even though it is locked). +You can redefine this function to choose among those three alternatives +in any way you like. + +\(fn FILE OPPONENT)" nil nil) + +(autoload 'userlock--ask-user-about-supersession-threat "userlock" "\ + + +\(fn FN)" nil nil) + +(autoload 'ask-user-about-supersession-threat "userlock" "\ +Ask a user who is about to modify an obsolete buffer what to do. +This function has two choices: it can return, in which case the modification +of the buffer will proceed, or it can (signal \\='file-supersession (file)), +in which case the proposed buffer modification will not be made. + +You can rewrite this to use any criterion you like to choose which one to do. +The buffer in question is current when this function is called. + +\(fn FN)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "userlock" '("ask-user-about-" "userlock--check-content-unchanged" "file-"))) + +;;;*** + +;;;### (autoloads nil "utf-7" "international/utf-7.el" (0 0 0 0)) +;;; Generated autoloads from international/utf-7.el + +(autoload 'utf-7-post-read-conversion "utf-7" "\ + + +\(fn LEN)" nil nil) + +(autoload 'utf-7-imap-post-read-conversion "utf-7" "\ + + +\(fn LEN)" nil nil) + +(autoload 'utf-7-pre-write-conversion "utf-7" "\ + + +\(fn FROM TO)" nil nil) + +(autoload 'utf-7-imap-pre-write-conversion "utf-7" "\ + + +\(fn FROM TO)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "utf-7" '("utf-7-"))) + +;;;*** + +;;;### (autoloads nil "utf7" "international/utf7.el" (0 0 0 0)) +;;; Generated autoloads from international/utf7.el + +(autoload 'utf7-encode "utf7" "\ +Encode UTF-7 STRING. Use IMAP modification if FOR-IMAP is non-nil. + +\(fn STRING &optional FOR-IMAP)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "utf7" '("utf7-"))) + +;;;*** + +;;;### (autoloads nil "uudecode" "mail/uudecode.el" (0 0 0 0)) +;;; Generated autoloads from mail/uudecode.el + +(autoload 'uudecode-decode-region-external "uudecode" "\ +Uudecode region between START and END using external program. +If FILE-NAME is non-nil, save the result to FILE-NAME. The program +used is specified by `uudecode-decoder-program'. + +\(fn START END &optional FILE-NAME)" t nil) + +(autoload 'uudecode-decode-region-internal "uudecode" "\ +Uudecode region between START and END without using an external program. +If FILE-NAME is non-nil, save the result to FILE-NAME. + +\(fn START END &optional FILE-NAME)" t nil) + +(autoload 'uudecode-decode-region "uudecode" "\ +Uudecode region between START and END. +If FILE-NAME is non-nil, save the result to FILE-NAME. + +\(fn START END &optional FILE-NAME)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "uudecode" '("uudecode-"))) + +;;;*** + +;;;### (autoloads nil "vc" "vc/vc.el" (0 0 0 0)) +;;; Generated autoloads from vc/vc.el + +(defvar vc-checkout-hook nil "\ +Normal hook (list of functions) run after checking out a file. +See `run-hooks'.") + +(custom-autoload 'vc-checkout-hook "vc" t) + +(defvar vc-checkin-hook nil "\ +Normal hook (list of functions) run after commit or file checkin. +See also `log-edit-done-hook'.") + +(custom-autoload 'vc-checkin-hook "vc" t) + +(defvar vc-before-checkin-hook nil "\ +Normal hook (list of functions) run before a commit or a file checkin. +See `run-hooks'.") + +(custom-autoload 'vc-before-checkin-hook "vc" t) + +(autoload 'vc-responsible-backend "vc" "\ +Return the name of a backend system that is responsible for FILE. + +If FILE is already registered, return the +backend of FILE. If FILE is not registered, then the +first backend in `vc-handled-backends' that declares itself +responsible for FILE is returned. + +Note that if FILE is a symbolic link, it will not be resolved -- +the responsible backend system for the symbolic link itself will +be reported. + +\(fn FILE)" nil nil) + +(autoload 'vc-next-action "vc" "\ +Do the next logical version control operation on the current fileset. +This requires that all files in the current VC fileset be in the +same state. If not, signal an error. + +For merging-based version control systems: + If every file in the VC fileset is not registered for version + control, register the fileset (but don't commit). + If every work file in the VC fileset is added or changed, pop + up a *vc-log* buffer to commit the fileset. + For a centralized version control system, if any work file in + the VC fileset is out of date, offer to update the fileset. + +For old-style locking-based version control systems, like RCS: + If every file is not registered, register the file(s). + If every file is registered and unlocked, check out (lock) + the file(s) for editing. + If every file is locked by you and has changes, pop up a + *vc-log* buffer to check in the changes. Leave a + read-only copy of each changed file after checking in. + If every file is locked by you and unchanged, unlock them. + If every file is locked by someone else, offer to steal the lock. + +\(fn VERBOSE)" t nil) + +(autoload 'vc-register "vc" "\ +Register into a version control system. +If VC-FILESET is given, register the files in that fileset. +Otherwise register the current file. +If COMMENT is present, use that as an initial comment. + +The version control system to use is found by cycling through the list +`vc-handled-backends'. The first backend in that list which declares +itself responsible for the file (usually because other files in that +directory are already registered under that backend) will be used to +register the file. If no backend declares itself responsible, the +first backend that could register the file is used. + +\(fn &optional VC-FILESET COMMENT)" t nil) + +(autoload 'vc-version-diff "vc" "\ +Report diffs between revisions of the fileset in the repository history. + +\(fn FILES REV1 REV2)" t nil) + +(autoload 'vc-diff "vc" "\ +Display diffs between file revisions. +Normally this compares the currently selected fileset with their +working revisions. With a prefix argument HISTORIC, it reads two revision +designators specifying which revisions to compare. + +The optional argument NOT-URGENT non-nil means it is ok to say no to +saving the buffer. + +\(fn &optional HISTORIC NOT-URGENT)" t nil) + +(autoload 'vc-version-ediff "vc" "\ +Show differences between revisions of the fileset in the +repository history using ediff. + +\(fn FILES REV1 REV2)" t nil) + +(autoload 'vc-ediff "vc" "\ +Display diffs between file revisions using ediff. +Normally this compares the currently selected fileset with their +working revisions. With a prefix argument HISTORIC, it reads two revision +designators specifying which revisions to compare. + +The optional argument NOT-URGENT non-nil means it is ok to say no to +saving the buffer. + +\(fn HISTORIC &optional NOT-URGENT)" t nil) + +(autoload 'vc-root-diff "vc" "\ +Display diffs between VC-controlled whole tree revisions. +Normally, this compares the tree corresponding to the current +fileset with the working revision. +With a prefix argument HISTORIC, prompt for two revision +designators specifying which revisions to compare. + +The optional argument NOT-URGENT non-nil means it is ok to say no to +saving the buffer. + +\(fn HISTORIC &optional NOT-URGENT)" t nil) + +(autoload 'vc-root-dir "vc" "\ +Return the root directory for the current VC tree. +Return nil if the root directory cannot be identified. + +\(fn)" nil nil) + +(autoload 'vc-revision-other-window "vc" "\ +Visit revision REV of the current file in another window. +If the current file is named `F', the revision is named `F.~REV~'. +If `F.~REV~' already exists, use it instead of checking it out again. + +\(fn REV)" t nil) + +(autoload 'vc-insert-headers "vc" "\ +Insert headers into a file for use with a version control system. +Headers desired are inserted at point, and are pulled from +the variable `vc-BACKEND-header'. + +\(fn)" t nil) + +(autoload 'vc-merge "vc" "\ +Perform a version control merge operation. +You must be visiting a version controlled file, or in a `vc-dir' buffer. +On a distributed version control system, this runs a \"merge\" +operation to incorporate changes from another branch onto the +current branch, prompting for an argument list. + +On a non-distributed version control system, this merges changes +between two revisions into the current fileset. This asks for +two revisions to merge from in the minibuffer. If the first +revision is a branch number, then merge all changes from that +branch. If the first revision is empty, merge the most recent +changes from the current branch. + +\(fn)" t nil) + +(autoload 'vc-message-unresolved-conflicts "vc" "\ +Display a message indicating unresolved conflicts in FILENAME. + +\(fn FILENAME)" nil nil) + +(defalias 'vc-resolve-conflicts 'smerge-ediff) + +(autoload 'vc-create-tag "vc" "\ +Descending recursively from DIR, make a tag called NAME. +For each registered file, the working revision becomes part of +the named configuration. If the prefix argument BRANCHP is +given, the tag is made as a new branch and the files are +checked out in that new branch. + +\(fn DIR NAME BRANCHP)" t nil) + +(autoload 'vc-retrieve-tag "vc" "\ +For each file in or below DIR, retrieve their tagged version NAME. +NAME can name a branch, in which case this command will switch to the +named branch in the directory DIR. +Interactively, prompt for DIR only for VCS that works at file level; +otherwise use the repository root of the current buffer. +If NAME is empty, it refers to the latest revisions of the current branch. +If locking is used for the files in DIR, then there must not be any +locked files at or below DIR (but if NAME is empty, locked files are +allowed and simply skipped). + +\(fn DIR NAME)" t nil) + +(autoload 'vc-print-log "vc" "\ +List the change log of the current fileset in a window. +If WORKING-REVISION is non-nil, leave point at that revision. +If LIMIT is non-nil, it should be a number specifying the maximum +number of revisions to show; the default is `vc-log-show-limit'. + +When called interactively with a prefix argument, prompt for +WORKING-REVISION and LIMIT. + +\(fn &optional WORKING-REVISION LIMIT)" t nil) + +(autoload 'vc-print-root-log "vc" "\ +List the change log for the current VC controlled tree in a window. +If LIMIT is non-nil, it should be a number specifying the maximum +number of revisions to show; the default is `vc-log-show-limit'. +When called interactively with a prefix argument, prompt for LIMIT. + +\(fn &optional LIMIT)" t nil) + +(autoload 'vc-print-branch-log "vc" "\ + + +\(fn BRANCH)" t nil) + +(autoload 'vc-log-incoming "vc" "\ +Show a log of changes that will be received with a pull operation from REMOTE-LOCATION. +When called interactively with a prefix argument, prompt for REMOTE-LOCATION. + +\(fn &optional REMOTE-LOCATION)" t nil) + +(autoload 'vc-log-outgoing "vc" "\ +Show a log of changes that will be sent with a push operation to REMOTE-LOCATION. +When called interactively with a prefix argument, prompt for REMOTE-LOCATION. + +\(fn &optional REMOTE-LOCATION)" t nil) + +(autoload 'vc-region-history "vc" "\ +Show the history of the region FROM..TO. + +\(fn FROM TO)" t nil) + +(autoload 'vc-revert "vc" "\ +Revert working copies of the selected fileset to their repository contents. +This asks for confirmation if the buffer contents are not identical +to the working revision (except for keyword expansion). + +\(fn)" t nil) + +(define-obsolete-function-alias 'vc-revert-buffer 'vc-revert "23.1") + +(autoload 'vc-pull "vc" "\ +Update the current fileset or branch. +You must be visiting a version controlled file, or in a `vc-dir' buffer. +On a distributed version control system, this runs a \"pull\" +operation to update the current branch, prompting for an argument +list if required. Optional prefix ARG forces a prompt for the VCS +command to run. + +On a non-distributed version control system, update the current +fileset to the tip revisions. For each unchanged and unlocked +file, this simply replaces the work file with the latest revision +on its branch. If the file contains changes, any changes in the +tip revision are merged into the working file. + +\(fn &optional ARG)" t nil) + +(defalias 'vc-update 'vc-pull) + +(autoload 'vc-push "vc" "\ +Push the current branch. +You must be visiting a version controlled file, or in a `vc-dir' buffer. +On a distributed version control system, this runs a \"push\" +operation on the current branch, prompting for the precise command +if required. Optional prefix ARG non-nil forces a prompt for the +VCS command to run. + +On a non-distributed version control system, this signals an error. +It also signals an error in a Bazaar bound branch. + +\(fn &optional ARG)" t nil) + +(autoload 'vc-switch-backend "vc" "\ +Make BACKEND the current version control system for FILE. +FILE must already be registered in BACKEND. The change is not +permanent, only for the current session. This function only changes +VC's perspective on FILE, it does not register or unregister it. +By default, this command cycles through the registered backends. +To get a prompt, use a prefix argument. + +\(fn FILE BACKEND)" t nil) + +(autoload 'vc-transfer-file "vc" "\ +Transfer FILE to another version control system NEW-BACKEND. +If NEW-BACKEND has a higher precedence than FILE's current backend +\(i.e. it comes earlier in `vc-handled-backends'), then register FILE in +NEW-BACKEND, using the revision number from the current backend as the +base level. If NEW-BACKEND has a lower precedence than the current +backend, then commit all changes that were made under the current +backend to NEW-BACKEND, and unregister FILE from the current backend. +\(If FILE is not yet registered under NEW-BACKEND, register it.) + +\(fn FILE NEW-BACKEND)" nil nil) + +(autoload 'vc-delete-file "vc" "\ +Delete file and mark it as such in the version control system. +If called interactively, read FILE, defaulting to the current +buffer's file name if it's under version control. + +\(fn FILE)" t nil) + +(autoload 'vc-rename-file "vc" "\ +Rename file OLD to NEW in both work area and repository. +If called interactively, read OLD and NEW, defaulting OLD to the +current buffer's file name if it's under version control. + +\(fn OLD NEW)" t nil) + +(autoload 'vc-update-change-log "vc" "\ +Find change log file and add entries from recent version control logs. +Normally, find log entries for all registered files in the default +directory. + +With prefix arg of \\[universal-argument], only find log entries for the current buffer's file. + +With any numeric prefix arg, find log entries for all currently visited +files that are under version control. This puts all the entries in the +log for the default directory, which may not be appropriate. + +From a program, any ARGS are assumed to be filenames for which +log entries should be gathered. + +\(fn &rest ARGS)" t nil) + +(autoload 'vc-branch-part "vc" "\ +Return the branch part of a revision number REV. + +\(fn REV)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vc" '("vc-" "with-vc-properties"))) + +;;;*** + +;;;### (autoloads nil "vc-annotate" "vc/vc-annotate.el" (0 0 0 0)) +;;; Generated autoloads from vc/vc-annotate.el + +(autoload 'vc-annotate "vc-annotate" "\ +Display the edit history of the current FILE using colors. + +This command creates a buffer that shows, for each line of the current +file, when it was last edited and by whom. Additionally, colors are +used to show the age of each line--blue means oldest, red means +youngest, and intermediate colors indicate intermediate ages. By +default, the time scale stretches back one year into the past; +everything that is older than that is shown in blue. + +With a prefix argument, this command asks two questions in the +minibuffer. First, you may enter a revision number REV; then the buffer +displays and annotates that revision instead of the working revision +\(type RET in the minibuffer to leave that default unchanged). Then, +you are prompted for the time span in days which the color range +should cover. For example, a time span of 20 days means that changes +over the past 20 days are shown in red to blue, according to their +age, and everything that is older than that is shown in blue. + +If MOVE-POINT-TO is given, move the point to that line. + +If VC-BK is given used that VC backend. + +Customization variables: + +`vc-annotate-menu-elements' customizes the menu elements of the +mode-specific menu. `vc-annotate-color-map' and +`vc-annotate-very-old-color' define the mapping of time to colors. +`vc-annotate-background' specifies the background color. +`vc-annotate-background-mode' specifies whether the color map +should be applied to the background or to the foreground. + +\(fn FILE REV &optional DISPLAY-MODE BUF MOVE-POINT-TO VC-BK)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vc-annotate" '("vc-"))) + +;;;*** + +;;;### (autoloads nil "vc-bzr" "vc/vc-bzr.el" (0 0 0 0)) +;;; Generated autoloads from vc/vc-bzr.el + +(defconst vc-bzr-admin-dirname ".bzr" "\ +Name of the directory containing Bzr repository status files.") + +(defconst vc-bzr-admin-checkout-format-file (concat vc-bzr-admin-dirname "/checkout/format") "\ +Name of the format file in a .bzr directory.") + (defun vc-bzr-registered (file) + (if (vc-find-root file vc-bzr-admin-checkout-format-file) + (progn + (load "vc-bzr" nil t) + (vc-bzr-registered file)))) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vc-bzr" '("vc-bzr-"))) + +;;;*** + +;;;### (autoloads nil "vc-cvs" "vc/vc-cvs.el" (0 0 0 0)) +;;; Generated autoloads from vc/vc-cvs.el +(defun vc-cvs-registered (f) + "Return non-nil if file F is registered with CVS." + (when (file-readable-p (expand-file-name + "CVS/Entries" (file-name-directory f))) + (load "vc-cvs" nil t) + (vc-cvs-registered f))) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vc-cvs" '("vc-cvs-"))) + +;;;*** + +;;;### (autoloads nil "vc-dav" "vc/vc-dav.el" (0 0 0 0)) +;;; Generated autoloads from vc/vc-dav.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vc-dav" '("vc-dav-"))) + +;;;*** + +;;;### (autoloads nil "vc-dir" "vc/vc-dir.el" (0 0 0 0)) +;;; Generated autoloads from vc/vc-dir.el + +(autoload 'vc-dir "vc-dir" "\ +Show the VC status for \"interesting\" files in and below DIR. +This allows you to mark files and perform VC operations on them. +The list omits files which are up to date, with no changes in your copy +or the repository, if there is nothing in particular to say about them. + +Preparing the list of file status takes time; when the buffer +first appears, it has only the first few lines of summary information. +The file lines appear later. + +Optional second argument BACKEND specifies the VC backend to use. +Interactively, a prefix argument means to ask for the backend. + +These are the commands available for use in the file status buffer: + +\\{vc-dir-mode-map} + +\(fn DIR &optional BACKEND)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vc-dir" '("vc-"))) + +;;;*** + +;;;### (autoloads nil "vc-dispatcher" "vc/vc-dispatcher.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from vc/vc-dispatcher.el + +(autoload 'vc-do-command "vc-dispatcher" "\ +Execute a slave command, notifying user and checking for errors. +Output from COMMAND goes to BUFFER, or the current buffer if +BUFFER is t. If the destination buffer is not already current, +set it up properly and erase it. The command is considered +successful if its exit status does not exceed OKSTATUS (if +OKSTATUS is nil, that means to ignore error status, if it is +`async', that means not to wait for termination of the +subprocess; if it is t it means to ignore all execution errors). +FILE-OR-LIST is the name of a working file; it may be a list of +files or be nil (to execute commands that don't expect a file +name or set of files). If an optional list of FLAGS is present, +that is inserted into the command line before the filename. +Return the return value of the slave command in the synchronous +case, and the process object in the asynchronous case. + +\(fn BUFFER OKSTATUS COMMAND FILE-OR-LIST &rest FLAGS)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vc-dispatcher" '("vc-"))) + +;;;*** + +;;;### (autoloads nil "vc-filewise" "vc/vc-filewise.el" (0 0 0 0)) +;;; Generated autoloads from vc/vc-filewise.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vc-filewise" '("vc-"))) + +;;;*** + +;;;### (autoloads nil "vc-git" "vc/vc-git.el" (0 0 0 0)) +;;; Generated autoloads from vc/vc-git.el + (defun vc-git-registered (file) + "Return non-nil if FILE is registered with git." + (if (vc-find-root file ".git") ; Short cut. + (progn + (load "vc-git" nil t) + (vc-git-registered file)))) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vc-git" '("vc-git-"))) + +;;;*** + +;;;### (autoloads nil "vc-hg" "vc/vc-hg.el" (0 0 0 0)) +;;; Generated autoloads from vc/vc-hg.el + (defun vc-hg-registered (file) + "Return non-nil if FILE is registered with hg." + (if (vc-find-root file ".hg") ; short cut + (progn + (load "vc-hg" nil t) + (vc-hg-registered file)))) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vc-hg" '("vc-hg-"))) + +;;;*** + +;;;### (autoloads nil "vc-mtn" "vc/vc-mtn.el" (0 0 0 0)) +;;; Generated autoloads from vc/vc-mtn.el + +(defconst vc-mtn-admin-dir "_MTN" "\ +Name of the monotone directory.") + +(defconst vc-mtn-admin-format (concat vc-mtn-admin-dir "/format") "\ +Name of the monotone directory's format file.") + (defun vc-mtn-registered (file) + (if (vc-find-root file vc-mtn-admin-format) + (progn + (load "vc-mtn" nil t) + (vc-mtn-registered file)))) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vc-mtn" '("vc-mtn-"))) + +;;;*** + +;;;### (autoloads nil "vc-rcs" "vc/vc-rcs.el" (0 0 0 0)) +;;; Generated autoloads from vc/vc-rcs.el + +(defvar vc-rcs-master-templates (purecopy '("%sRCS/%s,v" "%s%s,v" "%sRCS/%s")) "\ +Where to look for RCS master files. +For a description of possible values, see `vc-check-master-templates'.") + +(custom-autoload 'vc-rcs-master-templates "vc-rcs" t) + +(defun vc-rcs-registered (f) (vc-default-registered 'RCS f)) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vc-rcs" '("vc-r"))) + +;;;*** + +;;;### (autoloads nil "vc-sccs" "vc/vc-sccs.el" (0 0 0 0)) +;;; Generated autoloads from vc/vc-sccs.el + +(defvar vc-sccs-master-templates (purecopy '("%sSCCS/s.%s" "%ss.%s" vc-sccs-search-project-dir)) "\ +Where to look for SCCS master files. +For a description of possible values, see `vc-check-master-templates'.") + +(custom-autoload 'vc-sccs-master-templates "vc-sccs" t) + +(defun vc-sccs-registered (f) (vc-default-registered 'SCCS f)) + +(defun vc-sccs-search-project-dir (_dirname basename) "\ +Return the name of a master file in the SCCS project directory. +Does not check whether the file exists but returns nil if it does not +find any project directory." (let ((project-dir (getenv "PROJECTDIR")) dirs dir) (when project-dir (if (file-name-absolute-p project-dir) (setq dirs (quote ("SCCS" ""))) (setq dirs (quote ("src/SCCS" "src" "source/SCCS" "source"))) (setq project-dir (expand-file-name (concat "~" project-dir)))) (while (and (not dir) dirs) (setq dir (expand-file-name (car dirs) project-dir)) (unless (file-directory-p dir) (setq dir nil) (setq dirs (cdr dirs)))) (and dir (expand-file-name (concat "s." basename) dir))))) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vc-sccs" '("vc-sccs-"))) + +;;;*** + +;;;### (autoloads nil "vc-src" "vc/vc-src.el" (0 0 0 0)) +;;; Generated autoloads from vc/vc-src.el + +(defvar vc-src-master-templates (purecopy '("%s.src/%s,v")) "\ +Where to look for SRC master files. +For a description of possible values, see `vc-check-master-templates'.") + +(custom-autoload 'vc-src-master-templates "vc-src" t) + +(defun vc-src-registered (f) (vc-default-registered 'src f)) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vc-src" '("vc-src-"))) + +;;;*** + +;;;### (autoloads nil "vc-svn" "vc/vc-svn.el" (0 0 0 0)) +;;; Generated autoloads from vc/vc-svn.el + (defun vc-svn-registered (f) + (let ((admin-dir (cond ((and (eq system-type 'windows-nt) + (getenv "SVN_ASP_DOT_NET_HACK")) + "_svn") + (t ".svn")))) + (when (vc-find-root f admin-dir) + (load "vc-svn" nil t) + (vc-svn-registered f)))) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vc-svn" '("vc-svn-"))) + +;;;*** + +;;;### (autoloads nil "vcursor" "vcursor.el" (0 0 0 0)) +;;; Generated autoloads from vcursor.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vcursor" '("vcursor-"))) + +;;;*** + +;;;### (autoloads nil "vera-mode" "progmodes/vera-mode.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from progmodes/vera-mode.el +(push (purecopy '(vera-mode 2 28)) package--builtin-versions) + (add-to-list 'auto-mode-alist (cons (purecopy "\\.vr[hi]?\\'") 'vera-mode)) + +(autoload 'vera-mode "vera-mode" "\ +Major mode for editing Vera code. + +Usage: +------ + + INDENTATION: Typing `TAB' at the beginning of a line indents the line. + The amount of indentation is specified by option `vera-basic-offset'. + Indentation can be done for an entire region (`M-C-\\') or buffer (menu). + `TAB' always indents the line if option `vera-intelligent-tab' is nil. + + WORD/COMMAND COMPLETION: Typing `TAB' after a (not completed) word looks + for a word in the buffer or a Vera keyword that starts alike, inserts it + and adjusts case. Re-typing `TAB' toggles through alternative word + completions. + + Typing `TAB' after a non-word character inserts a tabulator stop (if not + at the beginning of a line). `M-TAB' always inserts a tabulator stop. + + COMMENTS: `C-c C-c' comments out a region if not commented out, and + uncomments a region if already commented out. + + HIGHLIGHTING (fontification): Vera keywords, predefined types and + constants, function names, declaration names, directives, as well as + comments and strings are highlighted using different colors. + + VERA VERSION: OpenVera 1.4 and Vera version 6.2.8. + + +Maintenance: +------------ + +To submit a bug report, use the corresponding menu entry within Vera Mode. +Add a description of the problem and include a reproducible test case. + +Feel free to send questions and enhancement requests to . + +Official distribution is at +URL `http://www.iis.ee.ethz.ch/~zimmi/emacs/vera-mode.html' + + + The Vera Mode Maintainer + Reto Zimmermann + +Key bindings: +------------- + +\\{vera-mode-map} + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vera-mode" '("vera-"))) + +;;;*** + +;;;### (autoloads nil "verilog-mode" "progmodes/verilog-mode.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from progmodes/verilog-mode.el + +(autoload 'verilog-mode "verilog-mode" "\ +Major mode for editing Verilog code. +\\ +See \\[describe-function] verilog-auto (\\[verilog-auto]) for details on how +AUTOs can improve coding efficiency. + +Use \\[verilog-faq] for a pointer to frequently asked questions. + +NEWLINE, TAB indents for Verilog code. +Delete converts tabs to spaces as it moves back. + +Supports highlighting. + +Turning on Verilog mode calls the value of the variable `verilog-mode-hook' +with no args, if that value is non-nil. + +Variables controlling indentation/edit style: + + variable `verilog-indent-level' (default 3) + Indentation of Verilog statements with respect to containing block. + `verilog-indent-level-module' (default 3) + Absolute indentation of Module level Verilog statements. + Set to 0 to get initial and always statements lined up + on the left side of your screen. + `verilog-indent-level-declaration' (default 3) + Indentation of declarations with respect to containing block. + Set to 0 to get them list right under containing block. + `verilog-indent-level-behavioral' (default 3) + Indentation of first begin in a task or function block + Set to 0 to get such code to lined up underneath the task or + function keyword. + `verilog-indent-level-directive' (default 1) + Indentation of \\=`ifdef/\\=`endif blocks. + `verilog-cexp-indent' (default 1) + Indentation of Verilog statements broken across lines i.e.: + if (a) + begin + `verilog-case-indent' (default 2) + Indentation for case statements. + `verilog-auto-newline' (default nil) + Non-nil means automatically newline after semicolons and the punctuation + mark after an end. + `verilog-auto-indent-on-newline' (default t) + Non-nil means automatically indent line after newline. + `verilog-tab-always-indent' (default t) + Non-nil means TAB in Verilog mode should always reindent the current line, + regardless of where in the line point is when the TAB command is used. + `verilog-indent-begin-after-if' (default t) + Non-nil means to indent begin statements following a preceding + if, else, while, for and repeat statements, if any. Otherwise, + the begin is lined up with the preceding token. If t, you get: + if (a) + begin // amount of indent based on `verilog-cexp-indent' + otherwise you get: + if (a) + begin + `verilog-auto-endcomments' (default t) + Non-nil means a comment /* ... */ is set after the ends which ends + cases, tasks, functions and modules. + The type and name of the object will be set between the braces. + `verilog-minimum-comment-distance' (default 10) + Minimum distance (in lines) between begin and end required before a comment + will be inserted. Setting this variable to zero results in every + end acquiring a comment; the default avoids too many redundant + comments in tight quarters. + `verilog-auto-lineup' (default `declarations') + List of contexts where auto lineup of code should be done. + +Variables controlling other actions: + + `verilog-linter' (default `surelint') + Unix program to call to run the lint checker. This is the default + command for \\[compile-command] and \\[verilog-auto-save-compile]. + +See \\[customize] for the complete list of variables. + +AUTO expansion functions are, in part: + + \\[verilog-auto] Expand AUTO statements. + \\[verilog-delete-auto] Remove the AUTOs. + \\[verilog-inject-auto] Insert AUTOs for the first time. + +Some other functions are: + + \\[completion-at-point] Complete word with appropriate possibilities. + \\[verilog-mark-defun] Mark function. + \\[verilog-beg-of-defun] Move to beginning of current function. + \\[verilog-end-of-defun] Move to end of current function. + \\[verilog-label-be] Label matching begin ... end, fork ... join, etc statements. + + \\[verilog-comment-region] Put marked area in a comment. + \\[verilog-uncomment-region] Uncomment an area commented with \\[verilog-comment-region]. + \\[verilog-insert-block] Insert begin ... end. + \\[verilog-star-comment] Insert /* ... */. + + \\[verilog-sk-always] Insert an always @(AS) begin .. end block. + \\[verilog-sk-begin] Insert a begin .. end block. + \\[verilog-sk-case] Insert a case block, prompting for details. + \\[verilog-sk-for] Insert a for (...) begin .. end block, prompting for details. + \\[verilog-sk-generate] Insert a generate .. endgenerate block. + \\[verilog-sk-header] Insert a header block at the top of file. + \\[verilog-sk-initial] Insert an initial begin .. end block. + \\[verilog-sk-fork] Insert a fork begin .. end .. join block. + \\[verilog-sk-module] Insert a module .. (/*AUTOARG*/);.. endmodule block. + \\[verilog-sk-ovm-class] Insert an OVM Class block. + \\[verilog-sk-uvm-object] Insert an UVM Object block. + \\[verilog-sk-uvm-component] Insert an UVM Component block. + \\[verilog-sk-primitive] Insert a primitive .. (.. );.. endprimitive block. + \\[verilog-sk-repeat] Insert a repeat (..) begin .. end block. + \\[verilog-sk-specify] Insert a specify .. endspecify block. + \\[verilog-sk-task] Insert a task .. begin .. end endtask block. + \\[verilog-sk-while] Insert a while (...) begin .. end block, prompting for details. + \\[verilog-sk-casex] Insert a casex (...) item: begin.. end endcase block, prompting for details. + \\[verilog-sk-casez] Insert a casez (...) item: begin.. end endcase block, prompting for details. + \\[verilog-sk-if] Insert an if (..) begin .. end block. + \\[verilog-sk-else-if] Insert an else if (..) begin .. end block. + \\[verilog-sk-comment] Insert a comment block. + \\[verilog-sk-assign] Insert an assign .. = ..; statement. + \\[verilog-sk-function] Insert a function .. begin .. end endfunction block. + \\[verilog-sk-input] Insert an input declaration, prompting for details. + \\[verilog-sk-output] Insert an output declaration, prompting for details. + \\[verilog-sk-state-machine] Insert a state machine definition, prompting for details. + \\[verilog-sk-inout] Insert an inout declaration, prompting for details. + \\[verilog-sk-wire] Insert a wire declaration, prompting for details. + \\[verilog-sk-reg] Insert a register declaration, prompting for details. + \\[verilog-sk-define-signal] Define signal under point as a register at the top of the module. + +All key bindings can be seen in a Verilog-buffer with \\[describe-bindings]. +Key bindings specific to `verilog-mode-map' are: + +\\{verilog-mode-map} + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "verilog-mode" '("vl-" "verilog-" "electric-verilog-"))) + +;;;*** + +;;;### (autoloads nil "vhdl-mode" "progmodes/vhdl-mode.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from progmodes/vhdl-mode.el + +(autoload 'vhdl-mode "vhdl-mode" "\ +Major mode for editing VHDL code. + +Usage: +------ + + TEMPLATE INSERTION (electrification): + After typing a VHDL keyword and entering `SPC', you are prompted for + arguments while a template is generated for that VHDL construct. Typing + `RET' or `C-g' at the first (mandatory) prompt aborts the current + template generation. Optional arguments are indicated by square + brackets and removed if the queried string is left empty. Prompts for + mandatory arguments remain in the code if the queried string is left + empty. They can be queried again by `C-c C-t C-q'. Enabled + electrification is indicated by `/e' in the mode line. + + Typing `M-SPC' after a keyword inserts a space without calling the + template generator. Automatic template generation (i.e. + electrification) can be disabled (enabled) by typing `C-c C-m C-e' or by + setting option `vhdl-electric-mode' (see OPTIONS). + + Template generators can be invoked from the VHDL menu, by key + bindings, by typing `C-c C-i C-c' and choosing a construct, or by typing + the keyword (i.e. first word of menu entry not in parenthesis) and + `SPC'. The following abbreviations can also be used: arch, attr, cond, + conf, comp, cons, func, inst, pack, sig, var. + + Template styles can be customized in customization group + `vhdl-template' (see OPTIONS). + + + HEADER INSERTION: + A file header can be inserted by `C-c C-t C-h'. A file footer + (template at the end of the file) can be inserted by `C-c C-t C-f'. + See customization group `vhdl-header'. + + + STUTTERING: + Double striking of some keys inserts cumbersome VHDL syntax elements. + Stuttering can be disabled (enabled) by typing `C-c C-m C-s' or by + option `vhdl-stutter-mode'. Enabled stuttering is indicated by `/s' in + the mode line. The stuttering keys and their effects are: + + ;; --> \" : \" [ --> ( -- --> comment + ;;; --> \" := \" [[ --> [ --CR --> comment-out code + .. --> \" => \" ] --> ) --- --> horizontal line + ,, --> \" <= \" ]] --> ] ---- --> display comment + == --> \" == \" \\='\\=' --> \\\" + + + WORD COMPLETION: + Typing `TAB' after a (not completed) word looks for a VHDL keyword or a + word in the buffer that starts alike, inserts it and adjusts case. + Re-typing `TAB' toggles through alternative word completions. This also + works in the minibuffer (i.e. in template generator prompts). + + Typing `TAB' after `(' looks for and inserts complete parenthesized + expressions (e.g. for array index ranges). All keywords as well as + standard types and subprograms of VHDL have predefined abbreviations + (e.g., type \"std\" and `TAB' will toggle through all standard types + beginning with \"std\"). + + Typing `TAB' after a non-word character indents the line if at the + beginning of a line (i.e. no preceding non-blank characters), and + inserts a tabulator stop otherwise. `M-TAB' always inserts a tabulator + stop. + + + COMMENTS: + `--' puts a single comment. + `---' draws a horizontal line for separating code segments. + `----' inserts a display comment, i.e. two horizontal lines + with a comment in between. + `--CR' comments out code on that line. Re-hitting CR comments + out following lines. + `C-c C-c' comments out a region if not commented out, + uncomments a region if already commented out. Option + `comment-style' defines where the comment characters + should be placed (beginning of line, indent, etc.). + + You are prompted for comments after object definitions (i.e. signals, + variables, constants, ports) and after subprogram and process + specifications if option `vhdl-prompt-for-comments' is non-nil. + Comments are automatically inserted as additional labels (e.g. after + begin statements) and as help comments if `vhdl-self-insert-comments' is + non-nil. + + Inline comments (i.e. comments after a piece of code on the same line) + are indented at least to `vhdl-inline-comment-column'. Comments go at + maximum to `vhdl-end-comment-column'. `RET' after a space in a comment + will open a new comment line. Typing beyond `vhdl-end-comment-column' + in a comment automatically opens a new comment line. `M-q' re-fills + multi-line comments. + + + INDENTATION: + `TAB' indents a line if at the beginning of the line. The amount of + indentation is specified by option `vhdl-basic-offset'. `C-c C-i C-l' + always indents the current line (is bound to `TAB' if option + `vhdl-intelligent-tab' is nil). If a region is active, `TAB' indents + the entire region. + + Indentation can be done for a group of lines (`C-c C-i C-g'), a region + (`M-C-\\') or the entire buffer (menu). Argument and port lists are + indented normally (nil) or relative to the opening parenthesis (non-nil) + according to option `vhdl-argument-list-indent'. + + If option `vhdl-indent-tabs-mode' is nil, spaces are used instead of + tabs. `\\[tabify]' and `\\[untabify]' allow the conversion of spaces to + tabs and vice versa. + + Syntax-based indentation can be very slow in large files. Option + `vhdl-indent-syntax-based' allows you to use faster but simpler indentation. + + Option `vhdl-indent-comment-like-next-code-line' controls whether + comment lines are indented like the preceding or like the following code + line. + + + ALIGNMENT: + The alignment functions align operators, keywords, and inline comments + to beautify the code. `C-c C-a C-a' aligns a group of consecutive lines + separated by blank lines, `C-c C-a C-i' a block of lines with same + indent. `C-c C-a C-l' aligns all lines belonging to a list enclosed by + a pair of parentheses (e.g. port clause/map, argument list), and `C-c + C-a C-d' all lines within the declarative part of a design unit. `C-c + C-a M-a' aligns an entire region. `C-c C-a C-c' aligns inline comments + for a group of lines, and `C-c C-a M-c' for a region. + + If option `vhdl-align-groups' is non-nil, groups of code lines + separated by special lines (see option `vhdl-align-group-separate') are + aligned individually. If option `vhdl-align-same-indent' is non-nil, + blocks of lines with same indent are aligned separately. Some templates + are automatically aligned after generation if option `vhdl-auto-align' + is non-nil. + + Alignment tries to align inline comments at + `vhdl-inline-comment-column' and tries inline comment not to exceed + `vhdl-end-comment-column'. + + `C-c C-x M-w' fixes up whitespace in a region. That is, operator + symbols are surrounded by one space, and multiple spaces are eliminated. + + + CODE FILLING: + Code filling allows you to condense code (e.g. sensitivity lists or port + maps) by removing comments and newlines and re-wrapping so that all + lines are maximally filled (block filling). `C-c C-f C-f' fills a list + enclosed by parenthesis, `C-c C-f C-g' a group of lines separated by + blank lines, `C-c C-f C-i' a block of lines with same indent, and + `C-c C-f M-f' an entire region. + + + CODE BEAUTIFICATION: + `C-c M-b' and `C-c C-b' beautify the code of a region or of the entire + buffer respectively. This includes indentation, alignment, and case + fixing. Code beautification can also be run non-interactively using the + command: + + emacs -batch -l ~/.emacs filename.vhd -f vhdl-beautify-buffer + + + PORT TRANSLATION: + Generic and port clauses from entity or component declarations can be + copied (`C-c C-p C-w') and pasted as entity and component declarations, + as component instantiations and corresponding internal constants and + signals, as a generic map with constants as actual generics, and as + internal signal initializations (menu). + + To include formals in component instantiations, see option + `vhdl-association-list-with-formals'. To include comments in pasting, + see options `vhdl-include-...-comments'. + + A clause with several generic/port names on the same line can be + flattened (`C-c C-p C-f') so that only one name per line exists. The + direction of ports can be reversed (`C-c C-p C-r'), i.e., inputs become + outputs and vice versa, which can be useful in testbenches. (This + reversion is done on the internal data structure and is only reflected + in subsequent paste operations.) + + Names for actual ports, instances, testbenches, and + design-under-test instances can be derived from existing names according + to options `vhdl-...-name'. See customization group `vhdl-port'. + + + SUBPROGRAM TRANSLATION: + Similar functionality exists for copying/pasting the interface of + subprograms (function/procedure). A subprogram interface can be copied + and then pasted as a subprogram declaration, body or call (uses + association list with formals). + + + TESTBENCH GENERATION: + A copied port can also be pasted as a testbench. The generated + testbench includes an entity, an architecture, and an optional + configuration. The architecture contains the component declaration and + instantiation of the DUT as well as internal constant and signal + declarations. Additional user-defined templates can be inserted. The + names used for entity/architecture/configuration/DUT as well as the file + structure to be generated can be customized. See customization group + `vhdl-testbench'. + + + KEY BINDINGS: + Key bindings (`C-c ...') exist for most commands (see in menu). + + + VHDL MENU: + All commands can be found in the VHDL menu including their key bindings. + + + FILE BROWSER: + The speedbar allows browsing of directories and file contents. It can + be accessed from the VHDL menu and is automatically opened if option + `vhdl-speedbar-auto-open' is non-nil. + + In speedbar, open files and directories with `mouse-2' on the name and + browse/rescan their contents with `mouse-2'/`S-mouse-2' on the `+'. + + + DESIGN HIERARCHY BROWSER: + The speedbar can also be used for browsing the hierarchy of design units + contained in the source files of the current directory or the specified + projects (see option `vhdl-project-alist'). + + The speedbar can be switched between file, directory hierarchy and + project hierarchy browsing mode in the speedbar menu or by typing `f', + `h' or `H' in speedbar. + + In speedbar, open design units with `mouse-2' on the name and browse + their hierarchy with `mouse-2' on the `+'. Ports can directly be copied + from entities and components (in packages). Individual design units and + complete designs can directly be compiled (\"Make\" menu entry). + + The hierarchy is automatically updated upon saving a modified source + file when option `vhdl-speedbar-update-on-saving' is non-nil. The + hierarchy is only updated for projects that have been opened once in the + speedbar. The hierarchy is cached between Emacs sessions in a file (see + options in group `vhdl-speedbar'). + + Simple design consistency checks are done during scanning, such as + multiple declarations of the same unit or missing primary units that are + required by secondary units. + + + STRUCTURAL COMPOSITION: + Enables simple structural composition. `C-c C-m C-n' creates a skeleton + for a new component. Subcomponents (i.e. component declaration and + instantiation) can be automatically placed from a previously read port + (`C-c C-m C-p') or directly from the hierarchy browser (`P'). Finally, + all subcomponents can be automatically connected using internal signals + and ports (`C-c C-m C-w') following these rules: + - subcomponent actual ports with same name are considered to be + connected by a signal (internal signal or port) + - signals that are only inputs to subcomponents are considered as + inputs to this component -> input port created + - signals that are only outputs from subcomponents are considered as + outputs from this component -> output port created + - signals that are inputs to AND outputs from subcomponents are + considered as internal connections -> internal signal created + + Purpose: With appropriate naming conventions it is possible to + create higher design levels with only a few mouse clicks or key + strokes. A new design level can be created by simply generating a new + component, placing the required subcomponents from the hierarchy + browser, and wiring everything automatically. + + Note: Automatic wiring only works reliably on templates of new + components and component instantiations that were created by VHDL mode. + + Component declarations can be placed in a components package (option + `vhdl-use-components-package') which can be automatically generated for + an entire directory or project (`C-c C-m M-p'). The VHDL'93 direct + component instantiation is also supported (option + `vhdl-use-direct-instantiation'). + + Configuration declarations can automatically be generated either from + the menu (`C-c C-m C-f') (for the architecture the cursor is in) or from + the speedbar menu (for the architecture under the cursor). The + configurations can optionally be hierarchical (i.e. include all + component levels of a hierarchical design, option + `vhdl-compose-configuration-hierarchical') or include subconfigurations + (option `vhdl-compose-configuration-use-subconfiguration'). For + subcomponents in hierarchical configurations, the most-recently-analyzed + (mra) architecture is selected. If another architecture is desired, it + can be marked as most-recently-analyzed (speedbar menu) before + generating the configuration. + + Note: Configurations of subcomponents (i.e. hierarchical configuration + declarations) are currently not considered when displaying + configurations in speedbar. + + See the options group `vhdl-compose' for all relevant user options. + + + SOURCE FILE COMPILATION: + The syntax of the current buffer can be analyzed by calling a VHDL + compiler (menu, `C-c C-k'). The compiler to be used is specified by + option `vhdl-compiler'. The available compilers are listed in option + `vhdl-compiler-alist' including all required compilation command, + command options, compilation directory, and error message syntax + information. New compilers can be added. + + All the source files of an entire design can be compiled by the `make' + command (menu, `C-c M-C-k') if an appropriate Makefile exists. + + + MAKEFILE GENERATION: + Makefiles can be generated automatically by an internal generation + routine (`C-c M-k'). The library unit dependency information is + obtained from the hierarchy browser. Makefile generation can be + customized for each compiler in option `vhdl-compiler-alist'. + + Makefile generation can also be run non-interactively using the + command: + + emacs -batch -l ~/.emacs -l vhdl-mode + [-compiler compilername] [-project projectname] + -f vhdl-generate-makefile + + The Makefile's default target \"all\" compiles the entire design, the + target \"clean\" removes it and the target \"library\" creates the + library directory if not existent. These target names can be customized + by option `vhdl-makefile-default-targets'. The Makefile also includes a + target for each primary library unit which allows selective compilation + of this unit, its secondary units and its subhierarchy (example: + compilation of a design specified by a configuration). User specific + parts can be inserted into a Makefile with option + `vhdl-makefile-generation-hook'. + + Limitations: + - Only library units and dependencies within the current library are + considered. Makefiles for designs that span multiple libraries are + not (yet) supported. + - Only one-level configurations are supported (also hierarchical), + but configurations that go down several levels are not. + - The \"others\" keyword in configurations is not supported. + + + PROJECTS: + Projects can be defined in option `vhdl-project-alist' and a current + project be selected using option `vhdl-project' (permanently) or from + the menu or speedbar (temporarily). For each project, title and + description strings (for the file headers), source files/directories + (for the hierarchy browser and Makefile generation), library name, and + compiler-dependent options, exceptions and compilation directory can be + specified. Compilation settings overwrite the settings of option + `vhdl-compiler-alist'. + + Project setups can be exported (i.e. written to a file) and imported. + Imported setups are not automatically saved in `vhdl-project-alist' but + can be saved afterwards in its customization buffer. When starting + Emacs with VHDL Mode (i.e. load a VHDL file or use \"emacs -l + vhdl-mode\") in a directory with an existing project setup file, it is + automatically loaded and its project activated if option + `vhdl-project-auto-load' is non-nil. Names/paths of the project setup + files can be specified in option `vhdl-project-file-name'. Multiple + project setups can be automatically loaded from global directories. + This is an alternative to specifying project setups with option + `vhdl-project-alist'. + + + SPECIAL MENUES: + As an alternative to the speedbar, an index menu can be added (set + option `vhdl-index-menu' to non-nil) or made accessible as a mouse menu + (e.g. add \"(global-set-key [S-down-mouse-3] \\='imenu)\" to your start-up + file) for browsing the file contents (is not populated if buffer is + larger than 256000). Also, a source file menu can be + added (set option `vhdl-source-file-menu' to non-nil) for browsing the + current directory for VHDL source files. + + + VHDL STANDARDS: + The VHDL standards to be used are specified in option `vhdl-standard'. + Available standards are: VHDL'87/'93(02)/'08, VHDL-AMS, and Math Packages. + + + KEYWORD CASE: + Lower and upper case for keywords and standardized types, attributes, + and enumeration values is supported. If the option + `vhdl-upper-case-keywords' is set to non-nil, keywords can be typed in + lower case and are converted into upper case automatically (not for + types, attributes, and enumeration values). The case of keywords, + types, attributes,and enumeration values can be fixed for an entire + region (menu) or buffer (`C-c C-x C-c') according to the options + `vhdl-upper-case-{keywords,types,attributes,enum-values}'. + + + HIGHLIGHTING (fontification): + Keywords and standardized types, attributes, enumeration values, and + function names (controlled by option `vhdl-highlight-keywords'), as well + as comments, strings, and template prompts are highlighted using + different colors. Unit, subprogram, signal, variable, constant, + parameter and generic/port names in declarations as well as labels are + highlighted if option `vhdl-highlight-names' is non-nil. + + Additional reserved words or words with a forbidden syntax (e.g. words + that should be avoided) can be specified in option + `vhdl-forbidden-words' or `vhdl-forbidden-syntax' and be highlighted in + a warning color (option `vhdl-highlight-forbidden-words'). Verilog + keywords are highlighted as forbidden words if option + `vhdl-highlight-verilog-keywords' is non-nil. + + Words with special syntax can be highlighted by specifying their + syntax and color in option `vhdl-special-syntax-alist' and by setting + option `vhdl-highlight-special-words' to non-nil. This allows you to + establish some naming conventions (e.g. to distinguish different kinds + of signals or other objects by using name suffices) and to support them + visually. + + Option `vhdl-highlight-case-sensitive' can be set to non-nil in order + to support case-sensitive highlighting. However, keywords are then only + highlighted if written in lower case. + + Code between \"translate_off\" and \"translate_on\" pragmas is + highlighted using a different background color if option + `vhdl-highlight-translate-off' is non-nil. + + For documentation and customization of the used colors see + customization group `vhdl-highlight-faces' (`\\[customize-group]'). For + highlighting of matching parenthesis, see customization group + `paren-showing'. Automatic buffer highlighting is turned on/off by + option `global-font-lock-mode' (`font-lock-auto-fontify' in XEmacs). + + + USER MODELS: + VHDL models (templates) can be specified by the user and made accessible + in the menu, through key bindings (`C-c C-m ...'), or by keyword + electrification. See option `vhdl-model-alist'. + + + HIDE/SHOW: + The code of blocks, processes, subprograms, component declarations and + instantiations, generic/port clauses, and configuration declarations can + be hidden using the `Hide/Show' menu or by pressing `S-mouse-2' within + the code (see customization group `vhdl-menu'). XEmacs: limited + functionality due to old `hideshow.el' package. + + + CODE UPDATING: + - Sensitivity List: `C-c C-u C-s' updates the sensitivity list of the + current process, `C-c C-u M-s' of all processes in the current buffer. + Limitations: + - Only declared local signals (ports, signals declared in + architecture and blocks) are automatically inserted. + - Global signals declared in packages are not automatically inserted. + Insert them once manually (will be kept afterwards). + - Out parameters of procedures are considered to be read. + Use option `vhdl-entity-file-name' to specify the entity file name + (used to obtain the port names). + Use option `vhdl-array-index-record-field-in-sensitivity-list' to + specify whether to include array indices and record fields in + sensitivity lists. + + + CODE FIXING: + `C-c C-x C-p' fixes the closing parenthesis of a generic/port clause + (e.g., if the closing parenthesis is on the wrong line or is missing). + + + PRINTING: + PostScript printing with different faces (an optimized set of faces is + used if `vhdl-print-customize-faces' is non-nil) or colors (if + `ps-print-color-p' is non-nil) is possible using the standard Emacs + PostScript printing commands. Option `vhdl-print-two-column' defines + appropriate default settings for nice landscape two-column printing. + The paper format can be set by option `ps-paper-type'. Do not forget to + switch `ps-print-color-p' to nil for printing on black-and-white + printers. + + + OPTIONS: + User options allow customization of VHDL Mode. All options are + accessible from the \"Options\" menu entry. Simple options (switches + and choices) can directly be changed, while for complex options a + customization buffer is opened. Changed options can be saved for future + sessions using the \"Save Options\" menu entry. + + Options and their detailed descriptions can also be accessed by using + the \"Customize\" menu entry or the command `\\[customize-option]' + (`\\[customize-group]' for groups). Some customizations only take effect + after some action (read the NOTE in the option documentation). + Customization can also be done globally (i.e. site-wide, read the + INSTALL file). + + Not all options are described in this documentation, so go and see + what other useful user options there are (`\\[vhdl-customize]' or menu)! + + + FILE EXTENSIONS: + As default, files with extensions \".vhd\" and \".vhdl\" are + automatically recognized as VHDL source files. To add an extension + \".xxx\", add the following line to your Emacs start-up file (`.emacs'): + + (push \\='(\"\\\\.xxx\\\\\\='\" . vhdl-mode) auto-mode-alist) + + + HINTS: + - To start Emacs with open VHDL hierarchy browser without having to load + a VHDL file first, use the command: + + emacs -l vhdl-mode -f speedbar-frame-mode + + - Type `C-g C-g' to interrupt long operations or if Emacs hangs. + + - Some features only work on properly indented code. + + + RELEASE NOTES: + See also the release notes (menu) for added features in new releases. + + +Maintenance: +------------ + +To submit a bug report, enter `\\[vhdl-submit-bug-report]' within VHDL Mode. +Add a description of the problem and include a reproducible test case. + +Questions and enhancement requests can be sent to . + +The `vhdl-mode-announce' mailing list informs about new VHDL Mode releases. +The `vhdl-mode-victims' mailing list informs about new VHDL Mode beta +releases. You are kindly invited to participate in beta testing. Subscribe +to above mailing lists by sending an email to . + +VHDL Mode is officially distributed at +http://www.iis.ee.ethz.ch/~zimmi/emacs/vhdl-mode.html +where the latest version can be found. + + +Known problems: +--------------- + +- XEmacs: Incorrect start-up when automatically opening speedbar. +- XEmacs: Indentation in XEmacs 21.4 (and higher). +- Indentation incorrect for new 'postponed' VHDL keyword. +- Indentation incorrect for 'protected body' construct. + + + The VHDL Mode Authors + Reto Zimmermann and Rod Whitby + +Key bindings: +------------- + +\\{vhdl-mode-map} + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vhdl-mode" '("vhdl-"))) + +;;;*** + +;;;### (autoloads nil "viet-util" "language/viet-util.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from language/viet-util.el + +(autoload 'viet-encode-viscii-char "viet-util" "\ +Return VISCII character code of CHAR if appropriate. + +\(fn CHAR)" nil nil) + +(autoload 'viet-decode-viqr-region "viet-util" "\ +Convert `VIQR' mnemonics of the current region to Vietnamese characters. +When called from a program, expects two arguments, +positions (integers or markers) specifying the stretch of the region. + +\(fn FROM TO)" t nil) + +(autoload 'viet-decode-viqr-buffer "viet-util" "\ +Convert `VIQR' mnemonics of the current buffer to Vietnamese characters. + +\(fn)" t nil) + +(autoload 'viet-encode-viqr-region "viet-util" "\ +Convert Vietnamese characters of the current region to `VIQR' mnemonics. +When called from a program, expects two arguments, +positions (integers or markers) specifying the stretch of the region. + +\(fn FROM TO)" t nil) + +(autoload 'viet-encode-viqr-buffer "viet-util" "\ +Convert Vietnamese characters of the current buffer to `VIQR' mnemonics. + +\(fn)" t nil) + +(autoload 'viqr-post-read-conversion "viet-util" "\ + + +\(fn LEN)" nil nil) + +(autoload 'viqr-pre-write-conversion "viet-util" "\ + + +\(fn FROM TO)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "viet-util" '("viet-viqr-alist" "viqr-regexp"))) + +;;;*** + +;;;### (autoloads nil "view" "view.el" (0 0 0 0)) +;;; Generated autoloads from view.el + +(defvar view-remove-frame-by-deleting t "\ +Determine how View mode removes a frame no longer needed. +If nil, make an icon of the frame. If non-nil, delete the frame.") + +(custom-autoload 'view-remove-frame-by-deleting "view" t) + +(defvar view-mode nil "\ +Non-nil if View mode is enabled. +Don't change this variable directly, you must change it by one of the +functions that enable or disable view mode.") + +(make-variable-buffer-local 'view-mode) + +(autoload 'kill-buffer-if-not-modified "view" "\ +Like `kill-buffer', but does nothing if the buffer is modified. + +\(fn BUF)" nil nil) + +(autoload 'view-file "view" "\ +View FILE in View mode, returning to previous buffer when done. +Emacs commands editing the buffer contents are not available; instead, a +special set of commands (mostly letters and punctuation) are defined for +moving around in the buffer. +Space scrolls forward, Delete scrolls backward. +For a list of all View commands, type H or h while viewing. + +This command runs the normal hook `view-mode-hook'. + +\(fn FILE)" t nil) + +(autoload 'view-file-other-window "view" "\ +View FILE in View mode in another window. +When done, return that window to its previous buffer, and kill the +buffer visiting FILE if unmodified and if it wasn't visited before. + +Emacs commands editing the buffer contents are not available; instead, +a special set of commands (mostly letters and punctuation) +are defined for moving around in the buffer. +Space scrolls forward, Delete scrolls backward. +For a list of all View commands, type H or h while viewing. + +This command runs the normal hook `view-mode-hook'. + +\(fn FILE)" t nil) + +(autoload 'view-file-other-frame "view" "\ +View FILE in View mode in another frame. +When done, kill the buffer visiting FILE if unmodified and if it wasn't +visited before; also, maybe delete other frame and/or return to previous +buffer. + +Emacs commands editing the buffer contents are not available; instead, +a special set of commands (mostly letters and punctuation) +are defined for moving around in the buffer. +Space scrolls forward, Delete scrolls backward. +For a list of all View commands, type H or h while viewing. + +This command runs the normal hook `view-mode-hook'. + +\(fn FILE)" t nil) + +(autoload 'view-buffer "view" "\ +View BUFFER in View mode, returning to previous buffer when done. +Emacs commands editing the buffer contents are not available; instead, a +special set of commands (mostly letters and punctuation) are defined for +moving around in the buffer. +Space scrolls forward, Delete scrolls backward. +For a list of all View commands, type H or h while viewing. + +This command runs the normal hook `view-mode-hook'. + +Optional argument EXIT-ACTION is either nil or a function with buffer as +argument. This function is called when finished viewing buffer. Use +this argument instead of explicitly setting `view-exit-action'. + +Do not set EXIT-ACTION to `kill-buffer' when BUFFER visits a +file: Users may suspend viewing in order to modify the buffer. +Exiting View mode will then discard the user's edits. Setting +EXIT-ACTION to `kill-buffer-if-not-modified' avoids this. + +This function does not enable View mode if the buffer's major-mode +has a `special' mode-class, because such modes usually have their +own View-like bindings. + +\(fn BUFFER &optional EXIT-ACTION)" t nil) + +(autoload 'view-buffer-other-window "view" "\ +View BUFFER in View mode in another window. +Emacs commands editing the buffer contents are not available; +instead, a special set of commands (mostly letters and +punctuation) are defined for moving around in the buffer. +Space scrolls forward, Delete scrolls backward. +For a list of all View commands, type H or h while viewing. + +This command runs the normal hook `view-mode-hook'. + +Optional argument NOT-RETURN is ignored. + +Optional argument EXIT-ACTION is either nil or a function with buffer as +argument. This function is called when finished viewing buffer. Use +this argument instead of explicitly setting `view-exit-action'. + +This function does not enable View mode if the buffer's major-mode +has a `special' mode-class, because such modes usually have their +own View-like bindings. + +\(fn BUFFER &optional NOT-RETURN EXIT-ACTION)" t nil) + +(autoload 'view-buffer-other-frame "view" "\ +View BUFFER in View mode in another frame. +Emacs commands editing the buffer contents are not available; +instead, a special set of commands (mostly letters and +punctuation) are defined for moving around in the buffer. +Space scrolls forward, Delete scrolls backward. +For a list of all View commands, type H or h while viewing. + +This command runs the normal hook `view-mode-hook'. + +Optional argument NOT-RETURN is ignored. + +Optional argument EXIT-ACTION is either nil or a function with buffer as +argument. This function is called when finished viewing buffer. Use +this argument instead of explicitly setting `view-exit-action'. + +This function does not enable View mode if the buffer's major-mode +has a `special' mode-class, because such modes usually have their +own View-like bindings. + +\(fn BUFFER &optional NOT-RETURN EXIT-ACTION)" t nil) + +(autoload 'view-mode "view" "\ +Toggle View mode, a minor mode for viewing text but not editing it. +With a prefix argument ARG, enable View mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable View mode +if ARG is omitted or nil. + +When View mode is enabled, commands that do not change the buffer +contents are available as usual. Kill commands insert text in +kill buffers but do not delete. Most other commands beep and +tell the user that the buffer is read-only. + +\\ + +The following additional commands are provided. Most commands +take prefix arguments. Page commands default to \"page size\" +lines which is almost a whole window, or number of lines set by +\\[View-scroll-page-forward-set-page-size] or \\[View-scroll-page-backward-set-page-size]. +Half page commands default to and set \"half page size\" lines +which initially is half a window full. Search commands default +to a repeat count of one. + +H, h, ? This message. +Digits provide prefix arguments. +\\[negative-argument] negative prefix argument. +\\[beginning-of-buffer] move to the beginning of buffer. +> move to the end of buffer. +\\[View-scroll-to-buffer-end] scroll so that buffer end is at last line of window. +SPC scroll forward \"page size\" lines. + With prefix scroll forward prefix lines. +DEL, S-SPC scroll backward \"page size\" lines. + With prefix scroll backward prefix lines. +\\[View-scroll-page-forward-set-page-size] like \\[View-scroll-page-forward] but with prefix sets \"page size\" to prefix. +\\[View-scroll-page-backward-set-page-size] like \\[View-scroll-page-backward] but with prefix sets \"page size\" to prefix. +\\[View-scroll-half-page-forward] scroll forward \"half page size\" lines. With prefix, sets + \"half page size\" to prefix lines and scrolls forward that much. +\\[View-scroll-half-page-backward] scroll backward \"half page size\" lines. With prefix, sets + \"half page size\" to prefix lines and scrolls backward that much. +RET, LFD scroll forward one line. With prefix scroll forward prefix line(s). +y scroll backward one line. With prefix scroll backward prefix line(s). +\\[View-revert-buffer-scroll-page-forward] revert-buffer if necessary and scroll forward. + Use this to view a changing file. +\\[what-line] prints the current line number. +\\[View-goto-percent] goes prefix argument (default 100) percent into buffer. +\\[View-goto-line] goes to line given by prefix argument (default first line). +. set the mark. +x exchanges point and mark. +\\[View-back-to-mark] return to mark and pops mark ring. + Mark ring is pushed at start of every successful search and when + jump to line occurs. The mark is set on jump to buffer start or end. +\\[point-to-register] save current position in character register. +\\=' go to position saved in character register. +s do forward incremental search. +r do reverse incremental search. +\\[View-search-regexp-forward] searches forward for regular expression, starting after current page. + ! and @ have a special meaning at the beginning of the regexp. + ! means search for a line with no match for regexp. @ means start + search at beginning (end for backward search) of buffer. +\\ searches backward for regular expression, starting before current page. +\\[View-search-last-regexp-forward] searches forward for last regular expression. +p searches backward for last regular expression. +\\[View-quit] quit View mode, restoring this window and buffer to previous state. + \\[View-quit] is the normal way to leave view mode. +\\[View-exit] exit View mode but stay in current buffer. Use this if you started + viewing a buffer (file) and find out you want to edit it. + This command restores the previous read-only status of the buffer. +\\[View-exit-and-edit] exit View mode, and make the current buffer editable + even if it was not editable before entry to View mode. +\\[View-quit-all] quit View mode, restoring all windows to previous state. +\\[View-leave] quit View mode and maybe switch buffers, but don't kill this buffer. +\\[View-kill-and-leave] quit View mode, kill current buffer and go back to other buffer. + +The effect of \\[View-leave], \\[View-quit] and \\[View-kill-and-leave] depends on how view-mode was entered. If it was +entered by view-file, view-file-other-window, view-file-other-frame, or +\\[dired-view-file] (\\[view-file], \\[view-file-other-window], +\\[view-file-other-frame], or the Dired mode v command), +then \\[View-quit] will try to kill the current buffer. +If view-mode was entered from another buffer, by \\[view-buffer], +\\[view-buffer-other-window], \\[view-buffer-other frame], \\[view-file], +\\[view-file-other-window], or \\[view-file-other-frame], +then \\[View-leave], \\[View-quit] and \\[View-kill-and-leave] will return to that buffer. + +Entry to view-mode runs the normal hook `view-mode-hook'. + +\(fn &optional ARG)" t nil) + +(autoload 'view-return-to-alist-update "view" "\ +Update `view-return-to-alist' of buffer BUFFER. +Remove from `view-return-to-alist' all entries referencing dead +windows. Optional argument ITEM non-nil means add ITEM to +`view-return-to-alist' after purging. For a description of items +that can be added see the RETURN-TO-ALIST argument of the +function `view-mode-exit'. If `view-return-to-alist' contains an +entry for the selected window, purge that entry from +`view-return-to-alist' before adding ITEM. + +\(fn BUFFER &optional ITEM)" nil nil) + +(make-obsolete 'view-return-to-alist-update '"this function has no effect." '"24.1") + +(autoload 'view-mode-enter "view" "\ +Enter View mode and set up exit from view mode depending on optional arguments. +Optional argument QUIT-RESTORE if non-nil must specify a valid +entry for quitting and restoring any window showing the current +buffer. This entry replaces any parameter installed by +`display-buffer' and is used by `view-mode-exit'. + +Optional argument EXIT-ACTION, if non-nil, must specify a +function that takes a buffer as argument. This function will be +called by `view-mode-exit'. + +For a list of all View commands, type H or h while viewing. + +This function runs the normal hook `view-mode-hook'. + +\(fn &optional QUIT-RESTORE EXIT-ACTION)" nil nil) + +(autoload 'View-exit-and-edit "view" "\ +Exit View mode and make the current buffer editable. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "view" '("view-" "View-"))) + +;;;*** + +;;;### (autoloads nil "viper" "emulation/viper.el" (0 0 0 0)) +;;; Generated autoloads from emulation/viper.el +(push (purecopy '(viper 3 14 1)) package--builtin-versions) + +(autoload 'toggle-viper-mode "viper" "\ +Toggle Viper on/off. +If Viper is enabled, turn it off. Otherwise, turn it on. + +\(fn)" t nil) + +(autoload 'viper-mode "viper" "\ +Turn on Viper emulation of Vi in Emacs. See Info node `(viper)Top'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "viper" '("viper-" "set-viper-state-in-major-mode" "this-major-mode-requires-vi-state"))) + +;;;*** + +;;;### (autoloads nil "viper-cmd" "emulation/viper-cmd.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from emulation/viper-cmd.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "viper-cmd" '("viper-"))) + +;;;*** + +;;;### (autoloads nil "viper-ex" "emulation/viper-ex.el" (0 0 0 0)) +;;; Generated autoloads from emulation/viper-ex.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "viper-ex" '("ex-" "viper-"))) + +;;;*** + +;;;### (autoloads nil "viper-init" "emulation/viper-init.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from emulation/viper-init.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "viper-init" '("viper-"))) + +;;;*** + +;;;### (autoloads nil "viper-keym" "emulation/viper-keym.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from emulation/viper-keym.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "viper-keym" '("viper-" "ex-read-filename-map"))) + +;;;*** + +;;;### (autoloads nil "viper-macs" "emulation/viper-macs.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from emulation/viper-macs.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "viper-macs" '("viper-" "ex-"))) + +;;;*** + +;;;### (autoloads nil "viper-mous" "emulation/viper-mous.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from emulation/viper-mous.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "viper-mous" '("viper-"))) + +;;;*** + +;;;### (autoloads nil "viper-util" "emulation/viper-util.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from emulation/viper-util.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "viper-util" '("viper"))) + +;;;*** + +;;;### (autoloads nil "vt-control" "vt-control.el" (0 0 0 0)) +;;; Generated autoloads from vt-control.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vt-control" '("vt-"))) + +;;;*** + +;;;### (autoloads nil "vt100-led" "vt100-led.el" (0 0 0 0)) +;;; Generated autoloads from vt100-led.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "vt100-led" '("led-"))) + +;;;*** + +;;;### (autoloads nil "w32-fns" "w32-fns.el" (0 0 0 0)) +;;; Generated autoloads from w32-fns.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "w32-fns" '("w32-"))) + +;;;*** + +;;;### (autoloads nil "w32-vars" "w32-vars.el" (0 0 0 0)) +;;; Generated autoloads from w32-vars.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "w32-vars" '("w32-"))) + +;;;*** + +;;;### (autoloads nil "warnings" "emacs-lisp/warnings.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from emacs-lisp/warnings.el + +(defvar warning-prefix-function nil "\ +Function to generate warning prefixes. +This function, if non-nil, is called with two arguments, +the severity level and its entry in `warning-levels', +and should return the entry that should actually be used. +The warnings buffer is current when this function is called +and the function can insert text in it. This text becomes +the beginning of the warning.") + +(defvar warning-series nil "\ +Non-nil means treat multiple `display-warning' calls as a series. +A marker indicates a position in the warnings buffer +which is the start of the current series; it means that +additional warnings in the same buffer should not move point. +If t, the next warning begins a series (and stores a marker here). +A symbol with a function definition is like t, except +also call that function before the next warning.") + +(defvar warning-fill-prefix nil "\ +Non-nil means fill each warning text using this string as `fill-prefix'.") + +(defvar warning-type-format (purecopy " (%s)") "\ +Format for displaying the warning type in the warning message. +The result of formatting the type this way gets included in the +message under the control of the string in `warning-levels'.") + +(autoload 'display-warning "warnings" "\ +Display a warning message, MESSAGE. +TYPE is the warning type: either a custom group name (a symbol), +or a list of symbols whose first element is a custom group name. +\(The rest of the symbols represent subcategories, for warning purposes +only, and you can use whatever symbols you like.) + +LEVEL should be either :debug, :warning, :error, or :emergency +\(but see `warning-minimum-level' and `warning-minimum-log-level'). +Default is :warning. + +:emergency -- a problem that will seriously impair Emacs operation soon + if you do not attend to it promptly. +:error -- data or circumstances that are inherently wrong. +:warning -- data or circumstances that are not inherently wrong, + but raise suspicion of a possible problem. +:debug -- info for debugging only. + +BUFFER-NAME, if specified, is the name of the buffer for logging +the warning. By default, it is `*Warnings*'. If this function +has to create the buffer, it disables undo in the buffer. + +See the `warnings' custom group for user customization features. + +See also `warning-series', `warning-prefix-function' and +`warning-fill-prefix' for additional programming features. + +\(fn TYPE MESSAGE &optional LEVEL BUFFER-NAME)" nil nil) + +(autoload 'lwarn "warnings" "\ +Display a warning message made from (format-message MESSAGE ARGS...). +\\ +Aside from generating the message with `format-message', +this is equivalent to `display-warning'. + +TYPE is the warning type: either a custom group name (a symbol), +or a list of symbols whose first element is a custom group name. +\(The rest of the symbols represent subcategories and +can be whatever you like.) + +LEVEL should be either :debug, :warning, :error, or :emergency +\(but see `warning-minimum-level' and `warning-minimum-log-level'). + +:emergency -- a problem that will seriously impair Emacs operation soon + if you do not attend to it promptly. +:error -- invalid data or circumstances. +:warning -- suspicious data or circumstances. +:debug -- info for debugging only. + +\(fn TYPE LEVEL MESSAGE &rest ARGS)" nil nil) + +(autoload 'warn "warnings" "\ +Display a warning message made from (format-message MESSAGE ARGS...). +Aside from generating the message with `format-message', +this is equivalent to `display-warning', using +`emacs' as the type and `:warning' as the level. + +\(fn MESSAGE &rest ARGS)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "warnings" '("warning-" "log-warning-minimum-level" "display-warning-minimum-level"))) + +;;;*** + +;;;### (autoloads nil "wdired" "wdired.el" (0 0 0 0)) +;;; Generated autoloads from wdired.el +(push (purecopy '(wdired 2 0)) package--builtin-versions) + +(autoload 'wdired-change-to-wdired-mode "wdired" "\ +Put a Dired buffer in Writable Dired (WDired) mode. +\\ +In WDired mode, you can edit the names of the files in the +buffer, the target of the links, and the permission bits of the +files. After typing \\[wdired-finish-edit], Emacs modifies the files and +directories to reflect your edits. + +See `wdired-mode'. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "wdired" '("wdired-"))) + +;;;*** + +;;;### (autoloads nil "webjump" "net/webjump.el" (0 0 0 0)) +;;; Generated autoloads from net/webjump.el + +(autoload 'webjump "webjump" "\ +Jumps to a Web site from a programmable hotlist. + +See the documentation for the `webjump-sites' variable for how to customize the +hotlist. + +Please submit bug reports and other feedback to the author, Neil W. Van Dyke +. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "webjump" '("webjump-"))) + +;;;*** + +;;;### (autoloads nil "which-func" "progmodes/which-func.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from progmodes/which-func.el + (put 'which-func-format 'risky-local-variable t) + (put 'which-func-current 'risky-local-variable t) + +(define-obsolete-function-alias 'which-func-mode 'which-function-mode "24.1") + +(defvar which-function-mode nil "\ +Non-nil if Which-Function mode is enabled. +See the `which-function-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `which-function-mode'.") + +(custom-autoload 'which-function-mode "which-func" nil) + +(autoload 'which-function-mode "which-func" "\ +Toggle mode line display of current function (Which Function mode). +With a prefix argument ARG, enable Which Function mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Which Function mode is a global minor mode. When enabled, the +current function name is continuously displayed in the mode line, +in certain major modes. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "which-func" '("which-func"))) + +;;;*** + +;;;### (autoloads nil "whitespace" "whitespace.el" (0 0 0 0)) +;;; Generated autoloads from whitespace.el +(push (purecopy '(whitespace 13 2 2)) package--builtin-versions) + +(autoload 'whitespace-mode "whitespace" "\ +Toggle whitespace visualization (Whitespace mode). +With a prefix argument ARG, enable Whitespace mode if ARG is +positive, and disable it otherwise. + +If called from Lisp, also enables the mode if ARG is omitted or nil, +and toggles it if ARG is `toggle'. + +See also `whitespace-style', `whitespace-newline' and +`whitespace-display-mappings'. + +\(fn &optional ARG)" t nil) + +(autoload 'whitespace-newline-mode "whitespace" "\ +Toggle newline visualization (Whitespace Newline mode). +With a prefix argument ARG, enable Whitespace Newline mode if ARG +is positive, and disable it otherwise. + +If called from Lisp, also enables the mode if ARG is omitted or nil, +and toggles it if ARG is `toggle'. + +Use `whitespace-newline-mode' only for NEWLINE visualization +exclusively. For other visualizations, including NEWLINE +visualization together with (HARD) SPACEs and/or TABs, please, +use `whitespace-mode'. + +See also `whitespace-newline' and `whitespace-display-mappings'. + +\(fn &optional ARG)" t nil) + +(defvar global-whitespace-mode nil "\ +Non-nil if Global Whitespace mode is enabled. +See the `global-whitespace-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `global-whitespace-mode'.") + +(custom-autoload 'global-whitespace-mode "whitespace" nil) + +(autoload 'global-whitespace-mode "whitespace" "\ +Toggle whitespace visualization globally (Global Whitespace mode). +With a prefix argument ARG, enable Global Whitespace mode if ARG +is positive, and disable it otherwise. + +If called from Lisp, also enables the mode if ARG is omitted or nil, +and toggles it if ARG is `toggle'. + +See also `whitespace-style', `whitespace-newline' and +`whitespace-display-mappings'. + +\(fn &optional ARG)" t nil) + +(defvar global-whitespace-newline-mode nil "\ +Non-nil if Global Whitespace-Newline mode is enabled. +See the `global-whitespace-newline-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `global-whitespace-newline-mode'.") + +(custom-autoload 'global-whitespace-newline-mode "whitespace" nil) + +(autoload 'global-whitespace-newline-mode "whitespace" "\ +Toggle global newline visualization (Global Whitespace Newline mode). +With a prefix argument ARG, enable Global Whitespace Newline mode +if ARG is positive, and disable it otherwise. + +If called from Lisp, also enables the mode if ARG is omitted or nil, +and toggles it if ARG is `toggle'. + +Use `global-whitespace-newline-mode' only for NEWLINE +visualization exclusively. For other visualizations, including +NEWLINE visualization together with (HARD) SPACEs and/or TABs, +please use `global-whitespace-mode'. + +See also `whitespace-newline' and `whitespace-display-mappings'. + +\(fn &optional ARG)" t nil) + +(autoload 'whitespace-toggle-options "whitespace" "\ +Toggle local `whitespace-mode' options. + +If local whitespace-mode is off, toggle the option given by ARG +and turn on local whitespace-mode. + +If local whitespace-mode is on, toggle the option given by ARG +and restart local whitespace-mode. + +Interactively, it reads one of the following chars: + + CHAR MEANING + (VIA FACES) + f toggle face visualization + t toggle TAB visualization + s toggle SPACE and HARD SPACE visualization + r toggle trailing blanks visualization + l toggle \"long lines\" visualization + L toggle \"long lines\" tail visualization + n toggle NEWLINE visualization + e toggle empty line at bob and/or eob visualization + C-i toggle indentation SPACEs visualization (via `indent-tabs-mode') + I toggle indentation SPACEs visualization + i toggle indentation TABs visualization + C-t toggle big indentation visualization + C-a toggle SPACEs after TAB visualization (via `indent-tabs-mode') + A toggle SPACEs after TAB: SPACEs visualization + a toggle SPACEs after TAB: TABs visualization + C-b toggle SPACEs before TAB visualization (via `indent-tabs-mode') + B toggle SPACEs before TAB: SPACEs visualization + b toggle SPACEs before TAB: TABs visualization + + (VIA DISPLAY TABLE) + T toggle TAB visualization + S toggle SPACEs before TAB visualization + N toggle NEWLINE visualization + + x restore `whitespace-style' value + ? display brief help + +Non-interactively, ARG should be a symbol or a list of symbols. +The valid symbols are: + + face toggle face visualization + tabs toggle TAB visualization + spaces toggle SPACE and HARD SPACE visualization + trailing toggle trailing blanks visualization + lines toggle \"long lines\" visualization + lines-tail toggle \"long lines\" tail visualization + newline toggle NEWLINE visualization + empty toggle empty line at bob and/or eob visualization + indentation toggle indentation SPACEs visualization + indentation::tab toggle indentation SPACEs visualization + indentation::space toggle indentation TABs visualization + big-indent toggle big indentation visualization + space-after-tab toggle SPACEs after TAB visualization + space-after-tab::tab toggle SPACEs after TAB: SPACEs visualization + space-after-tab::space toggle SPACEs after TAB: TABs visualization + space-before-tab toggle SPACEs before TAB visualization + space-before-tab::tab toggle SPACEs before TAB: SPACEs visualization + space-before-tab::space toggle SPACEs before TAB: TABs visualization + + tab-mark toggle TAB visualization + space-mark toggle SPACEs before TAB visualization + newline-mark toggle NEWLINE visualization + + whitespace-style restore `whitespace-style' value + +See `whitespace-style' and `indent-tabs-mode' for documentation. + +\(fn ARG)" t nil) + +(autoload 'global-whitespace-toggle-options "whitespace" "\ +Toggle global `whitespace-mode' options. + +If global whitespace-mode is off, toggle the option given by ARG +and turn on global whitespace-mode. + +If global whitespace-mode is on, toggle the option given by ARG +and restart global whitespace-mode. + +Interactively, it accepts one of the following chars: + + CHAR MEANING + (VIA FACES) + f toggle face visualization + t toggle TAB visualization + s toggle SPACE and HARD SPACE visualization + r toggle trailing blanks visualization + l toggle \"long lines\" visualization + L toggle \"long lines\" tail visualization + n toggle NEWLINE visualization + e toggle empty line at bob and/or eob visualization + C-i toggle indentation SPACEs visualization (via `indent-tabs-mode') + I toggle indentation SPACEs visualization + i toggle indentation TABs visualization + C-t toggle big indentation visualization + C-a toggle SPACEs after TAB visualization (via `indent-tabs-mode') + A toggle SPACEs after TAB: SPACEs visualization + a toggle SPACEs after TAB: TABs visualization + C-b toggle SPACEs before TAB visualization (via `indent-tabs-mode') + B toggle SPACEs before TAB: SPACEs visualization + b toggle SPACEs before TAB: TABs visualization + + (VIA DISPLAY TABLE) + T toggle TAB visualization + S toggle SPACEs before TAB visualization + N toggle NEWLINE visualization + + x restore `whitespace-style' value + ? display brief help + +Non-interactively, ARG should be a symbol or a list of symbols. +The valid symbols are: + + face toggle face visualization + tabs toggle TAB visualization + spaces toggle SPACE and HARD SPACE visualization + trailing toggle trailing blanks visualization + lines toggle \"long lines\" visualization + lines-tail toggle \"long lines\" tail visualization + newline toggle NEWLINE visualization + empty toggle empty line at bob and/or eob visualization + indentation toggle indentation SPACEs visualization + indentation::tab toggle indentation SPACEs visualization + indentation::space toggle indentation TABs visualization + big-indent toggle big indentation visualization + space-after-tab toggle SPACEs after TAB visualization + space-after-tab::tab toggle SPACEs after TAB: SPACEs visualization + space-after-tab::space toggle SPACEs after TAB: TABs visualization + space-before-tab toggle SPACEs before TAB visualization + space-before-tab::tab toggle SPACEs before TAB: SPACEs visualization + space-before-tab::space toggle SPACEs before TAB: TABs visualization + + tab-mark toggle TAB visualization + space-mark toggle SPACEs before TAB visualization + newline-mark toggle NEWLINE visualization + + whitespace-style restore `whitespace-style' value + +See `whitespace-style' and `indent-tabs-mode' for documentation. + +\(fn ARG)" t nil) + +(autoload 'whitespace-cleanup "whitespace" "\ +Cleanup some blank problems in all buffer or at region. + +It usually applies to the whole buffer, but in transient mark +mode when the mark is active, it applies to the region. It also +applies to the region when it is not in transient mark mode, the +mark is active and \\[universal-argument] was pressed just before +calling `whitespace-cleanup' interactively. + +See also `whitespace-cleanup-region'. + +The problems cleaned up are: + +1. empty lines at beginning of buffer. +2. empty lines at end of buffer. + If `whitespace-style' includes the value `empty', remove all + empty lines at beginning and/or end of buffer. + +3. `tab-width' or more SPACEs at beginning of line. + If `whitespace-style' includes the value `indentation': + replace `tab-width' or more SPACEs at beginning of line by + TABs, if `indent-tabs-mode' is non-nil; otherwise, replace TABs by + SPACEs. + If `whitespace-style' includes the value `indentation::tab', + replace `tab-width' or more SPACEs at beginning of line by TABs. + If `whitespace-style' includes the value `indentation::space', + replace TABs by SPACEs. + +4. SPACEs before TAB. + If `whitespace-style' includes the value `space-before-tab': + replace SPACEs by TABs, if `indent-tabs-mode' is non-nil; + otherwise, replace TABs by SPACEs. + If `whitespace-style' includes the value + `space-before-tab::tab', replace SPACEs by TABs. + If `whitespace-style' includes the value + `space-before-tab::space', replace TABs by SPACEs. + +5. SPACEs or TABs at end of line. + If `whitespace-style' includes the value `trailing', remove + all SPACEs or TABs at end of line. + +6. `tab-width' or more SPACEs after TAB. + If `whitespace-style' includes the value `space-after-tab': + replace SPACEs by TABs, if `indent-tabs-mode' is non-nil; + otherwise, replace TABs by SPACEs. + If `whitespace-style' includes the value + `space-after-tab::tab', replace SPACEs by TABs. + If `whitespace-style' includes the value + `space-after-tab::space', replace TABs by SPACEs. + +See `whitespace-style', `indent-tabs-mode' and `tab-width' for +documentation. + +\(fn)" t nil) + +(autoload 'whitespace-cleanup-region "whitespace" "\ +Cleanup some blank problems at region. + +The problems cleaned up are: + +1. `tab-width' or more SPACEs at beginning of line. + If `whitespace-style' includes the value `indentation': + replace `tab-width' or more SPACEs at beginning of line by TABs, + if `indent-tabs-mode' is non-nil; otherwise, replace TABs by + SPACEs. + If `whitespace-style' includes the value `indentation::tab', + replace `tab-width' or more SPACEs at beginning of line by TABs. + If `whitespace-style' includes the value `indentation::space', + replace TABs by SPACEs. + +2. SPACEs before TAB. + If `whitespace-style' includes the value `space-before-tab': + replace SPACEs by TABs, if `indent-tabs-mode' is non-nil; + otherwise, replace TABs by SPACEs. + If `whitespace-style' includes the value + `space-before-tab::tab', replace SPACEs by TABs. + If `whitespace-style' includes the value + `space-before-tab::space', replace TABs by SPACEs. + +3. SPACEs or TABs at end of line. + If `whitespace-style' includes the value `trailing', remove + all SPACEs or TABs at end of line. + +4. `tab-width' or more SPACEs after TAB. + If `whitespace-style' includes the value `space-after-tab': + replace SPACEs by TABs, if `indent-tabs-mode' is non-nil; + otherwise, replace TABs by SPACEs. + If `whitespace-style' includes the value + `space-after-tab::tab', replace SPACEs by TABs. + If `whitespace-style' includes the value + `space-after-tab::space', replace TABs by SPACEs. + +See `whitespace-style', `indent-tabs-mode' and `tab-width' for +documentation. + +\(fn START END)" t nil) + +(autoload 'whitespace-report "whitespace" "\ +Report some whitespace problems in buffer. + +Perform `whitespace-report-region' on the current buffer. + +\(fn &optional FORCE REPORT-IF-BOGUS)" t nil) + +(autoload 'whitespace-report-region "whitespace" "\ +Report some whitespace problems in a region. + +Return nil if there is no whitespace problem; otherwise, return +non-nil. + +If FORCE is non-nil or \\[universal-argument] was pressed just +before calling `whitespace-report-region' interactively, it +forces all classes of whitespace problem to be considered +significant. + +If REPORT-IF-BOGUS is t, it reports only when there are any +whitespace problems in buffer; if it is `never', it does not +report problems. + +Report if some of the following whitespace problems exist: + +* If `indent-tabs-mode' is non-nil: + empty 1. empty lines at beginning of buffer. + empty 2. empty lines at end of buffer. + trailing 3. SPACEs or TABs at end of line. + indentation 4. line starts with `tab-width' or more SPACEs. + space-before-tab 5. SPACEs before TAB. + space-after-tab 6. `tab-width' or more SPACEs after TAB. + +* If `indent-tabs-mode' is nil: + empty 1. empty lines at beginning of buffer. + empty 2. empty lines at end of buffer. + trailing 3. SPACEs or TABs at end of line. + indentation 4. TABS at beginning of line. + space-before-tab 5. SPACEs before TAB. + space-after-tab 6. `tab-width' or more SPACEs after TAB. + +See `whitespace-style' for documentation. +See also `whitespace-cleanup' and `whitespace-cleanup-region' for +cleaning up these problems. + +\(fn START END &optional FORCE REPORT-IF-BOGUS)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "whitespace" '("whitespace-"))) + +;;;*** + +;;;### (autoloads nil "wid-browse" "wid-browse.el" (0 0 0 0)) +;;; Generated autoloads from wid-browse.el + +(autoload 'widget-browse-at "wid-browse" "\ +Browse the widget under point. + +\(fn POS)" t nil) + +(autoload 'widget-browse "wid-browse" "\ +Create a widget browser for WIDGET. + +\(fn WIDGET)" t nil) + +(autoload 'widget-browse-other-window "wid-browse" "\ +Show widget browser for WIDGET in other window. + +\(fn &optional WIDGET)" t nil) + +(autoload 'widget-minor-mode "wid-browse" "\ +Minor mode for traversing widgets. +With a prefix argument ARG, enable the mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable the mode +if ARG is omitted or nil. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "wid-browse" '("widget-"))) + +;;;*** + +;;;### (autoloads nil "wid-edit" "wid-edit.el" (0 0 0 0)) +;;; Generated autoloads from wid-edit.el + +(autoload 'widgetp "wid-edit" "\ +Return non-nil if WIDGET is a widget. + +\(fn WIDGET)" nil nil) + +(autoload 'widget-prompt-value "wid-edit" "\ +Prompt for a value matching WIDGET, using PROMPT. +The current value is assumed to be VALUE, unless UNBOUND is non-nil. + +\(fn WIDGET PROMPT &optional VALUE UNBOUND)" nil nil) + +(autoload 'widget-create "wid-edit" "\ +Create widget of TYPE. +The optional ARGS are additional keyword arguments. + +\(fn TYPE &rest ARGS)" nil nil) + +(autoload 'widget-delete "wid-edit" "\ +Delete WIDGET. + +\(fn WIDGET)" nil nil) + +(autoload 'widget-insert "wid-edit" "\ +Call `insert' with ARGS even if surrounding text is read only. + +\(fn &rest ARGS)" nil nil) + +(defvar widget-keymap (let ((map (make-sparse-keymap))) (define-key map " " 'widget-forward) (define-key map " " 'widget-backward) (define-key map [(shift tab)] 'widget-backward) (put 'widget-backward :advertised-binding [(shift tab)]) (define-key map [backtab] 'widget-backward) (define-key map [down-mouse-2] 'widget-button-click) (define-key map [down-mouse-1] 'widget-button-click) (define-key map [(control 109)] 'widget-button-press) map) "\ +Keymap containing useful binding for buffers containing widgets. +Recommended as a parent keymap for modes using widgets. +Note that such modes will need to require wid-edit.") + +(autoload 'widget-setup "wid-edit" "\ +Setup current buffer so editing string widgets works. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "wid-edit" '("widget-"))) + +;;;*** + +;;;### (autoloads nil "windmove" "windmove.el" (0 0 0 0)) +;;; Generated autoloads from windmove.el + +(autoload 'windmove-left "windmove" "\ +Select the window to the left of the current one. +With no prefix argument, or with prefix argument equal to zero, +\"left\" is relative to the position of point in the window; otherwise +it is relative to the top edge (for positive ARG) or the bottom edge +\(for negative ARG) of the current window. +If no window is at the desired location, an error is signaled. + +\(fn &optional ARG)" t nil) + +(autoload 'windmove-up "windmove" "\ +Select the window above the current one. +With no prefix argument, or with prefix argument equal to zero, \"up\" +is relative to the position of point in the window; otherwise it is +relative to the left edge (for positive ARG) or the right edge (for +negative ARG) of the current window. +If no window is at the desired location, an error is signaled. + +\(fn &optional ARG)" t nil) + +(autoload 'windmove-right "windmove" "\ +Select the window to the right of the current one. +With no prefix argument, or with prefix argument equal to zero, +\"right\" is relative to the position of point in the window; +otherwise it is relative to the top edge (for positive ARG) or the +bottom edge (for negative ARG) of the current window. +If no window is at the desired location, an error is signaled. + +\(fn &optional ARG)" t nil) + +(autoload 'windmove-down "windmove" "\ +Select the window below the current one. +With no prefix argument, or with prefix argument equal to zero, +\"down\" is relative to the position of point in the window; otherwise +it is relative to the left edge (for positive ARG) or the right edge +\(for negative ARG) of the current window. +If no window is at the desired location, an error is signaled. + +\(fn &optional ARG)" t nil) + +(autoload 'windmove-default-keybindings "windmove" "\ +Set up keybindings for `windmove'. +Keybindings are of the form MODIFIER-{left,right,up,down}. +Default MODIFIER is `shift'. + +\(fn &optional MODIFIER)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "windmove" '("windmove-"))) + +;;;*** + +;;;### (autoloads nil "winner" "winner.el" (0 0 0 0)) +;;; Generated autoloads from winner.el + +(defvar winner-mode nil "\ +Non-nil if Winner mode is enabled. +See the `winner-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `winner-mode'.") + +(custom-autoload 'winner-mode "winner" nil) + +(autoload 'winner-mode "winner" "\ +Toggle Winner mode on or off. +With a prefix argument ARG, enable Winner mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil, and toggle it if ARG is ‘toggle’. + +Winner mode is a global minor mode that records the changes in +the window configuration (i.e. how the frames are partitioned +into windows) so that the changes can be \"undone\" using the +command `winner-undo'. By default this one is bound to the key +sequence `C-c '. If you change your mind (while undoing), +you can press `C-c ' (calling `winner-redo'). + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "winner" '("winner-"))) + +;;;*** + +;;;### (autoloads nil "woman" "woman.el" (0 0 0 0)) +;;; Generated autoloads from woman.el +(push (purecopy '(woman 0 551)) package--builtin-versions) + +(defvar woman-locale nil "\ +String specifying a manual page locale, or nil. +If a manual page is available in the specified locale +\(e.g. \"sv_SE.ISO8859-1\"), it will be offered in preference to the +default version. Normally, `set-locale-environment' sets this at startup.") + +(custom-autoload 'woman-locale "woman" t) + +(autoload 'woman "woman" "\ +Browse UN*X man page for TOPIC (Without using external Man program). +The major browsing mode used is essentially the standard Man mode. +Choose the filename for the man page using completion, based on the +topic selected from the directories specified in `woman-manpath' and +`woman-path'. The directory expansions and topics are cached for +speed. With a prefix argument, force the caches to be +updated (e.g. to re-interpret the current directory). + +Used non-interactively, arguments are optional: if given then TOPIC +should be a topic string and non-nil RE-CACHE forces re-caching. + +\(fn &optional TOPIC RE-CACHE)" t nil) + +(autoload 'woman-dired-find-file "woman" "\ +In dired, run the WoMan man-page browser on this file. + +\(fn)" t nil) + +(autoload 'woman-find-file "woman" "\ +Find, decode and browse a specific UN*X man-page source file FILE-NAME. +Use existing buffer if possible; reformat only if prefix arg given. +When called interactively, optional argument REFORMAT forces reformatting +of an existing WoMan buffer formatted earlier. +No external programs are used, except that `gunzip' will be used to +decompress the file if appropriate. See the documentation for the +`woman' command for further details. + +\(fn FILE-NAME &optional REFORMAT)" t nil) + +(autoload 'woman-bookmark-jump "woman" "\ +Default bookmark handler for Woman buffers. + +\(fn BOOKMARK)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "woman" '("woman" "WoMan-" "menu-bar-manuals-menu" "set-woman-file-regexp"))) + +;;;*** + +;;;### (autoloads nil "x-dnd" "x-dnd.el" (0 0 0 0)) +;;; Generated autoloads from x-dnd.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "x-dnd" '("x-dnd-"))) + +;;;*** + +;;;### (autoloads nil "xdg" "xdg.el" (0 0 0 0)) +;;; Generated autoloads from xdg.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "xdg" '("xdg-"))) + +;;;*** + +;;;### (autoloads nil "xml" "xml.el" (0 0 0 0)) +;;; Generated autoloads from xml.el + +(autoload 'xml-parse-file "xml" "\ +Parse the well-formed XML file FILE. +Return the top node with all its children. +If PARSE-DTD is non-nil, the DTD is parsed rather than skipped. + +If PARSE-NS is non-nil, then QNAMES are expanded. By default, +the variable `xml-default-ns' is the mapping from namespaces to +URIs, and expanded names will be returned as a cons + + (\"namespace:\" . \"foo\"). + +If PARSE-NS is an alist, it will be used as the mapping from +namespace to URIs instead. + +If it is the symbol `symbol-qnames', expanded names will be +returned as a plain symbol `namespace:foo' instead of a cons. + +Both features can be combined by providing a cons cell + + (symbol-qnames . ALIST). + +\(fn FILE &optional PARSE-DTD PARSE-NS)" nil nil) + +(autoload 'xml-parse-region "xml" "\ +Parse the region from BEG to END in BUFFER. +Return the XML parse tree, or raise an error if the region does +not contain well-formed XML. + +If BEG is nil, it defaults to `point-min'. +If END is nil, it defaults to `point-max'. +If BUFFER is nil, it defaults to the current buffer. +If PARSE-DTD is non-nil, parse the DTD and return it as the first +element of the list. +If PARSE-NS is non-nil, then QNAMES are expanded. By default, +the variable `xml-default-ns' is the mapping from namespaces to +URIs, and expanded names will be returned as a cons + + (\"namespace:\" . \"foo\"). + +If PARSE-NS is an alist, it will be used as the mapping from +namespace to URIs instead. + +If it is the symbol `symbol-qnames', expanded names will be +returned as a plain symbol `namespace:foo' instead of a cons. + +Both features can be combined by providing a cons cell + + (symbol-qnames . ALIST). + +\(fn &optional BEG END BUFFER PARSE-DTD PARSE-NS)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "xml" '("xml-"))) + +;;;*** + +;;;### (autoloads nil "xmltok" "nxml/xmltok.el" (0 0 0 0)) +;;; Generated autoloads from nxml/xmltok.el + +(autoload 'xmltok-get-declared-encoding-position "xmltok" "\ +Return the position of the encoding in the XML declaration at point. +If there is a well-formed XML declaration starting at point and it +contains an encoding declaration, then return (START . END) +where START and END are the positions of the start and the end +of the encoding name; if there is no encoding declaration return +the position where and encoding declaration could be inserted. +If there is XML that is not well-formed that looks like an XML +declaration, return nil. Otherwise, return t. +If LIMIT is non-nil, then do not consider characters beyond LIMIT. + +\(fn &optional LIMIT)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "xmltok" '("xmltok-"))) + +;;;*** + +;;;### (autoloads nil "xref" "progmodes/xref.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/xref.el + +(autoload 'xref-find-backend "xref" "\ + + +\(fn)" nil nil) + +(autoload 'xref-pop-marker-stack "xref" "\ +Pop back to where \\[xref-find-definitions] was last invoked. + +\(fn)" t nil) + +(autoload 'xref-marker-stack-empty-p "xref" "\ +Return t if the marker stack is empty; nil otherwise. + +\(fn)" nil nil) + +(autoload 'xref-find-definitions "xref" "\ +Find the definition of the identifier at point. +With prefix argument or when there's no identifier at point, +prompt for it. + +If sufficient information is available to determine a unique +definition for IDENTIFIER, display it in the selected window. +Otherwise, display the list of the possible definitions in a +buffer where the user can select from the list. + +\(fn IDENTIFIER)" t nil) + +(autoload 'xref-find-definitions-other-window "xref" "\ +Like `xref-find-definitions' but switch to the other window. + +\(fn IDENTIFIER)" t nil) + +(autoload 'xref-find-definitions-other-frame "xref" "\ +Like `xref-find-definitions' but switch to the other frame. + +\(fn IDENTIFIER)" t nil) + +(autoload 'xref-find-references "xref" "\ +Find references to the identifier at point. +With prefix argument, prompt for the identifier. + +\(fn IDENTIFIER)" t nil) + +(autoload 'xref-find-apropos "xref" "\ +Find all meaningful symbols that match PATTERN. +The argument has the same meaning as in `apropos'. + +\(fn PATTERN)" t nil) + (define-key esc-map "." #'xref-find-definitions) + (define-key esc-map "," #'xref-pop-marker-stack) + (define-key esc-map "?" #'xref-find-references) + (define-key esc-map [?\C-.] #'xref-find-apropos) + (define-key ctl-x-4-map "." #'xref-find-definitions-other-window) + (define-key ctl-x-5-map "." #'xref-find-definitions-other-frame) + +(autoload 'xref-collect-matches "xref" "\ +Collect matches for REGEXP inside FILES in DIR. +FILES is a string with glob patterns separated by spaces. +IGNORES is a list of glob patterns. + +\(fn REGEXP FILES DIR IGNORES)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "xref" '("xref-"))) + +;;;*** + +;;;### (autoloads nil "xscheme" "progmodes/xscheme.el" (0 0 0 0)) +;;; Generated autoloads from progmodes/xscheme.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "xscheme" '("xscheme-" "start-scheme" "scheme-" "exit-scheme-interaction-mode" "verify-xscheme-buffer" "local-" "global-set-scheme-interaction-buffer" "run-scheme" "reset-scheme" "default-xscheme-runlight"))) + +;;;*** + +;;;### (autoloads nil "xsd-regexp" "nxml/xsd-regexp.el" (0 0 0 0)) +;;; Generated autoloads from nxml/xsd-regexp.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "xsd-regexp" '("xsdre-"))) + +;;;*** + +;;;### (autoloads nil "xt-mouse" "xt-mouse.el" (0 0 0 0)) +;;; Generated autoloads from xt-mouse.el + +(defvar xterm-mouse-mode nil "\ +Non-nil if Xterm-Mouse mode is enabled. +See the `xterm-mouse-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `xterm-mouse-mode'.") + +(custom-autoload 'xterm-mouse-mode "xt-mouse" nil) + +(autoload 'xterm-mouse-mode "xt-mouse" "\ +Toggle XTerm mouse mode. +With a prefix argument ARG, enable XTerm mouse mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Turn it on to use Emacs mouse commands, and off to use xterm mouse commands. +This works in terminal emulators compatible with xterm. It only +works for simple uses of the mouse. Basically, only non-modified +single clicks are supported. When turned on, the normal xterm +mouse functionality for such clicks is still available by holding +down the SHIFT key while pressing the mouse button. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "xt-mouse" '("turn-o" "xt-mouse-epoch" "xterm-mouse-"))) + +;;;*** + +;;;### (autoloads nil "xwidget" "xwidget.el" (0 0 0 0)) +;;; Generated autoloads from xwidget.el + +(autoload 'xwidget-webkit-browse-url "xwidget" "\ +Ask xwidget-webkit to browse URL. +NEW-SESSION specifies whether to create a new xwidget-webkit session. +Interactively, URL defaults to the string looking like a url around point. + +\(fn URL &optional NEW-SESSION)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "xwidget" '("xwidget-"))) + +;;;*** + +;;;### (autoloads nil "yenc" "mail/yenc.el" (0 0 0 0)) +;;; Generated autoloads from mail/yenc.el + +(autoload 'yenc-decode-region "yenc" "\ +Yenc decode region between START and END using an internal decoder. + +\(fn START END)" t nil) + +(autoload 'yenc-extract-filename "yenc" "\ +Extract file name from an yenc header. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "yenc" '("yenc-"))) + +;;;*** + +;;;### (autoloads nil "zeroconf" "net/zeroconf.el" (0 0 0 0)) +;;; Generated autoloads from net/zeroconf.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "zeroconf" '("zeroconf-"))) + +;;;*** + +;;;### (autoloads nil "zone" "play/zone.el" (0 0 0 0)) +;;; Generated autoloads from play/zone.el + +(autoload 'zone "zone" "\ +Zone out, completely. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "zone" '("zone-"))) + +;;;*** + +;;;### (autoloads nil nil ("abbrev.el" "bindings.el" "buff-menu.el" +;;;;;; "button.el" "calc/calc-aent.el" "calc/calc-embed.el" "calc/calc-misc.el" +;;;;;; "calc/calc-yank.el" "calendar/cal-loaddefs.el" "calendar/diary-loaddefs.el" +;;;;;; "calendar/hol-loaddefs.el" "case-table.el" "cedet/ede/base.el" +;;;;;; "cedet/ede/config.el" "cedet/ede/cpp-root.el" "cedet/ede/custom.el" +;;;;;; "cedet/ede/dired.el" "cedet/ede/emacs.el" "cedet/ede/files.el" +;;;;;; "cedet/ede/generic.el" "cedet/ede/linux.el" "cedet/ede/locate.el" +;;;;;; "cedet/ede/make.el" "cedet/ede/shell.el" "cedet/ede/speedbar.el" +;;;;;; "cedet/ede/system.el" "cedet/ede/util.el" "cedet/semantic/analyze.el" +;;;;;; "cedet/semantic/analyze/complete.el" "cedet/semantic/analyze/refs.el" +;;;;;; "cedet/semantic/bovine.el" "cedet/semantic/bovine/c-by.el" +;;;;;; "cedet/semantic/bovine/c.el" "cedet/semantic/bovine/el.el" +;;;;;; "cedet/semantic/bovine/gcc.el" "cedet/semantic/bovine/make-by.el" +;;;;;; "cedet/semantic/bovine/make.el" "cedet/semantic/bovine/scm-by.el" +;;;;;; "cedet/semantic/bovine/scm.el" "cedet/semantic/complete.el" +;;;;;; "cedet/semantic/ctxt.el" "cedet/semantic/db-file.el" "cedet/semantic/db-find.el" +;;;;;; "cedet/semantic/db-global.el" "cedet/semantic/db-mode.el" +;;;;;; "cedet/semantic/db-typecache.el" "cedet/semantic/db.el" "cedet/semantic/debug.el" +;;;;;; "cedet/semantic/decorate/include.el" "cedet/semantic/decorate/mode.el" +;;;;;; "cedet/semantic/dep.el" "cedet/semantic/doc.el" "cedet/semantic/edit.el" +;;;;;; "cedet/semantic/find.el" "cedet/semantic/format.el" "cedet/semantic/html.el" +;;;;;; "cedet/semantic/ia-sb.el" "cedet/semantic/ia.el" "cedet/semantic/idle.el" +;;;;;; "cedet/semantic/imenu.el" "cedet/semantic/lex-spp.el" "cedet/semantic/lex.el" +;;;;;; "cedet/semantic/mru-bookmark.el" "cedet/semantic/scope.el" +;;;;;; "cedet/semantic/senator.el" "cedet/semantic/sort.el" "cedet/semantic/symref.el" +;;;;;; "cedet/semantic/symref/cscope.el" "cedet/semantic/symref/global.el" +;;;;;; "cedet/semantic/symref/grep.el" "cedet/semantic/symref/idutils.el" +;;;;;; "cedet/semantic/symref/list.el" "cedet/semantic/tag-file.el" +;;;;;; "cedet/semantic/tag-ls.el" "cedet/semantic/tag-write.el" +;;;;;; "cedet/semantic/tag.el" "cedet/semantic/texi.el" "cedet/semantic/util-modes.el" +;;;;;; "cedet/semantic/wisent/java-tags.el" "cedet/semantic/wisent/javascript.el" +;;;;;; "cedet/semantic/wisent/javat-wy.el" "cedet/semantic/wisent/js-wy.el" +;;;;;; "cedet/semantic/wisent/python-wy.el" "cedet/semantic/wisent/python.el" +;;;;;; "cedet/srecode/compile.el" "cedet/srecode/cpp.el" "cedet/srecode/document.el" +;;;;;; "cedet/srecode/el.el" "cedet/srecode/expandproto.el" "cedet/srecode/getset.el" +;;;;;; "cedet/srecode/insert.el" "cedet/srecode/java.el" "cedet/srecode/map.el" +;;;;;; "cedet/srecode/mode.el" "cedet/srecode/srt-wy.el" "cedet/srecode/srt.el" +;;;;;; "cedet/srecode/template.el" "cedet/srecode/texi.el" "composite.el" +;;;;;; "cus-face.el" "cus-start.el" "custom.el" "dired-aux.el" "dired-x.el" +;;;;;; "electric.el" "emacs-lisp/backquote.el" "emacs-lisp/byte-run.el" +;;;;;; "emacs-lisp/cl-extra.el" "emacs-lisp/cl-macs.el" "emacs-lisp/cl-preloaded.el" +;;;;;; "emacs-lisp/cl-seq.el" "emacs-lisp/eieio-compat.el" "emacs-lisp/eieio-custom.el" +;;;;;; "emacs-lisp/eieio-opt.el" "emacs-lisp/eldoc.el" "emacs-lisp/float-sup.el" +;;;;;; "emacs-lisp/lisp-mode.el" "emacs-lisp/lisp.el" "emacs-lisp/macroexp.el" +;;;;;; "emacs-lisp/map-ynp.el" "emacs-lisp/nadvice.el" "emacs-lisp/syntax.el" +;;;;;; "emacs-lisp/timer.el" "env.el" "epa-hook.el" "eshell/em-alias.el" +;;;;;; "eshell/em-banner.el" "eshell/em-basic.el" "eshell/em-cmpl.el" +;;;;;; "eshell/em-dirs.el" "eshell/em-glob.el" "eshell/em-hist.el" +;;;;;; "eshell/em-ls.el" "eshell/em-pred.el" "eshell/em-prompt.el" +;;;;;; "eshell/em-rebind.el" "eshell/em-script.el" "eshell/em-smart.el" +;;;;;; "eshell/em-term.el" "eshell/em-tramp.el" "eshell/em-unix.el" +;;;;;; "eshell/em-xtra.el" "facemenu.el" "faces.el" "files.el" "font-core.el" +;;;;;; "font-lock.el" "format.el" "frame.el" "help.el" "hfy-cmap.el" +;;;;;; "ibuf-ext.el" "indent.el" "international/characters.el" "international/charprop.el" +;;;;;; "international/charscript.el" "international/cp51932.el" +;;;;;; "international/eucjp-ms.el" "international/mule-cmds.el" +;;;;;; "international/mule-conf.el" "international/mule.el" "international/uni-bidi.el" +;;;;;; "international/uni-brackets.el" "international/uni-category.el" +;;;;;; "international/uni-combining.el" "international/uni-comment.el" +;;;;;; "international/uni-decimal.el" "international/uni-decomposition.el" +;;;;;; "international/uni-digit.el" "international/uni-lowercase.el" +;;;;;; "international/uni-mirrored.el" "international/uni-name.el" +;;;;;; "international/uni-numeric.el" "international/uni-old-name.el" +;;;;;; "international/uni-titlecase.el" "international/uni-uppercase.el" +;;;;;; "isearch.el" "jit-lock.el" "jka-cmpr-hook.el" "language/burmese.el" +;;;;;; "language/cham.el" "language/chinese.el" "language/cyrillic.el" +;;;;;; "language/czech.el" "language/english.el" "language/ethiopic.el" +;;;;;; "language/european.el" "language/georgian.el" "language/greek.el" +;;;;;; "language/hebrew.el" "language/indian.el" "language/japanese.el" +;;;;;; "language/khmer.el" "language/korean.el" "language/lao.el" +;;;;;; "language/misc-lang.el" "language/romanian.el" "language/sinhala.el" +;;;;;; "language/slovak.el" "language/tai-viet.el" "language/thai.el" +;;;;;; "language/tibetan.el" "language/utf-8-lang.el" "language/vietnamese.el" +;;;;;; "ldefs-boot.el" "leim/ja-dic/ja-dic.el" "leim/leim-list.el" +;;;;;; "leim/quail/4Corner.el" "leim/quail/ARRAY30.el" "leim/quail/CCDOSPY.el" +;;;;;; "leim/quail/CTLau-b5.el" "leim/quail/CTLau.el" "leim/quail/ECDICT.el" +;;;;;; "leim/quail/ETZY.el" "leim/quail/PY-b5.el" "leim/quail/PY.el" +;;;;;; "leim/quail/Punct-b5.el" "leim/quail/Punct.el" "leim/quail/QJ-b5.el" +;;;;;; "leim/quail/QJ.el" "leim/quail/SW.el" "leim/quail/TONEPY.el" +;;;;;; "leim/quail/ZIRANMA.el" "leim/quail/ZOZY.el" "leim/quail/arabic.el" +;;;;;; "leim/quail/croatian.el" "leim/quail/cyril-jis.el" "leim/quail/cyrillic.el" +;;;;;; "leim/quail/czech.el" "leim/quail/georgian.el" "leim/quail/greek.el" +;;;;;; "leim/quail/hanja-jis.el" "leim/quail/hanja.el" "leim/quail/hanja3.el" +;;;;;; "leim/quail/hebrew.el" "leim/quail/ipa-praat.el" "leim/quail/latin-alt.el" +;;;;;; "leim/quail/latin-ltx.el" "leim/quail/latin-post.el" "leim/quail/latin-pre.el" +;;;;;; "leim/quail/persian.el" "leim/quail/programmer-dvorak.el" +;;;;;; "leim/quail/py-punct.el" "leim/quail/pypunct-b5.el" "leim/quail/quick-b5.el" +;;;;;; "leim/quail/quick-cns.el" "leim/quail/rfc1345.el" "leim/quail/sgml-input.el" +;;;;;; "leim/quail/slovak.el" "leim/quail/symbol-ksc.el" "leim/quail/tamil-dvorak.el" +;;;;;; "leim/quail/tsang-b5.el" "leim/quail/tsang-cns.el" "leim/quail/vntelex.el" +;;;;;; "leim/quail/vnvni.el" "leim/quail/welsh.el" "loadup.el" "mail/blessmail.el" +;;;;;; "mail/rmailedit.el" "mail/rmailkwd.el" "mail/rmailmm.el" +;;;;;; "mail/rmailmsc.el" "mail/rmailsort.el" "mail/rmailsum.el" +;;;;;; "mail/undigest.el" "menu-bar.el" "mh-e/mh-gnus.el" "mh-e/mh-loaddefs.el" +;;;;;; "minibuffer.el" "mouse.el" "net/tramp-loaddefs.el" "newcomment.el" +;;;;;; "obarray.el" "org/ob-core.el" "org/ob-keys.el" "org/ob-lob.el" +;;;;;; "org/ob-matlab.el" "org/ob-tangle.el" "org/ob.el" "org/org-archive.el" +;;;;;; "org/org-attach.el" "org/org-bbdb.el" "org/org-clock.el" +;;;;;; "org/org-datetree.el" "org/org-element.el" "org/org-feed.el" +;;;;;; "org/org-footnote.el" "org/org-id.el" "org/org-indent.el" +;;;;;; "org/org-install.el" "org/org-irc.el" "org/org-mobile.el" +;;;;;; "org/org-plot.el" "org/org-table.el" "org/org-timer.el" "org/ox-ascii.el" +;;;;;; "org/ox-beamer.el" "org/ox-html.el" "org/ox-icalendar.el" +;;;;;; "org/ox-latex.el" "org/ox-man.el" "org/ox-md.el" "org/ox-odt.el" +;;;;;; "org/ox-org.el" "org/ox-publish.el" "org/ox-texinfo.el" "org/ox.el" +;;;;;; "progmodes/elisp-mode.el" "progmodes/prog-mode.el" "ps-def.el" +;;;;;; "ps-mule.el" "register.el" "replace.el" "rfn-eshadow.el" +;;;;;; "select.el" "simple.el" "startup.el" "subdirs.el" "subr.el" +;;;;;; "textmodes/fill.el" "textmodes/page.el" "textmodes/paragraphs.el" +;;;;;; "textmodes/reftex-auc.el" "textmodes/reftex-cite.el" "textmodes/reftex-dcr.el" +;;;;;; "textmodes/reftex-global.el" "textmodes/reftex-index.el" +;;;;;; "textmodes/reftex-parse.el" "textmodes/reftex-ref.el" "textmodes/reftex-sel.el" +;;;;;; "textmodes/reftex-toc.el" "textmodes/text-mode.el" "uniquify.el" +;;;;;; "vc/ediff-hook.el" "vc/vc-hooks.el" "version.el" "widget.el" +;;;;;; "window.el") (0 0 0 0)) + +;;;*** + +(provide 'loaddefs) +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; loaddefs.el ends here diff --git a/lisp/leim/quail/cyrillic.el b/lisp/leim/quail/cyrillic.el index af9f66c47f4..600193ddc18 100644 --- a/lisp/leim/quail/cyrillic.el +++ b/lisp/leim/quail/cyrillic.el @@ -235,8 +235,8 @@ ("^" ?:) ("&" ??) ("*" ?*) - ("(" ?() - (")" ?)) + ("(" ?\() + (")" ?\)) ("_" ?_) ("+" ?+) ("~" ?Ё) @@ -789,8 +789,8 @@ Sorry, but `ghe with upturn' is not included in ISO 8859-5." ("^" ?:) ("&" ??) ("*" ?*) - ("(" ?() - (")" ?)) + ("(" ?\() + (")" ?\)) ("_" ?_) ("+" ?+) ("~" ?') diff --git a/lisp/linum.el b/lisp/linum.el index 8baa263f0b3..9cfb94dab68 100644 --- a/lisp/linum.el +++ b/lisp/linum.el @@ -112,7 +112,16 @@ Linum mode is a buffer-local minor mode." (define-globalized-minor-mode global-linum-mode linum-mode linum-on) (defun linum-on () - (unless (minibufferp) + (unless (or (minibufferp) + ;; Turning linum-mode in the daemon's initial frame + ;; could significantly slow down startup, if the buffer + ;; in which this is done is large, because Emacs thinks + ;; the "window" spans the entire buffer then. This + ;; could happen when restoring session via desktop.el, + ;; if some large buffer was under linum-mode when + ;; desktop was saved. So we disable linum-mode for + ;; non-client frames in a daemon session. + (and (daemonp) (null (frame-parameter nil 'client)))) (linum-mode 1))) (defun linum-delete-overlays () diff --git a/lisp/loadup.el b/lisp/loadup.el index e7df6f00fea..9af08e7ec4a 100644 --- a/lisp/loadup.el +++ b/lisp/loadup.el @@ -59,8 +59,11 @@ ;; This is because PATH_DUMPLOADSEARCH is just "../lisp". (if (or (equal (member "bootstrap" command-line-args) '("bootstrap")) ;; FIXME this is irritatingly fragile. - (equal (nth 4 command-line-args) "unidata-gen.el") - (equal (nth 7 command-line-args) "unidata-gen-files") + (and (stringp (nth 4 command-line-args)) + (string-match "^unidata-gen\\(\\.elc?\\)?$" + (nth 4 command-line-args))) + (member (nth 7 command-line-args) '("unidata-gen-file" + "unidata-gen-charprop")) (if (fboundp 'dump-emacs) (string-match "src/bootstrap-emacs" (nth 0 command-line-args)) t)) @@ -85,8 +88,9 @@ (message "Using load-path %s" load-path) ;; This is a poor man's `last', since we haven't loaded subr.el yet. -(if (or (equal (member "bootstrap" command-line-args) '("bootstrap")) - (equal (member "dump" command-line-args) '("dump"))) +(if (and (fboundp 'dump-emacs) + (or (equal (member "bootstrap" command-line-args) '("bootstrap")) + (equal (member "dump" command-line-args) '("dump")))) (progn ;; To reduce the size of dumped Emacs, we avoid making huge char-tables. (setq inhibit-load-charset-map t) @@ -143,21 +147,19 @@ (load "button") ;; We don't want to store loaddefs.el in the repository because it is -;; a generated file; but it is required in order to compile the lisp -;; files. When bootstrapping, we cannot generate loaddefs.el until an -;; emacs binary has been built. We therefore support the build with -;; two files, ldefs-boot-manual.el and ldefs-boot-auto.el, which -;; contain the autoloads that are actually called during bootstrap. -;; These do not need to be updated as often as the real loaddefs.el -;; would. Bootstrap should always work with ldefs-boot-manual.el. -;; Therefore, Whenever a new autoload cookie gets added that is -;; necessary during bootstrapping, ldefs-boot-auto.el should be -;; updated using the "generate-ldefs-boot" make target. -;; autogen/update_autogen can be used to periodically update -;; ldefs-boot. +;; a generated file; but it is required in order to compile the lisp files. +;; When bootstrapping, we cannot generate loaddefs.el until an +;; emacs binary has been built. We therefore compromise and keep +;; ldefs-boot.el in the repository. This does not need to be updated +;; as often as the real loaddefs.el would. Bootstrap should always +;; work with ldefs-boot.el. Therefore, whenever a new autoload cookie +;; gets added that is necessary during bootstrapping, ldefs-boot.el +;; should be updated by overwriting it with an up-to-date copy of +;; loaddefs.el that is not corrupted by local changes. +;; admin/update_autogen can be used to update ldefs-boot.el periodically. (condition-case nil (load "loaddefs.el") ;; In case loaddefs hasn't been generated yet. - (file-error (load "ldefs-boot-manual.el"))) + (file-error (load "ldefs-boot.el"))) (let ((new (make-hash-table :test 'equal))) ;; Now that loaddefs has populated definition-prefixes, purify its contents. @@ -182,7 +184,8 @@ (load "case-table") ;; This file doesn't exist when building a development version of Emacs ;; from the repository. It is generated just after temacs is built. -(if (load "international/charprop.el" t) +(load "international/charprop.el" t) +(if (featurep 'charprop) (setq redisplay--inhibit-bidi nil)) (load "international/characters") (load "composite") @@ -300,7 +303,7 @@ ;; Don't load ucs-normalize.el unless uni-*.el files were ;; already produced, because it needs uni-*.el files that might ;; not be built early enough during bootstrap. - (when (load-history-filename-element "charprop\\.el") + (when (featurep 'charprop) (load "international/mule-util") (load "international/ucs-normalize") (load "term/ns-win")))) @@ -347,12 +350,14 @@ lost after dumping"))) ;; in non-ASCII directories is to manipulate unibyte strings in the ;; current locale's encoding. (if (and (member (car (last command-line-args)) '("dump" "bootstrap")) + (fboundp 'dump-emacs) (multibyte-string-p default-directory)) (error "default-directory must be unibyte when dumping Emacs!")) ;; Determine which build number to use ;; based on the executables that now exist. (if (and (equal (last command-line-args) '("dump")) + (fboundp 'dump-emacs) (not (eq system-type 'ms-dos))) (let* ((base (concat "remacs-" emacs-version ".")) (exelen (if (eq system-type 'windows-nt) -4)) @@ -370,7 +375,8 @@ lost after dumping"))) (message "Finding pointers to doc strings...") -(if (equal (last command-line-args) '("dump")) +(if (and (fboundp 'dump-emacs) + (equal (last command-line-args) '("dump"))) (Snarf-documentation "DOC") (condition-case nil (Snarf-documentation "DOC") @@ -429,12 +435,6 @@ lost after dumping"))) (message "Pure-hashed: %d strings, %d vectors, %d conses, %d bytecodes, %d others" strings vectors conses bytecodes others))) -;; Prevent build-time PATH getting stored in the binary. -;; Mainly cosmetic, but helpful for Guix. (Bug#20330) -;; Do this here, rather than earlier, so that the above code -;; can invoke Git commands and the like. -(setq exec-path nil) - ;; Avoid error if user loads some more libraries now and make sure the ;; hash-consing hash table is GC'd. (setq purify-flag nil) @@ -445,8 +445,14 @@ lost after dumping"))) ;; Make sure we will attempt bidi reordering henceforth. (setq redisplay--inhibit-bidi nil) -(if (member (car (last command-line-args)) '("dump" "bootstrap")) +(if (and (fboundp 'dump-emacs) + (member (car (last command-line-args)) '("dump" "bootstrap"))) (progn + ;; Prevent build-time PATH getting stored in the binary. + ;; Mainly cosmetic, but helpful for Guix. (Bug#20330) + ;; Do this here, rather than earlier, so that the above code + ;; can invoke Git commands and the like. + (setq exec-path nil) (message "Dumping under the name emacs") (condition-case () (delete-file "remacs") diff --git a/lisp/mail/emacsbug.el b/lisp/mail/emacsbug.el index ecb7db60ae1..c1aec6923fb 100644 --- a/lisp/mail/emacsbug.el +++ b/lisp/mail/emacsbug.el @@ -77,33 +77,12 @@ (equal (executable-find "open") "/usr/bin/open") (memq system-type '(darwin)))) -;; FIXME this duplicates much of the logic from browse-url-can-use-xdg-open. (defun report-emacs-bug-can-use-xdg-email () "Return non-nil if the \"xdg-email\" command can be used. -xdg-email is a desktop utility that calls your preferred mail client. -This requires you to be running either Gnome, KDE, or Xfce4." - (and (getenv "DISPLAY") - (executable-find "xdg-email") - (or (getenv "GNOME_DESKTOP_SESSION_ID") - ;; GNOME_DESKTOP_SESSION_ID is deprecated, check on Dbus also. - (condition-case nil - (eq 0 (call-process - "dbus-send" nil nil nil - "--dest=org.gnome.SessionManager" - "--print-reply" - "/org/gnome/SessionManager" - "org.gnome.SessionManager.CanShutdown")) - (error nil)) - (equal (getenv "KDE_FULL_SESSION") "true") - ;; FIXME? browse-url-can-use-xdg-open also accepts LXDE. - ;; Is that no good here, or just overlooked? - (condition-case nil - (eq 0 (call-process - "/bin/sh" nil nil nil - "-c" - ;; FIXME use string-match rather than grep. - "xprop -root _DT_SAVE_MODE|grep xfce4")) - (error nil))))) +xdg-email is a desktop utility that calls your preferred mail client." + (and ;; See browse-url-can-use-xdg-open. + (or (getenv "DISPLAY") (getenv "WAYLAND_DISPLAY")) + (executable-find "xdg-email"))) (defun report-emacs-bug-insert-to-mailer () "Send the message to your preferred mail client. diff --git a/lisp/mail/hashcash.el b/lisp/mail/hashcash.el index 1c24d0aac36..71567b4c0fd 100644 --- a/lisp/mail/hashcash.el +++ b/lisp/mail/hashcash.el @@ -3,7 +3,7 @@ ;; Copyright (C) 2003-2005, 2007-2017 Free Software Foundation, Inc. ;; Written by: Paul Foley (1997-2002) -;; Maintainer: Paul Foley +;; Maintainer: emacs-devel@gnu.org ;; Keywords: mail, hashcash ;; This file is part of GNU Emacs. diff --git a/lisp/mail/rfc2045.el b/lisp/mail/rfc2045.el index f6000500e11..11a6151887a 100644 --- a/lisp/mail/rfc2045.el +++ b/lisp/mail/rfc2045.el @@ -28,7 +28,7 @@ (require 'ietf-drums) (defun rfc2045-encode-string (param value) - "Return and PARAM=VALUE string encoded according to RFC2045." + "Return a PARAM=VALUE string encoded according to RFC2045." (if (or (string-match (concat "[" ietf-drums-no-ws-ctl-token "]") value) (string-match (concat "[" ietf-drums-tspecials "]") value) (string-match "[ \n\t]" value) diff --git a/lisp/mail/rfc2047.el b/lisp/mail/rfc2047.el index bcbdc17631d..e2af86b3246 100644 --- a/lisp/mail/rfc2047.el +++ b/lisp/mail/rfc2047.el @@ -1,4 +1,4 @@ -;;; rfc2047.el --- functions for encoding and decoding rfc2047 messages +;;; rfc2047.el --- functions for encoding and decoding rfc2047 messages -*- lexical-binding:t -*- ;; Copyright (C) 1998-2017 Free Software Foundation, Inc. @@ -26,8 +26,7 @@ ;;; Code: -(eval-when-compile - (require 'cl)) +(eval-when-compile (require 'cl-lib)) (defvar message-posting-charset) (require 'mm-util) @@ -155,7 +154,7 @@ This is either `base64' or `quoted-printable'." (goto-char (point-min)) (skip-chars-forward "\x20-\x7f\r\n\t" limit) (while (< (point) limit) - (incf n8bit) + (cl-incf n8bit) (forward-char 1) (skip-chars-forward "\x20-\x7f\r\n\t" limit)) (if (or (< (* 6 n8bit) (- limit (point-min))) @@ -851,7 +850,7 @@ Point moves to the end of the region." (buffer-string))) (defun rfc2047-encode-parameter (param value) - "Return and PARAM=VALUE string encoded in the RFC2047-like style. + "Return a PARAM=VALUE string encoded in the RFC2047-like style. This is a substitution for the `rfc2231-encode-string' function, that is the standard but many mailers don't support it." (let ((rfc2047-encoding-type 'mime) @@ -931,11 +930,10 @@ only be used for decoding, not for encoding." "Decode successive encoded-words in WORDS and return a decoded string. Each element of WORDS looks like (CHARSET ENCODING ENCODED-TEXT ENCODED-WORD)." - (let (word charset cs encoding text rest) - (while words - (setq word (pop words)) + (let (cs text rest) + (dolist (word words) (if (and (setq cs (rfc2047-charset-to-coding-system - (setq charset (car word)) t)) + (car word) t)) (condition-case code (cond ((char-equal ?B (nth 1 word)) (setq text (base64-decode-string @@ -954,7 +952,10 @@ ENCODED-WORD)." (push (cons cs text) rest)) ;; Don't decode encoded-word. (push (cons nil (nth 3 word)) rest))) + (setq words nil) (while rest + ;; FIXME: This looks O(N²). Can we make it more efficient + ;; with something like mapconcat? (setq words (concat (or (and (setq cs (caar rest)) (condition-case code @@ -1140,7 +1141,9 @@ other than `\"' and `\\' in quoted strings." ;; string is purely ASCII string (decode-coding-string string mail-parse-charset)) - (string-to-multibyte string)))) + (if (multibyte-string-p string) + string + (decode-coding-string string 'us-ascii))))) (defun rfc2047-decode-address-string (string) "Decode MIME-encoded STRING and return the result. @@ -1157,7 +1160,7 @@ strings are stripped." string (when (string-match "=+$" string) (setq string (substring string 0 (match-beginning 0)))) - (case (mod (length string) 4) + (pcase (mod (length string) 4) (0 string) (1 string) ;; Error, don't pad it. (2 (concat string "==")) diff --git a/lisp/mail/rfc2231.el b/lisp/mail/rfc2231.el index ba972c73460..66f539f6986 100644 --- a/lisp/mail/rfc2231.el +++ b/lisp/mail/rfc2231.el @@ -234,7 +234,7 @@ These look like: (decode-coding-string (buffer-string) coding-system))))) (defun rfc2231-encode-string (param value) - "Return and PARAM=VALUE string encoded according to RFC2231. + "Return a PARAM=VALUE string encoded according to RFC2231. Use `mml-insert-parameter' or `mml-insert-parameter-string' to insert the result of this function." (let ((control (ietf-drums-token-to-list ietf-drums-no-ws-ctl-token)) diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el index 4b72b3562d1..df07140d87b 100644 --- a/lisp/mail/rmail.el +++ b/lisp/mail/rmail.el @@ -363,6 +363,9 @@ explicitly.") "\\|^importance:\\|^envelope-to:\\|^delivery-date\\|^openpgp:" "\\|^mbox-line:\\|^cancel-lock:" "\\|^DomainKey-Signature:\\|^dkim-signature:" + "\\|^ARC-.*:" + "\\|^Received-SPF:" + "\\|^Authentication-Results:" "\\|^resent-face:\\|^resent-x.*:\\|^resent-organization:\\|^resent-openpgp:" "\\|^x-.*:")) "Regexp to match header fields that Rmail should normally hide. @@ -1884,14 +1887,19 @@ not be a new one). It returns non-nil if it got any new messages." (setq result (> new-messages 0)) result)))) +(defun rmail-remote-proto-p (proto) + "Return non-nil if string PROTO refers to a remote mailbox protocol." + (string-match-p "^\\(imap\\|pop\\)s?$" proto)) + (defun rmail-parse-url (file) - "Parse the supplied URL. Return (list MAILBOX-NAME REMOTE PASSWORD GOT-PASSWORD) -WHERE MAILBOX-NAME is the name of the mailbox suitable as argument to the -actual version of `movemail', REMOTE is non-nil if MAILBOX-NAME refers to -a remote mailbox, PASSWORD is the password if it should be -supplied as a separate argument to `movemail' or nil otherwise, GOT-PASSWORD -is non-nil if the user has supplied the password interactively. -" + "Parse a mailbox URL string FILE. +Return (MAILBOX-NAME PROTO PASSWORD GOT-PASSWORD), where MAILBOX-NAME is +the name of the mailbox suitable as argument to the actual version of +`movemail', PROTO is the movemail protocol (use `rmail-remote-proto-p' +to see if it refers to a remote mailbox), PASSWORD is the password if it +should be supplied as a separate argument to `movemail' or nil otherwise, +and GOT-PASSWORD is non-nil if the user has supplied the password +interactively." (cond ((string-match "^\\([^:]+\\)://\\(\\([^:@]+\\)\\(:\\([^@]+\\)\\)?@\\)?.*" file) (let (got-password supplied-password @@ -1901,24 +1909,26 @@ is non-nil if the user has supplied the password interactively. (host (substring file (or (match-end 2) (+ 3 (match-end 1)))))) - (if (not pass) - (when rmail-remote-password-required - (setq got-password (not (rmail-have-password))) - (setq supplied-password (rmail-get-remote-password - (string-equal proto "imap")))) - ;; The password is embedded. Strip it out since movemail - ;; does not really like it, in spite of the movemail spec. - (setq file (concat proto "://" user "@" host))) + (if (rmail-remote-proto-p proto) + (if (not pass) + (when rmail-remote-password-required + (setq got-password (not (rmail-have-password))) + (setq supplied-password (rmail-get-remote-password + (string-match "^imaps?" proto)))) + ;; FIXME + ;; The password is embedded. Strip it out since movemail + ;; does not really like it, in spite of the movemail spec. + (setq file (concat proto "://" user "@" host)))) (if (rmail-movemail-variant-p 'emacs) (if (string-equal proto "pop") (list (concat "po:" user ":" host) - t + proto (or pass supplied-password) got-password) (error "Emacs movemail does not support %s protocol" proto)) (list file - (or (string-equal proto "pop") (string-equal proto "imap")) + proto (or supplied-password pass) got-password)))) @@ -1981,18 +1991,18 @@ Value is the size of the newly read mail after conversion." size)) (defun rmail-insert-inbox-text (files renamep) - (let (file tofile delete-files popmail got-password password) + (let (file tofile delete-files proto got-password password) (while files ;; Handle remote mailbox names specially; don't expand as filenames ;; in case the userid contains a directory separator. (setq file (car files)) (let ((url-data (rmail-parse-url file))) (setq file (nth 0 url-data)) - (setq popmail (nth 1 url-data)) + (setq proto (nth 1 url-data)) (setq password (nth 2 url-data)) (setq got-password (nth 3 url-data))) - (if popmail + (if proto (setq renamep t) (setq file (file-truename (substitute-in-file-name (expand-file-name file))))) @@ -2013,14 +2023,17 @@ Value is the size of the newly read mail after conversion." (expand-file-name buffer-file-name)))) ;; Always use movemail to rename the file, ;; since there can be mailboxes in various directories. - (when (not popmail) + (when (not proto) ;; On some systems, /usr/spool/mail/foo is a directory ;; and the actual inbox is /usr/spool/mail/foo/foo. (if (file-directory-p file) (setq file (expand-file-name (user-login-name) file)))) - (cond (popmail - (message "Getting mail from the remote server ...")) + (cond (proto + (message "Getting mail from %s..." + (if (rmail-remote-proto-p proto) + "the remote server" + proto))) ((and (file-exists-p tofile) (/= 0 (nth 7 (file-attributes tofile)))) (message "Getting mail from %s..." tofile)) @@ -2031,7 +2044,7 @@ Value is the size of the newly read mail after conversion." ;; rename or copy the file FILE to TOFILE if and as appropriate. (cond ((not renamep) (setq tofile file)) - ((or (file-exists-p tofile) (and (not popmail) + ((or (file-exists-p tofile) (and (not proto) (not (file-exists-p file)))) nil) (t @@ -2066,9 +2079,10 @@ Value is the size of the newly read mail after conversion." ;; If we just read the password, most likely it is ;; wrong. Otherwise, see if there is a specific ;; reason to think that the problem is a wrong passwd. - (if (or got-password - (re-search-forward rmail-remote-password-error - nil t)) + (if (and (rmail-remote-proto-p proto) + (or got-password + (re-search-forward rmail-remote-password-error + nil t))) (rmail-set-remote-password nil)) ;; If using Mailutils, remove initial error code diff --git a/lisp/mail/rmailmm.el b/lisp/mail/rmailmm.el index c6b9cfddb66..1ffd4668ac8 100644 --- a/lisp/mail/rmailmm.el +++ b/lisp/mail/rmailmm.el @@ -817,12 +817,13 @@ directly." (bulk-data (aref tagline 1)) (body (rmail-mime-entity-body entity)) ;; Find the default directory for this media type. - (directory (catch 'directory - (dolist (entry rmail-mime-attachment-dirs-alist) - (when (string-match (car entry) (car content-type)) - (dolist (dir (cdr entry)) - (when (file-directory-p dir) - (throw 'directory dir))))))) + (directory (or (catch 'directory + (dolist (entry rmail-mime-attachment-dirs-alist) + (when (string-match (car entry) (car content-type)) + (dolist (dir (cdr entry)) + (when (file-directory-p dir) + (throw 'directory dir)))))) + "~")) (filename (or (cdr (assq 'name (cdr content-type))) (cdr (assq 'filename (cdr content-disposition))) "noname")) diff --git a/lisp/mail/sendmail.el b/lisp/mail/sendmail.el index 70c8ea1f937..12d69aa23c3 100644 --- a/lisp/mail/sendmail.el +++ b/lisp/mail/sendmail.el @@ -555,8 +555,9 @@ This also saves the value of `send-mail-function' via Customize." (goto-char (point-min)) (display-buffer (current-buffer)) (let ((completion-ignore-case t)) - (completing-read "Send mail via: " - options nil 'require-match))))) + (completing-read + (format "Send mail via (default %s): " (caar options)) + options nil 'require-match nil nil (car options)))))) (customize-save-variable 'send-mail-function (cdr (assoc-string choice options t))))) @@ -1676,7 +1677,7 @@ and don't delete any header fields." ;; Call yank function, and set the mark if it doesn't. (apply (car original) (cdr original)) (if (eq omark (mark t)) - (push-mark (point)))) + (push-mark))) ;; If the original message is in another window in the same ;; frame, delete that window to save space. (delete-windows-on original t) diff --git a/lisp/man.el b/lisp/man.el index 4f6e1187e0d..0e1c92956b3 100644 --- a/lisp/man.el +++ b/lisp/man.el @@ -832,10 +832,7 @@ indicating optional parts and whitespace being interpreted somewhat loosely. foo[, bar [, ...]] [other stuff] (sec) - description -foo(sec)[, bar(sec) [, ...]] [other stuff] - description - -For more details and some regression tests, please see -test/automated/man-tests.el in the emacs repository." +foo(sec)[, bar(sec) [, ...]] [other stuff] - description" (goto-char (point-min)) ;; See man-tests for data about which systems use which format (hopefully we ;; will be able to simplify the code if/when some of those formats aren't diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el index 28464f13df7..3ca7d1b5b3d 100644 --- a/lisp/menu-bar.el +++ b/lisp/menu-bar.el @@ -970,54 +970,40 @@ The selected font will be the default on both the existing and future frames." (interactive) (customize-set-variable 'scroll-bar-mode nil)) -(defun menu-bar-horizontal-scroll-bar () - "Display horizontal scroll bars on each window." - (interactive) - (customize-set-variable 'horizontal-scroll-bar-mode t)) - -(defun menu-bar-no-horizontal-scroll-bar () - "Turn off horizontal scroll bars." - (interactive) - (customize-set-variable 'horizontal-scroll-bar-mode nil)) - (defvar menu-bar-showhide-scroll-bar-menu - (let ((menu (make-sparse-keymap "Scroll-bar")) - (vsb (frame-parameter nil 'vertical-scroll-bars)) - (hsb (frame-parameter nil 'horizontal-scroll-bars))) + (let ((menu (make-sparse-keymap "Scroll Bar"))) + (bindings--define-key menu [horizontal] - `(menu-item "Horizontal" - menu-bar-horizontal-scroll-bar - :help "Horizontal scroll bar" - :visible (horizontal-scroll-bars-available-p) - :button (:radio . ,hsb))) - - (bindings--define-key menu [none-horizontal] - `(menu-item "None-horizontal" - menu-bar-no-horizontal-scroll-bar - :help "Turn off horizontal scroll bars" - :visible (horizontal-scroll-bars-available-p) - :button (:radio . (not ,hsb)))) + (menu-bar-make-mm-toggle horizontal-scroll-bar-mode + "Horizontal" + "Horizontal scroll bar")) + + (bindings--define-key menu [scrollbar-separator] + menu-bar-separator) (bindings--define-key menu [right] - `(menu-item "On the Right" - menu-bar-right-scroll-bar - :help "Scroll-bar on the right side" + '(menu-item "On the Right" menu-bar-right-scroll-bar + :help "Scroll bar on the right side" :visible (display-graphic-p) - :button (:radio . (eq ,vsb 'right)))) + :button (:radio . (and scroll-bar-mode + (eq (frame-parameter + nil 'vertical-scroll-bars) + 'right))))) (bindings--define-key menu [left] - `(menu-item "On the Left" - menu-bar-left-scroll-bar - :help "Scroll-bar on the left side" + '(menu-item "On the Left" menu-bar-left-scroll-bar + :help "Scroll bar on the left side" :visible (display-graphic-p) - :button (:radio . (eq ,vsb 'left)))) + :button (:radio . (and scroll-bar-mode + (eq (frame-parameter + nil 'vertical-scroll-bars) + 'left))))) (bindings--define-key menu [none] - `(menu-item "None" - menu-bar-no-scroll-bar - :help "Turn off scroll-bar" + '(menu-item "No Vertical Scroll Bar" menu-bar-no-scroll-bar + :help "Turn off vertical scroll bar" :visible (display-graphic-p) - :button (:radio . (not ,vsb)))) + :button (:radio . (eq scroll-bar-mode nil)))) menu)) (defun menu-bar-frame-for-menubar () @@ -1057,24 +1043,24 @@ The selected font will be the default on both the existing and future frames." (when (featurep 'move-toolbar) (defvar menu-bar-showhide-tool-bar-menu - (let ((menu (make-sparse-keymap "Tool-bar"))) + (let ((menu (make-sparse-keymap "Tool Bar"))) (bindings--define-key menu [showhide-tool-bar-left] '(menu-item "On the Left" menu-bar-showhide-tool-bar-menu-customize-enable-left - :help "Tool-bar at the left side" + :help "Tool bar at the left side" :visible (display-graphic-p) :button (:radio . (and tool-bar-mode - (eq (frame-parameter + (frame-parameter (menu-bar-frame-for-menubar) 'tool-bar-position) - 'left))))) + 'left)))) (bindings--define-key menu [showhide-tool-bar-right] '(menu-item "On the Right" menu-bar-showhide-tool-bar-menu-customize-enable-right - :help "Tool-bar at the right side" + :help "Tool bar at the right side" :visible (display-graphic-p) :button (:radio . (and tool-bar-mode @@ -1086,7 +1072,7 @@ The selected font will be the default on both the existing and future frames." (bindings--define-key menu [showhide-tool-bar-bottom] '(menu-item "On the Bottom" menu-bar-showhide-tool-bar-menu-customize-enable-bottom - :help "Tool-bar at the bottom" + :help "Tool bar at the bottom" :visible (display-graphic-p) :button (:radio . (and tool-bar-mode @@ -1098,7 +1084,7 @@ The selected font will be the default on both the existing and future frames." (bindings--define-key menu [showhide-tool-bar-top] '(menu-item "On the Top" menu-bar-showhide-tool-bar-menu-customize-enable-top - :help "Tool-bar at the top" + :help "Tool bar at the top" :visible (display-graphic-p) :button (:radio . (and tool-bar-mode @@ -1110,22 +1096,37 @@ The selected font will be the default on both the existing and future frames." (bindings--define-key menu [showhide-tool-bar-none] '(menu-item "None" menu-bar-showhide-tool-bar-menu-customize-disable - :help "Turn tool-bar off" + :help "Turn tool bar off" :visible (display-graphic-p) :button (:radio . (eq tool-bar-mode nil)))) menu))) +(defun toggle-display-line-numbers () + (interactive) + (if display-line-numbers + (setq display-line-numbers nil) + (setq display-line-numbers t)) + (force-mode-line-update)) + (defvar menu-bar-showhide-menu (let ((menu (make-sparse-keymap "Show/Hide"))) + (bindings--define-key menu [display-line-numbers] + `(menu-item "Line Numbers for All Lines" + ,(lambda () + (interactive) + (toggle-display-line-numbers)) + :help "Show the line number alongside each line" + :button (:toggle . display-line-numbers))) + (bindings--define-key menu [column-number-mode] (menu-bar-make-mm-toggle column-number-mode - "Column Numbers" + "Column Numbers in Mode Line" "Show the current column number in the mode line")) (bindings--define-key menu [line-number-mode] (menu-bar-make-mm-toggle line-number-mode - "Line Numbers" + "Line Numbers in Mode Line" "Show the current line number in the mode line")) (bindings--define-key menu [size-indication-mode] @@ -1168,7 +1169,7 @@ mail status in mode line")) :visible (display-graphic-p))) (bindings--define-key menu [showhide-scroll-bar] - `(menu-item "Scroll-bar" ,menu-bar-showhide-scroll-bar-menu + `(menu-item "Scroll Bar" ,menu-bar-showhide-scroll-bar-menu :visible (display-graphic-p))) (bindings--define-key menu [showhide-tooltip-mode] @@ -1178,8 +1179,8 @@ mail status in mode line")) :button (:toggle . tooltip-mode))) (bindings--define-key menu [menu-bar-mode] - '(menu-item "Menu-bar" toggle-menu-bar-mode-from-frame - :help "Turn menu-bar on/off" + '(menu-item "Menu Bar" toggle-menu-bar-mode-from-frame + :help "Turn menu bar on/off" :button (:toggle . (menu-bar-positive-p (frame-parameter (menu-bar-frame-for-menubar) @@ -1188,12 +1189,12 @@ mail status in mode line")) (if (and (boundp 'menu-bar-showhide-tool-bar-menu) (keymapp menu-bar-showhide-tool-bar-menu)) (bindings--define-key menu [showhide-tool-bar] - `(menu-item "Tool-bar" ,menu-bar-showhide-tool-bar-menu + `(menu-item "Tool Bar" ,menu-bar-showhide-tool-bar-menu :visible (display-graphic-p))) ;; else not tool bar that can move. (bindings--define-key menu [showhide-tool-bar] - '(menu-item "Tool-bar" toggle-tool-bar-mode-from-frame - :help "Turn tool-bar on/off" + '(menu-item "Tool Bar" toggle-tool-bar-mode-from-frame + :help "Turn tool bar on/off" :visible (display-graphic-p) :button (:toggle . (menu-bar-positive-p @@ -1898,7 +1899,10 @@ updating the menu." (defun kill-this-buffer () ; for the menu bar "Kill the current buffer. When called in the minibuffer, get out of the minibuffer -using `abort-recursive-edit'." +using `abort-recursive-edit'. + +This command can be reliably invoked only from the menu bar, +otherwise it could decide to silently do nothing." (interactive) (cond ;; Don't do anything when `menu-frame' is not alive or visible @@ -1971,7 +1975,7 @@ using `abort-recursive-edit'." "Insert the stretch of previously-killed text selected from menu. The menu shows all the killed text sequences stored in `kill-ring'." (interactive "*") - (push-mark (point)) + (push-mark) (insert last-command-event)) @@ -2265,11 +2269,11 @@ created in the future." (assq-delete-all 'menu-bar-lines default-frame-alist))))) ;; Make the message appear when Emacs is idle. We can not call message - ;; directly. The minor-mode message "Menu-bar mode disabled" comes + ;; directly. The minor-mode message "Menu Bar mode disabled" comes ;; after this function returns, overwriting any message we do here. (when (and (called-interactively-p 'interactive) (not menu-bar-mode)) (run-with-idle-timer 0 nil 'message - "Menu-bar mode disabled. Use M-x menu-bar-mode to make the menu bar appear."))) + "Menu Bar mode disabled. Use M-x menu-bar-mode to make the menu bar appear."))) ;;;###autoload ;; (This does not work right unless it comes after the above definition.) diff --git a/lisp/mh-e/mh-acros.el b/lisp/mh-e/mh-acros.el index 0c89efbe3c1..d424247a4fc 100644 --- a/lisp/mh-e/mh-acros.el +++ b/lisp/mh-e/mh-acros.el @@ -90,10 +90,9 @@ loads \"cl\" appropriately." "Create function NAME. If FUNCTION exists, then NAME becomes an alias for FUNCTION. Otherwise, create function NAME with ARG-LIST and BODY." - (let ((defined-p (fboundp function))) - (if defined-p - `(defalias ',name ',function) - `(defun ,name ,arg-list ,@body)))) + `(if (fboundp ',function) + (defalias ',name ',function) + (defun ,name ,arg-list ,@body))) (put 'defun-mh 'lisp-indent-function 'defun) (put 'defun-mh 'doc-string-elt 4) diff --git a/lisp/mh-e/mh-alias.el b/lisp/mh-e/mh-alias.el index e2f747cf92d..d62ac671ea1 100644 --- a/lisp/mh-e/mh-alias.el +++ b/lisp/mh-e/mh-alias.el @@ -252,8 +252,9 @@ Blind aliases or users from /etc/passwd are not expanded." (t (mh-alias-ali alias)))) -(mh-require 'crm nil t) ; completing-read-multiple -(mh-require 'multi-prompt nil t) +(eval-and-compile + (mh-require 'crm nil t) ; completing-read-multiple + (mh-require 'multi-prompt nil t)) ;;;###mh-autoload (defun mh-read-address (prompt) @@ -589,7 +590,7 @@ filing messages." (set-buffer (get-buffer-create mh-temp-buffer)) (insert-file-contents (mh-msg-filename (mh-get-msg-num t)))) ((eq major-mode 'mh-folder-mode) - (error "Cursor not pointing to a message"))) + (user-error "Cursor not pointing to a message"))) (let* ((address (or (mh-extract-from-header-value) (error "Message has no From: header"))) (alias (mh-alias-suggest-alias address))) diff --git a/lisp/mh-e/mh-compat.el b/lisp/mh-e/mh-compat.el index 3f3990e8695..dbdadb10bf6 100644 --- a/lisp/mh-e/mh-compat.el +++ b/lisp/mh-e/mh-compat.el @@ -40,7 +40,7 @@ ;; Items are listed alphabetically (except for mh-require which is ;; needed sooner it would normally appear). -(require 'mh-acros) +(eval-when-compile (require 'mh-acros)) (mh-do-in-gnu-emacs (defalias 'mh-require 'require)) @@ -316,15 +316,14 @@ XEmacs does not have `test-completion'. This function returns nil on that system." nil) ;; Copy of constant from url-util.el in Emacs 22; needed by Emacs 21. -(if (not (boundp 'url-unreserved-chars)) - (defconst mh-url-unreserved-chars - '( - ?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z - ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z - ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 - ?- ?_ ?. ?! ?~ ?* ?' ?\( ?\)) - "A list of characters that are _NOT_ reserved in the URL spec. -This is taken from RFC 2396.")) +(defconst mh-url-unreserved-chars + '( + ?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z + ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z + ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 + ?- ?_ ?. ?! ?~ ?* ?' ?\( ?\)) + "A list of characters that are _NOT_ reserved in the URL spec. +This is taken from RFC 2396.") (defun-mh mh-url-hexify-string url-hexify-string (str) "Escape characters in a string. @@ -374,7 +373,6 @@ XEmacs." (provide 'mh-compat) ;; Local Variables: -;; no-byte-compile: t ;; indent-tabs-mode: nil ;; sentence-end-double-space: nil ;; End: diff --git a/lisp/mh-e/mh-folder.el b/lisp/mh-e/mh-folder.el index acef35d6cd2..f846f179433 100644 --- a/lisp/mh-e/mh-folder.el +++ b/lisp/mh-e/mh-folder.el @@ -525,7 +525,7 @@ font-lock is done highlighting.") (cons (current-buffer) nil))))) ;; Register mh-folder-mode as supporting which-function-mode... -(mh-require 'which-func nil t) +(eval-and-compile (mh-require 'which-func nil t)) (when (and (boundp 'which-func-modes) (listp which-func-modes)) (add-to-list 'which-func-modes 'mh-folder-mode)) diff --git a/lisp/mh-e/mh-gnus.el b/lisp/mh-e/mh-gnus.el index 3afdb7501ff..318759ddc1b 100644 --- a/lisp/mh-e/mh-gnus.el +++ b/lisp/mh-e/mh-gnus.el @@ -30,11 +30,12 @@ (require 'mh-e) -(mh-require 'gnus-util nil t) -(mh-require 'mm-bodies nil t) -(mh-require 'mm-decode nil t) -(mh-require 'mm-view nil t) -(mh-require 'mml nil t) +(eval-and-compile + (mh-require 'gnus-util nil t) + (mh-require 'mm-bodies nil t) + (mh-require 'mm-decode nil t) + (mh-require 'mm-view nil t) + (mh-require 'mml nil t)) ;; Copy of function from gnus-util.el. ;; TODO This is not in Gnus 5.11. @@ -170,7 +171,6 @@ PROMPT overrides the default one used to ask user for a file name." (provide 'mh-gnus) ;; Local Variables: -;; no-byte-compile: t ;; no-update-autoloads: t ;; indent-tabs-mode: nil ;; sentence-end-double-space: nil diff --git a/lisp/mh-e/mh-junk.el b/lisp/mh-e/mh-junk.el index 54c3daa423a..25e116cb28e 100644 --- a/lisp/mh-e/mh-junk.el +++ b/lisp/mh-e/mh-junk.el @@ -169,7 +169,7 @@ classified as spam (see the option `mh-junk-program')." -;; Spamassassin Interface +;; SpamAssassin Interface (defvar mh-spamassassin-executable (executable-find "spamassassin")) (defvar mh-sa-learn-executable (executable-find "sa-learn")) diff --git a/lisp/mh-e/mh-search.el b/lisp/mh-e/mh-search.el index 099f922a5e8..b0fdfce8e87 100644 --- a/lisp/mh-e/mh-search.el +++ b/lisp/mh-e/mh-search.el @@ -1416,7 +1416,7 @@ being the list of messages originally from that folder." (when cur-msg (mh-goto-msg cur-msg t t)) (set-buffer-modified-p old-buffer-modified-flag))) -(mh-require 'which-func nil t) +(eval-and-compile (mh-require 'which-func nil t)) ;; Shush compiler. (defvar which-func-mode) ; < Emacs 22, XEmacs @@ -1517,8 +1517,8 @@ construct the base name." (setq string (mh-replace-string "-lbrace" " ")) (setq string (mh-replace-string "-rbrace" " ")) (setq string (mh-replace-string "-search" " ")) - (subst-char-in-region (point-min) (point-max) ?( ? t) - (subst-char-in-region (point-min) (point-max) ?) ? t) + (subst-char-in-region (point-min) (point-max) ?\( ? t) + (subst-char-in-region (point-min) (point-max) ?\) ? t) (subst-char-in-region (point-min) (point-max) ?- ? t) (goto-char (point-min)) (while (and (not (eobp)) (memq (char-after) '(? ?\t ?\n ?\r ?_))) diff --git a/lisp/mh-e/mh-utils.el b/lisp/mh-e/mh-utils.el index 3bc5fef51a8..1ed2e0f8713 100644 --- a/lisp/mh-e/mh-utils.el +++ b/lisp/mh-e/mh-utils.el @@ -349,11 +349,9 @@ the cursor is not pointing to a message." (string-to-number (buffer-substring (match-beginning 1) (match-end 1)))) (error-if-no-message - (error "Cursor not pointing to message")) + (user-error "Cursor not pointing to message")) (t nil)))) -(add-to-list 'debug-ignored-errors "^Cursor not pointing to message$") - ;;; Folder Cache and Access diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 00722ec4b15..e5b1029c01f 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -746,7 +746,7 @@ If the current buffer is not a minibuffer, erase its entire contents." (defcustom completion-auto-help t "Non-nil means automatically provide help for invalid completion input. -If the value is t the *Completion* buffer is displayed whenever completion +If the value is t the *Completions* buffer is displayed whenever completion is requested but cannot be done. If the value is `lazy', the *Completions* buffer is only displayed after the second failed attempt to complete." @@ -834,7 +834,8 @@ styles for specific categories, such as files, buffers, etc." (defvar completion-category-defaults '((buffer (styles . (basic substring))) (unicode-name (styles . (basic substring))) - (project-file (styles . (basic substring)))) + (project-file (styles . (basic substring))) + (info-menu (styles . (basic substring)))) "Default settings for specific completion categories. Each entry has the shape (CATEGORY . ALIST) where ALIST is an association list that can specify properties such as: @@ -3005,7 +3006,7 @@ PATTERN is as returned by `completion-pcm--string->pattern'." (let ((poss ())) (dolist (c compl) (when (string-match-p regex c) (push c poss))) - poss))))) + (nreverse poss)))))) (defun completion-pcm--hilit-commonality (pattern completions) (when completions @@ -3257,7 +3258,7 @@ the same set of elements." "\\)\\'"))) (dolist (f all) (unless (string-match-p re f) (push f try))) - (or try all)))) + (or (nreverse try) all)))) (defun completion-pcm--merge-try (pattern all prefix suffix) diff --git a/lisp/mouse.el b/lisp/mouse.el index 0f1d4460405..2fbaaadf16b 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -380,7 +380,7 @@ This command must be bound to a mouse click." (defun mouse-drag-line (start-event line) "Drag a mode line, header line, or vertical line with the mouse. -START-EVENT is the starting mouse-event of the drag action. LINE +START-EVENT is the starting mouse event of the drag action. LINE must be one of the symbols `header', `mode', or `vertical'." ;; Give temporary modes such as isearch a chance to turn off. (run-hooks 'mouse-leave-buffer-hook) @@ -405,29 +405,15 @@ must be one of the symbols `header', `mode', or `vertical'." ;; window's edge we drag. (cond ((eq line 'header) - (if (window-at-side-p window 'top) - ;; We can't drag the header line of a topmost window. - (setq draggable nil) - ;; Drag bottom edge of window above the header line. - (setq window (window-in-direction 'above window t)))) - ((eq line 'mode) - (if (and (window-at-side-p window 'bottom) - ;; Allow resizing the minibuffer window if it's on the - ;; same frame as and immediately below `window', and it's - ;; either active or `resize-mini-windows' is nil. - (let ((minibuffer-window (minibuffer-window frame))) - (not (and (eq (window-frame minibuffer-window) frame) - (or (not resize-mini-windows) - (eq minibuffer-window - (active-minibuffer-window))))))) - (setq draggable nil))) + ;; Drag bottom edge of window above the header line. + (setq window (window-in-direction 'above window t))) + ((eq line 'mode)) ((eq line 'vertical) (let ((divider-width (frame-right-divider-width frame))) (when (and (or (not (numberp divider-width)) (zerop divider-width)) (eq (frame-parameter frame 'vertical-scroll-bars) 'left)) (setq window (window-in-direction 'left window t)))))) - (let* ((exitfun nil) (move (lambda (event) (interactive "e") @@ -530,20 +516,405 @@ must be one of the symbols `header', `mode', or `vertical'." t (lambda () (setq track-mouse old-track-mouse))))))) (defun mouse-drag-mode-line (start-event) - "Change the height of a window by dragging on the mode line." + "Change the height of a window by dragging on its mode line. +START-EVENT is the starting mouse event of the drag action. + +If the drag happens in a mode line on the bottom of a frame and +that frame's `drag-with-mode-line' parameter is non-nil, drag the +frame instead." (interactive "e") - (mouse-drag-line start-event 'mode)) + (let* ((start (event-start start-event)) + (window (posn-window start)) + (frame (window-frame window))) + (cond + ((not (window-live-p window))) + ((or (not (window-at-side-p window 'bottom)) + ;; Allow resizing the minibuffer window if it's on the + ;; same frame as and immediately below `window', and it's + ;; either active or `resize-mini-windows' is nil. + (let ((minibuffer-window (minibuffer-window frame))) + (and (eq (window-frame minibuffer-window) frame) + (or (not resize-mini-windows) + (eq minibuffer-window + (active-minibuffer-window)))))) + (mouse-drag-line start-event 'mode)) + ((and (frame-parameter frame 'drag-with-mode-line) + (window-at-side-p window 'bottom) + (let ((minibuffer-window (minibuffer-window frame))) + (not (eq (window-frame minibuffer-window) frame)))) + ;; Drag frame when the window is on the bottom of its frame and + ;; there is no minibuffer window below. + (mouse-drag-frame start-event 'move))))) (defun mouse-drag-header-line (start-event) - "Change the height of a window by dragging on the header line." + "Change the height of a window by dragging on its header line. +START-EVENT is the starting mouse event of the drag action. + +If the drag happens in a header line on the top of a frame and +that frame's `drag-with-header-line' parameter is non-nil, drag +the frame instead." (interactive "e") - (mouse-drag-line start-event 'header)) + (let* ((start (event-start start-event)) + (window (posn-window start))) + (if (and (window-live-p window) + (not (window-at-side-p window 'top))) + (mouse-drag-line start-event 'header) + (let ((frame (window-frame window))) + (when (frame-parameter frame 'drag-with-header-line) + (mouse-drag-frame start-event 'move)))))) (defun mouse-drag-vertical-line (start-event) - "Change the width of a window by dragging on the vertical line." + "Change the width of a window by dragging on a vertical line. +START-EVENT is the starting mouse event of the drag action." (interactive "e") (mouse-drag-line start-event 'vertical)) +(defun mouse-resize-frame (frame x-diff y-diff &optional x-move y-move) + "Helper function for `mouse-drag-frame'." + (let* ((frame-x-y (frame-position frame)) + (frame-x (car frame-x-y)) + (frame-y (cdr frame-x-y)) + alist) + (if (> x-diff 0) + (when x-move + (setq x-diff (min x-diff frame-x)) + (setq x-move (- frame-x x-diff))) + (let* ((min-width (frame-windows-min-size frame t nil t)) + (min-diff (max 0 (- (frame-inner-width frame) min-width)))) + (setq x-diff (max x-diff (- min-diff))) + (when x-move + (setq x-move (+ frame-x (- x-diff)))))) + + (if (> y-diff 0) + (when y-move + (setq y-diff (min y-diff frame-y)) + (setq y-move (- frame-y y-diff))) + (let* ((min-height (frame-windows-min-size frame nil nil t)) + (min-diff (max 0 (- (frame-inner-height frame) min-height)))) + (setq y-diff (max y-diff (- min-diff))) + (when y-move + (setq y-move (+ frame-y (- y-diff)))))) + + (unless (zerop x-diff) + (when x-move + (push `(left . ,x-move) alist)) + (push `(width . (text-pixels . ,(+ (frame-text-width frame) x-diff))) + alist)) + (unless (zerop y-diff) + (when y-move + (push `(top . ,y-move) alist)) + (push `(height . (text-pixels . ,(+ (frame-text-height frame) y-diff))) + alist)) + (when alist + (modify-frame-parameters frame alist)))) + +(defun mouse-drag-frame (start-event part) + "Drag a frame or one of its edges with the mouse. +START-EVENT is the starting mouse event of the drag action. Its +position window denotes the frame that will be dragged. + +PART specifies the part that has been dragged and must be one of +the symbols 'left', 'top', 'right', 'bottom', 'top-left', +'top-right', 'bottom-left', 'bottom-right' to drag an internal +border or edge. If PART equals 'move', this means to move the +frame with the mouse." + ;; Give temporary modes such as isearch a chance to turn off. + (run-hooks 'mouse-leave-buffer-hook) + (let* ((echo-keystrokes 0) + (start (event-start start-event)) + (window (posn-window start)) + ;; FRAME is the frame to drag. + (frame (if (window-live-p window) + (window-frame window) + window)) + (width (frame-native-width frame)) + (height (frame-native-height frame)) + ;; PARENT is the parent frame of FRAME or, if FRAME is a + ;; top-level frame, FRAME's workarea. + (parent (frame-parent frame)) + (parent-edges + (if parent + `(0 0 ,(frame-native-width parent) ,(frame-native-height parent)) + (let* ((attributes + (car (display-monitor-attributes-list))) + (workarea (assq 'workarea attributes))) + (and workarea + `(,(nth 1 workarea) ,(nth 2 workarea) + ,(+ (nth 1 workarea) (nth 3 workarea)) + ,(+ (nth 2 workarea) (nth 4 workarea))))))) + (parent-left (and parent-edges (nth 0 parent-edges))) + (parent-top (and parent-edges (nth 1 parent-edges))) + (parent-right (and parent-edges (nth 2 parent-edges))) + (parent-bottom (and parent-edges (nth 3 parent-edges))) + ;; `pos-x' and `pos-y' record the x- and y-coordinates of the + ;; last sampled mouse position. Note that we sample absolute + ;; mouse positions to avoid that moving the mouse from one + ;; frame into another gets into our way. `last-x' and `last-y' + ;; records the x- and y-coordinates of the previously sampled + ;; position. The differences between `last-x' and `pos-x' as + ;; well as `last-y' and `pos-y' determine the amount the mouse + ;; has been dragged between the last two samples. + pos-x-y pos-x pos-y + (last-x-y (mouse-absolute-pixel-position)) + (last-x (car last-x-y)) + (last-y (cdr last-x-y)) + ;; `snap-x' and `snap-y' record the x- and y-coordinates of the + ;; mouse position when FRAME snapped. As soon as the + ;; difference between `pos-x' and `snap-x' (or `pos-y' and + ;; `snap-y') exceeds the value of FRAME's `snap-width' + ;; parameter, unsnap FRAME (at the respective side). `snap-x' + ;; and `snap-y' nil mean FRAME is currently not snapped. + snap-x snap-y + (exitfun nil) + (move + (lambda (event) + (interactive "e") + (when (consp event) + (setq pos-x-y (mouse-absolute-pixel-position)) + (setq pos-x (car pos-x-y)) + (setq pos-y (cdr pos-x-y)) + (cond + ((eq part 'left) + (mouse-resize-frame frame (- last-x pos-x) 0 t)) + ((eq part 'top) + (mouse-resize-frame frame 0 (- last-y pos-y) nil t)) + ((eq part 'right) + (mouse-resize-frame frame (- pos-x last-x) 0)) + ((eq part 'bottom) + (mouse-resize-frame frame 0 (- pos-y last-y))) + ((eq part 'top-left) + (mouse-resize-frame + frame (- last-x pos-x) (- last-y pos-y) t t)) + ((eq part 'top-right) + (mouse-resize-frame + frame (- pos-x last-x) (- last-y pos-y) nil t)) + ((eq part 'bottom-left) + (mouse-resize-frame + frame (- last-x pos-x) (- pos-y last-y) t)) + ((eq part 'bottom-right) + (mouse-resize-frame + frame (- pos-x last-x) (- pos-y last-y))) + ((eq part 'move) + (let* ((old-position (frame-position frame)) + (old-left (car old-position)) + (old-top (cdr old-position)) + (left (+ old-left (- pos-x last-x))) + (top (+ old-top (- pos-y last-y))) + right bottom + ;; `snap-width' (maybe also a yet to be provided + ;; `snap-height') could become floats to handle + ;; proportionality wrt PARENT. We don't do any + ;; checks on this parameter so far. + (snap-width (frame-parameter frame 'snap-width))) + ;; Docking and constraining. + (when (and (numberp snap-width) parent-edges) + (cond + ;; Docking at the left parent edge. + ((< pos-x last-x) + (cond + ((and (> left parent-left) + (<= (- left parent-left) snap-width)) + ;; Snap when the mouse moved leftward and + ;; FRAME's left edge would end up within + ;; `snap-width' pixels from PARENT's left edge. + (setq snap-x pos-x) + (setq left parent-left)) + ((and (<= left parent-left) + (<= (- parent-left left) snap-width) + snap-x (<= (- snap-x pos-x) snap-width)) + ;; Stay snapped when the mouse moved leftward + ;; but not more than `snap-width' pixels from + ;; the time FRAME snapped. + (setq left parent-left)) + (t + ;; Unsnap when the mouse moved more than + ;; `snap-width' pixels leftward from the time + ;; FRAME snapped. + (setq snap-x nil)))) + ((> pos-x last-x) + (setq right (+ left width)) + (cond + ((and (< right parent-right) + (<= (- parent-right right) snap-width)) + ;; Snap when the mouse moved rightward and + ;; FRAME's right edge would end up within + ;; `snap-width' pixels from PARENT's right edge. + (setq snap-x pos-x) + (setq left (- parent-right width))) + ((and (>= right parent-right) + (<= (- right parent-right) snap-width) + snap-x (<= (- pos-x snap-x) snap-width)) + ;; Stay snapped when the mouse moved rightward + ;; but not more more than `snap-width' pixels + ;; from the time FRAME snapped. + (setq left (- parent-right width))) + (t + ;; Unsnap when the mouse moved rightward more + ;; than `snap-width' pixels from the time FRAME + ;; snapped. + (setq snap-x nil))))) + + (cond + ((< pos-y last-y) + (cond + ((and (> top parent-top) + (<= (- top parent-top) snap-width)) + ;; Snap when the mouse moved upward and FRAME's + ;; top edge would end up within `snap-width' + ;; pixels from PARENT's top edge. + (setq snap-y pos-y) + (setq top parent-top)) + ((and (<= top parent-top) + (<= (- parent-top top) snap-width) + snap-y (<= (- snap-y pos-y) snap-width)) + ;; Stay snapped when the mouse moved upward but + ;; not more more than `snap-width' pixels from + ;; the time FRAME snapped. + (setq top parent-top)) + (t + ;; Unsnap when the mouse moved upward more than + ;; `snap-width' pixels from the time FRAME + ;; snapped. + (setq snap-y nil)))) + ((> pos-y last-y) + (setq bottom (+ top height)) + (cond + ((and (< bottom parent-bottom) + (<= (- parent-bottom bottom) snap-width)) + ;; Snap when the mouse moved downward and + ;; FRAME's bottom edge would end up within + ;; `snap-width' pixels from PARENT's bottom + ;; edge. + (setq snap-y pos-y) + (setq top (- parent-bottom height))) + ((and (>= bottom parent-bottom) + (<= (- bottom parent-bottom) snap-width) + snap-y (<= (- pos-y snap-y) snap-width)) + ;; Stay snapped when the mouse moved downward + ;; but not more more than `snap-width' pixels + ;; from the time FRAME snapped. + (setq top (- parent-bottom height))) + (t + ;; Unsnap when the mouse moved downward more + ;; than `snap-width' pixels from the time FRAME + ;; snapped. + (setq snap-y nil)))))) + + ;; If requested, constrain FRAME's draggable areas to + ;; PARENT's edges. The `top-visible' parameter should + ;; be set when FRAME has a draggable header-line. If + ;; set to a number, it ascertains that the top of + ;; FRAME is always constrained to the top of PARENT + ;; and that at least as many pixels of FRAME as + ;; specified by that number are visible on each of the + ;; three remaining sides of PARENT. + ;; + ;; The `bottom-visible' parameter should be set when + ;; FRAME has a draggable mode-line. If set to a + ;; number, it ascertains that the bottom of FRAME is + ;; always constrained to the bottom of PARENT and that + ;; at least as many pixels of FRAME as specified by + ;; that number are visible on each of the three + ;; remaining sides of PARENT. + (let ((par (frame-parameter frame 'top-visible)) + bottom-visible) + (unless par + (setq par (frame-parameter frame 'bottom-visible)) + (setq bottom-visible t)) + (when (and (numberp par) parent-edges) + (setq left + (max (min (- parent-right par) left) + (+ (- parent-left width) par))) + (setq top + (if bottom-visible + (min (max top (- parent-top (- height par))) + (- parent-bottom height)) + (min (max top parent-top) + (- parent-bottom par)))))) + + ;; Use `modify-frame-parameters' since `left' and + ;; `top' may want to move FRAME out of its PARENT. + (modify-frame-parameters + frame + `((left . (+ ,left)) (top . (+ ,top))))))) + (setq last-x pos-x) + (setq last-y pos-y)))) + (old-track-mouse track-mouse)) + ;; Start tracking. The special value 'dragging' signals the + ;; display engine to freeze the mouse pointer shape for as long + ;; as we drag. + (setq track-mouse 'dragging) + ;; Loop reading events and sampling the position of the mouse. + (setq exitfun + (set-transient-map + (let ((map (make-sparse-keymap))) + (define-key map [switch-frame] #'ignore) + (define-key map [select-window] #'ignore) + (define-key map [scroll-bar-movement] #'ignore) + (define-key map [mouse-movement] move) + ;; Swallow drag-mouse-1 events to avoid selecting some other window. + (define-key map [drag-mouse-1] + (lambda () (interactive) (funcall exitfun))) + ;; Some of the events will of course end up looked up + ;; with a mode-line, header-line or vertical-line prefix ... + (define-key map [mode-line] map) + (define-key map [header-line] map) + (define-key map [vertical-line] map) + ;; ... and some maybe even with a right- or bottom-divider + ;; prefix. + (define-key map [right-divider] map) + (define-key map [bottom-divider] map) + map) + t (lambda () (setq track-mouse old-track-mouse)))))) + +(defun mouse-drag-left-edge (start-event) + "Drag left edge of a frame with the mouse. +START-EVENT is the starting mouse event of the drag action." + (interactive "e") + (mouse-drag-frame start-event 'left)) + +(defun mouse-drag-top-left-corner (start-event) + "Drag top left corner of a frame with the mouse. +START-EVENT is the starting mouse event of the drag action." + (interactive "e") + (mouse-drag-frame start-event 'top-left)) + +(defun mouse-drag-top-edge (start-event) + "Drag top edge of a frame with the mouse. +START-EVENT is the starting mouse event of the drag action." + (interactive "e") + (mouse-drag-frame start-event 'top)) + +(defun mouse-drag-top-right-corner (start-event) + "Drag top right corner of a frame with the mouse. +START-EVENT is the starting mouse event of the drag action." + (interactive "e") + (mouse-drag-frame start-event 'top-right)) + +(defun mouse-drag-right-edge (start-event) + "Drag right edge of a frame with the mouse. +START-EVENT is the starting mouse event of the drag action." + (interactive "e") + (mouse-drag-frame start-event 'right)) + +(defun mouse-drag-bottom-right-corner (start-event) + "Drag bottom right corner of a frame with the mouse. +START-EVENT is the starting mouse event of the drag action." + (interactive "e") + (mouse-drag-frame start-event 'bottom-right)) + +(defun mouse-drag-bottom-edge (start-event) + "Drag bottom edge of a frame with the mouse. +START-EVENT is the starting mouse event of the drag action." + (interactive "e") + (mouse-drag-frame start-event 'bottom)) + +(defun mouse-drag-bottom-left-corner (start-event) + "Drag bottom left corner of a frame with the mouse. +START-EVENT is the starting mouse event of the drag action." + (interactive "e") + (mouse-drag-frame start-event 'bottom-left)) + (defcustom mouse-select-region-move-to-beginning nil "Effect of selecting a region extending backward from double click. Nil means keep point at the position clicked (region end); @@ -714,12 +1085,19 @@ Upon exit, point is at the far edge of the newly visible text." Highlight the drag area as you move the mouse. This must be bound to a button-down mouse event. In Transient Mark mode, the highlighting remains as long as the mark -remains active. Otherwise, it remains until the next input event." - (interactive "e") - ;; Give temporary modes such as isearch a chance to turn off. - (run-hooks 'mouse-leave-buffer-hook) - (mouse-drag-track start-event)) +remains active. Otherwise, it remains until the next input event. +When the region already exists and `mouse-drag-and-drop-region' +is non-nil, this moves the entire region of text to where mouse +is dragged over to." + (interactive "e") + (if (and mouse-drag-and-drop-region + (not (member 'triple (event-modifiers start-event))) + (equal (mouse-posn-property (event-start start-event) 'face) 'region)) + (mouse-drag-and-drop-region start-event) + ;; Give temporary modes such as isearch a chance to turn off. + (run-hooks 'mouse-leave-buffer-hook) + (mouse-drag-track start-event))) (defun mouse-posn-property (pos property) "Look for a property at click position. @@ -1135,7 +1513,7 @@ regardless of where you click." (deactivate-mark))) (or mouse-yank-at-point (mouse-set-point click)) (let ((primary (gui-get-primary-selection))) - (push-mark (point)) + (push-mark) (insert-for-yank primary))) (defun mouse-kill-ring-save (click) @@ -1937,6 +2315,84 @@ choose a font." t (called-interactively-p 'interactive))))))))) +;; Drag and drop support. +(defcustom mouse-drag-and-drop-region nil + "If non-nil, dragging the mouse drags the region, if that exists. +If the value is a modifier, such as `control' or `shift' or `meta', +then if that modifier key is pressed when dropping the region, region +text is copied instead of being cut." + :type 'symbol + :version "26.1" + :group 'mouse) + +(defun mouse-drag-and-drop-region (event) + "Move text in the region to point where mouse is dragged to. +The transportation of text is also referred as `drag and drop'. +When text is dragged over to a different buffer, or if a +modifier key was pressed when dropping, and the value of the +variable `mouse-drag-and-drop-region' is that modifier, the text +is copied instead of being cut." + (interactive "e") + (require 'tooltip) + (let ((start (region-beginning)) + (end (region-end)) + (point (point)) + (buffer (current-buffer)) + (window (selected-window)) + value-selection) + (track-mouse + ;; When event was click instead of drag, skip loop + (while (progn + (setq event (read-event)) + (mouse-movement-p event)) + (unless value-selection ; initialization + (delete-overlay mouse-secondary-overlay) + (setq value-selection (buffer-substring start end)) + (move-overlay mouse-secondary-overlay start end)) ; (deactivate-mark) + (ignore-errors (deactivate-mark) ; care existing region in other window + (mouse-set-point event) + (tooltip-show value-selection))) + (tooltip-hide)) + ;; Do not modify buffer under mouse when "event was click", + ;; "drag negligible", or + ;; "drag to read-only". + (if (or (equal (mouse-posn-property (event-end event) 'face) 'region) ; "event was click" + (member 'secondary-selection ; "drag negligible" + (mapcar (lambda (xxx) (overlay-get xxx 'face)) + (overlays-at (posn-point (event-end event))))) + buffer-read-only) + ;; Do not modify buffer under mouse. + (cond + ;; "drag negligible" or "drag to read-only", restore region. + (value-selection + (select-window window) ; In case miss drag to other window + (goto-char point) + (setq deactivate-mark nil) + (activate-mark)) + ;; "event was click" + (t + (deactivate-mark) + (mouse-set-point event))) + ;; Modify buffer under mouse by inserting text. + (push-mark) + (insert value-selection) + (when (not (equal (mark) (point))) ; on success insert + (setq deactivate-mark nil) + (activate-mark)) ; have region on destination + ;; Take care of initial region on source. + (if (equal (current-buffer) buffer) ; when same buffer + (let (deactivate-mark) ; remove text + (unless (member mouse-drag-and-drop-region (event-modifiers event)) + (kill-region (overlay-start mouse-secondary-overlay) + (overlay-end mouse-secondary-overlay)))) + (let ((window1 (selected-window))) ; when beyond buffer + (select-window window) + (goto-char point) ; restore point on source window + (activate-mark) ; restore region + (select-window window1)))) + (delete-overlay mouse-secondary-overlay))) + + ;;; Bindings for mouse commands. (global-set-key [down-mouse-1] 'mouse-drag-region) @@ -1993,6 +2449,22 @@ choose a font." (global-set-key [bottom-divider down-mouse-1] 'mouse-drag-mode-line) (global-set-key [bottom-divider mouse-1] 'ignore) (global-set-key [bottom-divider C-mouse-2] 'mouse-split-window-horizontally) +(global-set-key [left-edge down-mouse-1] 'mouse-drag-left-edge) +(global-set-key [left-edge mouse-1] 'ignore) +(global-set-key [top-left-corner down-mouse-1] 'mouse-drag-top-left-corner) +(global-set-key [top-left-corner mouse-1] 'ignore) +(global-set-key [top-edge down-mouse-1] 'mouse-drag-top-edge) +(global-set-key [top-edge mouse-1] 'ignore) +(global-set-key [top-right-corner down-mouse-1] 'mouse-drag-top-right-corner) +(global-set-key [top-right-corner mouse-1] 'ignore) +(global-set-key [right-edge down-mouse-1] 'mouse-drag-right-edge) +(global-set-key [right-edge mouse-1] 'ignore) +(global-set-key [bottom-right-corner down-mouse-1] 'mouse-drag-bottom-right-corner) +(global-set-key [bottom-right-corner mouse-1] 'ignore) +(global-set-key [bottom-edge down-mouse-1] 'mouse-drag-bottom-edge) +(global-set-key [bottom-edge mouse-1] 'ignore) +(global-set-key [bottom-left-corner down-mouse-1] 'mouse-drag-bottom-left-corner) +(global-set-key [bottom-left-corner mouse-1] 'ignore) (provide 'mouse) diff --git a/lisp/mpc.el b/lisp/mpc.el index e56e7e42ba8..cce752739be 100644 --- a/lisp/mpc.el +++ b/lisp/mpc.el @@ -1131,8 +1131,8 @@ If PLAYLIST is t or nil or missing, use the main playlist." map)) (easy-menu-define mpc-mode-menu mpc-mode-map - "Menu for MPC.el." - '("MPC.el" + "Menu for MPC mode." + '("MPC" ["Play/Pause" mpc-toggle-play] ;FIXME: Add one of ⏯/▶/⏸ in there? ["Next Track" mpc-next] ;FIXME: Add ⇥ there? ["Previous Track" mpc-prev] ;FIXME: Add ⇤ there? diff --git a/lisp/mwheel.el b/lisp/mwheel.el index eaeb831e844..1428e5f4d01 100644 --- a/lisp/mwheel.el +++ b/lisp/mwheel.el @@ -187,20 +187,42 @@ This can be slightly disconcerting, but some people prefer it." (defun mwheel-scroll (event) "Scroll up or down according to the EVENT. -This should be bound only to mouse buttons 4 and 5 on non-Windows -systems." +This should be bound only to mouse buttons 4, 5, 6, and 7 on +non-Windows systems." (interactive (list last-input-event)) - (let* ((curwin (if mouse-wheel-follow-mouse - (prog1 - (selected-window) - (select-window (mwheel-event-window event))))) - (buffer (window-buffer curwin)) - (opoint (with-current-buffer buffer - (when (eq (car-safe transient-mark-mode) 'only) - (point)))) + (let* ((selected-window (selected-window)) + (scroll-window + (or (catch 'found + (let* ((window (if mouse-wheel-follow-mouse + (mwheel-event-window event) + (selected-window))) + (frame (when (window-live-p window) + (frame-parameter + (window-frame window) 'mouse-wheel-frame)))) + (when (frame-live-p frame) + (let* ((pos (mouse-absolute-pixel-position)) + (pos-x (car pos)) + (pos-y (cdr pos))) + (walk-window-tree + (lambda (window-1) + (let ((edges (window-edges window-1 nil t t))) + (when (and (<= (nth 0 edges) pos-x) + (<= pos-x (nth 2 edges)) + (<= (nth 1 edges) pos-y) + (<= pos-y (nth 3 edges))) + (throw 'found window-1)))) + frame nil t))))) + (mwheel-event-window event))) + (old-point + (and (eq scroll-window selected-window) + (eq (car-safe transient-mark-mode) 'only) + (window-point))) (mods (delq 'click (delq 'double (delq 'triple (event-modifiers event))))) (amt (assoc mods mouse-wheel-scroll-amount))) + (unless (eq scroll-window selected-window) + ;; Mark window to be scrolled for redisplay. + (select-window scroll-window 'mark-for-redisplay)) ;; Extract the actual amount or find the element that has no modifiers. (if amt (setq amt (cdr amt)) (let ((list-elt mouse-wheel-scroll-amount)) @@ -231,19 +253,29 @@ systems." (condition-case nil (funcall mwheel-scroll-up-function amt) ;; Make sure we do indeed scroll to the end of the buffer. (end-of-buffer (while t (funcall mwheel-scroll-up-function))))) + ((eq button mouse-wheel-left-event) ; for tilt scroll + (when mwheel-tilt-scroll-p + (funcall (if mwheel-flip-direction + mwheel-scroll-right-function + mwheel-scroll-left-function) amt))) + ((eq button mouse-wheel-right-event) ; for tilt scroll + (when mwheel-tilt-scroll-p + (funcall (if mwheel-flip-direction + mwheel-scroll-left-function + mwheel-scroll-right-function) amt))) (t (error "Bad binding in mwheel-scroll")))) - (if curwin (select-window curwin))) - ;; If there is a temporarily active region, deactivate it if - ;; scrolling moves point. - (when opoint - (with-current-buffer buffer - (when (/= opoint (point)) - ;; Call `deactivate-mark' at the original position, so that - ;; the original region is saved to the X selection. - (let ((newpoint (point))) - (goto-char opoint) - (deactivate-mark) - (goto-char newpoint)))))) + (if (eq scroll-window selected-window) + ;; If there is a temporarily active region, deactivate it if + ;; scrolling moved point. + (when (and old-point (/= old-point (window-point))) + ;; Call `deactivate-mark' at the original position, so that + ;; the original region is saved to the X selection. + (let ((new-point (window-point))) + (goto-char old-point) + (deactivate-mark) + (goto-char new-point))) + (select-window selected-window t)))) + (when (and mouse-wheel-click-event mouse-wheel-inhibit-click-time) (if mwheel-inhibit-click-event-timer (cancel-timer mwheel-inhibit-click-event-timer) @@ -276,7 +308,7 @@ the mode if ARG is omitted or nil." (global-unset-key key)))) ;; Setup bindings as needed. (when mouse-wheel-mode - (dolist (event (list mouse-wheel-down-event mouse-wheel-up-event)) + (dolist (event (list mouse-wheel-down-event mouse-wheel-up-event mouse-wheel-right-event mouse-wheel-left-event)) (dolist (key (mapcar (lambda (amt) `[(,@(if (consp amt) (car amt)) ,event)]) mouse-wheel-scroll-amount)) (global-set-key key 'mwheel-scroll) @@ -288,6 +320,45 @@ the mode if ARG is omitted or nil." "Enable mouse wheel support." (mouse-wheel-mode (if uninstall -1 1))) + +;;; For tilt-scroll +;;; +(defcustom mwheel-tilt-scroll-p nil + "Enable scroll using tilting mouse wheel." + :group 'mouse + :type 'boolean + :version "26.1") + +(defcustom mwheel-flip-direction nil + "Swap direction of 'wheel-right and 'wheel-left." + :group 'mouse + :type 'boolean + :version "26.1") + +(defcustom mwheel-scroll-left-function 'scroll-left + "Function that does the job of scrolling left." + :group 'mouse + :type 'function + :version "26.1") + +(defcustom mwheel-scroll-right-function 'scroll-right + "Function that does the job of scrolling right." + :group 'mouse + :type 'function + :version "26.1") + +(defvar mouse-wheel-left-event + (if (or (featurep 'w32-win) (featurep 'ns-win)) + 'wheel-left + (intern "mouse-6")) + "Event used for scrolling left.") + +(defvar mouse-wheel-right-event + (if (or (featurep 'w32-win) (featurep 'ns-win)) + 'wheel-right + (intern "mouse-7")) + "Event used for scrolling right.") + (provide 'mwheel) ;;; mwheel.el ends here diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el index cafdb3ecb06..ecb60e5a4f4 100644 --- a/lisp/net/ange-ftp.el +++ b/lisp/net/ange-ftp.el @@ -4125,15 +4125,15 @@ directory, so that Emacs will know its current contents." (ange-ftp-add-file-entry dir t)) (ange-ftp-real-make-directory dir))))) -(defun ange-ftp-delete-directory (dir &optional recursive) +(defun ange-ftp-delete-directory (dir &optional recursive trash) (if (file-directory-p dir) (let ((parsed (ange-ftp-ftp-name dir))) (if recursive (mapc (lambda (file) (if (file-directory-p file) - (ange-ftp-delete-directory file recursive) - (delete-file file))) + (ange-ftp-delete-directory file recursive trash) + (delete-file file trash))) ;; We do not want to delete "." and "..". (directory-files dir 'full "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"))) @@ -4167,7 +4167,7 @@ directory, so that Emacs will know its current contents." dir (cdr result)))) (ange-ftp-delete-file-entry dir t)) - (ange-ftp-real-delete-directory dir recursive))) + (ange-ftp-real-delete-directory dir recursive trash))) (error "Not a directory: %s" dir))) ;; Make a local copy of FILE and return its name. diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el index a7c879cbfbc..20ae072f652 100644 --- a/lisp/net/browse-url.el +++ b/lisp/net/browse-url.el @@ -45,7 +45,7 @@ ;; browse-url-generic arbitrary ;; browse-url-default-windows-browser MS-Windows browser ;; browse-url-default-macosx-browser macOS browser -;; browse-url-xdg-open Free Desktop xdg-open on Gnome, KDE, Xfce4, LXDE +;; browse-url-xdg-open freedesktop.org xdg-open ;; browse-url-kde KDE konqueror (kfm) ;; browse-url-elinks Elinks Don't know (tried with 0.12.GIT) @@ -878,7 +878,7 @@ The optional NEW-WINDOW argument is not used." (error "Browsing URLs is not supported on this system"))) ((eq system-type 'cygwin) (call-process "cygstart" nil nil nil url)) - (t (w32-shell-execute "open" url)))) + (t (w32-shell-execute "open" (url-unhex-string url))))) (defun browse-url-default-macosx-browser (url &optional _new-window) "Invoke the macOS system's default Web browser. @@ -944,36 +944,14 @@ instead of `browse-url-new-window-flag'." (defun browse-url-can-use-xdg-open () "Return non-nil if the \"xdg-open\" program can be used. -xdg-open is a desktop utility that calls your preferred web browser. -This requires you to be running either Gnome, KDE, Xfce4 or LXDE." - (and (getenv "DISPLAY") - (executable-find "xdg-open") - ;; xdg-open may call gnome-open and that does not wait for its child - ;; to finish. This child may then be killed when the parent dies. - ;; Use nohup to work around. See bug#7166, bug#8917, bug#9779 and - ;; http://lists.gnu.org/archive/html/emacs-devel/2009-07/msg00279.html - (executable-find "nohup") - (or (getenv "GNOME_DESKTOP_SESSION_ID") - ;; GNOME_DESKTOP_SESSION_ID is deprecated, check on Dbus also. - (condition-case nil - (eq 0 (call-process - "dbus-send" nil nil nil - "--dest=org.gnome.SessionManager" - "--print-reply" - "/org/gnome/SessionManager" - "org.gnome.SessionManager.CanShutdown")) - (error nil)) - (equal (getenv "KDE_FULL_SESSION") "true") - (condition-case nil - (eq 0 (call-process - "/bin/sh" nil nil nil - "-c" - ;; FIXME use string-match rather than grep. - "xprop -root _DT_SAVE_MODE|grep xfce4")) - (error nil)) - (member (getenv "DESKTOP_SESSION") '("LXDE" "Lubuntu")) - (equal (getenv "XDG_CURRENT_DESKTOP") "LXDE")))) - +xdg-open is a desktop utility that calls your preferred web browser." + ;; The exact set of situations where xdg-open works is complicated, + ;; and it would be a pain to duplicate xdg-open's situation-specific + ;; code here, as the code is a moving target. So assume that + ;; xdg-open will work if there is a graphical display; this should + ;; be good enough for platforms Emacs is likely to be running on. + (and (or (getenv "DISPLAY") (getenv "WAYLAND_DISPLAY")) + (executable-find "xdg-open"))) ;;;###autoload (defun browse-url-xdg-open (url &optional ignored) diff --git a/lisp/net/eudc-hotlist.el b/lisp/net/eudc-hotlist.el index 5c170d0aea6..083fd7fe7e4 100644 --- a/lisp/net/eudc-hotlist.el +++ b/lisp/net/eudc-hotlist.el @@ -42,7 +42,7 @@ (define-key map "s" 'eudc-hotlist-select-server) (define-key map "t" 'eudc-hotlist-transpose-servers) (define-key map "q" 'eudc-hotlist-quit-edit) - (define-key map "x" 'kill-this-buffer) + (define-key map "x" 'kill-current-buffer) map)) (define-derived-mode eudc-hotlist-mode fundamental-mode "EUDC-Servers" diff --git a/lisp/net/eudc.el b/lisp/net/eudc.el index bdd69bf53e1..644df7ab786 100644 --- a/lisp/net/eudc.el +++ b/lisp/net/eudc.el @@ -68,8 +68,8 @@ (defvar eudc-mode-map (let ((map (make-sparse-keymap))) - (define-key map "q" 'kill-this-buffer) - (define-key map "x" 'kill-this-buffer) + (define-key map "q" 'kill-current-buffer) + (define-key map "x" 'kill-current-buffer) (define-key map "f" 'eudc-query-form) (define-key map "b" 'eudc-try-bbdb-insert) (define-key map "n" 'eudc-move-to-next-record) diff --git a/lisp/net/eww.el b/lisp/net/eww.el index c9f4e61a6fe..2fc36e180ee 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el @@ -312,11 +312,19 @@ word(s) will be searched for via `eww-search-prefix'." (expand-file-name file)))) ;;;###autoload -(defun eww-search-words (&optional beg end) +(defun eww-search-words () "Search the web for the text between BEG and END. -See the `eww-search-prefix' variable for the search engine used." - (interactive "r") - (eww (buffer-substring beg end))) +If region is active (and not whitespace), search the web for +the text between BEG and END. Else, prompt the user for a search +string. See the `eww-search-prefix' variable for the search +engine used." + (interactive) + (if (use-region-p) + (let ((region-string (buffer-substring (region-beginning) (region-end)))) + (if (not (string-match-p "\\`[ \n\t\r\v\f]*\\'" region-string)) + (eww region-string) + (call-interactively 'eww))) + (call-interactively 'eww))) (defun eww-open-in-new-buffer () "Fetch link at point in a new EWW buffer." @@ -514,6 +522,7 @@ Currently this means either text/html or application/xhtml+xml." (< eww-redirect-level 5)) (when-let (refresh (dom-attr dom 'content)) (when (or (string-match "^\\([0-9]+\\) *;.*url=\"\\([^\"]+\\)\"" refresh) + (string-match "^\\([0-9]+\\) *;.*url='\\([^']+\\)'" refresh) (string-match "^\\([0-9]+\\) *;.*url=\\([^ ]+\\)" refresh)) (let ((timeout (match-string 1 refresh)) (url (match-string 2 refresh)) @@ -640,8 +649,11 @@ Currently this means either text/html or application/xhtml+xml." (when (coding-system-p cs) (decode-coding-region (point-min) (point-max) cs) (setq buffer-file-coding-system last-coding-system-used)))) - (when (fboundp 'html-mode) - (html-mode)))) + (cond + ((fboundp 'mhtml-mode) + (mhtml-mode)) + ((fboundp 'html-mode) + (html-mode))))) (view-buffer buf))) (defun eww-toggle-paragraph-direction () @@ -899,8 +911,9 @@ appears in a or tag." (defun eww-reload (&optional local encode) "Reload the current page. -If LOCAL (the command prefix), don't reload the page from the -network, but just re-display the HTML already fetched." +If LOCAL is non-nil (interactively, the command was invoked with +a prefix argument), don't reload the page from the network, but +just re-display the HTML already fetched." (interactive "P") (let ((url (plist-get eww-data :url))) (if local diff --git a/lisp/net/gnutls.el b/lisp/net/gnutls.el index d0dab738164..5db87329c36 100644 --- a/lisp/net/gnutls.el +++ b/lisp/net/gnutls.el @@ -52,7 +52,27 @@ set this variable to \"normal:-dhe-rsa\"." string)) (defcustom gnutls-verify-error nil - "If non-nil, this should be a list of checks per hostname regex or t." + "If non-nil, this should be t or a list of checks per hostname regex. +If nil, the default, failures in certificate verification will be +logged (subject to `gnutls-log-level'), but the connection will be +allowed to proceed. +If the value is a list, it should have the form + + ((HOST-REGEX FLAGS...) (HOST-REGEX FLAGS...) ...) + +where each HOST-REGEX is a regular expression to be matched +against the hostname, and FLAGS is either t or a list of +one or more verification flags. The supported flags and the +corresponding conditions to be tested are: + + :trustfiles -- certificate must be issued by a trusted authority. + :hostname -- hostname must match presented certificate's host name. + t -- all of the above conditions are tested. + +If the condition test fails, an error will be signaled. + +If the value of this variable is t, every connection will be subjected +to all of the tests described above." :group 'gnutls :version "24.4" :type '(choice diff --git a/lisp/net/imap.el b/lisp/net/imap.el index ada2c477e9e..7b293921a43 100644 --- a/lisp/net/imap.el +++ b/lisp/net/imap.el @@ -249,9 +249,7 @@ See also `imap-log'." :group 'imap :type 'string) -(defcustom imap-read-timeout (if (string-match - "windows-nt\\|os/2\\|cygwin" - (symbol-name system-type)) +(defcustom imap-read-timeout (if (memq system-type '(windows-nt cygwin)) 1.0 0.1) "How long to wait between checking for the end of output. diff --git a/lisp/net/mailcap.el b/lisp/net/mailcap.el index 4e53b5a2861..89f6c91156b 100644 --- a/lisp/net/mailcap.el +++ b/lisp/net/mailcap.el @@ -853,7 +853,7 @@ If NO-DECODE is non-nil, don't decode STRING." (".css" . "text/css") (".dvi" . "application/x-dvi") (".diff" . "text/x-patch") - (".dpatch". "test/x-patch") + (".dpatch". "text/x-patch") (".el" . "application/emacs-lisp") (".eps" . "application/postscript") (".etx" . "text/x-setext") diff --git a/lisp/net/net-utils.el b/lisp/net/net-utils.el index 06b67dcc4f4..280c6674707 100644 --- a/lisp/net/net-utils.el +++ b/lisp/net/net-utils.el @@ -199,6 +199,12 @@ This variable is only used if the variable :group 'net-utils :type 'string) +(defcustom dig-program-options nil + "Options for the dig program." + :group 'net-utils + :type '(repeat string) + :version "26.1") + (defcustom ftp-program "ftp" "Program to run to do FTP transfers." :group 'net-utils @@ -418,7 +424,7 @@ This variable is only used if the variable ;;;###autoload (defun ifconfig () - "Run ifconfig and display diagnostic output." + "Run `ifconfig-program' and display diagnostic output." (interactive) (net-utils-run-simple (format "*%s*" ifconfig-program) @@ -429,7 +435,7 @@ This variable is only used if the variable ;;;###autoload (defun iwconfig () - "Run iwconfig and display diagnostic output." + "Run `iwconfig-program' and display diagnostic output." (interactive) (net-utils-run-simple (format "*%s*" iwconfig-program) @@ -438,7 +444,7 @@ This variable is only used if the variable ;;;###autoload (defun netstat () - "Run netstat and display diagnostic output." + "Run `netstat-program' and display diagnostic output." (interactive) (net-utils-run-simple (format "*%s*" netstat-program) @@ -447,7 +453,7 @@ This variable is only used if the variable ;;;###autoload (defun arp () - "Run arp and display diagnostic output." + "Run `arp-program' and display diagnostic output." (interactive) (net-utils-run-simple (format "*%s*" arp-program) @@ -456,7 +462,7 @@ This variable is only used if the variable ;;;###autoload (defun route () - "Run route and display diagnostic output." + "Run `route-program' and display diagnostic output." (interactive) (net-utils-run-simple (format "*%s*" route-program) @@ -469,7 +475,7 @@ This variable is only used if the variable ;;;###autoload (defun traceroute (target) - "Run traceroute program for TARGET." + "Run `traceroute-program' for TARGET." (interactive "sTarget: ") (let ((options (if traceroute-program-options @@ -507,14 +513,19 @@ If your system's ping continues until interrupted, you can try setting ;; (delete-matching-lines filter)) ;;;###autoload -(defun nslookup-host (host) - "Lookup the DNS information for HOST." +(defun nslookup-host (host &optional name-server) + "Look up the DNS information for HOST (name or IP address). +Optional argument NAME-SERVER says which server to use for +DNS resolution. +Interactively, prompt for NAME-SERVER if invoked with prefix argument. + +This command uses `nslookup-program' for looking up the DNS information." (interactive - (list (read-from-minibuffer "Lookup host: " (net-utils-machine-at-point)))) + (list (read-from-minibuffer "Lookup host: " (net-utils-machine-at-point)) + (if current-prefix-arg (read-from-minibuffer "Name server: ")))) (let ((options - (if nslookup-program-options - (append nslookup-program-options (list host)) - (list host)))) + (append nslookup-program-options (list host) + (if name-server (list name-server))))) (net-utils-run-program "Nslookup" (concat "** " @@ -526,7 +537,7 @@ If your system's ping continues until interrupted, you can try setting ;;;###autoload (defun nslookup () - "Run nslookup program." + "Run `nslookup-program'." (interactive) (switch-to-buffer (make-comint "nslookup" nslookup-program)) (nslookup-mode)) @@ -551,14 +562,19 @@ If your system's ping continues until interrupted, you can try setting (setq comint-input-autoexpand t)) ;;;###autoload -(defun dns-lookup-host (host) - "Lookup the DNS information for HOST (name or IP address)." +(defun dns-lookup-host (host &optional name-server) + "Look up the DNS information for HOST (name or IP address). +Optional argument NAME-SERVER says which server to use for +DNS resolution. +Interactively, prompt for NAME-SERVER if invoked with prefix argument. + +This command uses `dns-lookup-program' for looking up the DNS information." (interactive - (list (read-from-minibuffer "Lookup host: " (net-utils-machine-at-point)))) + (list (read-from-minibuffer "Lookup host: " (net-utils-machine-at-point)) + (if current-prefix-arg (read-from-minibuffer "Name server: ")))) (let ((options - (if dns-lookup-program-options - (append dns-lookup-program-options (list host)) - (list host)))) + (append dns-lookup-program-options (list host) + (if name-server (list name-server))))) (net-utils-run-program (concat "DNS Lookup [" host "]") (concat "** " @@ -568,15 +584,20 @@ If your system's ping continues until interrupted, you can try setting dns-lookup-program options))) -(autoload 'ffap-string-at-point "ffap") - ;;;###autoload -(defun run-dig (host) - "Run dig program." +(defun run-dig (host &optional name-server) + "Look up DNS information for HOST (name or IP address). +Optional argument NAME-SERVER says which server to use for +DNS resolution. +Interactively, prompt for NAME-SERVER if invoked with prefix argument. + +This command uses `dig-program' for looking up the DNS information." (interactive - (list - (read-from-minibuffer "Lookup host: " - (or (ffap-string-at-point 'machine) "")))) + (list (read-from-minibuffer "Lookup host: " (net-utils-machine-at-point)) + (if current-prefix-arg (read-from-minibuffer "Name server: ")))) + (let ((options + (append dig-program-options (list host) + (if name-server (list (concat "@" name-server)))))) (net-utils-run-program "Dig" (concat "** " @@ -584,14 +605,14 @@ If your system's ping continues until interrupted, you can try setting (list "Dig" host dig-program) " ** ")) dig-program - (list host))) + options))) (autoload 'comint-exec "comint") ;; This is a lot less than ange-ftp, but much simpler. ;;;###autoload (defun ftp (host) - "Run ftp program." + "Run `ftp-program' to connect to HOST." (interactive (list (read-from-minibuffer @@ -627,7 +648,9 @@ If your system's ping continues until interrupted, you can try setting nil t))) (defun smbclient (host service) - "Connect to SERVICE on HOST via SMB." + "Connect to SERVICE on HOST via SMB. + +This command uses `smbclient-program' to connect to HOST." (interactive (list (read-from-minibuffer @@ -645,7 +668,8 @@ If your system's ping continues until interrupted, you can try setting (pop-to-buffer buf))) (defun smbclient-list-shares (host) - "List services on HOST." + "List services on HOST. +This command uses `smbclient-program' to connect to HOST." (interactive (list (read-from-minibuffer @@ -740,7 +764,9 @@ queries of the form USER@HOST, and wants a query containing USER only." ;; Finger protocol ;;;###autoload (defun finger (user host) - "Finger USER on HOST." + "Finger USER on HOST. +This command uses `finger-X.500-host-regexps' +and `network-connection-service-alist', which see." ;; One of those great interactive statements that's actually ;; longer than the function call! The idea is that if the user ;; uses a string like "pbreton@cs.umb.edu", we won't ask for the @@ -834,7 +860,8 @@ then the server named by `whois-server-name' is used." (defun whois (arg search-string) "Send SEARCH-STRING to server defined by the `whois-server-name' variable. If `whois-guess-server' is non-nil, then try to deduce the correct server -from SEARCH-STRING. With argument, prompt for whois server." +from SEARCH-STRING. With argument, prompt for whois server. +The port is deduced from `network-connection-service-alist'." (interactive "P\nsWhois: ") (let* ((whois-apropos-host (if whois-guess-server (rassoc (whois-get-tld search-string) @@ -882,7 +909,8 @@ from SEARCH-STRING. With argument, prompt for whois server." ;;;###autoload (defun network-connection-to-service (host service) - "Open a network connection to SERVICE on HOST." + "Open a network connection to SERVICE on HOST. +This command uses `network-connection-service-alist', which see." (interactive (list (read-from-minibuffer "Host: " (net-utils-machine-at-point)) @@ -903,7 +931,8 @@ from SEARCH-STRING. With argument, prompt for whois server." (network-service-connection host (number-to-string port))) (defun network-service-connection (host service) - "Open a network connection to SERVICE on HOST." + "Open a network connection to SERVICE on HOST. +The port to use is determined from `network-connection-service-alist'." (let* ((process-name (concat "Network Connection [" host " " service "]")) (portnum (string-to-number service)) (buf (get-buffer-create (concat "*" process-name "*")))) @@ -919,7 +948,8 @@ from SEARCH-STRING. With argument, prompt for whois server." (defvar comint-input-ring) (defun network-connection-reconnect () - "Reconnect a network connection, preserving the old input ring." + "Reconnect a network connection, preserving the old input ring. +This command uses `network-connection-service-alist', which see." (interactive) (let ((proc (get-buffer-process (current-buffer))) (old-comint-input-ring comint-input-ring) diff --git a/lisp/net/nsm.el b/lisp/net/nsm.el index ccb596f4ddc..8d3463ef0a5 100644 --- a/lisp/net/nsm.el +++ b/lisp/net/nsm.el @@ -25,7 +25,7 @@ ;;; Code: (require 'cl-lib) -(require 'subr-x) +(require 'subr-x) ; read-multiple-choice (defvar nsm-permanent-host-settings nil) (defvar nsm-temporary-host-settings nil) diff --git a/lisp/net/pop3.el b/lisp/net/pop3.el index 6230a15c85b..2ef63217256 100644 --- a/lisp/net/pop3.el +++ b/lisp/net/pop3.el @@ -159,8 +159,7 @@ Used for APOP authentication.") (defalias 'pop3-accept-process-output 'nnheader-accept-process-output) ;; Borrowed from `nnheader.el': (defvar pop3-read-timeout - (if (string-match "windows-nt\\|os/2\\|cygwin" - (symbol-name system-type)) + (if (memq system-type '(windows-nt cygwin)) 1.0 0.01) "How long pop3 should wait between checking for the end of output. diff --git a/lisp/net/puny.el b/lisp/net/puny.el index c718d958be1..bdd59be070a 100644 --- a/lisp/net/puny.el +++ b/lisp/net/puny.el @@ -150,10 +150,12 @@ For instance \"xn--bcher-kva\" => \"bücher\"." (defun puny-decode-string-internal (string) (with-temp-buffer (insert string) - (goto-char (point-max)) - (search-backward "-" nil (point-min)) - ;; The encoded chars are after the final dash. - (let ((encoded (buffer-substring (1+ (point)) (point-max))) + ;; The encoded chars are after any final dash, else the whole string. + (let ((encoded (buffer-substring + (if (search-backward "-" nil 'move) + (1+ (point)) + (point)) + (point-max))) (ic 0) (i 0) (bias puny-initial-bias) diff --git a/lisp/net/secrets.el b/lisp/net/secrets.el index 4d6e48ba2e0..9bcfc378f42 100644 --- a/lisp/net/secrets.el +++ b/lisp/net/secrets.el @@ -737,7 +737,7 @@ If there is no such item, or the item doesn't own this attribute, return nil." (set-keymap-parent map (make-composed-keymap special-mode-map widget-keymap)) (define-key map "n" 'next-line) (define-key map "p" 'previous-line) - (define-key map "z" 'kill-this-buffer) + (define-key map "z" 'kill-current-buffer) map) "Keymap used in `secrets-mode' buffers.") diff --git a/lisp/net/shr-color.el b/lisp/net/shr-color.el index cb081cbbb10..b0c706eb5da 100644 --- a/lisp/net/shr-color.el +++ b/lisp/net/shr-color.el @@ -260,7 +260,7 @@ Like rgb() or hsl()." (l (/ (string-to-number (match-string-no-properties 3 color)) 100.0))) (destructuring-bind (r g b) (shr-color-hsl-to-rgb-fractions h s l) - (color-rgb-to-hex r g b)))) + (color-rgb-to-hex r g b 2)))) ;; Color names ((cdr (assoc-string color shr-color-html-colors-alist t))) ;; Unrecognized color :( diff --git a/lisp/net/shr.el b/lisp/net/shr.el index b7c48288494..4d4e8a809e1 100644 --- a/lisp/net/shr.el +++ b/lisp/net/shr.el @@ -30,10 +30,10 @@ ;;; Code: -(eval-when-compile (require 'cl)) +(eval-when-compile (require 'cl-lib)) (eval-when-compile (require 'url)) ;For url-filename's setf handler. (require 'browse-url) -(require 'subr-x) +(eval-when-compile (require 'subr-x)) (require 'dom) (require 'seq) (require 'svg) @@ -185,8 +185,8 @@ and other things: (define-key map [follow-link] 'mouse-face) (define-key map [mouse-2] 'shr-browse-url) (define-key map "I" 'shr-insert-image) - (define-key map "w" 'shr-copy-url) - (define-key map "u" 'shr-copy-url) + (define-key map "w" 'shr-maybe-probe-and-copy-url) + (define-key map "u" 'shr-maybe-probe-and-copy-url) (define-key map "v" 'shr-browse-url) (define-key map "O" 'shr-save-contents) (define-key map "\r" 'shr-browse-url) @@ -290,43 +290,59 @@ DOM should be a parse tree as generated by (forward-line 1) (delete-region (point) (point-max)))))) -(defun shr-copy-url (&optional image-url) +(defun shr-url-at-point (image-url) + "Return the URL under point as a string. +If IMAGE-URL is non-nil, or there is no link under point, but +there is an image under point then copy the URL of the image +under point instead." + (if image-url + (get-text-property (point) 'image-url) + (or (get-text-property (point) 'shr-url) + (get-text-property (point) 'image-url)))) + +(defun shr-copy-url (url) "Copy the URL under point to the kill ring. If IMAGE-URL (the prefix) is non-nil, or there is no link under point, but there is an image under point then copy the URL of the -image under point instead. -If called twice, then try to fetch the URL and see whether it -redirects somewhere else." +image under point instead." + (interactive (list (shr-url-at-point current-prefix-arg))) + (if (not url) + (message "No URL under point") + (setq url (url-encode-url url)) + (kill-new url) + (message "Copied %s" url))) + +(defun shr-probe-url (url cont) + "Pass URL's redirect destination to CONT, if it has one. +CONT should be a function of one argument, the redirect +destination URL. If URL is not redirected, then CONT is never +called." (interactive "P") - (let ((url (if image-url - (get-text-property (point) 'image-url) - (or (get-text-property (point) 'shr-url) - (get-text-property (point) 'image-url))))) - (cond - ((not url) - (message "No URL under point")) - ;; Resolve redirected URLs. - ((equal url (car kill-ring)) - (url-retrieve - url - (lambda (a) - (when (and (consp a) - (eq (car a) :redirect)) - (with-temp-buffer - (insert (cadr a)) - (goto-char (point-min)) - ;; Remove common tracking junk from the URL. - (when (re-search-forward ".utm_.*" nil t) - (replace-match "" t t)) - (message "Copied %s" (buffer-string)) - (copy-region-as-kill (point-min) (point-max))))) - nil t)) - ;; Copy the URL to the kill ring. - (t - (with-temp-buffer - (insert (url-encode-url url)) - (copy-region-as-kill (point-min) (point-max)) - (message "Copied %s" (buffer-string))))))) + (url-retrieve + url (lambda (a) + (pcase a + (`(:redirect ,destination . ,_) + ;; Remove common tracking junk from the URL. + (funcall cont (replace-regexp-in-string + ".utm_.*" "" destination))))) + nil t)) + +(defun shr-probe-and-copy-url (url) + "Copy the URL under point to the kill ring. +Like `shr-copy-url', but additionally fetch URL and use its +redirection destination if it has one." + (interactive (list (shr-url-at-point current-prefix-arg))) + (if url (shr-probe-url url #'shr-copy-url) + (shr-copy-url url))) + +(defun shr-maybe-probe-and-copy-url (url) + "Copy the URL under point to the kill ring. +If the URL is already at the front of the kill ring act like +`shr-probe-and-copy-url', otherwise like `shr-copy-url'." + (interactive (list (shr-url-at-point current-prefix-arg))) + (if (equal url (car kill-ring)) + (shr-probe-and-copy-url url) + (shr-copy-url url))) (defun shr-next-link () "Skip to the next link." @@ -512,6 +528,7 @@ size, and full-buffer size." (* (frame-char-width) 2) 0)))) (shr-insert text) + (shr-fill-lines (point-min) (point-max)) (buffer-string))))) (define-inline shr-char-breakable-p (char) @@ -933,17 +950,19 @@ If EXTERNAL, browse the URL using `shr-external-browser'." (let ((data (shr-parse-image-data))) (with-current-buffer buffer (save-excursion - (let ((alt (buffer-substring start end)) - (properties (text-properties-at start)) - (inhibit-read-only t)) - (delete-region start end) - (goto-char start) - (funcall shr-put-image-function data alt flags) - (while properties - (let ((type (pop properties)) - (value (pop properties))) - (unless (memq type '(display image-size)) - (put-text-property start (point) type value)))))))))) + (save-restriction + (widen) + (let ((alt (buffer-substring start end)) + (properties (text-properties-at start)) + (inhibit-read-only t)) + (delete-region start end) + (goto-char start) + (funcall shr-put-image-function data alt flags) + (while properties + (let ((type (pop properties)) + (value (pop properties))) + (unless (memq type '(display image-size)) + (put-text-property start (point) type value))))))))))) (kill-buffer image-buffer))) (defun shr-image-from-data (data) @@ -1788,14 +1807,14 @@ The preference is a float determined from `shr-prefer-media-type'." (elems (or (dom-attr dom 'shr-suggested-widths) (shr-make-table dom suggested-widths nil 'shr-suggested-widths))) - (sketch (loop for line in elems - collect (mapcar #'car line))) - (natural (loop for line in elems - collect (mapcar #'cdr line))) + (sketch (cl-loop for line in elems + collect (mapcar #'car line))) + (natural (cl-loop for line in elems + collect (mapcar #'cdr line))) (sketch-widths (shr-table-widths sketch natural suggested-widths))) ;; This probably won't work very well. - (when (> (+ (loop for width across sketch-widths - summing (1+ width)) + (when (> (+ (cl-loop for width across sketch-widths + summing (1+ width)) shr-indentation shr-table-separator-pixel-width) (frame-width)) (setq truncate-lines t)) @@ -2228,6 +2247,9 @@ flags that control whether to collect or render objects." (if (get-buffer-window) (car (window-text-pixel-size nil (point-min) (point-max))) (save-window-excursion + ;; Avoid errors if the selected window is a dedicated one, + ;; and they just want to insert a document into it. + (set-window-dedicated-p nil nil) (set-window-buffer nil (current-buffer)) (car (window-text-pixel-size nil (point-min) (point-max))))))) @@ -2271,6 +2293,9 @@ flags that control whether to collect or render objects." (shr-indentation 0)) (shr-descend dom)) (save-window-excursion + ;; Avoid errors if the selected window is a dedicated one, + ;; and they just want to insert a document into it. + (set-window-dedicated-p nil nil) (set-window-buffer nil (current-buffer)) (unless fill (setq natural-width @@ -2307,13 +2332,14 @@ flags that control whether to collect or render objects." (defun shr-dom-max-natural-width (dom max) (if (eq (dom-tag dom) 'table) (max max (or - (loop for line in (dom-attr dom 'shr-suggested-widths) - maximize (+ - shr-table-separator-length - (loop for elem in line - summing - (+ (cdr elem) - (* 2 shr-table-separator-length))))) + (cl-loop + for line in (dom-attr dom 'shr-suggested-widths) + maximize (+ + shr-table-separator-length + (cl-loop for elem in line + summing + (+ (cdr elem) + (* 2 shr-table-separator-length))))) 0)) (dolist (child (dom-children dom)) (unless (stringp child) diff --git a/lisp/net/soap-client.el b/lisp/net/soap-client.el index 5d36cfa89b8..c0b71cdf170 100644 --- a/lisp/net/soap-client.el +++ b/lisp/net/soap-client.el @@ -5,11 +5,11 @@ ;; Author: Alexandru Harsanyi ;; Author: Thomas Fitzsimmons ;; Created: December, 2009 -;; Version: 3.1.1 +;; Version: 3.1.3 ;; Keywords: soap, web-services, comm, hypermedia ;; Package: soap-client ;; Homepage: https://github.com/alex-hhh/emacs-soap-client -;; Package-Requires: ((cl-lib "0.5")) +;; Package-Requires: ((cl-lib "0.6.1")) ;; This file is part of GNU Emacs. @@ -43,7 +43,6 @@ ;;; Code: -(eval-when-compile (require 'cl)) (require 'cl-lib) (require 'xml) @@ -206,7 +205,7 @@ different namespace aliases for the same element." local-name-1))))) (defun soap-name-p (name) - "Return true if NAME is a valid name for XMLSchema types. + "Return t if NAME is a valid name for XMLSchema types. A valid name is either a string or a cons of (NAMESPACE . NAME)." (or (stringp name) (and (consp name) @@ -298,7 +297,7 @@ be tagged with a namespace tag." ;; An element in an XML namespace, "things" stored in soap-xml-namespaces will ;; be derived from this object. -(defstruct soap-element +(cl-defstruct soap-element name ;; The "well-known" namespace tag for the element. For example, while ;; parsing XML documents, we can have different tags for the XMLSchema @@ -321,13 +320,13 @@ element name." ;; a namespace link stores an alias for an object in once namespace to a ;; "target" object possibly in a different namespace -(defstruct (soap-namespace-link (:include soap-element)) +(cl-defstruct (soap-namespace-link (:include soap-element)) target) ;; A namespace is a collection of soap-element objects under a name (the name ;; of the namespace). -(defstruct soap-namespace +(cl-defstruct soap-namespace (name nil :read-only t) ; e.g "http://xml.apache.org/xml-soap" (elements (make-hash-table :test 'equal) :read-only t)) @@ -360,9 +359,9 @@ added to the namespace." (setq name target)))))) ;; by now, name should be valid - (assert (and name (not (equal name ""))) - nil - "Cannot determine name for namespace link") + (cl-assert (and name (not (equal name ""))) + nil + "Cannot determine name for namespace link") (push (make-soap-namespace-link :name name :target target) (gethash name (soap-namespace-elements ns)))) @@ -372,7 +371,7 @@ If multiple elements with the same name exist, DISCRIMINANT-PREDICATE is used to pick one of them. This allows storing elements of different types (like a message type and a binding) but the same name." - (assert (stringp name)) + (cl-assert (stringp name)) (let ((elements (gethash name (soap-namespace-elements ns)))) (cond (discriminant-predicate (catch 'found @@ -394,14 +393,14 @@ binding) but the same name." ;; message exchange. We include here an XML schema model with a parser and ;; serializer/deserializer. -(defstruct (soap-xs-type (:include soap-element)) +(cl-defstruct (soap-xs-type (:include soap-element)) id attributes attribute-groups) ;;;;; soap-xs-basic-type -(defstruct (soap-xs-basic-type (:include soap-xs-type)) +(cl-defstruct (soap-xs-basic-type (:include soap-xs-type)) ;; Basic types are "built in" and we know how to handle them directly. ;; Other type definitions reference basic types, so we need to create them ;; in a namespace (see `soap-make-xs-basic-types') @@ -483,7 +482,7 @@ This is a specialization of `soap-encode-value' for (when (or value (eq kind 'boolean)) (let ((value-string - (case kind + (cl-case kind ((string anyURI QName ID IDREF language) (unless (stringp value) (error "Not a string value: %s" value)) @@ -495,7 +494,7 @@ This is a specialization of `soap-encode-value' for ;; string format in UTC. (format-time-string (concat - (ecase kind + (cl-ecase kind (dateTime "%Y-%m-%dT%H:%M:%S") (time "%H:%M:%S") (date "%Y-%m-%d") @@ -673,7 +672,7 @@ This is a specialization of `soap-decode-type' for (if (null contents) nil - (ecase kind + (cl-ecase kind ((string anyURI QName ID IDREF language) (car contents)) ((dateTime time date gYearMonth gYear gMonthDay gDay gMonth) (car contents)) @@ -694,7 +693,7 @@ This is a specialization of `soap-decode-type' for ;;;;; soap-xs-element -(defstruct (soap-xs-element (:include soap-element)) +(cl-defstruct (soap-xs-element (:include soap-element)) ;; NOTE: we don't support exact number of occurrences via minOccurs, ;; maxOccurs. Instead we support optional? and multiple? @@ -738,8 +737,8 @@ contains a reference, retrieve the type of the reference." (ref (xml-get-attribute-or-nil node 'ref)) (substitution-group (xml-get-attribute-or-nil node 'substitutionGroup)) (node-name (soap-l2wk (xml-node-name node)))) - (assert (memq node-name '(xsd:element xsd:group)) - "expecting xsd:element or xsd:group, got %s" node-name) + (cl-assert (memq node-name '(xsd:element xsd:group)) + "expecting xsd:element or xsd:group, got %s" node-name) (when type (setq type (soap-l2fq type 'tns))) @@ -895,11 +894,10 @@ This is a specialization of `soap-encode-value' for (soap-element-namespace-tag type))) (setf (soap-xs-element-type^ new-element) (soap-xs-complex-type-base type)) - (loop for i below (length value) - do (progn - (soap-encode-xs-element (aref value i) new-element) - ))) - (soap-encode-value value type)) + (cl-loop for i below (length value) + do (soap-encode-xs-element + (aref value i) new-element))) + (soap-encode-value value type)) (insert "\n")) ;; else (insert "/>\n")))) @@ -925,18 +923,18 @@ This is a specialization of `soap-decode-type' for ;;;;; soap-xs-attribute -(defstruct (soap-xs-attribute (:include soap-element)) +(cl-defstruct (soap-xs-attribute (:include soap-element)) type ; a simple type or basic type default ; the default value, if any reference) -(defstruct (soap-xs-attribute-group (:include soap-xs-type)) +(cl-defstruct (soap-xs-attribute-group (:include soap-xs-type)) reference) (defun soap-xs-parse-attribute (node) "Construct a `soap-xs-attribute' from NODE." - (assert (eq (soap-l2wk (xml-node-name node)) 'xsd:attribute) - "expecting xsd:attribute, got %s" (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'xsd:attribute) + "expecting xsd:attribute, got %s" (soap-l2wk (xml-node-name node))) (let* ((name (xml-get-attribute-or-nil node 'name)) (type (soap-l2fq (xml-get-attribute-or-nil node 'type))) (default (xml-get-attribute-or-nil node 'fixed)) @@ -952,8 +950,8 @@ This is a specialization of `soap-decode-type' for (defun soap-xs-parse-attribute-group (node) "Construct a `soap-xs-attribute-group' from NODE." (let ((node-name (soap-l2wk (xml-node-name node)))) - (assert (eq node-name 'xsd:attributeGroup) - "expecting xsd:attributeGroup, got %s" node-name) + (cl-assert (eq node-name 'xsd:attributeGroup) + "expecting xsd:attributeGroup, got %s" node-name) (let ((name (xml-get-attribute-or-nil node 'name)) (id (xml-get-attribute-or-nil node 'id)) (ref (xml-get-attribute-or-nil node 'ref)) @@ -970,7 +968,7 @@ This is a specialization of `soap-decode-type' for (unless (stringp child) ;; Ignore optional annotation. ;; Ignore anyAttribute nodes. - (case (soap-l2wk (xml-node-name child)) + (cl-case (soap-l2wk (xml-node-name child)) (xsd:attribute (push (soap-xs-parse-attribute child) (soap-xs-type-attributes attribute-group))) @@ -1043,7 +1041,7 @@ See also `soap-wsdl-resolve-references'." ;;;;; soap-xs-simple-type -(defstruct (soap-xs-simple-type (:include soap-xs-type)) +(cl-defstruct (soap-xs-simple-type (:include soap-xs-type)) ;; A simple type is an extension on the basic type to which some ;; restrictions can be added. For example we can define a simple type based ;; off "string" with the restrictions that only the strings "one", "two" and @@ -1064,11 +1062,11 @@ See also `soap-wsdl-resolve-references'." (defun soap-xs-parse-simple-type (node) "Construct an `soap-xs-simple-type' object from the XML NODE." - (assert (memq (soap-l2wk (xml-node-name node)) - '(xsd:simpleType xsd:simpleContent)) - nil - "expecting xsd:simpleType or xsd:simpleContent node, got %s" - (soap-l2wk (xml-node-name node))) + (cl-assert (memq (soap-l2wk (xml-node-name node)) + '(xsd:simpleType xsd:simpleContent)) + nil + "expecting xsd:simpleType or xsd:simpleContent node, got %s" + (soap-l2wk (xml-node-name node))) ;; NOTE: name can be nil for inline types. Such types cannot be added to a ;; namespace. @@ -1079,7 +1077,7 @@ See also `soap-wsdl-resolve-references'." :name name :namespace-tag soap-target-xmlns :id id)) (def (soap-xml-node-find-matching-child node '(xsd:restriction xsd:extension xsd:union xsd:list)))) - (ecase (soap-l2wk (xml-node-name def)) + (cl-ecase (soap-l2wk (xml-node-name def)) (xsd:restriction (soap-xs-add-restriction def type)) (xsd:extension (soap-xs-add-extension def type)) (xsd:union (soap-xs-add-union def type)) @@ -1090,10 +1088,10 @@ See also `soap-wsdl-resolve-references'." (defun soap-xs-add-restriction (node type) "Add restrictions defined in XML NODE to TYPE, an `soap-xs-simple-type'." - (assert (eq (soap-l2wk (xml-node-name node)) 'xsd:restriction) - nil - "expecting xsd:restriction node, got %s" - (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'xsd:restriction) + nil + "expecting xsd:restriction node, got %s" + (soap-l2wk (xml-node-name node))) (setf (soap-xs-simple-type-base type) (soap-l2fq (xml-get-attribute node 'base))) @@ -1101,7 +1099,7 @@ See also `soap-wsdl-resolve-references'." (dolist (r (xml-node-children node)) (unless (stringp r) ; skip the white space (let ((value (xml-get-attribute r 'value))) - (case (soap-l2wk (xml-node-name r)) + (cl-case (soap-l2wk (xml-node-name r)) (xsd:enumeration (push value (soap-xs-simple-type-enumeration type))) (xsd:pattern @@ -1162,9 +1160,10 @@ See also `soap-wsdl-resolve-references'." (defun soap-xs-add-union (node type) "Add union members defined in XML NODE to TYPE, an `soap-xs-simple-type'." - (assert (eq (soap-l2wk (xml-node-name node)) 'xsd:union) - nil - "expecting xsd:union node, got %s" (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'xsd:union) + nil + "expecting xsd:union node, got %s" + (soap-l2wk (xml-node-name node))) (setf (soap-xs-simple-type-base type) (mapcar 'soap-l2fq @@ -1182,9 +1181,9 @@ See also `soap-wsdl-resolve-references'." (defun soap-xs-add-list (node type) "Add list defined in XML NODE to TYPE, a `soap-xs-simple-type'." - (assert (eq (soap-l2wk (xml-node-name node)) 'xsd:list) - nil - "expecting xsd:list node, got %s" (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'xsd:list) + nil + "expecting xsd:list node, got %s" (soap-l2wk (xml-node-name node))) ;; A simple type can be defined inline inside the list node or referenced by ;; the itemType attribute, in which case it will be resolved by the @@ -1219,7 +1218,7 @@ See also `soap-wsdl-resolve-references'." (defun soap-validate-xs-basic-type (value type) "Validate VALUE against the basic type TYPE." (let* ((kind (soap-xs-basic-type-kind type))) - (case kind + (cl-case kind ((anyType Array byte[]) value) (t @@ -1384,7 +1383,7 @@ This is a specialization of `soap-decode-type' for ;;;;; soap-xs-complex-type -(defstruct (soap-xs-complex-type (:include soap-xs-type)) +(cl-defstruct (soap-xs-complex-type (:include soap-xs-type)) indicator ; sequence, choice, all, array base elements @@ -1400,12 +1399,12 @@ This is a specialization of `soap-decode-type' for type attributes attribute-groups) - (assert (memq node-name '(xsd:complexType xsd:complexContent xsd:group)) - nil "unexpected node: %s" node-name) + (cl-assert (memq node-name '(xsd:complexType xsd:complexContent xsd:group)) + nil "unexpected node: %s" node-name) (dolist (def (xml-node-children node)) (when (consp def) ; skip text nodes - (case (soap-l2wk (xml-node-name def)) + (cl-case (soap-l2wk (xml-node-name def)) (xsd:attribute (push (soap-xs-parse-attribute def) attributes)) (xsd:attributeGroup (push (soap-xs-parse-attribute-group def) @@ -1416,7 +1415,7 @@ This is a specialization of `soap-decode-type' for (xsd:complexContent (dolist (def (xml-node-children def)) (when (consp def) - (case (soap-l2wk (xml-node-name def)) + (cl-case (soap-l2wk (xml-node-name def)) (xsd:attribute (push (soap-xs-parse-attribute def) attributes)) (xsd:attributeGroup @@ -1447,15 +1446,15 @@ This is a specialization of `soap-decode-type' for (defun soap-xs-parse-sequence (node) "Parse a sequence definition from XML NODE. Returns a `soap-xs-complex-type'" - (assert (memq (soap-l2wk (xml-node-name node)) - '(xsd:sequence xsd:choice xsd:all)) - nil - "unexpected node: %s" (soap-l2wk (xml-node-name node))) + (cl-assert (memq (soap-l2wk (xml-node-name node)) + '(xsd:sequence xsd:choice xsd:all)) + nil + "unexpected node: %s" (soap-l2wk (xml-node-name node))) (let ((type (make-soap-xs-complex-type))) (setf (soap-xs-complex-type-indicator type) - (ecase (soap-l2wk (xml-node-name node)) + (cl-ecase (soap-l2wk (xml-node-name node)) (xsd:sequence 'sequence) (xsd:all 'all) (xsd:choice 'choice))) @@ -1465,7 +1464,7 @@ Returns a `soap-xs-complex-type'" (dolist (r (xml-node-children node)) (unless (stringp r) ; skip the white space - (case (soap-l2wk (xml-node-name r)) + (cl-case (soap-l2wk (xml-node-name r)) ((xsd:element xsd:group) (push (soap-xs-parse-element r) (soap-xs-complex-type-elements type))) @@ -1489,10 +1488,10 @@ Returns a `soap-xs-complex-type'" (defun soap-xs-parse-extension-or-restriction (node) "Parse an extension or restriction definition from XML NODE. Return a `soap-xs-complex-type'." - (assert (memq (soap-l2wk (xml-node-name node)) - '(xsd:extension xsd:restriction)) - nil - "unexpected node: %s" (soap-l2wk (xml-node-name node))) + (cl-assert (memq (soap-l2wk (xml-node-name node)) + '(xsd:extension xsd:restriction)) + nil + "unexpected node: %s" (soap-l2wk (xml-node-name node))) (let (type attributes attribute-groups @@ -1507,7 +1506,7 @@ Return a `soap-xs-complex-type'." (dolist (def (xml-node-children node)) (when (consp def) ; skip text nodes - (case (soap-l2wk (xml-node-name def)) + (cl-case (soap-l2wk (xml-node-name def)) ((xsd:sequence xsd:choice xsd:all) (setq type (soap-xs-parse-sequence def))) (xsd:attribute @@ -1628,7 +1627,7 @@ position. This is a specialization of `soap-encode-value' for `soap-xs-complex-type' objects." - (case (soap-xs-complex-type-indicator type) + (cl-case (soap-xs-complex-type-indicator type) (array (error "Arrays of type soap-encode-xs-complex-type are handled elsewhere")) ((sequence choice all nil) @@ -1650,7 +1649,7 @@ This is a specialization of `soap-encode-value' for (let ((e-name (intern e-name))) (dolist (v value) (when (equal (car v) e-name) - (incf instance-count) + (cl-incf instance-count) (soap-encode-value (cdr v) candidate)))) (if (soap-xs-complex-type-indicator type) (let ((current-point (point))) @@ -1658,12 +1657,12 @@ This is a specialization of `soap-encode-value' for ;; characters were inserted in the buffer. (soap-encode-value value candidate) (when (not (equal current-point (point))) - (incf instance-count))) + (cl-incf instance-count))) (dolist (v value) (let ((current-point (point))) (soap-encode-value v candidate) (when (not (equal current-point (point))) - (incf instance-count)))))))) + (cl-incf instance-count)))))))) ;; Do some sanity checking (let* ((indicator (soap-xs-complex-type-indicator type)) (element-type (soap-xs-element-type element)) @@ -1801,7 +1800,7 @@ type-info stored in TYPE. This is a specialization of `soap-decode-type' for `soap-xs-basic-type' objects." - (case (soap-xs-complex-type-indicator type) + (cl-case (soap-xs-complex-type-indicator type) (array (let ((result nil) (element-type (soap-xs-complex-type-base type))) @@ -1878,7 +1877,7 @@ This is a specialization of `soap-decode-type' for (list node))) (element-type (soap-xs-element-type element))) (dolist (node children) - (incf instance-count) + (cl-incf instance-count) (let* ((attributes (soap-decode-xs-attributes element-type node)) ;; Attributes may specify xsi:type override. @@ -1939,11 +1938,11 @@ This is a specialization of `soap-decode-type' for ;;;;; WSDL document elements -(defstruct (soap-message (:include soap-element)) +(cl-defstruct (soap-message (:include soap-element)) parts ; ALIST of NAME => WSDL-TYPE name ) -(defstruct (soap-operation (:include soap-element)) +(cl-defstruct (soap-operation (:include soap-element)) parameter-order input ; (NAME . MESSAGE) output ; (NAME . MESSAGE) @@ -1951,13 +1950,13 @@ This is a specialization of `soap-decode-type' for input-action ; WS-addressing action string output-action) ; WS-addressing action string -(defstruct (soap-port-type (:include soap-element)) +(cl-defstruct (soap-port-type (:include soap-element)) operations) ; a namespace of operations ;; A bound operation is an operation which has a soap action and a use ;; method attached -- these are attached as part of a binding and we ;; can have different bindings for the same operations. -(defstruct soap-bound-operation +(cl-defstruct soap-bound-operation operation ; SOAP-OPERATION soap-action ; value for SOAPAction HTTP header soap-headers ; list of (message part use) @@ -1966,11 +1965,11 @@ This is a specialization of `soap-decode-type' for ; http://www.w3.org/TR/wsdl#_soap:body ) -(defstruct (soap-binding (:include soap-element)) +(cl-defstruct (soap-binding (:include soap-element)) port-type (operations (make-hash-table :test 'equal) :readonly t)) -(defstruct (soap-port (:include soap-element)) +(cl-defstruct (soap-port (:include soap-element)) service-url binding) @@ -1978,10 +1977,10 @@ This is a specialization of `soap-decode-type' for ;;;;; The WSDL document ;; The WSDL data structure used for encoding/decoding SOAP messages -(defstruct (soap-wsdl - ;; NOTE: don't call this constructor, see `soap-make-wsdl' - (:constructor soap-make-wsdl^) - (:copier soap-copy-wsdl)) +(cl-defstruct (soap-wsdl + ;; NOTE: don't call this constructor, see `soap-make-wsdl' + (:constructor soap-make-wsdl^) + (:copier soap-copy-wsdl)) origin ; file or URL from which this wsdl was loaded current-file ; most-recently fetched file or URL xmlschema-imports ; a list of schema imports @@ -2107,16 +2106,16 @@ used to resolve the namespace alias." "Parse a schema NODE, placing the results in WSDL. Return a SOAP-NAMESPACE containing the elements." (soap-with-local-xmlns node - (assert (eq (soap-l2wk (xml-node-name node)) 'xsd:schema) - nil - "expecting an xsd:schema node, got %s" - (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'xsd:schema) + nil + "expecting an xsd:schema node, got %s" + (soap-l2wk (xml-node-name node))) (let ((ns (make-soap-namespace :name (soap-get-target-namespace node)))) (dolist (def (xml-node-children node)) (unless (stringp def) ; skip text nodes - (case (soap-l2wk (xml-node-name def)) + (cl-case (soap-l2wk (xml-node-name def)) (xsd:import ;; Imports will be processed later ;; NOTE: we should expand the location now! @@ -2195,7 +2194,7 @@ See also `soap-resolve-references' and (message (cdr input))) ;; Name this part if it was not named (when (or (null name) (equal name "")) - (setq name (format "in%d" (incf counter)))) + (setq name (format "in%d" (cl-incf counter)))) (when (soap-name-p message) (setf (soap-operation-input operation) (cons (intern name) @@ -2206,7 +2205,7 @@ See also `soap-resolve-references' and (let ((name (car output)) (message (cdr output))) (when (or (null name) (equal name "")) - (setq name (format "out%d" (incf counter)))) + (setq name (format "out%d" (cl-incf counter)))) (when (soap-name-p message) (setf (soap-operation-output operation) (cons (intern name) @@ -2218,7 +2217,7 @@ See also `soap-resolve-references' and (let ((name (car fault)) (message (cdr fault))) (when (or (null name) (equal name "")) - (setq name (format "fault%d" (incf counter)))) + (setq name (format "fault%d" (cl-incf counter)))) (if (soap-name-p message) (push (cons (intern name) (soap-wsdl-get message wsdl 'soap-message-p)) @@ -2304,19 +2303,19 @@ traverse an element tree." ;; If this namespace does not have an alias, create one for it. (catch 'done (while t - (setq nstag (format "ns%d" (incf nstag-id))) + (setq nstag (format "ns%d" (cl-incf nstag-id))) (unless (assoc nstag alias-table) (soap-wsdl-add-alias nstag (soap-namespace-name ns) wsdl) (throw 'done t))))) (maphash (lambda (_name element) (cond ((soap-element-p element) ; skip links - (incf nprocessed) + (cl-incf nprocessed) (soap-resolve-references element wsdl)) ((listp element) (dolist (e element) (when (soap-element-p e) - (incf nprocessed) + (cl-incf nprocessed) (soap-resolve-references e wsdl)))))) (soap-namespace-elements ns))))) wsdl) @@ -2337,6 +2336,8 @@ traverse an element tree." (kill-buffer) (mm-destroy-part mime-part))))) +(defvar url-http-response-status) + (defun soap-fetch-xml-from-url (url wsdl) "Load an XML document from URL and return it. The previously parsed URL is read from WSDL." @@ -2350,7 +2351,6 @@ The previously parsed URL is read from WSDL." (setf (soap-wsdl-current-file wsdl) current-file) (let ((buffer (url-retrieve-synchronously current-file))) (with-current-buffer buffer - (declare (special url-http-response-status)) (if (> url-http-response-status 299) (error "Error retrieving WSDL: %s" url-http-response-status)) (soap-parse-server-response))))) @@ -2391,9 +2391,9 @@ Build on WSDL if it is provided." "Assert that NODE is valid." (soap-with-local-xmlns node (let ((node-name (soap-l2wk (xml-node-name node)))) - (assert (eq node-name 'wsdl:definitions) - nil - "expecting wsdl:definitions node, got %s" node-name)))) + (cl-assert (eq node-name 'wsdl:definitions) + nil + "expecting wsdl:definitions node, got %s" node-name)))) (defun soap-parse-wsdl-phase-fetch-imports (node wsdl) "Fetch and load files imported by NODE into WSDL." @@ -2473,10 +2473,10 @@ Build on WSDL if it is provided." (defun soap-parse-message (node) "Parse NODE as a wsdl:message and return the corresponding type." - (assert (eq (soap-l2wk (xml-node-name node)) 'wsdl:message) - nil - "expecting wsdl:message node, got %s" - (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'wsdl:message) + nil + "expecting wsdl:message node, got %s" + (soap-l2wk (xml-node-name node))) (let ((name (xml-get-attribute-or-nil node 'name)) parts) (dolist (p (soap-xml-get-children1 node 'wsdl:part)) @@ -2500,10 +2500,10 @@ Build on WSDL if it is provided." (defun soap-parse-port-type (node) "Parse NODE as a wsdl:portType and return the corresponding port." - (assert (eq (soap-l2wk (xml-node-name node)) 'wsdl:portType) - nil - "expecting wsdl:portType node got %s" - (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'wsdl:portType) + nil + "expecting wsdl:portType node got %s" + (soap-l2wk (xml-node-name node))) (let* ((soap-target-xmlns (concat "urn:" (xml-get-attribute node 'name))) (ns (make-soap-namespace :name soap-target-xmlns))) (dolist (node (soap-xml-get-children1 node 'wsdl:operation)) @@ -2522,14 +2522,14 @@ Build on WSDL if it is provided." ;; link all messages from this namespace, as this namespace ;; will be used for decoding the response. - (destructuring-bind (name . message) (soap-operation-input o) + (cl-destructuring-bind (name . message) (soap-operation-input o) (soap-namespace-put-link name message ns)) - (destructuring-bind (name . message) (soap-operation-output o) + (cl-destructuring-bind (name . message) (soap-operation-output o) (soap-namespace-put-link name message ns)) (dolist (fault (soap-operation-faults o)) - (destructuring-bind (name . message) fault + (cl-destructuring-bind (name . message) fault (soap-namespace-put-link name message ns))) ))))) @@ -2539,10 +2539,10 @@ Build on WSDL if it is provided." (defun soap-parse-operation (node) "Parse NODE as a wsdl:operation and return the corresponding type." - (assert (eq (soap-l2wk (xml-node-name node)) 'wsdl:operation) - nil - "expecting wsdl:operation node, got %s" - (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'wsdl:operation) + nil + "expecting wsdl:operation node, got %s" + (soap-l2wk (xml-node-name node))) (let ((name (xml-get-attribute node 'name)) (parameter-order (split-string (xml-get-attribute node 'parameterOrder))) @@ -2579,10 +2579,10 @@ Build on WSDL if it is provided." (defun soap-parse-binding (node) "Parse NODE as a wsdl:binding and return the corresponding type." - (assert (eq (soap-l2wk (xml-node-name node)) 'wsdl:binding) - nil - "expecting wsdl:binding node, got %s" - (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'wsdl:binding) + nil + "expecting wsdl:binding node, got %s" + (soap-l2wk (xml-node-name node))) (let ((name (xml-get-attribute node 'name)) (type (xml-get-attribute node 'type))) (let ((binding (make-soap-binding :name name @@ -2693,8 +2693,8 @@ decode function to perform the actual decoding." (when result (throw 'done result)))))) (t (let ((decoder (get (aref type 0) 'soap-decoder))) - (assert decoder nil - "no soap-decoder for %s type" (aref type 0)) + (cl-assert decoder nil + "no soap-decoder for %s type" (aref type 0)) (funcall decoder type node)))))))))) (defun soap-decode-any-type (node) @@ -2769,10 +2769,10 @@ decode function to perform the actual decoding." OPERATION is the WSDL operation for which we expect the response, WSDL is used to decode the NODE" (soap-with-local-xmlns node - (assert (eq (soap-l2wk (xml-node-name node)) 'soap:Envelope) - nil - "expecting soap:Envelope node, got %s" - (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'soap:Envelope) + nil + "expecting soap:Envelope node, got %s" + (soap-l2wk (xml-node-name node))) (let ((headers (soap-xml-get-children1 node 'soap:Header)) (body (car (soap-xml-get-children1 node 'soap:Body)))) @@ -2879,8 +2879,8 @@ for the type and calls that specialized function to do the work. Attributes are inserted in the current buffer at the current position." (let ((attribute-encoder (get (aref type 0) 'soap-attribute-encoder))) - (assert attribute-encoder nil - "no soap-attribute-encoder for %s type" (aref type 0)) + (cl-assert attribute-encoder nil + "no soap-attribute-encoder for %s type" (aref type 0)) (funcall attribute-encoder value type))) (defun soap-encode-value (value type) @@ -2893,7 +2893,7 @@ is to be encoded. This is a generic function which finds an encoder function based on TYPE and calls that encoder to do the work." (let ((encoder (get (aref type 0) 'soap-encoder))) - (assert encoder nil "no soap-encoder for %s type" (aref type 0)) + (cl-assert encoder nil "no soap-encoder for %s type" (aref type 0)) (funcall encoder value type)) (when (soap-element-namespace-tag type) (add-to-list 'soap-encoded-namespaces (soap-element-namespace-tag type)))) @@ -2909,9 +2909,9 @@ being used." (use (soap-bound-operation-use operation)) (message (cdr (soap-operation-input op))) (parameter-order (soap-operation-parameter-order op)) - (param-table (loop for formal in parameter-order - for value in parameters - collect (cons formal value)))) + (param-table (cl-loop for formal in parameter-order + for value in parameters + collect (cons formal value)))) (unless (= (length parameter-order) (length parameters)) (error "Wrong number of parameters for %s: expected %d, got %s" @@ -3049,8 +3049,11 @@ OPERATION-NAME and PARAMETERS are as described in `soap-invoke'." (url-request-extra-headers (list (cons "SOAPAction" - (concat "\"" (soap-bound-operation-soap-action - operation) "\"")) + (concat "\"" (encode-coding-string + (soap-bound-operation-soap-action + operation) + 'utf-8) + "\"")) (cons "Content-Type" "text/xml; charset=utf-8")))) (if callback @@ -3059,41 +3062,40 @@ OPERATION-NAME and PARAMETERS are as described in `soap-invoke'." (lambda (status) (let ((data-buffer (current-buffer))) (unwind-protect - (let ((error-status (plist-get status :error))) - (if error-status - (signal (car error-status) (cdr error-status)) - (apply callback - (soap-parse-envelope - (soap-parse-server-response) - operation wsdl) - cbargs))) + (let ((error-status (plist-get status :error))) + (if error-status + (signal (car error-status) (cdr error-status)) + (apply callback + (soap-parse-envelope + (soap-parse-server-response) + operation wsdl) + cbargs))) ;; Ensure the url-retrieve buffer is not leaked. (and (buffer-live-p data-buffer) (kill-buffer data-buffer)))))) - (let ((buffer (url-retrieve-synchronously - (soap-port-service-url port)))) - (condition-case err - (with-current-buffer buffer - (declare (special url-http-response-status)) - (if (null url-http-response-status) - (error "No HTTP response from server")) - (if (and soap-debug (> url-http-response-status 299)) - ;; This is a warning because some SOAP errors come - ;; back with a HTTP response 500 (internal server - ;; error) - (warn "Error in SOAP response: HTTP code %s" - url-http-response-status)) - (soap-parse-envelope (soap-parse-server-response) - operation wsdl)) - (soap-error - ;; Propagate soap-errors -- they are error replies of the - ;; SOAP protocol and don't indicate a communication - ;; problem or a bug in this code. - (signal (car err) (cdr err))) - (error - (when soap-debug - (pop-to-buffer buffer)) - (error (error-message-string err))))))))) + (let ((buffer (url-retrieve-synchronously + (soap-port-service-url port)))) + (condition-case err + (with-current-buffer buffer + (if (null url-http-response-status) + (error "No HTTP response from server")) + (if (and soap-debug (> url-http-response-status 299)) + ;; This is a warning because some SOAP errors come + ;; back with a HTTP response 500 (internal server + ;; error) + (warn "Error in SOAP response: HTTP code %s" + url-http-response-status)) + (soap-parse-envelope (soap-parse-server-response) + operation wsdl)) + (soap-error + ;; Propagate soap-errors -- they are error replies of the + ;; SOAP protocol and don't indicate a communication + ;; problem or a bug in this code. + (signal (car err) (cdr err))) + (error + (when soap-debug + (pop-to-buffer buffer)) + (error (error-message-string err))))))))) (defun soap-invoke (wsdl service operation-name &rest parameters) "Invoke a SOAP operation and return the result. diff --git a/lisp/net/soap-inspect.el b/lisp/net/soap-inspect.el index db83cf8463e..2516bc99248 100644 --- a/lisp/net/soap-inspect.el +++ b/lisp/net/soap-inspect.el @@ -37,8 +37,7 @@ ;;; Code: -(eval-when-compile (require 'cl)) - +(require 'cl-lib) (require 'soap-client) ;;; sample-value @@ -53,13 +52,13 @@ will be called." (let ((sample-value (get (aref type 0) 'soap-sample-value))) (if sample-value (funcall sample-value type) - (error "Cannot provide sample value for type %s" (aref type 0))))) + (error "Cannot provide sample value for type %s" (aref type 0))))) (defun soap-sample-value-for-xs-basic-type (type) "Provide a sample value for TYPE, an xs-basic-type. This is a specialization of `soap-sample-value' for xs-basic-type objects." - (case (soap-xs-basic-type-kind type) + (cl-case (soap-xs-basic-type-kind type) (string "a string") (anyURI "an URI") (QName "a QName") @@ -77,7 +76,7 @@ objects." (if (soap-xs-element-name element) (cons (intern (soap-xs-element-name element)) (soap-sample-value (soap-xs-element-type element))) - (soap-sample-value (soap-xs-element-type element)))) + (soap-sample-value (soap-xs-element-type element)))) (defun soap-sample-value-for-xs-attribute (attribute) "Provide a sample value for ATTRIBUTE, a WSDL attribute. @@ -119,20 +118,20 @@ This is a specialization of `soap-sample-value' for ((soap-xs-simple-type-pattern type) (format "a string matching %s" (soap-xs-simple-type-pattern type))) ((soap-xs-simple-type-length-range type) - (destructuring-bind (low . high) (soap-xs-simple-type-length-range type) + (cl-destructuring-bind (low . high) (soap-xs-simple-type-length-range type) (cond - ((and low high) - (format "a string between %d and %d chars long" low high)) - (low (format "a string at least %d chars long" low)) - (high (format "a string at most %d chars long" high)) - (t (format "a string OOPS"))))) + ((and low high) + (format "a string between %d and %d chars long" low high)) + (low (format "a string at least %d chars long" low)) + (high (format "a string at most %d chars long" high)) + (t (format "a string OOPS"))))) ((soap-xs-simple-type-integer-range type) - (destructuring-bind (min . max) (soap-xs-simple-type-integer-range type) + (cl-destructuring-bind (min . max) (soap-xs-simple-type-integer-range type) (cond - ((and min max) (+ min (random (- max min)))) - (min (+ min (random 10))) - (max (random max)) - (t (random 100))))) + ((and min max) (+ min (random (- max min)))) + (min (+ min (random 10))) + (max (random max)) + (t (random 100))))) ((consp (soap-xs-simple-type-base type)) ; an union of values (let ((base (soap-xs-simple-type-base type))) (soap-sample-value (nth (random (length base)) base)))) @@ -146,7 +145,7 @@ This is a specialization of `soap-sample-value' for (append (mapcar 'soap-sample-value-for-xs-attribute (soap-xs-type-attributes type)) - (case (soap-xs-complex-type-indicator type) + (cl-case (soap-xs-complex-type-indicator type) (array (let* ((element-type (soap-xs-complex-type-base type)) (sample1 (soap-sample-value element-type)) @@ -251,24 +250,24 @@ entire WSDL can be inspected." (define-button-type 'soap-client-describe-link - 'face 'link - 'help-echo "mouse-2, RET: describe item" - 'follow-link t - 'action (lambda (button) - (let ((item (button-get button 'item))) - (soap-inspect item))) - 'skip t) + 'face 'link + 'help-echo "mouse-2, RET: describe item" + 'follow-link t + 'action (lambda (button) + (let ((item (button-get button 'item))) + (soap-inspect item))) + 'skip t) (define-button-type 'soap-client-describe-back-link - 'face 'link - 'help-echo "mouse-2, RET: browse the previous item" - 'follow-link t - 'action (lambda (_button) - (let ((item (pop soap-inspect-previous-items))) - (when item - (setq soap-inspect-current-item nil) - (soap-inspect item)))) - 'skip t) + 'face 'link + 'help-echo "mouse-2, RET: browse the previous item" + 'follow-link t + 'action (lambda (_button) + (let ((item (pop soap-inspect-previous-items))) + (when item + (setq soap-inspect-current-item nil) + (soap-inspect item)))) + 'skip t) (defun soap-insert-describe-button (element) "Insert a button to inspect ELEMENT when pressed." @@ -297,8 +296,8 @@ entire WSDL can be inspected." (pp (soap-sample-value element) (current-buffer))) (defun soap-inspect-xs-attribute (attribute) - "Insert information about ATTRIBUTE, a soap-xs-attribute, in -the current buffer." + "Insert information about ATTRIBUTE in the current buffer. +ATTRIBUTE is a soap-xs-attribute." (insert "Attribute: " (soap-element-fq-name attribute)) (insert "\nType: ") (soap-insert-describe-button (soap-xs-attribute-type attribute)) @@ -306,8 +305,8 @@ the current buffer." (pp (soap-sample-value attribute) (current-buffer))) (defun soap-inspect-xs-attribute-group (attribute-group) - "Insert information about ATTRIBUTE-GROUP, a -soap-xs-attribute-group, in the current buffer." + "Insert information about ATTRIBUTE-GROUP in the current buffer. +ATTRIBUTE is a soap-xs-attribute-group." (insert "Attribute group: " (soap-element-fq-name attribute-group)) (insert "\nSample values:\n") (pp (soap-sample-value attribute-group) (current-buffer))) @@ -323,7 +322,7 @@ soap-xs-attribute-group, in the current buffer." (insert ", ") (setq first-time nil)) (soap-insert-describe-button b))) - (soap-insert-describe-button (soap-xs-simple-type-base type))) + (soap-insert-describe-button (soap-xs-simple-type-base type))) (insert "\nAttributes: ") (dolist (attribute (soap-xs-simple-type-attributes type)) (let ((name (or (soap-xs-attribute-name attribute) "*inline*")) @@ -359,7 +358,7 @@ soap-xs-attribute-group, in the current buffer." TYPE is a `soap-xs-complex-type'" (insert "Complex type: " (soap-element-fq-name type)) (insert "\nKind: ") - (case (soap-xs-complex-type-indicator type) + (cl-case (soap-xs-complex-type-indicator type) ((sequence all) (insert "a sequence ") (when (soap-xs-complex-type-base type) @@ -394,10 +393,10 @@ TYPE is a `soap-xs-complex-type'" (insert (make-string (- type-width (length (soap-element-fq-name type))) ?\ )) - (when (soap-xs-element-multiple? element) - (insert " multiple")) - (when (soap-xs-element-optional? element) - (insert " optional")))))) + (when (soap-xs-element-multiple? element) + (insert " multiple")) + (when (soap-xs-element-optional? element) + (insert " optional")))))) (choice (insert "a choice ") (when (soap-xs-complex-type-base type) @@ -449,11 +448,11 @@ TYPE is a `soap-xs-complex-type'" "Insert information about PORT-TYPE into the current buffer." (insert "Port-type name: " (soap-element-fq-name port-type) "\n") (insert "Operations:\n") - (loop for o being the hash-values of - (soap-namespace-elements (soap-port-type-operations port-type)) - do (progn - (insert "\t") - (soap-insert-describe-button (car o))))) + (cl-loop for o being the hash-values of + (soap-namespace-elements (soap-port-type-operations port-type)) + do (progn + (insert "\t") + (soap-insert-describe-button (car o))))) (defun soap-inspect-binding (binding) "Insert information about BINDING into the current buffer." @@ -461,13 +460,13 @@ TYPE is a `soap-xs-complex-type'" (insert "\n") (insert "Bound operations:\n") (let* ((ophash (soap-binding-operations binding)) - (operations (loop for o being the hash-keys of ophash - collect o)) + (operations (cl-loop for o being the hash-keys of ophash + collect o)) op-name-width) (setq operations (sort operations 'string<)) - (setq op-name-width (loop for o in operations maximizing (length o))) + (setq op-name-width (cl-loop for o in operations maximizing (length o))) (dolist (op operations) (let* ((bound-op (gethash op ophash)) diff --git a/lisp/net/tls.el b/lisp/net/tls.el index 2273d1345d5..11aae635aae 100644 --- a/lisp/net/tls.el +++ b/lisp/net/tls.el @@ -69,17 +69,15 @@ "^\\*\\*\\* Starting TLS handshake\n\\)*" "\\)") "Regexp matching end of TLS client informational messages. -Client data stream begins after the last character matched by -this. The default matches `openssl s_client' (version 0.9.8c) -and `gnutls-cli' (version 2.0.1) output." +Client data stream begins after the last character this matches. +The default matches the output of \"gnutls-cli\" (version 2.0.1)." :version "22.2" :type 'regexp :group 'tls) (defcustom tls-program '("gnutls-cli --x509cafile %t -p %p %h" - "gnutls-cli --x509cafile %t -p %p %h --protocols ssl3" - "openssl s_client -connect %h:%p -no_ssl2 -ign_eof") + "gnutls-cli --x509cafile %t -p %p %h --protocols ssl3") "List of strings containing commands to start TLS stream to a host. Each entry in the list is tried until a connection is successful. %h is replaced with the server hostname, %p with the port to @@ -94,24 +92,21 @@ successful negotiation." '(choice (const :tag "Default list of commands" ("gnutls-cli --x509cafile %t -p %p %h" - "gnutls-cli --x509cafile %t -p %p %h --protocols ssl3" - "openssl s_client -CAfile %t -connect %h:%p -no_ssl2 -ign_eof")) + "gnutls-cli --x509cafile %t -p %p %h --protocols ssl3")) (list :tag "Choose commands" :value ("gnutls-cli --x509cafile %t -p %p %h" - "gnutls-cli --x509cafile %t -p %p %h --protocols ssl3" - "openssl s_client -connect %h:%p -no_ssl2 -ign_eof") + "gnutls-cli --x509cafile %t -p %p %h --protocols ssl3") (set :inline t ;; FIXME: add brief `:tag "..."' descriptions. ;; (repeat :inline t :tag "Other" (string)) ;; No trust check: (const "gnutls-cli --insecure -p %p %h") - (const "gnutls-cli --insecure -p %p %h --protocols ssl3") - (const "openssl s_client -connect %h:%p -no_ssl2 -ign_eof")) + (const "gnutls-cli --insecure -p %p %h --protocols ssl3")) (repeat :inline t :tag "Other" (string))) (list :tag "List of commands" (repeat :tag "Command" (string)))) - :version "22.1" + :version "25.3" ; remove s_client :group 'tls) (defcustom tls-process-connection-type nil @@ -122,8 +117,8 @@ successful negotiation." (defcustom tls-success "- Handshake was completed\\|SSL handshake has read " "Regular expression indicating completed TLS handshakes. -The default is what GnuTLS's \"gnutls-cli\" or OpenSSL's -\"openssl s_client\" outputs." +The default is what GnuTLS's \"gnutls-cli\" outputs." +;; or OpenSSL's \"openssl s_client\" :version "22.1" :type 'regexp :group 'tls) @@ -138,8 +133,7 @@ consider trustworthy, e.g.: \(setq tls-program \\='(\"gnutls-cli --x509cafile /etc/ssl/certs/ca-certificates.crt -p %p %h\" - \"gnutls-cli --x509cafile /etc/ssl/certs/ca-certificates.crt -p %p %h --protocols ssl3\" - \"openssl s_client -connect %h:%p -CAfile /etc/ssl/certs/ca-certificates.crt -no_ssl2 -ign_eof\"))" + \"gnutls-cli --x509cafile /etc/ssl/certs/ca-certificates.crt -p %p %h --protocols ssl3\"))" :type '(choice (const :tag "Always" t) (const :tag "Never" nil) (const :tag "Ask" ask)) @@ -149,9 +143,9 @@ consider trustworthy, e.g.: (defcustom tls-untrusted "- Peer's certificate is NOT trusted\\|Verify return code: \\([^0] \\|.[^ ]\\)" "Regular expression indicating failure of TLS certificate verification. -The default is what GnuTLS's \"gnutls-cli\" or OpenSSL's -\"openssl s_client\" return in the event of unsuccessful -verification." +The default is what GnuTLS's \"gnutls-cli\" returns in the event of +unsuccessful verification." +;; or OpenSSL's \"openssl s_client\" :type 'regexp :version "23.1" ;; No Gnus :group 'tls) diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index 846b19575a6..346979000f5 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -1,4 +1,4 @@ -;;; tramp-adb.el --- Functions for calling Android Debug Bridge from Tramp +;;; tramp-adb.el --- Functions for calling Android Debug Bridge from Tramp -*- lexical-binding:t -*- ;; Copyright (C) 2011-2017 Free Software Foundation, Inc. @@ -58,7 +58,7 @@ It is used for TCP/IP devices." ;;;###tramp-autoload (defcustom tramp-adb-prompt - "^\\(?:[[:digit:]]*|?\\)?\\(?:[[:alnum:]\e;[]*@[[:alnum:]]*[^#\\$]*\\)?[#\\$][[:space:]]" + "^\\(?:[[:digit:]]*|?\\)?\\(?:[[:alnum:]\e;[]*@?[[:alnum:]]*[^#\\$]*\\)?[#\\$][[:space:]]" "Regexp used as prompt in almquist shell." :type 'string :version "24.4" @@ -72,6 +72,7 @@ It is used for TCP/IP devices." (defconst tramp-adb-ls-toolbox-regexp (concat "^[[:space:]]*\\([-[:alpha:]]+\\)" ; \1 permissions + "\\(?:[[:space:]]+[[:digit:]]+\\)?" ; links (Android 7/toybox) "[[:space:]]*\\([^[:space:]]+\\)" ; \2 username "[[:space:]]+\\([^[:space:]]+\\)" ; \3 group "[[:space:]]+\\([[:digit:]]+\\)" ; \4 size @@ -94,9 +95,6 @@ It is used for TCP/IP devices." tramp-adb-method '((tramp-adb-parse-device-names "")))) ;;;###tramp-autoload -(add-to-list 'tramp-foreign-file-name-handler-alist - (cons 'tramp-adb-file-name-p 'tramp-adb-file-name-handler)) - (defconst tramp-adb-file-name-handler-alist '((access-file . ignore) (add-name-to-file . tramp-adb-handle-copy-file) @@ -189,6 +187,10 @@ pass to the OPERATION." (save-match-data (apply (cdr fn) args)) (tramp-run-real-handler operation args)))) +;;;###tramp-autoload +(tramp-register-foreign-file-name-handler + 'tramp-adb-file-name-p 'tramp-adb-file-name-handler) + ;;;###tramp-autoload (defun tramp-adb-parse-device-names (_ignore) "Return a list of (nil host) tuples allowed to access." @@ -198,18 +200,20 @@ pass to the OPERATION." ;; That's why we use `start-process'. (let ((p (start-process tramp-adb-program (current-buffer) tramp-adb-program "devices")) - (v (vector tramp-adb-method tramp-current-user - tramp-current-host nil nil)) + (v (make-tramp-file-name + :method tramp-adb-method :user tramp-current-user + :host tramp-current-host)) result) (tramp-message v 6 "%s" (mapconcat 'identity (process-command p) " ")) + (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) - (while (tramp-compat-process-live-p p) + (while (process-live-p p) (accept-process-output p 0.1)) (accept-process-output p 0.1) (tramp-message v 6 "\n%s" (buffer-string)) (goto-char (point-min)) (while (search-forward-regexp "^\\(\\S-+\\)[[:space:]]+device$" nil t) - (add-to-list 'result (list nil (match-string 1)))) + (push (list nil (match-string 1)) result)) ;; Replace ":" by "#". (mapc @@ -240,7 +244,7 @@ pass to the OPERATION." ;; be problems with UNC shares or Cygwin mounts. (let ((default-directory (tramp-compat-temporary-file-directory))) (tramp-make-tramp-file-name - method user host + method user domain host port (tramp-drop-volume-letter (tramp-run-real-handler 'expand-file-name (list localname)))))))) @@ -259,7 +263,7 @@ pass to the OPERATION." "%s%s" (with-parsed-tramp-file-name (expand-file-name filename) nil (tramp-make-tramp-file-name - method user host + method user domain host port (with-tramp-file-property v localname "file-truename" (let ((result nil)) ; result steps in reverse order (tramp-message v 4 "Finding true name for `%s'" filename) @@ -287,7 +291,7 @@ pass to the OPERATION." (tramp-compat-file-attribute-type (file-attributes (tramp-make-tramp-file-name - method user host + method user domain host port (mapconcat 'identity (append '("") (reverse result) @@ -407,15 +411,17 @@ pass to the OPERATION." (tramp-adb-get-ls-command v) (tramp-shell-quote-argument localname))) ;; We insert also filename/. and filename/.., because "ls" doesn't. - (narrow-to-region (point) (point)) - (tramp-adb-send-command - v (format "%s -d -a -l %s %s" - (tramp-adb-get-ls-command v) - (tramp-shell-quote-argument - (concat (file-name-as-directory localname) ".")) - (tramp-shell-quote-argument - (concat (file-name-as-directory localname) "..")))) - (widen)) + ;; Looks like it does include them in toybox, since Android 6. + (unless (re-search-backward "\\.$" nil t) + (narrow-to-region (point-max) (point-max)) + (tramp-adb-send-command + v (format "%s -d -a -l %s %s" + (tramp-adb-get-ls-command v) + (tramp-shell-quote-argument + (concat (file-name-as-directory localname) ".")) + (tramp-shell-quote-argument + (concat (file-name-as-directory localname) "..")))) + (widen))) (tramp-adb-sh-fix-ls-output) (let ((result (tramp-do-parse-file-attributes-with-ls v (or id-format 'integer)))) @@ -438,12 +444,16 @@ pass to the OPERATION." "Determine `ls' command at its arguments." (with-tramp-connection-property vec "ls" (tramp-message vec 5 "Finding a suitable `ls' command") - (if (tramp-adb-send-command-and-check vec "ls --color=never -al /dev/null") - ;; On CyanogenMod based system BusyBox is used and "ls" output - ;; coloring is enabled by default. So we try to disable it - ;; when possible. - "ls --color=never" - "ls"))) + (cond + ;; Can't disable coloring explicitly for toybox ls command. We + ;; must force "ls" to print just one column. + ((tramp-adb-send-command-and-check vec "toybox") "env COLUMNS=1 ls") + ;; On CyanogenMod based system BusyBox is used and "ls" output + ;; coloring is enabled by default. So we try to disable it when + ;; possible. + ((tramp-adb-send-command-and-check vec "ls --color=never -al /dev/null") + "ls --color=never") + (t "ls")))) (defun tramp-adb--gnu-switches-to-ash (switches) "Almquist shell can't handle multiple arguments. @@ -520,7 +530,7 @@ Emacs dired can't find files." (tramp-flush-file-property v (file-name-directory localname)) (tramp-flush-directory-property v localname))) -(defun tramp-adb-handle-delete-directory (directory &optional recursive) +(defun tramp-adb-handle-delete-directory (directory &optional recursive _trash) "Like `delete-directory' for Tramp files." (setq directory (expand-file-name directory)) (with-parsed-tramp-file-name (file-truename directory) nil @@ -562,13 +572,17 @@ Emacs dired can't find files." (file-name-as-directory f) f)) (with-current-buffer (tramp-get-buffer v) - (append - '("." "..") - (delq - nil - (mapcar - (lambda (l) (and (not (string-match "^[[:space:]]*$" l)) l)) - (split-string (buffer-string) "\n"))))))))))) + (delete-dups + (append + ;; In older Android versions, "." and ".." are not + ;; included. In newer versions (toybox, since Android + ;; 6) they are. We fix this by `delete-dups'. + '("." "..") + (delq + nil + (mapcar + (lambda (l) (and (not (string-match "^[[:space:]]*$" l)) l)) + (split-string (buffer-string) "\n")))))))))))) (defun tramp-adb-handle-file-local-copy (filename) "Like `file-local-copy' for Tramp files." @@ -685,7 +699,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." newname (expand-file-name newname)) (if (file-directory-p filename) - (tramp-file-name-handler 'copy-directory filename newname keep-date t) + (copy-directory filename newname keep-date t) (let ((t1 (tramp-tramp-file-p filename)) (t2 (tramp-tramp-file-p newname))) @@ -813,7 +827,8 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (setq input (with-parsed-tramp-file-name infile nil localname)) ;; INFILE must be copied to remote host. (setq input (tramp-make-tramp-temp-file v) - tmpinput (tramp-make-tramp-file-name method user host input)) + tmpinput (tramp-make-tramp-file-name + method user domain host port input)) (copy-file infile tmpinput t))) (when input (setq command (format "%s <%s" command input))) @@ -847,7 +862,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." ;; file must be deleted after execution. (setq stderr (tramp-make-tramp-temp-file v) tmpstderr (tramp-make-tramp-file-name - method user host stderr)))) + method user domain host port stderr)))) ;; stderr to be discarded. ((null (cadr destination)) (setq stderr "/dev/null")))) @@ -1060,9 +1075,8 @@ E.g. a host name \"192.168.1.1#5555\" returns \"192.168.1.1:5555\" ;; unwanted entries first. (tramp-flush-connection-property nil) (with-tramp-connection-property (tramp-get-connection-process vec) "device" - (let* ((method (tramp-file-name-method vec)) - (host (tramp-file-name-host vec)) - (port (tramp-file-name-port vec)) + (let* ((host (tramp-file-name-host vec)) + (port (tramp-file-name-port-or-default vec)) (devices (mapcar 'cadr (tramp-adb-parse-device-names nil)))) (replace-regexp-in-string tramp-prefix-port-format ":" @@ -1163,7 +1177,9 @@ FMT and ARGS are passed to `error'." (delete-process proc) (tramp-error proc 'file-error "Process `%s' not available, try again" proc)) (with-current-buffer (process-buffer proc) - (if (tramp-wait-for-regexp proc timeout tramp-adb-prompt) + (if (tramp-wait-for-regexp + proc timeout + (tramp-get-connection-property proc "prompt" tramp-adb-prompt)) (let (buffer-read-only) (goto-char (point-min)) ;; ADB terminal sends "^H" sequences. @@ -1172,27 +1188,30 @@ FMT and ARGS are passed to `error'." (delete-region (point-min) (point))) ;; Delete the prompt. (goto-char (point-min)) - (when (re-search-forward tramp-adb-prompt (point-at-eol) t) + (when (re-search-forward + (tramp-get-connection-property proc "prompt" tramp-adb-prompt) + (point-at-eol) t) (forward-line 1) (delete-region (point-min) (point))) (goto-char (point-max)) - (re-search-backward tramp-adb-prompt nil t) + (re-search-backward + (tramp-get-connection-property proc "prompt" tramp-adb-prompt) nil t) (delete-region (point) (point-max))) (if timeout (tramp-error proc 'file-error "[[Remote adb prompt `%s' not found in %d secs]]" - tramp-adb-prompt timeout) + (tramp-get-connection-property proc "prompt" tramp-adb-prompt) + timeout) (tramp-error proc 'file-error - "[[Remote prompt `%s' not found]]" tramp-adb-prompt))))) + "[[Remote prompt `%s' not found]]" + (tramp-get-connection-property proc "prompt" tramp-adb-prompt)))))) (defun tramp-adb-maybe-open-connection (vec) "Maybe open a connection VEC. Does not do anything if a connection is already open, but re-opens the connection if a previous connection has died for some reason." - (tramp-check-proper-method-and-host vec) - (let* ((buf (tramp-get-connection-buffer vec)) (p (get-buffer-process buf)) (host (tramp-file-name-host vec)) @@ -1200,8 +1219,7 @@ connection if a previous connection has died for some reason." (device (tramp-adb-get-device vec))) ;; Set variables for proper tracing in `tramp-adb-parse-device-names'. - (setq tramp-current-method (tramp-file-name-method vec) - tramp-current-user (tramp-file-name-user vec) + (setq tramp-current-user (tramp-file-name-user vec) tramp-current-host (tramp-file-name-host vec)) ;; Maybe we know already that "su" is not supported. We cannot @@ -1210,7 +1228,7 @@ connection if a previous connection has died for some reason." (when (and user (not (tramp-get-file-property vec "" "su-command-p" t))) (tramp-error vec 'file-error "Cannot switch to user `%s'" user)) - (unless (tramp-compat-process-live-p p) + (unless (process-live-p p) (save-match-data (when (and p (processp p)) (delete-process p)) (if (zerop (length device)) @@ -1224,16 +1242,25 @@ connection if a previous connection has died for some reason." (p (let ((default-directory (tramp-compat-temporary-file-directory))) (apply 'start-process (tramp-get-connection-name vec) buf - tramp-adb-program args)))) + tramp-adb-program args))) + (prompt (md5 (concat (prin1-to-string process-environment) + (current-time-string))))) (tramp-message vec 6 "%s" (mapconcat 'identity (process-command p) " ")) ;; Wait for initial prompt. (tramp-adb-wait-for-output p 30) - (unless (tramp-compat-process-live-p p) + (unless (process-live-p p) (tramp-error vec 'file-error "Terminated!")) (tramp-set-connection-property p "vector" vec) + (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) + ;; Change prompt. + (tramp-set-connection-property + p "prompt" (regexp-quote (format "///%s#$" prompt))) + (tramp-adb-send-command + vec (format "PS1=\"///\"\"%s\"\"#$\"" prompt)) + ;; Check whether the properties have been changed. If ;; yes, this is a strong indication that we must expire all ;; connection properties. We start again. diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el index 5205eceacff..ac5a9c45bbd 100644 --- a/lisp/net/tramp-cache.el +++ b/lisp/net/tramp-cache.el @@ -1,9 +1,10 @@ -;;; tramp-cache.el --- file information caching for Tramp +;;; tramp-cache.el --- file information caching for Tramp -*- lexical-binding:t -*- ;; Copyright (C) 2000, 2005-2017 Free Software Foundation, Inc. ;; Author: Daniel Pittman ;; Michael Albinus +;; Maintainer: Michael Albinus ;; Keywords: comm, processes ;; Package: tramp @@ -26,9 +27,9 @@ ;; An implementation of information caching for remote files. -;; Each connection, identified by a vector [method user host -;; localname] or by a process, has a unique cache. We distinguish 3 -;; kind of caches, depending on the key: +;; Each connection, identified by a `tramp-file-name' structure or by +;; a process, has a unique cache. We distinguish 3 kind of caches, +;; depending on the key: ;; ;; - localname is NIL. This are reusable properties. Examples: ;; "remote-shell" identifies the POSIX shell to be called on the @@ -93,12 +94,14 @@ matching entries of `tramp-connection-properties'." (or (gethash key tramp-cache-data) (let ((hash (puthash key (make-hash-table :test 'equal) tramp-cache-data))) - (when (vectorp key) + (when (tramp-file-name-p key) (dolist (elt tramp-connection-properties) (when (string-match (or (nth 0 elt) "") (tramp-make-tramp-file-name - (aref key 0) (aref key 1) (aref key 2) nil)) + (tramp-file-name-method key) (tramp-file-name-user key) + (tramp-file-name-domain key) (tramp-file-name-host key) + (tramp-file-name-port key) nil)) (tramp-set-connection-property key (nth 1 elt) (nth 2 elt))))) hash))) @@ -106,11 +109,12 @@ matching entries of `tramp-connection-properties'." (defun tramp-get-file-property (key file property default) "Get the PROPERTY of FILE from the cache context of KEY. Returns DEFAULT if not set." - ;; Unify localname. Remove hop from vector. - (setq file (tramp-compat-file-name-unquote file)) - (setq key (copy-sequence key)) - (aset key 3 (tramp-run-real-handler 'directory-file-name (list file))) - (aset key 4 nil) + ;; Unify localname. Remove hop from `tramp-file-name' structure. + (setq file (tramp-compat-file-name-unquote file) + key (copy-tramp-file-name key)) + (setf (tramp-file-name-localname key) + (tramp-run-real-handler 'directory-file-name (list file)) + (tramp-file-name-hop key) nil) (let* ((hash (tramp-get-hash-table key)) (value (when (hash-table-p hash) (gethash property hash)))) (if @@ -140,11 +144,12 @@ Returns DEFAULT if not set." (defun tramp-set-file-property (key file property value) "Set the PROPERTY of FILE to VALUE, in the cache context of KEY. Returns VALUE." - ;; Unify localname. Remove hop from vector. - (setq file (tramp-compat-file-name-unquote file)) - (setq key (copy-sequence key)) - (aset key 3 (tramp-run-real-handler 'directory-file-name (list file))) - (aset key 4 nil) + ;; Unify localname. Remove hop from `tramp-file-name' structure. + (setq file (tramp-compat-file-name-unquote file) + key (copy-tramp-file-name key)) + (setf (tramp-file-name-localname key) + (tramp-run-real-handler 'directory-file-name (list file)) + (tramp-file-name-hop key) nil) (let ((hash (tramp-get-hash-table key))) ;; We put the timestamp there. (puthash property (cons (current-time) value) hash) @@ -161,11 +166,11 @@ Returns VALUE." (let* ((file (tramp-run-real-handler 'directory-file-name (list file))) (truename (tramp-get-file-property key file "file-truename" nil))) - ;; Unify localname. Remove hop from vector. - (setq file (tramp-compat-file-name-unquote file)) - (setq key (copy-sequence key)) - (aset key 3 file) - (aset key 4 nil) + ;; Unify localname. Remove hop from `tramp-file-name' structure. + (setq file (tramp-compat-file-name-unquote file) + key (copy-tramp-file-name key)) + (setf (tramp-file-name-localname key) file + (tramp-file-name-hop key) nil) (tramp-message key 8 "%s" file) (remhash key tramp-cache-data) ;; Remove file properties of symlinks. @@ -184,7 +189,8 @@ Remove also properties of all files in subdirectories." (tramp-message key 8 "%s" directory) (maphash (lambda (key _value) - (when (and (stringp (tramp-file-name-localname key)) + (when (and (tramp-file-name-p key) + (stringp (tramp-file-name-localname key)) (string-match (regexp-quote directory) (tramp-file-name-localname key))) (remhash key tramp-cache-data))) @@ -231,20 +237,20 @@ This is suppressed for temporary buffers." (defun tramp-get-connection-property (key property default) "Get the named PROPERTY for the connection. KEY identifies the connection, it is either a process or a -vector. A special case is nil, which is used to cache connection -properties of the local machine. If the value is not set for the -connection, returns DEFAULT." - ;; Unify key by removing localname and hop from vector. Work with a - ;; copy in order to avoid side effects. - (when (vectorp key) - (setq key (copy-sequence key)) - (aset key 3 nil) - (aset key 4 nil)) +`tramp-file-name' structure. A special case is nil, which is +used to cache connection properties of the local machine. If the +value is not set for the connection, returns DEFAULT." + ;; Unify key by removing localname and hop from `tramp-file-name' + ;; structure. Work with a copy in order to avoid side effects. + (when (tramp-file-name-p key) + (setq key (copy-tramp-file-name key)) + (setf (tramp-file-name-localname key) nil + (tramp-file-name-hop key) nil)) (let* ((hash (tramp-get-hash-table key)) (value ;; If the key is an auxiliary process object, check whether ;; the process is still alive. - (if (and (processp key) (not (tramp-compat-process-live-p key))) + (if (and (processp key) (not (process-live-p key))) default (if (hash-table-p hash) (gethash property hash default) @@ -256,15 +262,15 @@ connection, returns DEFAULT." (defun tramp-set-connection-property (key property value) "Set the named PROPERTY of a connection to VALUE. KEY identifies the connection, it is either a process or a -vector. A special case is nil, which is used to cache connection -properties of the local machine. PROPERTY is set persistent when -KEY is a vector." - ;; Unify key by removing localname and hop from vector. Work with a - ;; copy in order to avoid side effects. - (when (vectorp key) - (setq key (copy-sequence key)) - (aset key 3 nil) - (aset key 4 nil)) +`tramp-file-name' structure. A special case is nil, which is +used to cache connection properties of the local machine. +PROPERTY is set persistent when KEY is a `tramp-file-name' structure." + ;; Unify key by removing localname and hop from `tramp-file-name' + ;; structure. Work with a copy in order to avoid side effects. + (when (tramp-file-name-p key) + (setq key (copy-tramp-file-name key)) + (setf (tramp-file-name-localname key) nil + (tramp-file-name-hop key) nil)) (let ((hash (tramp-get-hash-table key))) (puthash property value hash) (setq tramp-cache-data-changed t) @@ -275,22 +281,22 @@ KEY is a vector." (defun tramp-connection-property-p (key property) "Check whether named PROPERTY of a connection is defined. KEY identifies the connection, it is either a process or a -vector. A special case is nil, which is used to cache connection -properties of the local machine." +`tramp-file-name' structure. A special case is nil, which is +used to cache connection properties of the local machine." (not (eq (tramp-get-connection-property key property 'undef) 'undef))) ;;;###tramp-autoload (defun tramp-flush-connection-property (key) "Remove all properties identified by KEY. KEY identifies the connection, it is either a process or a -vector. A special case is nil, which is used to cache connection -properties of the local machine." - ;; Unify key by removing localname and hop from vector. Work with a - ;; copy in order to avoid side effects. - (when (vectorp key) - (setq key (copy-sequence key)) - (aset key 3 nil) - (aset key 4 nil)) +`tramp-file-name' structure. A special case is nil, which is +used to cache connection properties of the local machine." + ;; Unify key by removing localname and hop from `tramp-file-name' + ;; structure. Work with a copy in order to avoid side effects. + (when (tramp-file-name-p key) + (setq key (copy-tramp-file-name key)) + (setf (tramp-file-name-localname key) nil + (tramp-file-name-hop key) nil)) (tramp-message key 7 "%s %s" key (let ((hash (gethash key tramp-cache-data)) @@ -309,10 +315,19 @@ properties of the local machine." (maphash (lambda (key value) ;; Remove text properties from KEY and VALUE. - (when (vectorp key) + ;; `cl-struct-slot-*' functions exist since Emacs 25 only; we + ;; ignore errors. + (when (tramp-file-name-p key) + ;; (dolist + ;; (slot + ;; (mapcar 'car (cdr (cl-struct-slot-info 'tramp-file-name)))) + ;; (when (stringp (cl-struct-slot-value 'tramp-file-name slot key)) + ;; (setf (cl-struct-slot-value 'tramp-file-name slot key) + ;; (substring-no-properties + ;; (cl-struct-slot-value 'tramp-file-name slot key)))))) (dotimes (i (length key)) - (when (stringp (aref key i)) - (aset key i (substring-no-properties (aref key i)))))) + (when (stringp (elt key i)) + (setf (elt key i) (substring-no-properties (elt key i)))))) (when (stringp key) (setq key (substring-no-properties key))) (when (stringp value) @@ -334,11 +349,12 @@ properties of the local machine." ;;;###tramp-autoload (defun tramp-list-connections () - "Return a list of all known connection vectors according to `tramp-cache'." + "Return all known `tramp-file-name' structs according to `tramp-cache'." (let (result tramp-verbose) (maphash (lambda (key _value) - (when (and (vectorp key) (null (aref key 3)) + (when (and (tramp-file-name-p key) + (null (tramp-file-name-localname key)) (tramp-connection-property-p key "process-buffer")) (add-to-list 'result key))) tramp-cache-data) @@ -357,12 +373,15 @@ properties of the local machine." ;; Remove temporary data. If there is the key "login-as", we ;; don't save either, because all other properties might ;; depend on the login name, and we want to give the - ;; possibility to use another login name later on. + ;; possibility to use another login name later on. Key + ;; "started" exists for the "ftp" method only, which must be + ;; be kept persistent. (maphash (lambda (key value) - (if (and (vectorp key) + (if (and (tramp-file-name-p key) value (not (tramp-file-name-localname key)) - (not (gethash "login-as" value))) + (not (gethash "login-as" value)) + (not (gethash "started" value))) (progn (remhash "process-name" value) (remhash "process-buffer" value) @@ -401,7 +420,7 @@ for all methods. Resulting data are derived from connection history." (let (res) (maphash (lambda (key _value) - (if (and (vectorp key) + (if (and (tramp-file-name-p key) (string-equal method (tramp-file-name-method key)) (not (tramp-file-name-localname key))) (push (list (tramp-file-name-user key) @@ -410,14 +429,16 @@ for all methods. Resulting data are derived from connection history." tramp-cache-data) res)) +;; When "emacs -Q" has been called, both variables are nil. We do not +;; load the persistency file then, in order to have a clean test environment. +;;;###tramp-autoload +(defvar tramp-cache-read-persistent-data (or init-file-user site-run-file) + "Whether to read persistent data at startup time.") + ;; Read persistent connection history. (when (and (stringp tramp-persistency-file-name) (zerop (hash-table-count tramp-cache-data)) - ;; When "emacs -Q" has been called, both variables are nil. - ;; We do not load the persistency file then, in order to - ;; have a clean test environment. - (or init-file-user - site-run-file)) + tramp-cache-read-persistent-data) (condition-case err (with-temp-buffer (insert-file-contents tramp-persistency-file-name) @@ -426,12 +447,13 @@ for all methods. Resulting data are derived from connection history." element key item) (while (setq element (pop list)) (setq key (pop element)) - (while (setq item (pop element)) - ;; We set only values which are not contained in - ;; `tramp-connection-properties'. The cache is - ;; initialized properly by side effect. - (unless (tramp-connection-property-p key (car item)) - (tramp-set-connection-property key (pop item) (car item)))))) + (when (tramp-file-name-p key) + (while (setq item (pop element)) + ;; We set only values which are not contained in + ;; `tramp-connection-properties'. The cache is + ;; initialized properly by side effect. + (unless (tramp-connection-property-p key (car item)) + (tramp-set-connection-property key (pop item) (car item))))))) (setq tramp-cache-data-changed nil)) (file-error ;; Most likely because the file doesn't exist yet. No message. diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el index 576f9b1eadc..4c5a12d33ba 100644 --- a/lisp/net/tramp-cmds.el +++ b/lisp/net/tramp-cmds.el @@ -1,4 +1,4 @@ -;;; tramp-cmds.el --- Interactive commands for Tramp +;;; tramp-cmds.el --- Interactive commands for Tramp -*- lexical-binding:t -*- ;; Copyright (C) 2007-2017 Free Software Foundation, Inc. @@ -37,6 +37,20 @@ (defvar reporter-eval-buffer) (defvar reporter-prompt-for-summary-p) +;;;###tramp-autoload +(defun tramp-change-syntax (&optional syntax) + "Change Tramp syntax. +SYNTAX can be one of the symbols `default' (default), +`simplified' (ange-ftp like) or `separate' (XEmacs like)." + (interactive + (let ((input (completing-read + "Enter Tramp syntax: " (tramp-syntax-values) nil t + (symbol-name tramp-syntax)))) + (unless (string-equal input "") + (list (intern input))))) + (when syntax + (custom-set-variables `(tramp-syntax ',syntax)))) + (defun tramp-list-tramp-buffers () "Return a list of all Tramp connection buffers." (append @@ -71,7 +85,9 @@ When called interactively, a Tramp connection has to be selected." (tramp-make-tramp-file-name (tramp-file-name-method x) (tramp-file-name-user x) + (tramp-file-name-domain x) (tramp-file-name-host x) + (tramp-file-name-port x) (tramp-file-name-localname x))) (tramp-list-connections))) name) @@ -233,10 +249,9 @@ buffer in your bug report. ;; Pretty print the cache. (set varsym (read (format "(%s)" (tramp-cache-print val)))) ;; There are non-7bit characters to be masked. - (when (and (boundp 'mm-7bit-chars) - (stringp val) + (when (and (stringp val) (string-match - (concat "[^" (symbol-value 'mm-7bit-chars) "]") val)) + (concat "[^" (bound-and-true-p mm-7bit-chars) "]") val)) (with-current-buffer reporter-eval-buffer (set varsym @@ -313,8 +328,7 @@ buffer in your bug report. ;; Append buffers only when we are in message mode. (when (and (eq major-mode 'message-mode) - (boundp 'mml-mode) - (symbol-value 'mml-mode)) + (bound-and-true-p mml-mode)) (let ((tramp-buf-regexp "\\*\\(debug \\)?tramp/") (buffer-list (tramp-list-tramp-buffers)) diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el index 8e5b3e45d13..b2df4d6324b 100644 --- a/lisp/net/tramp-compat.el +++ b/lisp/net/tramp-compat.el @@ -1,4 +1,4 @@ -;;; tramp-compat.el --- Tramp compatibility functions +;;; tramp-compat.el --- Tramp compatibility functions -*- lexical-binding:t -*- ;; Copyright (C) 2007-2017 Free Software Foundation, Inc. @@ -24,17 +24,13 @@ ;;; Commentary: ;; Tramp's main Emacs version for development is Emacs 26. This -;; package provides compatibility functions for Emacs 23, Emacs 24 and -;; Emacs 25. +;; package provides compatibility functions for Emacs 24 and Emacs 25. ;;; Code: -;; Pacify byte-compiler. -(eval-when-compile - (require 'cl)) - (require 'auth-source) (require 'advice) +(require 'cl-lib) (require 'custom) (require 'format-spec) (require 'parse-time) @@ -46,12 +42,6 @@ (require 'trampver) (require 'tramp-loaddefs) -;; `remote-file-name-inhibit-cache' has been introduced with Emacs -;; 24.1. Besides t, nil, and integer, we use also timestamps (as -;; returned by `current-time') internally. -(unless (boundp 'remote-file-name-inhibit-cache) - (defvar remote-file-name-inhibit-cache nil)) - ;; For not existing functions, obsolete functions, or functions with a ;; changed argument list, there are compiler warnings. We want to ;; avoid them in cases we know what we do. @@ -87,22 +77,6 @@ 'file-expand-wildcards 'around 'tramp-advice-file-expand-wildcards) (ad-activate 'file-expand-wildcards)))) -;; `condition-case-unless-debug' is introduced with Emacs 24. -(if (fboundp 'condition-case-unless-debug) - (defalias 'tramp-compat-condition-case-unless-debug - 'condition-case-unless-debug) - (defmacro tramp-compat-condition-case-unless-debug - (var bodyform &rest handlers) - "Like `condition-case' except that it does not catch anything when debugging." - (declare (debug condition-case) (indent 2)) - (let ((bodysym (make-symbol "body"))) - `(let ((,bodysym (lambda () ,bodyform))) - (if debug-on-error - (funcall ,bodysym) - (condition-case ,var - (funcall ,bodysym) - ,@handlers)))))) - (defsubst tramp-compat-temporary-file-directory () "Return name of directory for temporary files. It is the default value of `temporary-file-directory'." @@ -126,106 +100,6 @@ Add the extension of F, if existing." 'temporary-file-directory 'tramp-handle-temporary-file-directory)) -;; PRESERVE-EXTENDED-ATTRIBUTES has been introduced with Emacs 24.1 -;; (as PRESERVE-SELINUX-CONTEXT), and renamed in Emacs 24.3. -(defun tramp-compat-copy-file - (filename newname &optional ok-if-already-exists keep-date - preserve-uid-gid preserve-extended-attributes) - "Like `copy-file' for Tramp files (compat function)." - (cond - (preserve-extended-attributes - (condition-case nil - (tramp-compat-funcall - 'copy-file filename newname ok-if-already-exists keep-date - preserve-uid-gid preserve-extended-attributes) - (wrong-number-of-arguments - (copy-file - filename newname ok-if-already-exists keep-date preserve-uid-gid)))) - (t - (copy-file - filename newname ok-if-already-exists keep-date preserve-uid-gid)))) - -;; COPY-CONTENTS has been introduced with Emacs 24.1. -(defun tramp-compat-copy-directory - (directory newname &optional keep-time parents copy-contents) - "Make a copy of DIRECTORY (compat function)." - (condition-case nil - (tramp-compat-funcall - 'copy-directory directory newname keep-time parents copy-contents) - - ;; `copy-directory' is either not implemented, or it does not - ;; support the the COPY-CONTENTS flag. For the time being, we - ;; ignore COPY-CONTENTS as well. - - (error - ;; If `default-directory' is a remote directory, make sure we - ;; find its `copy-directory' handler. - (let ((handler (or (find-file-name-handler directory 'copy-directory) - (find-file-name-handler newname 'copy-directory)))) - (if handler - (funcall handler 'copy-directory directory newname keep-time parents) - - ;; Compute target name. - (setq directory (directory-file-name (expand-file-name directory)) - newname (directory-file-name (expand-file-name newname))) - (if (and (file-directory-p newname) - (not (string-equal (file-name-nondirectory directory) - (file-name-nondirectory newname)))) - (setq newname - (expand-file-name - (file-name-nondirectory directory) newname))) - (if (not (file-directory-p newname)) (make-directory newname parents)) - - ;; Copy recursively. - (mapc - (lambda (file) - (if (file-directory-p file) - (tramp-compat-copy-directory file newname keep-time parents) - (copy-file file newname t keep-time))) - ;; We do not want to delete "." and "..". - (directory-files directory 'full directory-files-no-dot-files-regexp)) - - ;; Set directory attributes. - (set-file-modes newname (file-modes directory)) - (if keep-time - (set-file-times newname (nth 5 (file-attributes directory))))))))) - -;; TRASH has been introduced with Emacs 24.1. -(defun tramp-compat-delete-file (filename &optional trash) - "Like `delete-file' for Tramp files (compat function)." - (condition-case nil - (tramp-compat-funcall 'delete-file filename trash) - ;; This Emacs version does not support the TRASH flag. - (wrong-number-of-arguments - (let ((delete-by-moving-to-trash - (and (boundp 'delete-by-moving-to-trash) - (symbol-value 'delete-by-moving-to-trash) - trash))) - (delete-file filename))))) - -;; RECURSIVE has been introduced with Emacs 23.2. TRASH has been -;; introduced with Emacs 24.1. -(defun tramp-compat-delete-directory (directory &optional recursive trash) - "Like `delete-directory' for Tramp files (compat function)." - (condition-case nil - (cond - (trash - (tramp-compat-funcall 'delete-directory directory recursive trash)) - (t - (delete-directory directory recursive))) - ;; This Emacs version does not support the TRASH flag. We use the - ;; implementation from Emacs 23.2. - (wrong-number-of-arguments - (setq directory (directory-file-name (expand-file-name directory))) - (when (not (file-symlink-p directory)) - (mapc (lambda (file) - (if (eq t (car (file-attributes file))) - (tramp-compat-delete-directory file recursive trash) - (tramp-compat-delete-file file trash))) - (directory-files - directory 'full directory-files-no-dot-files-regexp))) - (delete-directory directory)))) - (defun tramp-compat-process-running-p (process-name) "Returns t if system process PROCESS-NAME is running for `user-login-name'." (when (stringp process-name) @@ -250,19 +124,6 @@ Add the extension of F, if existing." process-name)))) (setq result t))))))))) -;; `process-running-live-p' is introduced in Emacs 24. -(defalias 'tramp-compat-process-live-p - (if (fboundp 'process-running-live-p) - 'process-running-live-p - (lambda (process) - "Returns non-nil if PROCESS is alive. -A process is considered alive if its status is `run', `open', -`listen', `connect' or `stop'. Value is nil if PROCESS is not a -process." - (and (processp process) - (memq (process-status process) - '(run open listen connect stop)))))) - ;; `user-error' has appeared in Emacs 24.3. (defsubst tramp-compat-user-error (vec-or-proc format &rest args) "Signal a pilot error." @@ -329,15 +190,15 @@ This is a floating point number if the size is too large for an integer." This is a string of ten letters or dashes as in ls -l." (nth 8 attributes))) -;; `default-toplevel-value' has been declared in Emacs 24. +;; `default-toplevel-value' has been declared in Emacs 24.4. (unless (fboundp 'default-toplevel-value) (defalias 'default-toplevel-value 'symbol-value)) -;; `format-message' is new in Emacs 25. +;; `format-message' is new in Emacs 25.1. (unless (fboundp 'format-message) (defalias 'format-message 'format)) -;; `file-missing' is introduced in Emacs 26. +;; `file-missing' is introduced in Emacs 26.1. (defconst tramp-file-missing (if (get 'file-missing 'error-conditions) 'file-missing 'file-error) "The error symbol for the `file-missing' error.") @@ -379,6 +240,21 @@ If NAME is a remote file name, the local part of NAME is unquoted." (if (= (length localname) 2) "/" "") nil t localname))) (concat (file-remote-p name) localname)))))) +;; `tramp-syntax' has changed its meaning in Emacs 26. We still +;; support old settings. +(defsubst tramp-compat-tramp-syntax () + "Return proper value of `tramp-syntax'." + (cond ((eq tramp-syntax 'ftp) 'default) + ((eq tramp-syntax 'sep) 'separate) + (t tramp-syntax))) + +;; Older Emacsen keep incompatible autoloaded values of `tramp-syntax'. +(eval-after-load 'tramp + '(unless + (memq tramp-syntax (tramp-compat-funcall (quote tramp-syntax-values))) + (tramp-compat-funcall + (quote tramp-change-syntax) (tramp-compat-tramp-syntax)))) + (provide 'tramp-compat) ;;; TODO: diff --git a/lisp/net/tramp-ftp.el b/lisp/net/tramp-ftp.el index 85e4f2b0f0c..8e489eee801 100644 --- a/lisp/net/tramp-ftp.el +++ b/lisp/net/tramp-ftp.el @@ -1,4 +1,4 @@ -;;; tramp-ftp.el --- Tramp convenience functions for Ange-FTP +;;; tramp-ftp.el --- Tramp convenience functions for Ange-FTP -*- lexical-binding:t -*- ;; Copyright (C) 2002-2017 Free Software Foundation, Inc. @@ -32,7 +32,6 @@ ;; Pacify byte-compiler. (eval-when-compile - (require 'cl) (require 'custom)) (defvar ange-ftp-ftp-name-arg) (defvar ange-ftp-ftp-name-res) @@ -122,10 +121,10 @@ pass to the OPERATION." (or (boundp 'ange-ftp-name-format) (let (file-name-handler-alist) (require 'ange-ftp))) (let ((ange-ftp-name-format - (list (nth 0 tramp-file-name-structure) - (nth 3 tramp-file-name-structure) - (nth 2 tramp-file-name-structure) - (nth 4 tramp-file-name-structure))) + (list (nth 0 (tramp-file-name-structure)) + (nth 3 (tramp-file-name-structure)) + (nth 2 (tramp-file-name-structure)) + (nth 4 (tramp-file-name-structure)))) ;; ange-ftp uses `ange-ftp-ftp-name-arg' and `ange-ftp-ftp-name-res' ;; for optimization in `ange-ftp-ftp-name'. If Tramp wasn't active, ;; there could be incorrect values from previous calls in case the @@ -145,7 +144,7 @@ pass to the OPERATION." ((memq operation '(file-directory-p file-exists-p)) (if (apply 'ange-ftp-hook-function operation args) (let ((v (tramp-dissect-file-name (car args) t))) - (aset v 0 tramp-ftp-method) + (setf (tramp-file-name-method v) tramp-ftp-method) (tramp-set-connection-property v "started" t)) nil)) diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index dd42d9c9830..4c750df3c40 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -1,4 +1,4 @@ -;;; tramp-gvfs.el --- Tramp access functions for GVFS daemon +;;; tramp-gvfs.el --- Tramp access functions for GVFS daemon -*- lexical-binding:t -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -39,7 +39,7 @@ ;; All actions to mount a remote location, and to retrieve mount ;; information, are performed by D-Bus messages. File operations ;; themselves are performed via the mounted filesystem in ~/.gvfs. -;; Consequently, GNU Emacs 23.1 with enabled D-Bus bindings is a +;; Consequently, GNU Emacs with enabled D-Bus bindings is a ;; precondition. ;; The GVFS D-Bus interface is said to be unstable. There were even @@ -106,7 +106,6 @@ ;; Pacify byte-compiler. (eval-when-compile - (require 'cl) (require 'custom)) ;;;###tramp-autoload @@ -159,7 +158,6 @@ (defconst tramp-gvfs-service-daemon "org.gtk.vfs.Daemon" "The well known name of the GVFS daemon.") -;; D-Bus integration is available since Emacs 23 on some system types. ;; We don't call `dbus-ping', because this would load dbus.el. (defconst tramp-gvfs-enabled (ignore-errors @@ -452,6 +450,7 @@ Every entry is a list (NAME ADDRESS).") ;; New handlers should be added here. +;;;###tramp-autoload (defconst tramp-gvfs-file-name-handler-alist '((access-file . ignore) (add-name-to-file . tramp-gvfs-handle-copy-file) @@ -548,12 +547,10 @@ pass to the OPERATION." (save-match-data (apply (cdr fn) args)) (tramp-run-real-handler operation args)))) -;; This might be moved to tramp.el. It shall be the first file name -;; handler. ;;;###tramp-autoload (when (featurep 'dbusbind) - (add-to-list 'tramp-foreign-file-name-handler-alist - (cons 'tramp-gvfs-file-name-p 'tramp-gvfs-file-name-handler))) + (tramp-register-foreign-file-name-handler + 'tramp-gvfs-file-name-p 'tramp-gvfs-file-name-handler)) ;; D-Bus helper function. @@ -565,14 +562,16 @@ pass to the OPERATION." (concat string (string 0)) string))) (defun tramp-gvfs-dbus-byte-array-to-string (byte-array) - "Like `dbus-byte-array-to-string' but remove trailing \\0 if exists." + "Like `dbus-byte-array-to-string' but remove trailing \\0 if exists. +Return nil for null BYTE-ARRAY." ;; The byte array could be a variant. Take care. (let ((byte-array (if (and (consp byte-array) (atom (car byte-array))) byte-array (car byte-array)))) - (dbus-byte-array-to-string - (if (and (consp byte-array) (zerop (car (last byte-array)))) - (butlast byte-array) byte-array)))) + (and byte-array + (dbus-byte-array-to-string + (if (and (consp byte-array) (zerop (car (last byte-array)))) + (butlast byte-array) byte-array))))) (defun tramp-gvfs-stringify-dbus-message (message) "Convert a D-Bus message into readable UTF8 strings, used for traces." @@ -620,7 +619,8 @@ is no information where to trace the message.") (tramp-message tramp-gvfs-dbus-event-vector 10 "%S" event) (tramp-error tramp-gvfs-dbus-event-vector 'file-error "%s" (cadr err)))) -;; `dbus-event-error-hooks' has been renamed to `dbus-event-error-functions'. +;; `dbus-event-error-hooks' has been renamed to +;; `dbus-event-error-functions' in Emacs 24.3. (add-hook (if (boundp 'dbus-event-error-functions) 'dbus-event-error-functions 'dbus-event-error-hooks) @@ -667,19 +667,10 @@ file names." (and t2 (not (tramp-gvfs-file-name-p newname)))) ;; We cannot copy or rename directly. - ;; PRESERVE-EXTENDED-ATTRIBUTES has been introduced with - ;; Emacs 24.1 (as PRESERVE-SELINUX-CONTEXT), and renamed - ;; in Emacs 24.3. (let ((tmpfile (tramp-compat-make-temp-file filename))) - (cond - (preserve-extended-attributes - (funcall - file-operation - filename tmpfile t keep-date preserve-uid-gid - preserve-extended-attributes)) - (t - (funcall - file-operation filename tmpfile t keep-date preserve-uid-gid))) + (funcall + file-operation filename tmpfile t keep-date preserve-uid-gid + preserve-extended-attributes) (rename-file tmpfile newname ok-if-already-exists)) ;; Direct action. @@ -730,25 +721,16 @@ file names." "Like `copy-file' for Tramp files." (setq filename (expand-file-name filename)) (setq newname (expand-file-name newname)) - (cond - ;; At least one file a Tramp file? - ((or (tramp-tramp-file-p filename) - (tramp-tramp-file-p newname)) - (tramp-gvfs-do-copy-or-rename-file - 'copy filename newname ok-if-already-exists keep-date - preserve-uid-gid preserve-extended-attributes)) - ;; Compat section. PRESERVE-EXTENDED-ATTRIBUTES has been - ;; introduced with Emacs 24.1 (as PRESERVE-SELINUX-CONTEXT), and - ;; renamed in Emacs 24.3. - (preserve-extended-attributes + ;; At least one file a Tramp file? + (if (or (tramp-tramp-file-p filename) + (tramp-tramp-file-p newname)) + (tramp-gvfs-do-copy-or-rename-file + 'copy filename newname ok-if-already-exists keep-date + preserve-uid-gid preserve-extended-attributes) (tramp-run-real-handler 'copy-file (list filename newname ok-if-already-exists keep-date - preserve-uid-gid preserve-extended-attributes))) - (t - (tramp-run-real-handler - 'copy-file - (list filename newname ok-if-already-exists keep-date preserve-uid-gid))))) + preserve-uid-gid preserve-extended-attributes)))) (defun tramp-gvfs-handle-delete-directory (directory &optional recursive trash) "Like `delete-directory' for Tramp files." @@ -757,8 +739,8 @@ file names." (mapc (lambda (file) (if (eq t (tramp-compat-file-attribute-type (file-attributes file))) - (tramp-compat-delete-directory file recursive trash) - (tramp-compat-delete-file file trash))) + (delete-directory file recursive trash) + (delete-file file trash))) (directory-files directory 'full directory-files-no-dot-files-regexp)) (when (directory-files directory nil directory-files-no-dot-files-regexp) @@ -807,7 +789,10 @@ file names." ;; If there is a default location, expand tilde. (when (string-match "\\`\\(~\\)\\(/\\|\\'\\)" localname) (save-match-data - (tramp-gvfs-maybe-open-connection (vector method user host "/" hop))) + (tramp-gvfs-maybe-open-connection + (make-tramp-file-name + :method method :user user :domain domain + :host host :port port :localname "/" :hop hop))) (setq localname (replace-match (tramp-get-connection-property v "default-location" "~") @@ -820,7 +805,7 @@ file names." (unless (tramp-run-real-handler 'file-name-absolute-p (list localname)) (setq localname (concat "/" localname))) ;; We do not pass "/..". - (if (string-match "^\\(afp\\|smb\\)$" method) + (if (string-match "^\\(afp\\|davs?\\|smb\\)$" method) (when (string-match "^/[^/]+\\(/\\.\\./?\\)" localname) (setq localname (replace-match "/" t t localname 1))) (when (string-match "^/\\.\\./?" localname) @@ -831,9 +816,8 @@ file names." ;; No tilde characters in file name, do normal ;; `expand-file-name' (this does "/./" and "/../"). (tramp-make-tramp-file-name - method user host - (tramp-run-real-handler - 'expand-file-name (list localname)))))) + method user domain host port + (tramp-run-real-handler 'expand-file-name (list localname)))))) (defun tramp-gvfs-get-directory-attributes (directory) "Return GVFS attributes association list of all files in DIRECTORY." @@ -902,10 +886,9 @@ file names." (setq filename (directory-file-name (expand-file-name filename))) (with-parsed-tramp-file-name filename nil (setq localname (tramp-compat-file-name-unquote localname)) - (if (or - (and (string-match "^\\(afp\\|smb\\)$" method) - (string-match "^/?\\([^/]+\\)$" localname)) - (string-equal localname "/")) + (if (or (and (string-match "^\\(afp\\|davs?\\|smb\\)$" method) + (string-match "^/?\\([^/]+\\)$" localname)) + (string-equal localname "/")) (tramp-gvfs-get-root-attributes filename) (assoc (file-name-nondirectory filename) @@ -1083,12 +1066,13 @@ file names." (tramp-set-connection-property p "vector" v) (process-put p 'events events) (process-put p 'watch-name localname) + (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) (set-process-filter p 'tramp-gvfs-monitor-file-process-filter) ;; There might be an error if the monitor is not supported. ;; Give the filter a chance to read the output. (tramp-accept-process-output p 1) - (unless (tramp-compat-process-live-p p) + (unless (process-live-p p) (tramp-error v 'file-notify-error "Monitoring not supported for `%s'" file-name)) p)))) @@ -1243,12 +1227,11 @@ file-notify events." (with-parsed-tramp-file-name filename nil (when (string-equal "gdrive" method) (setq method "google-drive")) - (when (and user (string-match tramp-user-with-domain-regexp user)) - (setq user - (concat (match-string 2 user) ";" (match-string 1 user)))) + (when (and user domain) + (setq user (concat domain ";" user))) (url-parse-make-urlobj - method (and user (url-hexify-string user)) nil - (tramp-file-name-real-host v) (tramp-file-name-port v) + method (and user (url-hexify-string user)) nil host + (if (stringp port) (string-to-number port) port) (and localname (url-hexify-string localname)) nil nil t)) (url-parse-make-urlobj "file" nil nil nil nil @@ -1316,9 +1299,12 @@ ADDRESS can have the form \"xx:xx:xx:xx:xx:xx\" or \"[xx:xx:xx:xx:xx:xx]\"." (unless (tramp-get-connection-property l "first-password-request" nil) (tramp-clear-passwd l)) + ;; Set variables for computing the prompt for reading password. (setq tramp-current-method l-method tramp-current-user user + tramp-current-domain l-domain tramp-current-host l-host + tramp-current-port l-port password (tramp-read-passwd (tramp-get-connection-process l) pw-prompt)) @@ -1328,12 +1314,12 @@ ADDRESS can have the form \"xx:xx:xx:xx:xx:xx\" or \"[xx:xx:xx:xx:xx:xx]\"." t ;; password handled. nil ;; no abort of D-Bus. password - (tramp-file-name-real-user l) + (tramp-file-name-user l) domain nil ;; not anonymous. 0) ;; no password save. ;; No password provided. - (list nil t "" (tramp-file-name-real-user l) domain nil 0))) + (list nil t "" (tramp-file-name-user l) domain nil 0))) ;; When QUIT is raised, we shall return this information to D-Bus. (quit (list nil t "" "" "" nil 0))))) @@ -1342,36 +1328,50 @@ ADDRESS can have the form \"xx:xx:xx:xx:xx:xx\" or \"[xx:xx:xx:xx:xx:xx]\"." "Implementation for the \"org.gtk.vfs.MountOperation.askQuestion\" method." (save-window-excursion (let ((enable-recursive-minibuffers t) - choice) + (use-dialog-box (and use-dialog-box (null noninteractive))) + result) - (condition-case nil - (with-parsed-tramp-file-name - (tramp-gvfs-file-name (dbus-event-path-name last-input-event)) nil - (tramp-message v 6 "%S %S" message choices) - - ;; In theory, there can be several choices. Until now, - ;; there is only the question whether to accept an unknown - ;; host signature. - (with-temp-buffer - ;; Preserve message for `progress-reporter'. - (with-temp-message "" - (insert message) - (pop-to-buffer (current-buffer)) - (setq choice (if (yes-or-no-p (concat (car choices) " ")) 0 1)) - (tramp-message v 6 "%d" choice))) - - ;; When the choice is "no", we set a dummy fuse-mountpoint - ;; in order to leave the timeout. - (unless (zerop choice) - (tramp-set-file-property v "/" "fuse-mountpoint" "/")) - - (list - t ;; handled. - nil ;; no abort of D-Bus. - choice)) - - ;; When QUIT is raised, we shall return this information to D-Bus. - (quit (list nil t 0)))))) + (with-parsed-tramp-file-name + (tramp-gvfs-file-name (dbus-event-path-name last-input-event)) nil + (tramp-message v 6 "%S %S" message choices) + + (setq result + (condition-case nil + (list + t ;; handled. + nil ;; no abort of D-Bus. + (with-tramp-connection-property + (tramp-get-connection-process v) message + ;; In theory, there can be several choices. + ;; Until now, there is only the question whether + ;; to accept an unknown host signature. + (with-temp-buffer + ;; Preserve message for `progress-reporter'. + (with-temp-message "" + (insert message) + (goto-char (point-max)) + (if noninteractive + (message "%s" message) + (pop-to-buffer (current-buffer))) + (if (yes-or-no-p + (concat + (buffer-substring + (line-beginning-position) (point)) + " ")) + 0 1))))) + + ;; When QUIT is raised, we shall return this + ;; information to D-Bus. + (quit (list nil t 1)))) + + (tramp-message v 6 "%s" result) + + ;; When the choice is "no", we set a dummy fuse-mountpoint in + ;; order to leave the timeout. + (unless (zerop (cl-caddr result)) + (tramp-set-file-property v "/" "fuse-mountpoint" "/")) + + result)))) (defun tramp-gvfs-handler-mounted-unmounted (mount-info) "Signal handler for the \"org.gtk.vfs.MountTracker.mounted\" and @@ -1384,9 +1384,9 @@ ADDRESS can have the form \"xx:xx:xx:xx:xx:xx\" or \"[xx:xx:xx:xx:xx:xx]\"." ;; elements. (while (stringp (car elt)) (setq elt (cdr elt))) (let* ((fuse-mountpoint (tramp-gvfs-dbus-byte-array-to-string (cadr elt))) - (mount-spec (caddr elt)) + (mount-spec (cl-caddr elt)) (default-location (tramp-gvfs-dbus-byte-array-to-string - (cadddr elt))) + (cl-cadddr elt))) (method (tramp-gvfs-dbus-byte-array-to-string (cadr (assoc "type" (cadr mount-spec))))) (user (tramp-gvfs-dbus-byte-array-to-string @@ -1414,12 +1414,8 @@ ADDRESS can have the form \"xx:xx:xx:xx:xx:xx\" or \"[xx:xx:xx:xx:xx:xx]\"." (setq method "davs")) (when (string-equal "google-drive" method) (setq method "gdrive")) - (unless (zerop (length domain)) - (setq user (concat user tramp-prefix-domain-format domain))) - (unless (zerop (length port)) - (setq host (concat host tramp-prefix-port-format port))) (with-parsed-tramp-file-name - (tramp-make-tramp-file-name method user host "") nil + (tramp-make-tramp-file-name method user domain host port "") nil (tramp-message v 6 "%s %s" signal-name (tramp-gvfs-stringify-dbus-message mount-info)) @@ -1470,9 +1466,9 @@ ADDRESS can have the form \"xx:xx:xx:xx:xx:xx\" or \"[xx:xx:xx:xx:xx:xx]\"." (while (stringp (car elt)) (setq elt (cdr elt))) (let* ((fuse-mountpoint (tramp-gvfs-dbus-byte-array-to-string (cadr elt))) - (mount-spec (caddr elt)) + (mount-spec (cl-caddr elt)) (default-location (tramp-gvfs-dbus-byte-array-to-string - (cadddr elt))) + (cl-cadddr elt))) (method (tramp-gvfs-dbus-byte-array-to-string (cadr (assoc "type" (cadr mount-spec))))) (user (tramp-gvfs-dbus-byte-array-to-string @@ -1503,14 +1499,12 @@ ADDRESS can have the form \"xx:xx:xx:xx:xx:xx\" or \"[xx:xx:xx:xx:xx:xx]\"." (setq method "gdrive")) (when (and (string-equal "synce" method) (zerop (length user))) (setq user (or (tramp-file-name-user vec) ""))) - (unless (zerop (length domain)) - (setq user (concat user tramp-prefix-domain-format domain))) - (unless (zerop (length port)) - (setq host (concat host tramp-prefix-port-format port))) (when (and (string-equal method (tramp-file-name-method vec)) - (string-equal user (or (tramp-file-name-user vec) "")) + (string-equal user (tramp-file-name-user vec)) + (string-equal domain (tramp-file-name-domain vec)) (string-equal host (tramp-file-name-host vec)) + (string-equal port (tramp-file-name-port vec)) (string-match (concat "^" (regexp-quote prefix)) (tramp-file-name-unquote-localname vec))) ;; Set prefix, mountpoint and location. @@ -1532,9 +1526,9 @@ It was \"a(say)\", but has changed to \"a{sv})\"." (defun tramp-gvfs-mount-spec (vec) "Return a mount-spec for \"org.gtk.vfs.MountTracker.mountLocation\"." (let* ((method (tramp-file-name-method vec)) - (user (tramp-file-name-real-user vec)) + (user (tramp-file-name-user vec)) (domain (tramp-file-name-domain vec)) - (host (tramp-file-name-real-host vec)) + (host (tramp-file-name-host vec)) (port (tramp-file-name-port vec)) (localname (tramp-file-name-unquote-localname vec)) (share (when (string-match "^/?\\([^/]+\\)" localname) @@ -1570,8 +1564,7 @@ It was \"a(say)\", but has changed to \"a{sv})\"." ,@(when domain (list (tramp-gvfs-mount-spec-entry "domain" domain))) ,@(when port - (list (tramp-gvfs-mount-spec-entry - "port" (number-to-string port)))))) + (list (tramp-gvfs-mount-spec-entry "port" port))))) (mount-pref (if (and (string-match "\\`dav" method) (string-match "^/?[^/]+" localname)) @@ -1590,7 +1583,9 @@ ID-FORMAT valid values are `string' and `integer'." (with-tramp-connection-property vec (format "uid-%s" id-format) (let ((method (tramp-file-name-method vec)) (user (tramp-file-name-user vec)) + (domain (tramp-file-name-domain vec)) (host (tramp-file-name-host vec)) + (port (tramp-file-name-port vec)) (localname (tramp-get-connection-property vec "default-location" nil))) (cond @@ -1598,7 +1593,8 @@ ID-FORMAT valid values are `string' and `integer'." (localname (tramp-compat-file-attribute-user-id (file-attributes - (tramp-make-tramp-file-name method user host localname) id-format))) + (tramp-make-tramp-file-name method user domain host port localname) + id-format))) ((equal id-format 'integer) tramp-unknown-id-integer) ((equal id-format 'string) tramp-unknown-id-string))))) @@ -1608,14 +1604,17 @@ ID-FORMAT valid values are `string' and `integer'." (with-tramp-connection-property vec (format "gid-%s" id-format) (let ((method (tramp-file-name-method vec)) (user (tramp-file-name-user vec)) + (domain (tramp-file-name-domain vec)) (host (tramp-file-name-host vec)) + (port (tramp-file-name-port vec)) (localname (tramp-get-connection-property vec "default-location" nil))) (cond (localname (tramp-compat-file-attribute-group-id (file-attributes - (tramp-make-tramp-file-name method user host localname) id-format))) + (tramp-make-tramp-file-name method user domain host port localname) + id-format))) ((equal id-format 'integer) tramp-unknown-id-integer) ((equal id-format 'string) tramp-unknown-id-string))))) @@ -1626,8 +1625,6 @@ ID-FORMAT valid values are `string' and `integer'." "Maybe open a connection VEC. Does not do anything if a connection is already open, but re-opens the connection if a previous connection has died for some reason." - (tramp-check-proper-method-and-host vec) - ;; We set the file name, in case there are incoming D-Bus signals or ;; D-Bus errors. (setq tramp-gvfs-dbus-event-vector vec) @@ -1645,16 +1642,22 @@ connection if a previous connection has died for some reason." (unless (tramp-gvfs-connection-mounted-p vec) (let* ((method (tramp-file-name-method vec)) (user (tramp-file-name-user vec)) + (domain (tramp-file-name-domain vec)) (host (tramp-file-name-host vec)) + (port (tramp-file-name-port vec)) (localname (tramp-file-name-unquote-localname vec)) (object-path (tramp-gvfs-object-path - (tramp-make-tramp-file-name method user host "")))) + (tramp-make-tramp-file-name method user domain host port "")))) (when (and (string-equal method "afp") (string-equal localname "/")) (tramp-error vec 'file-error "Filename must contain an AFP volume")) + (when (and (string-match method "davs?") + (string-equal localname "/")) + (tramp-error vec 'file-error "Filename must contain a WebDAV share")) + (when (and (string-equal method "smb") (string-equal localname "/")) (tramp-error vec 'file-error "Filename must contain a Windows share")) @@ -1666,10 +1669,10 @@ connection if a previous connection has died for some reason." (format "Opening connection for %s@%s using %s" user host method)) ;; Enable `auth-source'. - (tramp-set-connection-property vec "first-password-request" t) + (tramp-set-connection-property + vec "first-password-request" tramp-cache-read-persistent-data) - ;; There will be a callback of "askPassword" when a password is - ;; needed. + ;; There will be a callback of "askPassword" when a password is needed. (dbus-register-method :session dbus-service-emacs object-path tramp-gvfs-interface-mountoperation "askPassword" @@ -1690,7 +1693,7 @@ connection if a previous connection has died for some reason." 'tramp-gvfs-handler-askquestion) ;; The call must be asynchronously, because of the "askPassword" - ;; or "askQuestion"callbacks. + ;; or "askQuestion" callbacks. (if (string-match "(so)$" tramp-gvfs-mountlocation-signature) (with-tramp-dbus-call-method vec nil :session tramp-gvfs-service-daemon tramp-gvfs-path-mounttracker @@ -1876,12 +1879,9 @@ This uses \"avahi-browse\" in case D-Bus is not enabled in Avahi." (lambda (x) (let* ((list (split-string x ";")) (host (nth 6 list)) - (port (nth 8 list)) (text (tramp-compat-funcall 'split-string (nth 9 list) "\" \"" 'omit "\"")) user) -; (when (and port (not (string-equal port "0"))) -; (setq host (format "%s%s%s" host tramp-prefix-port-regexp port))) ;; A user is marked in a TXT field like "u=guest". (while text (when (string-match "u=\\(.+\\)$" (car text)) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 071ef7982af..4beb6fe5216 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -1,4 +1,4 @@ -;;; tramp-sh.el --- Tramp access functions for (s)sh-like connections +;;; tramp-sh.el --- Tramp access functions for (s)sh-like connections -*- lexical-binding:t -*- ;; Copyright (C) 1998-2017 Free Software Foundation, Inc. @@ -6,6 +6,7 @@ ;; Author: Kai Großjohann ;; Michael Albinus +;; Maintainer: Michael Albinus ;; Keywords: comm, processes ;; Package: tramp @@ -30,8 +31,10 @@ ;; Pacify byte-compiler. (eval-when-compile - (require 'cl) (require 'dired)) + +(declare-function dired-remove-file "dired-aux") +(defvar dired-compress-file-suffixes) (defvar vc-handled-backends) (defvar vc-bzr-program) (defvar vc-git-program) @@ -197,7 +200,7 @@ The string is used in `tramp-methods'.") (tramp-remote-shell-login ("-l")) (tramp-remote-shell-args ("-c")) (tramp-copy-program "rsync") - (tramp-copy-args (("-t" "%k") ("-p") ("-r") ("-s"))) + (tramp-copy-args (("-t" "%k") ("-p") ("-r") ("-s") ("-c"))) (tramp-copy-env (("RSYNC_RSH") ("ssh" "%c"))) (tramp-copy-keep-date t) (tramp-copy-keep-tmpfile t) @@ -977,6 +980,7 @@ here-document, otherwise the command could exceed maximum length of command line.") ;; New handlers should be added here. +;;;###tramp-autoload (defconst tramp-sh-file-name-handler-alist '(;; `access-file' performed by default handler. (add-name-to-file . tramp-sh-handle-add-name-to-file) @@ -1050,11 +1054,6 @@ of command line.") "Alist of handler functions. Operations not mentioned here will be handled by the normal Emacs functions.") -;; This must be the last entry, because `identity' always matches. -;;;###tramp-autoload -(add-to-list 'tramp-foreign-file-name-handler-alist - '(identity . tramp-sh-file-name-handler) 'append) - ;;; File Name Handler Functions: (defun tramp-sh-handle-make-symbolic-link @@ -1122,7 +1121,7 @@ target of the symlink differ." "%s%s" (with-parsed-tramp-file-name (expand-file-name filename) nil (tramp-make-tramp-file-name - method user host + method user domain host port (with-tramp-file-property v localname "file-truename" (let ((result nil) ; result steps in reverse order (quoted (tramp-compat-file-name-quoted-p localname)) @@ -1174,7 +1173,7 @@ target of the symlink differ." (tramp-compat-file-attribute-type (file-attributes (tramp-make-tramp-file-name - method user host + method user domain host port (mapconcat 'identity (append '("") (reverse result) @@ -1304,13 +1303,7 @@ target of the symlink differ." (when (> (buffer-size) 0) (goto-char (point-min)) ;; ... inode - (setq res-inode - (condition-case err - (read (current-buffer)) - ;; This error happens in Emacs 23. Starting with - ;; Emacs 24, a large integer will be converted into - ;; a float automatically during `read'. - (overflow-error (string-to-number (cadr err))))) + (setq res-inode (read (current-buffer))) ;; ... file mode flags (setq res-filemodes (symbol-name (read (current-buffer)))) ;; ... number links @@ -1550,14 +1543,13 @@ be non-negative integers." (tramp-shell-quote-argument localname)))))) ;; We handle also the local part, because there doesn't exist - ;; `set-file-uid-gid'. On W32 "chown" might not work. We add a - ;; timeout for this. - (with-timeout (5 nil) + ;; `set-file-uid-gid'. On W32 "chown" does not work. + (unless (memq system-type '(ms-dos windows-nt)) (let ((uid (or (and (natnump uid) uid) (tramp-get-local-uid 'integer))) (gid (or (and (natnump gid) gid) (tramp-get-local-gid 'integer)))) (tramp-call-process nil "chown" nil nil nil - (format "%d:%d" uid gid) (tramp-shell-quote-argument filename))))))) + (format "%d:%d" uid gid) (shell-quote-argument filename))))))) (defun tramp-remote-selinux-p (vec) "Check, whether SELINUX is enabled on the remote host." @@ -1951,27 +1943,17 @@ tramp-sh-handle-file-name-all-completions: internal error accessing `%s': `%s'" (filename newname &optional ok-if-already-exists keep-date preserve-uid-gid preserve-extended-attributes) "Like `copy-file' for Tramp files." - (setq filename (expand-file-name filename)) - (setq newname (expand-file-name newname)) - (cond - ;; At least one file a Tramp file? - ((or (tramp-tramp-file-p filename) - (tramp-tramp-file-p newname)) - (tramp-do-copy-or-rename-file - 'copy filename newname ok-if-already-exists keep-date - preserve-uid-gid preserve-extended-attributes)) - ;; Compat section. PRESERVE-EXTENDED-ATTRIBUTES has been - ;; introduced with Emacs 24.1 (as PRESERVE-SELINUX-CONTEXT), and - ;; renamed in Emacs 24.3. - (preserve-extended-attributes + (setq filename (expand-file-name filename) + newname (expand-file-name newname)) + (if (or (tramp-tramp-file-p filename) + (tramp-tramp-file-p newname)) + (tramp-do-copy-or-rename-file + 'copy filename newname ok-if-already-exists keep-date + preserve-uid-gid preserve-extended-attributes) (tramp-run-real-handler 'copy-file (list filename newname ok-if-already-exists keep-date - preserve-uid-gid preserve-extended-attributes))) - (t - (tramp-run-real-handler - 'copy-file - (list filename newname ok-if-already-exists keep-date preserve-uid-gid))))) + preserve-uid-gid preserve-extended-attributes)))) (defun tramp-sh-handle-copy-directory (dirname newname &optional keep-date parents copy-contents) @@ -2147,6 +2129,11 @@ file names." First arg OP is either `copy' or `rename' and indicates the operation. FILENAME is the source file, NEWNAME the target file. KEEP-DATE is non-nil if NEWNAME should have the same timestamp as FILENAME." + ;; Check, whether file is too large. Emacs checks in `insert-file-1' + ;; and `find-file-noselect', but that's not called here. + (abort-if-file-too-large + (tramp-compat-file-attribute-size (file-attributes (file-truename filename))) + (symbol-name op) filename) ;; We must disable multibyte, because binary data shall not be ;; converted. We don't want the target file to be compressed, so we ;; let-bind `jka-compr-inhibit' to t. `epa-file-handler' shall not @@ -2330,7 +2317,7 @@ The method used must be an out-of-band method." (let* ((t1 (tramp-tramp-file-p filename)) (t2 (tramp-tramp-file-p newname)) (orig-vec (tramp-dissect-file-name (if t1 filename newname))) - copy-program copy-args copy-env copy-keep-date port listener spec + copy-program copy-args copy-env copy-keep-date listener spec options source target remote-copy-program remote-copy-args) (with-parsed-tramp-file-name (if t1 filename newname) nil @@ -2357,13 +2344,14 @@ The method used must be an out-of-band method." (expand-file-name ".." tmpfile) 'recursive) (delete-file tmpfile))))) - ;; Set variables for computing the prompt for reading - ;; password. + ;; Set variables for computing the prompt for reading password. (setq tramp-current-method (tramp-file-name-method v) tramp-current-user (or (tramp-file-name-user v) (tramp-get-connection-property v "login-as" nil)) - tramp-current-host (tramp-file-name-real-host v)) + tramp-current-domain (tramp-file-name-domain v) + tramp-current-host (tramp-file-name-host v) + tramp-current-port (tramp-file-name-port v)) ;; Check which ones of source and target are Tramp files. (setq source (funcall @@ -2378,10 +2366,6 @@ The method used must be an out-of-band method." (tramp-make-copy-program-file-name v) (tramp-unquote-shell-quote-argument newname))) - ;; Check for host and port number. - (setq host (tramp-file-name-real-host v) - port (tramp-file-name-port v)) - ;; Check for user. There might be an interactive setting. (setq user (or (tramp-file-name-user v) (tramp-get-connection-property v "login-as" nil))) @@ -2512,6 +2496,7 @@ The method used must be an out-of-band method." command)))) (tramp-message orig-vec 6 "%s" command) (tramp-set-connection-property p "vector" orig-vec) + (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) ;; We must adapt `tramp-local-end-of-line' for @@ -2561,7 +2546,7 @@ The method used must be an out-of-band method." (tramp-shell-quote-argument localname)) "Couldn't make directory %s" dir)))) -(defun tramp-sh-handle-delete-directory (directory &optional recursive) +(defun tramp-sh-handle-delete-directory (directory &optional recursive trash) "Like `delete-directory' for Tramp files." (setq directory (expand-file-name directory)) (with-parsed-tramp-file-name directory nil @@ -2569,7 +2554,8 @@ The method used must be an out-of-band method." (tramp-flush-directory-property v localname) (tramp-barf-unless-okay v (format "cd / && %s %s" - (if recursive "rm -rf" "rmdir") + (or (and trash (tramp-get-remote-trash v)) + (if recursive "rm -rf" "rmdir")) (tramp-shell-quote-argument localname)) "Couldn't delete %s" directory))) @@ -2587,9 +2573,6 @@ The method used must be an out-of-band method." ;; Dired. -(defvar dired-compress-file-suffixes) -(declare-function dired-remove-file "dired-aux") - (defun tramp-sh-handle-dired-compress-file (file) "Like `dired-compress-file' for Tramp files." ;; Code stolen mainly from dired-aux.el. @@ -2805,7 +2788,7 @@ the result will be a local, non-Tramp, file name." ;; be problems with UNC shares or Cygwin mounts. (let ((default-directory (tramp-compat-temporary-file-directory))) (tramp-make-tramp-file-name - method user host + method user domain host port (tramp-drop-volume-letter (tramp-run-real-handler 'expand-file-name (list localname))) @@ -2815,7 +2798,7 @@ the result will be a local, non-Tramp, file name." (defun tramp-process-sentinel (proc event) "Flush file caches." - (unless (tramp-compat-process-live-p proc) + (unless (process-live-p proc) (let ((vec (tramp-get-connection-property proc "vector" nil))) (when vec (tramp-message vec 5 "Sentinel called: `%S' `%s'" proc event) @@ -2857,7 +2840,9 @@ the result will be a local, non-Tramp, file name." (tramp-make-tramp-file-name (tramp-file-name-method v) (tramp-file-name-user v) + (tramp-file-name-domain v) (tramp-file-name-host v) + (tramp-file-name-port v) (tramp-file-name-localname v)) tramp-initial-end-of-output)) ;; We use as environment the difference to toplevel @@ -2995,7 +2980,8 @@ the result will be a local, non-Tramp, file name." (setq input (with-parsed-tramp-file-name infile nil localname)) ;; INFILE must be copied to remote host. (setq input (tramp-make-tramp-temp-file v) - tmpinput (tramp-make-tramp-file-name method user host input)) + tmpinput + (tramp-make-tramp-file-name method user domain host port input)) (copy-file infile tmpinput t))) (when input (setq command (format "%s <%s" command input))) @@ -3029,7 +3015,7 @@ the result will be a local, non-Tramp, file name." ;; file must be deleted after execution. (setq stderr (tramp-make-tramp-temp-file v) tmpstderr (tramp-make-tramp-file-name - method user host stderr)))) + method user domain host port stderr)))) ;; stderr to be discarded. ((null (cadr destination)) (setq stderr "/dev/null")))) @@ -3443,10 +3429,12 @@ the result will be a local, non-Tramp, file name." (let (tramp-vc-registered-file-names (remote-file-name-inhibit-cache (current-time)) (file-name-handler-alist - `((,tramp-file-name-regexp . tramp-vc-file-name-handler)))) + `((,(tramp-file-name-regexp) . tramp-vc-file-name-handler)))) ;; Here we collect only file names, which need an operation. - (ignore-errors (tramp-run-real-handler 'vc-registered (list file))) + (tramp-with-demoted-errors + v "Error in 1st pass of `vc-registered': %s" + (tramp-run-real-handler 'vc-registered (list file))) (tramp-message v 10 "\n%s" tramp-vc-registered-file-names) ;; Send just one command, in order to fill the cache. @@ -3507,28 +3495,23 @@ the result will be a local, non-Tramp, file name." v vc-hg-program (tramp-get-remote-path v))))) (setq vc-handled-backends (remq 'Hg vc-handled-backends))) ;; Run. - (ignore-errors + (tramp-with-demoted-errors + v "Error in 2nd pass of `vc-registered': %s" (tramp-run-real-handler 'vc-registered (list file)))))))) ;;;###tramp-autoload (defun tramp-sh-file-name-handler (operation &rest args) "Invoke remote-shell Tramp file name handler. Fall back to normal file name handler if no Tramp handler exists." - (when (and tramp-locked (not tramp-locker)) - (setq tramp-locked nil) - (tramp-error - (car-safe tramp-current-connection) 'file-error - "Forbidden reentrant call of Tramp")) - (let ((tl tramp-locked)) - (setq tramp-locked t) - (unwind-protect - (let ((tramp-locker t)) - (save-match-data - (let ((fn (assoc operation tramp-sh-file-name-handler-alist))) - (if fn - (apply (cdr fn) args) - (tramp-run-real-handler operation args))))) - (setq tramp-locked tl)))) + (let ((fn (assoc operation tramp-sh-file-name-handler-alist))) + (if fn + (save-match-data (apply (cdr fn) args)) + (tramp-run-real-handler operation args)))) + +;; This must be the last entry, because `identity' always matches. +;;;###tramp-autoload +(tramp-register-foreign-file-name-handler + 'identity 'tramp-sh-file-name-handler 'append) (defun tramp-vc-file-name-handler (operation &rest args) "Invoke special file name handler, which collects files to be handled." @@ -3621,7 +3604,7 @@ Fall back to normal file name handler if no Tramp handler exists." ;; There might be an error if the monitor is not supported. ;; Give the filter a chance to read the output. (tramp-accept-process-output p 1) - (unless (tramp-compat-process-live-p p) + (unless (process-live-p p) (tramp-error v 'file-notify-error "Monitoring not supported for `%s'" file-name)) p)))) @@ -3666,13 +3649,13 @@ file-notify events." (when file1 (concat remote-prefix file1))))) (setq string (replace-match "" nil nil string)) ;; Remove watch when file or directory to be watched is deleted. - (when (and (member (caadr object) '(moved deleted)) + (when (and (member (cl-caadr object) '(moved deleted)) (string-equal file (process-get proc 'watch-name))) (delete-process proc)) ;; Usually, we would add an Emacs event now. Unfortunately, ;; `unread-command-events' does not accept several events at ;; once. Therefore, we apply the handler directly. - (when (member (caadr object) events) + (when (member (cl-caadr object) events) (tramp-compat-funcall 'file-notify-handle-event `(file-notify ,object file-notify-callback))))) @@ -3706,12 +3689,12 @@ file-notify events." (split-string (match-string 1 line) "," 'omit)) (match-string 3 line)))) ;; Remove watch when file or directory to be watched is deleted. - (when (member (caadr object) '(move-self delete-self ignored)) + (when (member (cl-caadr object) '(move-self delete-self ignored)) (delete-process proc)) ;; Usually, we would add an Emacs event now. Unfortunately, ;; `unread-command-events' does not accept several events at ;; once. Therefore, we apply the handler directly. - (when (member (caadr object) events) + (when (member (cl-caadr object) events) (tramp-compat-funcall 'file-notify-handle-event `(file-notify ,object file-notify-callback))))))) @@ -4434,7 +4417,8 @@ Goes through the list `tramp-inline-compress-commands'." (if (memq system-type '(windows-nt)) "echo %s | \"%s\" | \"%s\"" "echo %s | %s | %s") - magic compress decompress) nil nil)) + magic compress decompress) + nil nil)) (throw 'next nil)) (tramp-message vec 5 @@ -4475,7 +4459,7 @@ Goes through the list `tramp-inline-compress-commands'." (let ((user (tramp-file-name-user item)) (host (tramp-file-name-host item)) (proxy (concat - tramp-prefix-format proxy tramp-postfix-host-format))) + (tramp-prefix-format) proxy (tramp-postfix-host-format)))) (tramp-message vec 5 "Add proxy (\"%s\" \"%s\" \"%s\")" (and (stringp host) (regexp-quote host)) @@ -4571,38 +4555,41 @@ Goes through the list `tramp-inline-compress-commands'." (let ((case-fold-search t)) (ignore-errors (when (executable-find "ssh") - (with-temp-buffer - (tramp-call-process vec "ssh" nil t nil "-o" "ControlMaster") - (goto-char (point-min)) - (when (search-forward-regexp "missing.+argument" nil t) - (setq tramp-ssh-controlmaster-options "-o ControlMaster=auto"))) - (unless (zerop (length tramp-ssh-controlmaster-options)) - (with-temp-buffer - ;; We use a non-existing IP address, in order to avoid - ;; useless connections, and DNS timeouts. - (tramp-call-process - vec "ssh" nil t nil "-o" "ControlPath=%C" "0.0.0.1") - (goto-char (point-min)) - (setq tramp-ssh-controlmaster-options - (concat tramp-ssh-controlmaster-options - (if (search-forward-regexp "unknown.+key" nil t) - " -o ControlPath='tramp.%%r@%%h:%%p'" - " -o ControlPath='tramp.%%C'")))) + (with-tramp-progress-reporter + vec 4 "Computing ControlMaster options" (with-temp-buffer - (tramp-call-process vec "ssh" nil t nil "-o" "ControlPersist") + (tramp-call-process vec "ssh" nil t nil "-o" "ControlMaster") (goto-char (point-min)) (when (search-forward-regexp "missing.+argument" nil t) + (setq tramp-ssh-controlmaster-options + "-o ControlMaster=auto"))) + (unless (zerop (length tramp-ssh-controlmaster-options)) + (with-temp-buffer + ;; We use a non-existing IP address, in order to + ;; avoid useless connections, and DNS timeouts. + ;; Setting ConnectTimeout is needed since OpenSSH 7. + (tramp-call-process + vec "ssh" nil t nil + "-o" "ConnectTimeout=1" "-o" "ControlPath=%C" "0.0.0.1") + (goto-char (point-min)) (setq tramp-ssh-controlmaster-options (concat tramp-ssh-controlmaster-options - " -o ControlPersist=no")))))))) + (if (search-forward-regexp "unknown.+key" nil t) + " -o ControlPath='tramp.%%r@%%h:%%p'" + " -o ControlPath='tramp.%%C'")))) + (with-temp-buffer + (tramp-call-process vec "ssh" nil t nil "-o" "ControlPersist") + (goto-char (point-min)) + (when (search-forward-regexp "missing.+argument" nil t) + (setq tramp-ssh-controlmaster-options + (concat tramp-ssh-controlmaster-options + " -o ControlPersist=no"))))))))) tramp-ssh-controlmaster-options))) (defun tramp-maybe-open-connection (vec) "Maybe open a connection VEC. Does not do anything if a connection is already open, but re-opens the connection if a previous connection has died for some reason." - (tramp-check-proper-method-and-host vec) - (let ((p (tramp-get-connection-process vec)) (process-name (tramp-get-connection-property vec "process-name" nil)) (process-environment (copy-sequence process-environment)) @@ -4610,9 +4597,9 @@ connection if a previous connection has died for some reason." ;; If Tramp opens the same connection within a short time frame, ;; there is a problem. We shall signal this. - (unless (or (tramp-compat-process-live-p p) - (not (equal (butlast (append vec nil) 2) - (car tramp-current-connection))) + (unless (or (process-live-p p) + (not (tramp-file-name-equal-p + vec (car tramp-current-connection))) (> (tramp-time-diff (current-time) (cdr tramp-current-connection)) (or tramp-connection-min-time-diff 0))) @@ -4631,9 +4618,9 @@ connection if a previous connection has died for some reason." (tramp-get-connection-property p "last-cmd-time" '(0 0 0))) 60) - (tramp-compat-process-live-p p)) + (process-live-p p)) (tramp-send-command vec "echo are you awake" t t) - (unless (and (tramp-compat-process-live-p p) + (unless (and (process-live-p p) (tramp-wait-for-output p 10)) ;; The error will be caught locally. (tramp-error vec 'file-error "Awake did fail"))) @@ -4643,7 +4630,7 @@ connection if a previous connection has died for some reason." ;; New connection must be opened. (condition-case err - (unless (tramp-compat-process-live-p p) + (unless (process-live-p p) ;; During completion, don't reopen a new connection. We ;; check this for the process related to @@ -4707,9 +4694,9 @@ connection if a previous connection has died for some reason." ;; Set sentinel and query flag. (tramp-set-connection-property p "vector" vec) (set-process-sentinel p 'tramp-process-sentinel) + (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) - (setq tramp-current-connection - (cons (butlast (append vec nil) 2) (current-time)) + (setq tramp-current-connection (cons vec (current-time)) tramp-current-host (system-name)) (tramp-message @@ -4725,8 +4712,9 @@ connection if a previous connection has died for some reason." (let* ((hop (car target-alist)) (l-method (tramp-file-name-method hop)) (l-user (tramp-file-name-user hop)) + (l-domain (tramp-file-name-domain hop)) (l-host (tramp-file-name-host hop)) - (l-port nil) + (l-port (tramp-file-name-port hop)) (login-program (tramp-get-method-parameter hop 'tramp-login-program)) (login-args @@ -4761,12 +4749,6 @@ connection if a previous connection has died for some reason." (when (and process-name async-args) (setq login-args (append async-args login-args))) - ;; Check for port number. Until now, there's no - ;; need for handling like method, user, host. - (when (string-match tramp-host-with-port-regexp l-host) - (setq l-port (match-string 2 l-host) - l-host (match-string 1 l-host))) - ;; Check, whether there is a restricted shell. (dolist (elt tramp-restricted-shell-hosts-alist) (when (string-match elt tramp-current-host) @@ -4776,7 +4758,9 @@ connection if a previous connection has died for some reason." ;; reading password. (setq tramp-current-method l-method tramp-current-user l-user - tramp-current-host l-host) + tramp-current-domain l-domain + tramp-current-host l-host + tramp-current-port l-port) ;; Add login environment. (when login-env @@ -5091,7 +5075,7 @@ Return ATTR." "Create a file name suitable for `scp', `pscp', or `nc' and workalikes." (let ((method (tramp-file-name-method vec)) (user (tramp-file-name-user vec)) - (host (tramp-file-name-real-host vec)) + (host (tramp-file-name-host vec)) (localname (directory-file-name (tramp-file-name-unquote-localname vec)))) (when (string-match tramp-ipv6-regexp host) @@ -5205,7 +5189,9 @@ Nonexistent directories are removed from spec." (tramp-make-tramp-file-name (tramp-file-name-method vec) (tramp-file-name-user vec) + (tramp-file-name-domain vec) (tramp-file-name-host vec) + (tramp-file-name-port vec) x)) x)) remote-path))))) @@ -5214,7 +5200,7 @@ Nonexistent directories are removed from spec." "Determine remote locale, supporting UTF8 if possible." (with-tramp-connection-property vec "locale" (tramp-send-command vec "locale -a") - (let ((candidates '("en_US.utf8" "C.utf8" "en_US.UTF-8")) + (let ((candidates '("en_US.utf8" "C.utf8" "en_US.UTF-8" "C.UTF-8")) locale) (with-current-buffer (tramp-get-connection-buffer vec) (while candidates @@ -5383,10 +5369,12 @@ Nonexistent directories are removed from spec." result)))) (defun tramp-get-remote-trash (vec) - "Determine remote `trash' command." - (with-tramp-connection-property vec "trash" - (tramp-message vec 5 "Finding a suitable `trash' command") - (tramp-find-executable vec "trash" (tramp-get-remote-path vec)))) + "Determine remote `trash' command. +This command is returned only if `delete-by-moving-to-trash' is non-nil." + (and delete-by-moving-to-trash + (with-tramp-connection-property vec "trash" + (tramp-message vec 5 "Finding a suitable `trash' command") + (tramp-find-executable vec "trash" (tramp-get-remote-path vec))))) (defun tramp-get-remote-touch (vec) "Determine remote `touch' command." @@ -5621,14 +5609,14 @@ function cell is returned to be applied on a buffer." (let ((coding-system-for-write 'binary) (coding-system-for-read 'binary)) (apply - 'tramp-call-process-region ,vec (point-min) (point-max) + 'tramp-call-process-region ',vec (point-min) (point-max) (car (split-string ,compress)) t t nil (cdr (split-string ,compress))))) `(lambda (beg end) (let ((coding-system-for-write 'binary) (coding-system-for-read 'binary)) (apply - 'tramp-call-process-region ,vec beg end + 'tramp-call-process-region ',vec beg end (car (split-string ,compress)) t t nil (cdr (split-string ,compress)))) (,coding (point-min) (point-max))))) diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index 53e1ce8159d..1aadd14fb41 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -1,4 +1,4 @@ -;;; tramp-smb.el --- Tramp access functions for SMB servers +;;; tramp-smb.el --- Tramp access functions for SMB servers -*- lexical-binding:t -*- ;; Copyright (C) 2002-2017 Free Software Foundation, Inc. @@ -29,10 +29,6 @@ (require 'tramp) -;; Pacify byte-compiler. -(eval-when-compile - (require 'cl)) - ;; Define SMB method ... ;;;###tramp-autoload (defconst tramp-smb-method "smb" @@ -53,12 +49,6 @@ ;; Another guess. We might implement a better check later on. (tramp-case-insensitive t)))) -;; Add a default for `tramp-default-method-alist'. Rule: If there is -;; a domain in USER, it must be the SMB method. -;;;###tramp-autoload -(add-to-list 'tramp-default-method-alist - `(nil ,tramp-prefix-domain-regexp ,tramp-smb-method)) - ;; Add a default for `tramp-default-user-alist'. Rule: For the SMB method, ;; the anonymous user is chosen. ;;;###tramp-autoload @@ -157,6 +147,7 @@ call, letting the SMB client use the default one." "NT_STATUS_OBJECT_NAME_COLLISION" "NT_STATUS_OBJECT_NAME_INVALID" "NT_STATUS_OBJECT_NAME_NOT_FOUND" + "NT_STATUS_PASSWORD_MUST_CHANGE" "NT_STATUS_SHARING_VIOLATION" "NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE" "NT_STATUS_UNSUCCESSFUL" @@ -217,6 +208,7 @@ This list is used for smbcacls actions. See `tramp-actions-before-shell' for more info.") ;; New handlers should be added here. +;;;###tramp-autoload (defconst tramp-smb-file-name-handler-alist '(;; `access-file' performed by default handler. (add-name-to-file . tramp-smb-handle-add-name-to-file) @@ -340,9 +332,8 @@ pass to the OPERATION." ;;;###tramp-autoload (unless (memq system-type '(cygwin windows-nt)) - (add-to-list 'tramp-foreign-file-name-handler-alist - (cons 'tramp-smb-file-name-p 'tramp-smb-file-name-handler))) - + (tramp-register-foreign-file-name-handler + 'tramp-smb-file-name-p 'tramp-smb-file-name-handler)) ;; File name primitives. @@ -391,7 +382,7 @@ pass to the OPERATION." (defun tramp-smb-action-with-tar (proc vec) "Untar from connection buffer." - (if (not (tramp-compat-process-live-p proc)) + (if (not (process-live-p proc)) (throw 'tramp-action 'process-died) (with-current-buffer (tramp-get-connection-buffer vec) @@ -448,15 +439,14 @@ pass to the OPERATION." (if (not (file-directory-p newname)) (make-directory newname parents)) - (setq tramp-current-method (tramp-file-name-method v) - tramp-current-user (tramp-file-name-user v) - tramp-current-host (tramp-file-name-real-host v)) + ;; Set variables for computing the prompt for reading password. + (setq tramp-current-method method + tramp-current-user user + tramp-current-domain domain + tramp-current-host host + tramp-current-port port) - (let* ((real-user (tramp-file-name-real-user v)) - (real-host (tramp-file-name-real-host v)) - (domain (tramp-file-name-domain v)) - (port (tramp-file-name-port v)) - (share (tramp-smb-get-share v)) + (let* ((share (tramp-smb-get-share v)) (localname (file-name-as-directory (replace-regexp-in-string "\\\\" "/" (tramp-smb-get-localname v)))) @@ -464,10 +454,10 @@ pass to the OPERATION." (expand-file-name tramp-temp-name-prefix (tramp-compat-temporary-file-directory)))) - (args (list (concat "//" real-host "/" share) "-E"))) + (args (list (concat "//" host "/" share) "-E"))) - (if (not (zerop (length real-user))) - (setq args (append args (list "-U" real-user))) + (if (not (zerop (length user))) + (setq args (append args (list "-U" user))) (setq args (append args (list "-N")))) (when domain (setq args (append args (list "-W" domain)))) @@ -525,10 +515,11 @@ pass to the OPERATION." (tramp-message v 6 "%s" (mapconcat 'identity (process-command p) " ")) (tramp-set-connection-property p "vector" v) + (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) (tramp-process-actions p v nil tramp-smb-actions-with-tar) - (while (tramp-compat-process-live-p p) + (while (process-live-p p) (sit-for 0.1)) (tramp-message v 6 "\n%s" (buffer-string)))) @@ -573,7 +564,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." 0 (format "Copying %s to %s" filename newname) (if (file-directory-p filename) - (tramp-compat-copy-directory + (copy-directory filename newname keep-date 'parents 'copy-contents) (let ((tmpfile (file-local-copy filename))) @@ -616,7 +607,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (tramp-compat-file-attribute-modification-time (file-attributes filename)))))) -(defun tramp-smb-handle-delete-directory (directory &optional recursive) +(defun tramp-smb-handle-delete-directory (directory &optional recursive _trash) "Like `delete-directory' for Tramp files." (setq directory (directory-file-name (expand-file-name directory))) (when (file-exists-p directory) @@ -706,7 +697,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (setq localname (replace-match (if (zerop (length (match-string 1 localname))) - (tramp-file-name-real-user v) + user (match-string 1 localname)) nil nil localname))) ;; Make the file name absolute. @@ -715,12 +706,12 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." ;; No tilde characters in file name, do normal ;; `expand-file-name' (this does "/./" and "/../"). (tramp-make-tramp-file-name - method user host + method user domain host port (tramp-run-real-handler 'expand-file-name (list localname)))))) (defun tramp-smb-action-get-acl (proc vec) "Read ACL data from connection buffer." - (unless (tramp-compat-process-live-p proc) + (unless (process-live-p proc) ;; Accept pending output. (while (tramp-accept-process-output proc 0.1)) (with-current-buffer (tramp-get-connection-buffer vec) @@ -741,22 +732,20 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (with-parsed-tramp-file-name filename nil (with-tramp-file-property v localname "file-acl" (when (executable-find tramp-smb-acl-program) - - (setq tramp-current-method (tramp-file-name-method v) - tramp-current-user (tramp-file-name-user v) - tramp-current-host (tramp-file-name-real-host v)) - - (let* ((real-user (tramp-file-name-real-user v)) - (real-host (tramp-file-name-real-host v)) - (domain (tramp-file-name-domain v)) - (port (tramp-file-name-port v)) - (share (tramp-smb-get-share v)) + ;; Set variables for computing the prompt for reading password. + (setq tramp-current-method method + tramp-current-user user + tramp-current-domain domain + tramp-current-host host + tramp-current-port port) + + (let* ((share (tramp-smb-get-share v)) (localname (replace-regexp-in-string "\\\\" "/" (tramp-smb-get-localname v))) - (args (list (concat "//" real-host "/" share) "-E"))) + (args (list (concat "//" host "/" share) "-E"))) - (if (not (zerop (length real-user))) - (setq args (append args (list "-U" real-user))) + (if (not (zerop (length user))) + (setq args (append args (list "-U" user))) (setq args (append args (list "-N")))) (when domain (setq args (append args (list "-W" domain)))) @@ -787,6 +776,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (tramp-message v 6 "%s" (mapconcat 'identity (process-command p) " ")) (tramp-set-connection-property p "vector" v) + (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) (tramp-process-actions p v nil tramp-smb-actions-get-acl) (when (> (point-max) (point-min)) @@ -1176,7 +1166,8 @@ target of the symlink differ." (setq input (with-parsed-tramp-file-name infile nil localname)) ;; INFILE must be copied to remote host. (setq input (tramp-make-tramp-temp-file v) - tmpinput (tramp-make-tramp-file-name method user host input)) + tmpinput + (tramp-make-tramp-file-name method user domain host port input)) (copy-file infile tmpinput t)) ;; Transform input into a filename powershell does understand. (setq input (format "//%s%s" host input))) @@ -1238,7 +1229,7 @@ target of the symlink differ." (narrow-to-region (point-max) (point-max)) (let ((p (tramp-get-connection-process v))) (tramp-smb-send-command v "exit $lasterrorcode") - (while (tramp-compat-process-live-p p) + (while (process-live-p p) (sleep-for 0.1) (setq ret (process-exit-status p)))) (delete-region (point-min) (point-max)) @@ -1322,7 +1313,7 @@ target of the symlink differ." (defun tramp-smb-action-set-acl (proc vec) "Read ACL data from connection buffer." - (unless (tramp-compat-process-live-p proc) + (unless (process-live-p proc) ;; Accept pending output. (while (tramp-accept-process-output proc 0.1)) (with-current-buffer (tramp-get-connection-buffer vec) @@ -1334,24 +1325,23 @@ target of the symlink differ." (ignore-errors (with-parsed-tramp-file-name filename nil (when (and (stringp acl-string) (executable-find tramp-smb-acl-program)) - (setq tramp-current-method (tramp-file-name-method v) - tramp-current-user (tramp-file-name-user v) - tramp-current-host (tramp-file-name-real-host v)) + ;; Set variables for computing the prompt for reading password. + (setq tramp-current-method method + tramp-current-user user + tramp-current-domain domain + tramp-current-host host + tramp-current-port port) (tramp-set-file-property v localname "file-acl" 'undef) - (let* ((real-user (tramp-file-name-real-user v)) - (real-host (tramp-file-name-real-host v)) - (domain (tramp-file-name-domain v)) - (port (tramp-file-name-port v)) - (share (tramp-smb-get-share v)) + (let* ((share (tramp-smb-get-share v)) (localname (replace-regexp-in-string "\\\\" "/" (tramp-smb-get-localname v))) - (args (list (concat "//" real-host "/" share) "-E" "-S" + (args (list (concat "//" host "/" share) "-E" "-S" (replace-regexp-in-string "\n" "," acl-string)))) - (if (not (zerop (length real-user))) - (setq args (append args (list "-U" real-user))) + (if (not (zerop (length user))) + (setq args (append args (list "-U" user))) (setq args (append args (list "-N")))) (when domain (setq args (append args (list "-W" domain)))) @@ -1383,6 +1373,7 @@ target of the symlink differ." (tramp-message v 6 "%s" (mapconcat 'identity (process-command p) " ")) (tramp-set-connection-property p "vector" v) + (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) (tramp-process-actions p v nil tramp-smb-actions-set-acl) (goto-char (point-max)) @@ -1668,13 +1659,13 @@ Result is the list (LOCALNAME MODE SIZE MTIME)." size 0)) ;; Real listing. - (block nil + (cl-block nil ;; year. (if (string-match "\\([0-9]+\\)$" line) (setq year (string-to-number (match-string 1 line)) line (substring line 0 -5)) - (return)) + (cl-return)) ;; time. (if (string-match "\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\)$" line) @@ -1682,24 +1673,24 @@ Result is the list (LOCALNAME MODE SIZE MTIME)." min (string-to-number (match-string 2 line)) sec (string-to-number (match-string 3 line)) line (substring line 0 -9)) - (return)) + (cl-return)) ;; day. (if (string-match "\\([0-9]+\\)$" line) (setq day (string-to-number (match-string 1 line)) line (substring line 0 -3)) - (return)) + (cl-return)) ;; month. (if (string-match "\\(\\w+\\)$" line) (setq month (match-string 1 line) line (substring line 0 -4)) - (return)) + (cl-return)) ;; weekday. (if (string-match "\\(\\w+\\)$" line) (setq line (substring line 0 -5)) - (return)) + (cl-return)) ;; size. (if (string-match "\\([0-9]+\\)$" line) @@ -1708,7 +1699,7 @@ Result is the list (LOCALNAME MODE SIZE MTIME)." (when (string-match "\\([ADHRSV]+\\)" (substring line length)) (setq length (+ length (match-end 0)))) (setq line (substring line 0 length))) - (return)) + (cl-return)) ;; mode: ARCH, DIR, HIDDEN, RONLY, SYSTEM, VOLID. (if (string-match "\\([ADHRSV]+\\)?$" line) @@ -1721,12 +1712,12 @@ Result is the list (LOCALNAME MODE SIZE MTIME)." (lambda (_x) "") " " (concat "r" (if (string-match "R" mode) "-" "w") "x")))) line (substring line 0 -6)) - (return)) + (cl-return)) ;; localname. (if (string-match "^\\s-+\\(\\S-\\(.*\\S-\\)?\\)\\s-*$" line) (setq localname (match-string 1 line)) - (return)))) + (cl-return)))) (when (and localname mode size) (setq mtime @@ -1741,7 +1732,7 @@ Result is the list (LOCALNAME MODE SIZE MTIME)." (defun tramp-smb-get-cifs-capabilities (vec) "Check, whether the SMB server supports POSIX commands." ;; When we are not logged in yet, we return nil. - (if (tramp-compat-process-live-p (tramp-get-connection-process vec)) + (if (process-live-p (tramp-get-connection-process vec)) (with-tramp-connection-property (tramp-get-connection-process vec) "cifs-capabilities" (save-match-data @@ -1759,7 +1750,7 @@ Result is the list (LOCALNAME MODE SIZE MTIME)." "Check, whether the SMB server supports the STAT command." ;; When we are not logged in yet, we return nil. (if (and (tramp-smb-get-share vec) - (tramp-compat-process-live-p (tramp-get-connection-process vec))) + (process-live-p (tramp-get-connection-process vec))) (with-tramp-connection-property (tramp-get-connection-process vec) "stat-capability" (tramp-smb-send-command vec "stat \"/\"")))) @@ -1781,8 +1772,6 @@ Does not do anything if a connection is already open, but re-opens the connection if a previous connection has died for some reason. If ARGUMENT is non-nil, use it as argument for `tramp-smb-winexe-program', and suppress any checks." - (tramp-check-proper-method-and-host vec) - (let* ((share (tramp-smb-get-share vec)) (buf (tramp-get-connection-buffer vec)) (p (get-buffer-process buf))) @@ -1826,13 +1815,13 @@ If ARGUMENT is non-nil, use it as argument for (tramp-get-connection-property p "last-cmd-time" '(0 0 0))) 60) - (tramp-compat-process-live-p p) + (process-live-p p) (re-search-forward tramp-smb-errors nil t)) (delete-process p) (setq p nil))) ;; Check whether it is still the same share. - (unless (and (tramp-compat-process-live-p p) + (unless (and (process-live-p p) (or argument (string-equal share @@ -1843,24 +1832,22 @@ If ARGUMENT is non-nil, use it as argument for (when buf (with-current-buffer buf (erase-buffer))) (when (and p (processp p)) (delete-process p)) - (let* ((user (tramp-file-name-user vec)) - (host (tramp-file-name-host vec)) - (real-user (tramp-file-name-real-user vec)) - (real-host (tramp-file-name-real-host vec)) - (domain (tramp-file-name-domain vec)) - (port (tramp-file-name-port vec)) + (let* ((user (tramp-file-name-user vec)) + (host (tramp-file-name-host vec)) + (domain (tramp-file-name-domain vec)) + (port (tramp-file-name-port vec)) args) (cond (argument - (setq args (list (concat "//" real-host)))) + (setq args (list (concat "//" host)))) (share - (setq args (list (concat "//" real-host "/" share)))) + (setq args (list (concat "//" host "/" share)))) (t - (setq args (list "-g" "-L" real-host )))) + (setq args (list "-g" "-L" host )))) - (if (not (zerop (length real-user))) - (setq args (append args (list "-U" real-user))) + (if (not (zerop (length user))) + (setq args (append args (list "-U" user))) (setq args (append args (list "-N")))) (when domain (setq args (append args (list "-W" domain)))) @@ -1891,12 +1878,15 @@ If ARGUMENT is non-nil, use it as argument for (tramp-message vec 6 "%s" (mapconcat 'identity (process-command p) " ")) (tramp-set-connection-property p "vector" vec) + (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) ;; Set variables for computing the prompt for reading password. (setq tramp-current-method tramp-smb-method tramp-current-user user - tramp-current-host host) + tramp-current-domain domain + tramp-current-host host + tramp-current-port port) (condition-case err (let (tramp-message-show-message) @@ -1942,8 +1932,7 @@ If ARGUMENT is non-nil, use it as argument for (error (with-current-buffer (tramp-get-connection-buffer vec) (goto-char (point-min)) - (if (and (boundp 'auth-sources) - (symbol-value 'auth-sources) + (if (and (bound-and-true-p auth-sources) (search-forward-regexp tramp-smb-wrong-passwd-regexp nil t)) ;; Disable `auth-source' and `password-cache'. @@ -1970,7 +1959,7 @@ Returns nil if an error message has appeared." ;; Algorithm: get waiting output. See if last line contains ;; `tramp-smb-prompt' sentinel or `tramp-smb-errors' strings. ;; If not, wait a bit and again get waiting output. - (while (and (not found) (not err) (tramp-compat-process-live-p p)) + (while (and (not found) (not err) (process-live-p p)) ;; Accept pending output. (tramp-accept-process-output p 0.1) @@ -1984,7 +1973,7 @@ Returns nil if an error message has appeared." (setq err (re-search-forward tramp-smb-errors nil t))) ;; When the process is still alive, read pending output. - (while (and (not found) (tramp-compat-process-live-p p)) + (while (and (not found) (process-live-p p)) ;; Accept pending output. (tramp-accept-process-output p 0.1) @@ -2008,7 +1997,7 @@ Returns nil if an error message has appeared." "Send SIGKILL to the winexe process." (ignore-errors (let ((p (get-buffer-process (current-buffer)))) - (when (tramp-compat-process-live-p p) + (when (process-live-p p) (signal-process (process-id p) 'SIGINT))))) (defun tramp-smb-call-winexe (vec) diff --git a/lisp/net/tramp-uu.el b/lisp/net/tramp-uu.el index ec2f46be730..5e5f05da4a8 100644 --- a/lisp/net/tramp-uu.el +++ b/lisp/net/tramp-uu.el @@ -1,8 +1,9 @@ -;;; tramp-uu.el --- uuencode in Lisp +;;; tramp-uu.el --- uuencode in Lisp -*- lexical-binding:t -*- ;; Copyright (C) 2002-2017 Free Software Foundation, Inc. ;; Author: Kai Großjohann +;; Maintainer: Michael Albinus ;; Keywords: comm, terminals ;; Package: tramp diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 406cd02b52d..8d7fbc068b8 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -1,9 +1,10 @@ -;;; tramp.el --- Transparent Remote Access, Multiple Protocol +;;; tramp.el --- Transparent Remote Access, Multiple Protocol -*- lexical-binding:t -*- ;; Copyright (C) 1998-2017 Free Software Foundation, Inc. ;; Author: Kai Großjohann ;; Michael Albinus +;; Maintainer: Michael Albinus ;; Keywords: comm, processes ;; Package: tramp @@ -34,7 +35,7 @@ ;; Notes: ;; ----- ;; -;; This package only works for Emacs 23.1 and higher. +;; This package only works for Emacs 24.1 and higher. ;; ;; Also see the todo list at the bottom of this file. ;; @@ -57,9 +58,11 @@ (require 'tramp-compat) ;; Pacify byte-compiler. -(eval-when-compile - (require 'cl)) +(require 'cl-lib) +(defvar auto-save-file-name-transforms) (defvar eshell-path-env) +(defvar ls-lisp-use-insert-directory-program) +(defvar outline-regexp) ;;; User Customizable Internal Variables: @@ -328,6 +331,9 @@ See `tramp-methods' for a list of possibilities for METHOD." (choice :tag "Method name" string (const nil)))) :require 'tramp) +(defconst tramp-default-method-marker "-" + "Marker for default method in remote file names.") + (defcustom tramp-default-user nil "Default user to use for transferring files. It is nil by default; otherwise settings in configuration files like @@ -526,9 +532,8 @@ This regexp must match both `tramp-initial-end-of-output' and (defcustom tramp-password-prompt-regexp (format "^.*\\(%s\\).*:\^@? *" ;; `password-word-equivalents' has been introduced with Emacs 24.4. - (if (boundp 'password-word-equivalents) - (regexp-opt (symbol-value 'password-word-equivalents)) - "password\\|passphrase")) + (regexp-opt (or (bound-and-true-p password-word-equivalents) + '("password" "passphrase")))) "Regexp matching password-like prompts. The regexp should match at end of buffer. @@ -550,7 +555,8 @@ The `sudo' program appears to insert a `^@' character into the prompt." "Sorry, try again." "Name or service not known" "Host key verification failed." - "No supported authentication methods left to try!") t) + "No supported authentication methods left to try!") + t) ".*" "\\|" "^.*\\(" @@ -655,46 +661,79 @@ Useful for \"rsync\" like methods.") (put 'tramp-temp-buffer-file-name 'permanent-local t) ;;;###autoload -(defcustom tramp-syntax 'ftp +(defcustom tramp-syntax 'default "Tramp filename syntax to be used. It can have the following values: - `ftp' -- Ange-FTP like syntax - `sep' -- Syntax as defined for XEmacs originally." - :group 'tramp - :version "24.4" - :type '(choice (const :tag "Ange-FTP" ftp) - (const :tag "XEmacs" sep)) - :require 'tramp) + `default' -- Default syntax + `simplified' -- Ange-FTP like syntax + `separate' -- Syntax as defined for XEmacs originally -(defconst tramp-prefix-format - (cond ((equal tramp-syntax 'ftp) "/") - ((equal tramp-syntax 'sep) "/[") - (t (error "Wrong `tramp-syntax' defined"))) +Do not change the value by `setq', it must be changed only by +`custom-set-variables'. See also `tramp-change-syntax'." + :group 'tramp + :version "26.1" + :package-version '(Tramp . "2.3.2") + :type '(choice (const :tag "Default" default) + (const :tag "Ange-FTP" simplified) + (const :tag "XEmacs" separate)) + :require 'tramp + :initialize 'custom-initialize-set + :set (lambda (symbol value) + ;; Check allowed values. + (unless (memq value (tramp-syntax-values)) + (tramp-compat-user-error "Wrong `tramp-syntax' %s" tramp-syntax)) + ;; Cleanup existing buffers. + (unless (eq (symbol-value symbol) value) + (tramp-cleanup-all-buffers)) + ;; Set the value: + (set-default symbol value) + ;; Reset `tramp-file-name-regexp'. + (setq tramp-file-name-regexp (tramp-file-name-regexp)) + ;; Rearrange file name handlers. + (tramp-register-file-name-handlers))) + +(defun tramp-syntax-values () + "Return possible values of `tramp-syntax', a list" + (let ((values (cdr (get 'tramp-syntax 'custom-type)))) + (setq values (mapcar 'last values) + values (mapcar 'car values)))) + +(defun tramp-prefix-format () "String matching the very beginning of Tramp file names. -Used in `tramp-make-tramp-file-name'.") +Used in `tramp-make-tramp-file-name'." + (cond ((eq (tramp-compat-tramp-syntax) 'default) "/") + ((eq (tramp-compat-tramp-syntax) 'simplified) "/") + ((eq (tramp-compat-tramp-syntax) 'separate) "/[") + (t (error "Wrong `tramp-syntax' %s" tramp-syntax)))) -(defconst tramp-prefix-regexp - (concat "^" (regexp-quote tramp-prefix-format)) +(defun tramp-prefix-regexp () "Regexp matching the very beginning of Tramp file names. -Should always start with \"^\". Derived from `tramp-prefix-format'.") - -(defconst tramp-method-regexp - "[a-zA-Z_0-9-]+" - "Regexp matching methods identifiers.") - -(defconst tramp-postfix-method-format - (cond ((equal tramp-syntax 'ftp) ":") - ((equal tramp-syntax 'sep) "/") - (t (error "Wrong `tramp-syntax' defined"))) +Should always start with \"^\". Derived from `tramp-prefix-format'." + (concat "^" (regexp-quote (tramp-prefix-format)))) + +(defun tramp-method-regexp () + "Regexp matching methods identifiers. +The `ftp' syntax does not support methods." + (cond ((eq (tramp-compat-tramp-syntax) 'default) "[a-zA-Z0-9-]+") + ((eq (tramp-compat-tramp-syntax) 'simplified) "") + ((eq (tramp-compat-tramp-syntax) 'separate) "[a-zA-Z0-9-]*") + (t (error "Wrong `tramp-syntax' %s" tramp-syntax)))) + +(defun tramp-postfix-method-format () "String matching delimiter between method and user or host names. -Used in `tramp-make-tramp-file-name'.") - -(defconst tramp-postfix-method-regexp - (regexp-quote tramp-postfix-method-format) +The `ftp' syntax does not support methods. +Used in `tramp-make-tramp-file-name'." + (cond ((eq (tramp-compat-tramp-syntax) 'default) ":") + ((eq (tramp-compat-tramp-syntax) 'simplified) "") + ((eq (tramp-compat-tramp-syntax) 'separate) "/") + (t (error "Wrong `tramp-syntax' %s" tramp-syntax)))) + +(defun tramp-postfix-method-regexp () "Regexp matching delimiter between method and user or host names. -Derived from `tramp-postfix-method-format'.") +Derived from `tramp-postfix-method-format'." + (regexp-quote (tramp-postfix-method-format))) (defconst tramp-user-regexp "[^/|: \t]+" "Regexp matching user names.") @@ -709,7 +748,7 @@ Derived from `tramp-postfix-method-format'.") "Regexp matching delimiter between user and domain names. Derived from `tramp-prefix-domain-format'.") -(defconst tramp-domain-regexp "[-a-zA-Z0-9_.]+" +(defconst tramp-domain-regexp "[a-zA-Z0-9_.-]+" "Regexp matching domain names.") (defconst tramp-user-with-domain-regexp @@ -730,17 +769,18 @@ Derived from `tramp-postfix-user-format'.") (defconst tramp-host-regexp "[a-zA-Z0-9_.-]+" "Regexp matching host names.") -(defconst tramp-prefix-ipv6-format - (cond ((equal tramp-syntax 'ftp) "[") - ((equal tramp-syntax 'sep) "") - (t (error "Wrong `tramp-syntax' defined"))) +(defun tramp-prefix-ipv6-format () "String matching left hand side of IPv6 addresses. -Used in `tramp-make-tramp-file-name'.") +Used in `tramp-make-tramp-file-name'." + (cond ((eq (tramp-compat-tramp-syntax) 'default) "[") + ((eq (tramp-compat-tramp-syntax) 'simplified) "[") + ((eq (tramp-compat-tramp-syntax) 'separate) "") + (t (error "Wrong `tramp-syntax' %s" tramp-syntax)))) -(defconst tramp-prefix-ipv6-regexp - (regexp-quote tramp-prefix-ipv6-format) +(defun tramp-prefix-ipv6-regexp () "Regexp matching left hand side of IPv6 addresses. -Derived from `tramp-prefix-ipv6-format'.") +Derived from `tramp-prefix-ipv6-format'." + (regexp-quote (tramp-prefix-ipv6-format))) ;; The following regexp is a bit sloppy. But it shall serve our ;; purposes. It covers also IPv4 mapped IPv6 addresses, like in @@ -749,22 +789,20 @@ Derived from `tramp-prefix-ipv6-format'.") "\\(?:\\(?:[a-zA-Z0-9]+\\)?:\\)+[a-zA-Z0-9.]+" "Regexp matching IPv6 addresses.") -(defconst tramp-postfix-ipv6-format - (cond ((equal tramp-syntax 'ftp) "]") - ((equal tramp-syntax 'sep) "") - (t (error "Wrong `tramp-syntax' defined"))) +(defun tramp-postfix-ipv6-format () "String matching right hand side of IPv6 addresses. -Used in `tramp-make-tramp-file-name'.") +Used in `tramp-make-tramp-file-name'." + (cond ((eq (tramp-compat-tramp-syntax) 'default) "]") + ((eq (tramp-compat-tramp-syntax) 'simplified) "]") + ((eq (tramp-compat-tramp-syntax) 'separate) "") + (t (error "Wrong `tramp-syntax' %s" tramp-syntax)))) -(defconst tramp-postfix-ipv6-regexp - (regexp-quote tramp-postfix-ipv6-format) +(defun tramp-postfix-ipv6-regexp () "Regexp matching right hand side of IPv6 addresses. -Derived from `tramp-postfix-ipv6-format'.") +Derived from `tramp-postfix-ipv6-format'." + (regexp-quote (tramp-postfix-ipv6-format))) -(defconst tramp-prefix-port-format - (cond ((equal tramp-syntax 'ftp) "#") - ((equal tramp-syntax 'sep) "#") - (t (error "Wrong `tramp-syntax' defined"))) +(defconst tramp-prefix-port-format "#" "String matching delimiter between host names and port numbers.") (defconst tramp-prefix-port-regexp @@ -789,17 +827,18 @@ Derived from `tramp-prefix-port-format'.") "Regexp matching delimiter after ad-hoc hop definitions. Derived from `tramp-postfix-hop-format'.") -(defconst tramp-postfix-host-format - (cond ((equal tramp-syntax 'ftp) ":") - ((equal tramp-syntax 'sep) "]") - (t (error "Wrong `tramp-syntax' defined"))) +(defun tramp-postfix-host-format () "String matching delimiter between host names and localnames. -Used in `tramp-make-tramp-file-name'.") +Used in `tramp-make-tramp-file-name'." + (cond ((eq (tramp-compat-tramp-syntax) 'default) ":") + ((eq (tramp-compat-tramp-syntax) 'simplified) ":") + ((eq (tramp-compat-tramp-syntax) 'separate) "]") + (t (error "Wrong `tramp-syntax' %s" tramp-syntax)))) -(defconst tramp-postfix-host-regexp - (regexp-quote tramp-postfix-host-format) +(defun tramp-postfix-host-regexp () "Regexp matching delimiter between host names and localnames. -Derived from `tramp-postfix-host-format'.") +Derived from `tramp-postfix-host-format'." + (regexp-quote (tramp-postfix-host-format))) (defconst tramp-localname-regexp ".*$" "Regexp matching localnames.") @@ -812,25 +851,18 @@ Derived from `tramp-postfix-host-format'.") ;;; File name format: -(defconst tramp-remote-file-name-spec-regexp +(defun tramp-remote-file-name-spec-regexp () + "Regular expression matching a Tramp file name between prefix and postfix." (concat - "\\(?:" "\\(" tramp-method-regexp "\\)" tramp-postfix-method-regexp "\\)?" - "\\(?:" "\\(" tramp-user-regexp "\\)" tramp-postfix-user-regexp "\\)?" - "\\(" "\\(?:" tramp-host-regexp "\\|" - tramp-prefix-ipv6-regexp "\\(?:" tramp-ipv6-regexp "\\)?" - tramp-postfix-ipv6-regexp "\\)" - "\\(?:" tramp-prefix-port-regexp tramp-port-regexp "\\)?" "\\)?") - "Regular expression matching a Tramp file name between prefix and postfix.") - -(defconst tramp-file-name-structure - (list - (concat - tramp-prefix-regexp - "\\(" "\\(?:" tramp-remote-file-name-spec-regexp - tramp-postfix-hop-regexp "\\)+" "\\)?" - tramp-remote-file-name-spec-regexp tramp-postfix-host-regexp - "\\(" tramp-localname-regexp "\\)") - 5 6 7 8 1) + "\\(" (tramp-method-regexp) "\\)" (tramp-postfix-method-regexp) + "\\(?:" "\\(" tramp-user-regexp "\\)" tramp-postfix-user-regexp "\\)?" + "\\(" "\\(?:" tramp-host-regexp "\\|" + (tramp-prefix-ipv6-regexp) + "\\(?:" tramp-ipv6-regexp "\\)?" + (tramp-postfix-ipv6-regexp) "\\)?" + "\\(?:" tramp-prefix-port-regexp tramp-port-regexp "\\)?" "\\)?")) + +(defun tramp-file-name-structure () "List of six elements (REGEXP METHOD USER HOST FILE HOP), detailing \ the Tramp file name structure. @@ -848,53 +880,76 @@ cascade of several hops. These numbers are passed directly to `match-string', which see. That means the opening parentheses are counted to identify the pair. -See also `tramp-file-name-regexp'.") - -;;;###autoload -(defconst tramp-file-name-regexp-unified - (if (memq system-type '(cygwin windows-nt)) - "\\`/\\(\\[.*\\]\\|[^/|:]\\{2,\\}[^/|]*\\):" - "\\`/[^/|:][^/|]*:") - "Value for `tramp-file-name-regexp' for unified remoting. -See `tramp-file-name-structure' for more explanations. +See also `tramp-file-name-regexp'." + (list + (concat + (tramp-prefix-regexp) + "\\(" "\\(?:" (tramp-remote-file-name-spec-regexp) + tramp-postfix-hop-regexp "\\)+" "\\)?" + (tramp-remote-file-name-spec-regexp) (tramp-postfix-host-regexp) + "\\(" tramp-localname-regexp "\\)") + 5 6 7 8 1)) -On W32 systems, the volume letter must be ignored.") +(defun tramp-file-name-regexp () + "Regular expression matching file names handled by Tramp. +This regexp should match Tramp file names but no other file names." + (car (tramp-file-name-structure))) ;;;###autoload -(defconst tramp-file-name-regexp-separate "\\`/\\[.*\\]" - "Value for `tramp-file-name-regexp' for separate remoting. -See `tramp-file-name-structure' for more explanations.") +(defconst tramp-initial-file-name-regexp "\\`/.+:.*:" + "Value for `tramp-file-name-regexp' for autoload. +It must match the initial `tramp-syntax' settings.") +;; External packages use constant `tramp-file-name-regexp'. In order +;; not to break them, we still provide it. It is a variable now. ;;;###autoload -(defvar tramp-file-name-regexp - (cond ((equal tramp-syntax 'ftp) tramp-file-name-regexp-unified) - ((equal tramp-syntax 'sep) tramp-file-name-regexp-separate) - (t (error "Wrong `tramp-syntax' defined"))) - "Regular expression matching file names handled by Tramp. -This regexp should match Tramp file names but no other file -names. When calling `tramp-register-file-name-handlers', the -initial value is overwritten by the car of `tramp-file-name-structure'.") +(defvar tramp-file-name-regexp tramp-initial-file-name-regexp + "Value for `tramp-file-name-regexp' for autoload. +It must match the initial `tramp-syntax' settings.") ;;;###autoload -(defconst tramp-completion-file-name-regexp-unified - (if (memq system-type '(cygwin windows-nt)) - "\\`/[^/]\\{2,\\}\\'" "\\`/[^/]*\\'") - "Value for `tramp-completion-file-name-regexp' for unified remoting. +(defconst tramp-completion-file-name-regexp-default + (concat + "\\`/\\(" + ;; Optional multi hop. + "\\([^/|:]+:[^/|:]*|\\)*" + ;; Last hop. + (if (memq system-type '(cygwin windows-nt)) + ;; The method is either "-", or at least two characters. + "\\(-\\|[^/|:]\\{2,\\}\\)" + ;; At least one character for method. + "[^/|:]+") + ;; Method separator, user name and host name. + "\\(:[^/|:]*\\)?" + "\\)?\\'") + "Value for `tramp-completion-file-name-regexp' for default remoting. +See `tramp-file-name-structure' for more explanations. + +On W32 systems, the volume letter must be ignored.") + +(defconst tramp-completion-file-name-regexp-simplified + (concat + "\\`/\\(" + ;; Optional multi hop. + "\\([^/|:]*|\\)*" + ;; Last hop. + (if (memq system-type '(cygwin windows-nt)) + ;; At least two characters. + "[^/|:]\\{2,\\}" + ;; At least one character. + "[^/|:]+") + "\\)?\\'") + "Value for `tramp-completion-file-name-regexp' for simplified style remoting. See `tramp-file-name-structure' for more explanations. On W32 systems, the volume letter must be ignored.") -;;;###autoload (defconst tramp-completion-file-name-regexp-separate - "\\`/\\([[][^]]*\\)?\\'" + "\\`/\\(\\[[^]]*\\)?\\'" "Value for `tramp-completion-file-name-regexp' for separate remoting. See `tramp-file-name-structure' for more explanations.") -;;;###autoload -(defconst tramp-completion-file-name-regexp - (cond ((equal tramp-syntax 'ftp) tramp-completion-file-name-regexp-unified) - ((equal tramp-syntax 'sep) tramp-completion-file-name-regexp-separate) - (t (error "Wrong `tramp-syntax' defined"))) +(defun tramp-completion-file-name-regexp () "Regular expression matching file names handled by Tramp completion. This regexp should match partial Tramp file names only. @@ -903,7 +958,20 @@ this file \(tramp.el) is loaded. This means that this variable must be set before loading tramp.el. Alternatively, `file-name-handler-alist' can be updated after changing this variable. -Also see `tramp-file-name-structure'.") +Also see `tramp-file-name-structure'." + (cond ((eq (tramp-compat-tramp-syntax) 'default) + tramp-completion-file-name-regexp-default) + ((eq (tramp-compat-tramp-syntax) 'simplified) + tramp-completion-file-name-regexp-simplified) + ((eq (tramp-compat-tramp-syntax) 'separate) + tramp-completion-file-name-regexp-separate) + (t (error "Wrong `tramp-syntax' %s" tramp-syntax)))) + +;;;###autoload +(defconst tramp-initial-completion-file-name-regexp + tramp-completion-file-name-regexp-default + "Value for `tramp-completion-file-name-regexp' for autoload. +It must match the initial `tramp-syntax' settings.") ;; Chunked sending kludge. We set this to 500 for black-listed constellations ;; known to have a bug in `process-send-string'; some ssh connections appear @@ -1032,15 +1100,21 @@ means to use always cached values for the directory contents." (defvar tramp-current-user nil "Remote login name for this *tramp* buffer.") +(defvar tramp-current-domain nil + "Remote domain name for this *tramp* buffer.") + (defvar tramp-current-host nil "Remote host for this *tramp* buffer.") +(defvar tramp-current-port nil + "Remote port for this *tramp* buffer.") + (defvar tramp-current-connection nil "Last connection timestamp.") +;;;###autoload (defconst tramp-completion-file-name-handler-alist - '((expand-file-name . tramp-completion-handle-expand-file-name) - (file-name-all-completions + '((file-name-all-completions . tramp-completion-handle-file-name-all-completions) (file-name-completion . tramp-completion-handle-file-name-completion)) "Alist of completion handler functions. @@ -1061,6 +1135,43 @@ calling HANDLER.") ;; internal data structure. Convenience functions for internal ;; data structure. +;; The basic structure for remote file names. We use a list :type, +;; in order to be compatible with Emacs 24 and 25. +(cl-defstruct (tramp-file-name (:type list) :named) + method user domain host port localname hop) + +(defun tramp-file-name-user-domain (vec) + "Return user and domain components of VEC." + (when (or (tramp-file-name-user vec) (tramp-file-name-domain vec)) + (concat (tramp-file-name-user vec) + (and (tramp-file-name-domain vec) + tramp-prefix-domain-format) + (tramp-file-name-domain vec)))) + +(defun tramp-file-name-host-port (vec) + "Return host and port components of VEC." + (when (or (tramp-file-name-host vec) (tramp-file-name-port vec)) + (concat (tramp-file-name-host vec) + (and (tramp-file-name-port vec) + tramp-prefix-port-format) + (tramp-file-name-port vec)))) + +(defun tramp-file-name-port-or-default (vec) + "Return port component of VEC. +If nil, return `tramp-default-port'." + (or (tramp-file-name-port vec) + (tramp-get-method-parameter vec 'tramp-default-port))) + +(defun tramp-file-name-equal-p (vec1 vec2) + "Check, whether VEC1 and VEC2 denote the same `tramp-file-name'." + (and (tramp-file-name-p vec1) (tramp-file-name-p vec2) + (string-equal (tramp-file-name-method vec1) + (tramp-file-name-method vec2)) + (string-equal (tramp-file-name-user-domain vec1) + (tramp-file-name-user-domain vec2)) + (string-equal (tramp-file-name-host-port vec1) + (tramp-file-name-host-port vec2)))) + (defun tramp-get-method-parameter (vec param) "Return the method parameter PARAM. If VEC is a vector, check first in connection properties. @@ -1076,69 +1187,6 @@ entry does not exist, return nil." (assoc param (assoc (tramp-file-name-method vec) tramp-methods)))) (when methods-entry (cadr methods-entry)))))) -(defun tramp-file-name-p (vec) - "Check, whether VEC is a Tramp object." - (and (vectorp vec) (= 5 (length vec)))) - -(defun tramp-file-name-method (vec) - "Return method component of VEC." - (and (tramp-file-name-p vec) (aref vec 0))) - -(defun tramp-file-name-user (vec) - "Return user component of VEC." - (and (tramp-file-name-p vec) (aref vec 1))) - -(defun tramp-file-name-host (vec) - "Return host component of VEC." - (and (tramp-file-name-p vec) (aref vec 2))) - -(defun tramp-file-name-localname (vec) - "Return localname component of VEC." - (and (tramp-file-name-p vec) (aref vec 3))) - -(defun tramp-file-name-hop (vec) - "Return hop component of VEC." - (and (tramp-file-name-p vec) (aref vec 4))) - -;; The user part of a Tramp file name vector can be of kind -;; "user%domain". Sometimes, we must extract these parts. -(defun tramp-file-name-real-user (vec) - "Return the user name of VEC without domain." - (save-match-data - (let ((user (tramp-file-name-user vec))) - (if (and (stringp user) - (string-match tramp-user-with-domain-regexp user)) - (match-string 1 user) - user)))) - -(defun tramp-file-name-domain (vec) - "Return the domain name of VEC." - (save-match-data - (let ((user (tramp-file-name-user vec))) - (and (stringp user) - (string-match tramp-user-with-domain-regexp user) - (match-string 2 user))))) - -;; The host part of a Tramp file name vector can be of kind -;; "host#port". Sometimes, we must extract these parts. -(defun tramp-file-name-real-host (vec) - "Return the host name of VEC without port." - (save-match-data - (let ((host (tramp-file-name-host vec))) - (if (and (stringp host) - (string-match tramp-host-with-port-regexp host)) - (match-string 1 host) - host)))) - -(defun tramp-file-name-port (vec) - "Return the port number of VEC." - (save-match-data - (let ((host (tramp-file-name-host vec))) - (or (and (stringp host) - (string-match tramp-host-with-port-regexp host) - (string-to-number (match-string 2 host))) - (tramp-get-method-parameter vec 'tramp-default-port))))) - ;; The localname can be quoted with "/:". Extract this. (defun tramp-file-name-unquote-localname (vec) "Return unquoted localname component of VEC." @@ -1154,12 +1202,16 @@ entry does not exist, return nil." (if (memq system-type '(cygwin windows-nt)) "^/[[:alpha:]]?:" "^/:") name)) - (string-match tramp-file-name-regexp name)))) + (string-match (tramp-file-name-regexp) name)))) (defun tramp-find-method (method user host) "Return the right method string to use. This is METHOD, if non-nil. Otherwise, do a lookup in `tramp-default-method-alist'." + (when (and method + (or (string-equal method "") + (string-equal method tramp-default-method-marker))) + (setq method nil)) (let ((result (or method (let ((choices tramp-default-method-alist) @@ -1213,23 +1265,6 @@ This is HOST, if non-nil. Otherwise, it is `tramp-default-host'." lhost) tramp-default-host)) -(defun tramp-check-proper-method-and-host (vec) - "Check method and host name of VEC." - (let ((method (tramp-file-name-method vec)) - (user (tramp-file-name-user vec)) - (host (tramp-file-name-host vec)) - (methods (mapcar 'car tramp-methods))) - (when (and method (not (member method methods))) - (tramp-cleanup-connection vec) - (tramp-compat-user-error vec "Unknown method \"%s\"" method)) - (when (and (equal tramp-syntax 'ftp) host - (or (null method) (get-text-property 0 'tramp-default method)) - (or (null user) (get-text-property 0 'tramp-default user)) - (member host methods)) - (tramp-cleanup-connection vec) - (tramp-compat-user-error - vec "Host name must not match method \"%s\"" host)))) - (defun tramp-dissect-file-name (name &optional nodefault) "Return a `tramp-file-name' structure. The structure consists of remote method, remote user, remote host, @@ -1239,65 +1274,86 @@ values." (save-match-data (unless (tramp-tramp-file-p name) (tramp-compat-user-error nil "Not a Tramp file name: \"%s\"" name)) - (let ((match (string-match (nth 0 tramp-file-name-structure) name))) - (let ((method (match-string (nth 1 tramp-file-name-structure) name)) - (user (match-string (nth 2 tramp-file-name-structure) name)) - (host (match-string (nth 3 tramp-file-name-structure) name)) - (localname (match-string (nth 4 tramp-file-name-structure) name)) - (hop (match-string (nth 5 tramp-file-name-structure) name))) + (if (not (string-match (nth 0 (tramp-file-name-structure)) name)) + (error "`tramp-file-name-structure' didn't match!") + (let ((method (match-string (nth 1 (tramp-file-name-structure)) name)) + (user (match-string (nth 2 (tramp-file-name-structure)) name)) + (host (match-string (nth 3 (tramp-file-name-structure)) name)) + (localname (match-string (nth 4 (tramp-file-name-structure)) name)) + (hop (match-string (nth 5 (tramp-file-name-structure)) name)) + domain port) + (when user + (when (string-match tramp-user-with-domain-regexp user) + (setq domain (match-string 2 user) + user (match-string 1 user)))) + (when host - (when (string-match tramp-prefix-ipv6-regexp host) + (when (string-match tramp-host-with-port-regexp host) + (setq port (match-string 2 host) + host (match-string 1 host))) + (when (string-match (tramp-prefix-ipv6-regexp) host) (setq host (replace-match "" nil t host))) - (when (string-match tramp-postfix-ipv6-regexp host) + (when (string-match (tramp-postfix-ipv6-regexp) host) (setq host (replace-match "" nil t host)))) - (if nodefault - (vector method user host localname hop) - (vector - (tramp-find-method method user host) - (tramp-find-user method user host) - (tramp-find-host method user host) - localname hop)))))) + + (unless nodefault + (setq method (tramp-find-method method user host) + user (tramp-find-user method user host) + host (tramp-find-host method user host))) + + (make-tramp-file-name + :method method :user user :domain domain :host host :port port + :localname (or localname "") :hop hop))))) (defun tramp-buffer-name (vec) "A name for the connection buffer VEC." (let ((method (tramp-file-name-method vec)) - (user (tramp-file-name-user vec)) - (host (tramp-file-name-real-host vec))) - (if (not (zerop (length user))) - (format "*tramp/%s %s@%s*" method user host) - (format "*tramp/%s %s*" method host)))) - -(defun tramp-make-tramp-file-name (method user host localname &optional hop) + (user-domain (tramp-file-name-user-domain vec)) + (host-port (tramp-file-name-host-port vec))) + (if (not (zerop (length user-domain))) + (format "*tramp/%s %s@%s*" method user-domain host-port) + (format "*tramp/%s %s*" method host-port)))) + +(defun tramp-make-tramp-file-name + (method user domain host port localname &optional hop) "Constructs a Tramp file name from METHOD, USER, HOST and LOCALNAME. -When not nil, an optional HOP is prepended." - (concat tramp-prefix-format hop - (when (not (zerop (length method))) - (concat method tramp-postfix-method-format)) - (when (not (zerop (length user))) - (concat user tramp-postfix-user-format)) +When not nil, optional DOMAIN, PORT and HOP are used." + (concat (tramp-prefix-format) hop + (unless (or (zerop (length method)) + (zerop (length (tramp-postfix-method-format)))) + (concat method (tramp-postfix-method-format))) + user + (unless (zerop (length domain)) + (concat tramp-prefix-domain-format domain)) + (unless (zerop (length user)) + tramp-postfix-user-format) (when host (if (string-match tramp-ipv6-regexp host) - (concat tramp-prefix-ipv6-format host tramp-postfix-ipv6-format) + (concat + (tramp-prefix-ipv6-format) host (tramp-postfix-ipv6-format)) host)) - tramp-postfix-host-format + (unless (zerop (length port)) + (concat tramp-prefix-port-format port)) + (tramp-postfix-host-format) (when localname localname))) (defun tramp-completion-make-tramp-file-name (method user host localname) "Constructs a Tramp file name from METHOD, USER, HOST and LOCALNAME. It must not be a complete Tramp file name, but as long as there are necessary only. This function will be used in file name completion." - (concat tramp-prefix-format - (when (not (zerop (length method))) - (concat method tramp-postfix-method-format)) - (when (not (zerop (length user))) + (concat (tramp-prefix-format) + (unless (or (zerop (length method)) + (zerop (length (tramp-postfix-method-format)))) + (concat method (tramp-postfix-method-format))) + (unless (zerop (length user)) (concat user tramp-postfix-user-format)) - (when (not (zerop (length host))) + (unless (zerop (length host)) (concat (if (string-match tramp-ipv6-regexp host) (concat - tramp-prefix-ipv6-format host tramp-postfix-ipv6-format) + (tramp-prefix-ipv6-format) host (tramp-postfix-ipv6-format)) host) - tramp-postfix-host-format)) + (tramp-postfix-host-format))) (when localname localname))) (defun tramp-get-buffer (vec) @@ -1314,7 +1370,9 @@ necessary only. This function will be used in file name completion." (tramp-make-tramp-file-name (tramp-file-name-method vec) (tramp-file-name-user vec) + (tramp-file-name-domain vec) (tramp-file-name-host vec) + (tramp-file-name-port vec) "/")) (current-buffer)))) @@ -1336,7 +1394,7 @@ from the default one." "Get the connection process to be used for VEC. In case a second asynchronous communication has been started, it is different from the default one." - (get-process (tramp-get-connection-name vec))) + (and (tramp-file-name-p vec) (get-process (tramp-get-connection-name vec)))) (defun tramp-set-connection-local-variables (vec) "Set connection-local variables in the connection buffer used for VEC. @@ -1346,23 +1404,32 @@ version, the function does nothing." ;; `hack-connection-local-variables-apply' exists since Emacs 26.1. (tramp-compat-funcall 'hack-connection-local-variables-apply - (append - '(tramp) - (when (tramp-file-name-method vec) - `(:protocol ,(tramp-file-name-method vec))) - (when (tramp-file-name-user vec) - `(:user ,(tramp-file-name-user vec))) - (when (tramp-file-name-host vec) - `(:machine ,(tramp-file-name-host vec))))))) + `(:application tramp + :protocol ,(tramp-file-name-method vec) + :user ,(tramp-file-name-user-domain vec) + :machine ,(tramp-file-name-host-port vec))))) + +(defun tramp-set-connection-local-variables-for-buffer () + "Set connection-local variables in the current buffer. +If connection-local variables are not supported by this Emacs +version, the function does nothing." + (when (file-remote-p default-directory) + ;; `hack-connection-local-variables-apply' exists since Emacs 26.1. + (tramp-compat-funcall + 'hack-connection-local-variables-apply + `(:application tramp + :protocol ,(file-remote-p default-directory 'method) + :user ,(file-remote-p default-directory 'user) + :machine ,(file-remote-p default-directory 'host))))) (defun tramp-debug-buffer-name (vec) "A name for the debug buffer for VEC." (let ((method (tramp-file-name-method vec)) - (user (tramp-file-name-user vec)) - (host (tramp-file-name-real-host vec))) - (if (not (zerop (length user))) - (format "*debug tramp/%s %s@%s*" method user host) - (format "*debug tramp/%s %s*" method host)))) + (user-domain (tramp-file-name-user-domain vec)) + (host-port (tramp-file-name-host-port vec))) + (if (not (zerop (length user-domain))) + (format "*debug tramp/%s %s@%s*" method user-domain host-port) + (format "*debug tramp/%s %s*" method host-port)))) (defconst tramp-debug-outline-regexp "[0-9]+:[0-9]+:[0-9]+\\.[0-9]+ [a-z0-9-]+ (\\([0-9]+\\)) #" @@ -1436,7 +1503,6 @@ ARGUMENTS to actually emit the message (if applicable)." "^" (regexp-opt '("tramp-backtrace" - "tramp-compat-condition-case-unless-debug" "tramp-compat-funcall" "tramp-compat-user-error" "tramp-condition-case-unless-debug" @@ -1509,7 +1575,7 @@ applicable)." (setq fmt-string (concat fmt-string "\n%s") arguments (append arguments (list (buffer-string))))))) ;; Do it. - (when (vectorp vec-or-proc) + (when (tramp-file-name-p vec-or-proc) (apply 'tramp-debug-message vec-or-proc (concat (format "(%d) # " level) fmt-string) @@ -1548,9 +1614,9 @@ an input event arrives. The other arguments are passed to `tramp-error'." (save-window-excursion (let* ((buf (or (and (bufferp buf) buf) (and (processp vec-or-proc) (process-buffer vec-or-proc)) - (and (vectorp vec-or-proc) + (and (tramp-file-name-p vec-or-proc) (tramp-get-connection-buffer vec-or-proc)))) - (vec (or (and (vectorp vec-or-proc) vec-or-proc) + (vec (or (and (tramp-file-name-p vec-or-proc) vec-or-proc) (and buf (with-current-buffer buf (tramp-dissect-file-name default-directory)))))) (unwind-protect @@ -1559,6 +1625,7 @@ an input event arrives. The other arguments are passed to `tramp-error'." (when (and buf tramp-message-show-message (not (zerop tramp-verbose)) + ;; Do not show when flagged from outside. (not (tramp-completion-mode-p)) ;; Show only when Emacs has started already. (current-message)) @@ -1571,10 +1638,21 @@ an input event arrives. The other arguments are passed to `tramp-error'." (discard-input) (sit-for 30))) ;; Reset timestamp. It would be wrong after waiting for a while. - (when (equal (butlast (append vec nil) 2) - (car tramp-current-connection)) + (when (tramp-file-name-equal-p vec (car tramp-current-connection)) (setcdr tramp-current-connection (current-time))))))) +(defmacro tramp-with-demoted-errors (vec-or-proc format &rest body) + "Execute BODY while redirecting the error message to `tramp-message'. +BODY is executed like wrapped by `with-demoted-errors'. FORMAT +is a format-string containing a %-sequence meaning to substitute +the resulting error message." + (declare (debug (symbolp body)) + (indent 2)) + (let ((err (make-symbol "err"))) + `(condition-case-unless-debug ,err + (progn ,@body) + (error (tramp-message ,vec-or-proc 3 ,format ,err) nil)))) + (defmacro with-parsed-tramp-file-name (filename var &rest body) "Parse a Tramp filename and make components available in the body. @@ -1596,7 +1674,7 @@ If VAR is nil, then we bind `v' to the structure and `method', `user', `(,(if var (intern (format "%s-%s" var elem)) elem) (,(intern (format "tramp-file-name-%s" elem)) ,(or var 'v)))) - '(method user host localname hop)))) + '(method user domain host port localname hop)))) `(let* ((,(or var 'v) (tramp-dissect-file-name ,filename)) ,@bindings) ;; We don't know which of those vars will be used, so we bind them all, @@ -1625,16 +1703,14 @@ without a visible progress reporter." (tramp-message ,vec ,level "%s..." ,message) (let ((cookie "failed") (tm - ;; We start a pulsing progress reporter after 3 seconds. Feature - ;; introduced in Emacs 24.1. + ;; We start a pulsing progress reporter after 3 seconds. (when (and tramp-message-show-message ;; Display only when there is a minimum level. (<= ,level (min tramp-verbose 3))) - (ignore-errors - (let ((pr (make-progress-reporter ,message nil nil))) - (when pr - (run-at-time - 3 0.1 #'tramp-progress-reporter-update pr))))))) + (let ((pr (make-progress-reporter ,message nil nil))) + (when pr + (run-at-time + 3 0.1 #'tramp-progress-reporter-update pr)))))) (unwind-protect ;; Execute the body. (prog1 (progn ,@body) (setq cookie "done")) @@ -1782,8 +1858,8 @@ special handling of `substitute-in-file-name'." (remove-hook 'rfn-eshadow-setup-minibuffer-hook 'tramp-rfn-eshadow-setup-minibuffer))) -(defconst tramp-rfn-eshadow-update-overlay-regexp - (format "[^%s/~]*\\(/\\|~\\)" tramp-postfix-host-format)) +(defun tramp-rfn-eshadow-update-overlay-regexp () + (format "[^%s/~]*\\(/\\|~\\)" (tramp-postfix-host-format))) (defun tramp-rfn-eshadow-update-overlay () "Update `rfn-eshadow-overlay' to cover shadowed part of minibuffer input. @@ -1803,7 +1879,7 @@ been set up by `rfn-eshadow-setup-minibuffer'." (save-restriction (narrow-to-region (1+ (or (string-match - tramp-rfn-eshadow-update-overlay-regexp + (tramp-rfn-eshadow-update-overlay-regexp) (buffer-string) end) end)) (point-max)) @@ -1847,7 +1923,7 @@ value of `default-file-modes', without execute permissions." "Replace environment variables in FILENAME. Return the string with the replaced variables." (or (ignore-errors - ;; Optional arg has been introduced with Emacs 24 (?). + ;; Optional arg has been introduced with Emacs 24.4. (tramp-compat-funcall 'substitute-env-vars filename 'only-defined)) ;; We need an own implementation. (save-match-data @@ -1869,13 +1945,12 @@ temporary file names. If `file-coding-system-alist' contains an expression, which matches more than the file name suffix, the coding system might not be determined. This function repairs it." (let (result) - (dolist (elt file-coding-system-alist result) + (dolist (elt file-coding-system-alist (nreverse result)) (when (and (consp elt) (string-match (car elt) filename)) ;; We found a matching entry in `file-coding-system-alist'. ;; So we add a similar entry, but with the temporary file name ;; as regexp. - (add-to-list - 'result (cons (regexp-quote tmpname) (cdr elt)) 'append))))) + (push (cons (regexp-quote tmpname) (cdr elt)) result))))) (defun tramp-run-real-handler (operation args) "Invoke normal file name handler for OPERATION. @@ -1893,21 +1968,6 @@ pass to the OPERATION." (inhibit-file-name-operation operation)) (apply operation args))) -;;;###autoload -(progn (defun tramp-completion-run-real-handler (operation args) - "Invoke `tramp-file-name-handler' for OPERATION. -First arg specifies the OPERATION, second arg is a list of arguments to -pass to the OPERATION." - (let* ((inhibit-file-name-handlers - `(tramp-completion-file-name-handler - cygwin-mount-name-hook-function - cygwin-mount-map-drive-hook-function - . - ,(and (eq inhibit-file-name-operation operation) - inhibit-file-name-handlers))) - (inhibit-file-name-operation operation)) - (apply operation args)))) - ;; We handle here all file primitives. Most of them have the file ;; name as first parameter; nevertheless we check for them explicitly ;; in order to be signaled if a new primitive appears. This @@ -1924,42 +1984,42 @@ ARGS are the arguments OPERATION has been called with." '(access-file byte-compiler-base-file-name delete-directory delete-file diff-latest-backup-file directory-file-name directory-files directory-files-and-attributes - dired-compress-file dired-uncache + dired-compress-file dired-uncache file-acl file-accessible-directory-p file-attributes file-directory-p file-executable-p file-exists-p - file-local-copy file-modes - file-name-as-directory file-name-directory - file-name-nondirectory file-name-sans-versions + file-local-copy file-modes file-name-as-directory + file-name-directory file-name-nondirectory + file-name-sans-versions file-notify-add-watch file-ownership-preserved-p file-readable-p - file-regular-p file-remote-p file-symlink-p file-truename - file-writable-p find-backup-file-name find-file-noselect - get-file-buffer insert-directory insert-file-contents - load make-directory make-directory-internal - set-file-modes set-file-times substitute-in-file-name - unhandled-file-name-directory vc-registered - ;; Emacs 24+ only. - file-acl file-notify-add-watch file-selinux-context - set-file-acl set-file-selinux-context + file-regular-p file-remote-p file-selinux-context + file-symlink-p file-truename file-writable-p + find-backup-file-name find-file-noselect get-file-buffer + insert-directory insert-file-contents load + make-directory make-directory-internal set-file-acl + set-file-modes set-file-selinux-context set-file-times + substitute-in-file-name unhandled-file-name-directory + vc-registered ;; Emacs 26+ only. file-name-case-insensitive-p)) (if (file-name-absolute-p (nth 0 args)) (nth 0 args) - (expand-file-name (nth 0 args)))) + default-directory)) ;; FILE DIRECTORY resp FILE1 FILE2. ((member operation '(add-name-to-file copy-directory copy-file expand-file-name + file-equal-p file-in-directory-p file-name-all-completions file-name-completion - file-newer-than-file-p make-symbolic-link rename-file - ;; Emacs 24+ only. - file-equal-p file-in-directory-p)) + file-newer-than-file-p make-symbolic-link rename-file)) (save-match-data (cond ((tramp-tramp-file-p (nth 0 args)) (nth 0 args)) ((tramp-tramp-file-p (nth 1 args)) (nth 1 args)) - (t (buffer-file-name (current-buffer)))))) + (t default-directory)))) ;; START END FILE. ((eq operation 'write-region) - (nth 2 args)) + (if (file-name-absolute-p (nth 2 args)) + (nth 2 args) + default-directory)) ;; BUFFER. ((member operation '(make-auto-save-file-name @@ -1974,8 +2034,7 @@ ARGS are the arguments OPERATION has been called with." default-directory) ;; PROC. ((member operation - '(;; Emacs 24+ only. - file-notify-rm-watch + '(file-notify-rm-watch ;; Emacs 25+ only. file-notify-valid-p)) (when (processp (nth 0 args)) @@ -1984,33 +2043,18 @@ ARGS are the arguments OPERATION has been called with." ;; Unknown file primitive. (t (error "unknown file I/O primitive: %s" operation)))) -(defun tramp-find-foreign-file-name-handler - (filename &optional operation completion) +(defun tramp-find-foreign-file-name-handler (filename &optional _operation) "Return foreign file name handler if exists." (when (tramp-tramp-file-p filename) - (let ((v (tramp-dissect-file-name filename t)) - (handler tramp-foreign-file-name-handler-alist) + (let ((handler tramp-foreign-file-name-handler-alist) elt res) - ;; When we are not fully sure that filename completion is safe, - ;; we should not return a handler. - (when (or (not completion) - (tramp-file-name-method v) (tramp-file-name-user v) - (and (tramp-file-name-host v) - (not (member (tramp-file-name-host v) - (mapcar 'car tramp-methods)))) - ;; Some operations are safe by default. - (member - operation - '(file-name-as-directory - file-name-directory - file-name-nondirectory))) - (while handler - (setq elt (car handler) - handler (cdr handler)) - (when (funcall (car elt) filename) - (setq handler nil - res (cdr elt)))) - res)))) + (while handler + (setq elt (car handler) + handler (cdr handler)) + (when (funcall (car elt) filename) + (setq handler nil + res (cdr elt)))) + res))) (defvar tramp-debug-on-error nil "Like `debug-on-error' but used Tramp internal.") @@ -2019,7 +2063,34 @@ ARGS are the arguments OPERATION has been called with." (var bodyform &rest handlers) "Like `condition-case-unless-debug' but `tramp-debug-on-error'." `(let ((debug-on-error tramp-debug-on-error)) - (tramp-compat-condition-case-unless-debug ,var ,bodyform ,@handlers))) + (condition-case-unless-debug ,var ,bodyform ,@handlers))) + +;; In Emacs, there is some concurrency due to timers. If a timer +;; interrupts Tramp and wishes to use the same connection buffer as +;; the "main" Emacs, then garbage might occur in the connection +;; buffer. Therefore, we need to make sure that a timer does not use +;; the same connection buffer as the "main" Emacs. We implement a +;; cheap global lock, instead of locking each connection buffer +;; separately. The global lock is based on two variables, +;; `tramp-locked' and `tramp-locker'. `tramp-locked' is set to true +;; (with setq) to indicate a lock. But Tramp also calls itself during +;; processing of a single file operation, so we need to allow +;; recursive calls. That's where the `tramp-locker' variable comes in +;; -- it is let-bound to t during the execution of the current +;; handler. So if `tramp-locked' is t and `tramp-locker' is also t, +;; then we should just proceed because we have been called +;; recursively. But if `tramp-locker' is nil, then we are a timer +;; interrupting the "main" Emacs, and then we signal an error. + +(defvar tramp-locked nil + "If non-nil, then Tramp is currently busy. +Together with `tramp-locker', this implements a locking mechanism +preventing reentrant calls of Tramp.") + +(defvar tramp-locker nil + "If non-nil, then a caller has locked Tramp. +Together with `tramp-locked', this implements a locking mechanism +preventing reentrant calls of Tramp.") ;; Main function. (defun tramp-file-name-handler (operation &rest args) @@ -2028,17 +2099,12 @@ Falls back to normal file name handler if no Tramp file name handler exists." (let ((filename (apply 'tramp-file-name-for-operation operation args))) (if (and tramp-mode (tramp-tramp-file-p filename)) (save-match-data - (let* ((filename (tramp-replace-environment-variables filename)) - (non-essential - (and non-essential - (string-match - tramp-completion-file-name-regexp filename))) - (completion (tramp-completion-mode-p)) - (foreign - (tramp-find-foreign-file-name-handler - filename operation completion)) - result) - (with-parsed-tramp-file-name filename nil + (setq filename (tramp-replace-environment-variables filename)) + (with-parsed-tramp-file-name filename nil + (let ((completion (tramp-completion-mode-p)) + (foreign + (tramp-find-foreign-file-name-handler filename operation)) + result) ;; Call the backend function. (if foreign (tramp-condition-case-unless-debug err @@ -2048,7 +2114,7 @@ Falls back to normal file name handler if no Tramp file name handler exists." ;; are already loaded. This results in ;; recursive loading. Therefore, we load the ;; Tramp packages locally. - (when (and (listp sf) (eq (car sf) 'autoload)) + (when (autoloadp sf) (let ((default-directory (tramp-compat-temporary-file-directory))) (load (cadr sf) 'noerror 'nomessage))) @@ -2063,7 +2129,18 @@ Falls back to normal file name handler if no Tramp file name handler exists." (setq result (catch 'non-essential (catch 'suppress - (apply foreign operation args)))) + (when (and tramp-locked (not tramp-locker)) + (setq tramp-locked nil) + (tramp-error + (car-safe tramp-current-connection) + 'file-error + "Forbidden reentrant call of Tramp")) + (let ((tl tramp-locked)) + (setq tramp-locked t) + (unwind-protect + (let ((tramp-locker t)) + (apply foreign operation args)) + (setq tramp-locked tl)))))) (cond ((eq result 'non-essential) (tramp-message @@ -2118,83 +2195,69 @@ Falls back to normal file name handler if no Tramp file name handler exists." ;; we don't do anything. (tramp-run-real-handler operation args)))) -;; In Emacs, there is some concurrency due to timers. If a timer -;; interrupts Tramp and wishes to use the same connection buffer as -;; the "main" Emacs, then garbage might occur in the connection -;; buffer. Therefore, we need to make sure that a timer does not use -;; the same connection buffer as the "main" Emacs. We implement a -;; cheap global lock, instead of locking each connection buffer -;; separately. The global lock is based on two variables, -;; `tramp-locked' and `tramp-locker'. `tramp-locked' is set to true -;; (with setq) to indicate a lock. But Tramp also calls itself during -;; processing of a single file operation, so we need to allow -;; recursive calls. That's where the `tramp-locker' variable comes in -;; -- it is let-bound to t during the execution of the current -;; handler. So if `tramp-locked' is t and `tramp-locker' is also t, -;; then we should just proceed because we have been called -;; recursively. But if `tramp-locker' is nil, then we are a timer -;; interrupting the "main" Emacs, and then we signal an error. - -(defvar tramp-locked nil - "If non-nil, then Tramp is currently busy. -Together with `tramp-locker', this implements a locking mechanism -preventing reentrant calls of Tramp.") - -(defvar tramp-locker nil - "If non-nil, then a caller has locked Tramp. -Together with `tramp-locked', this implements a locking mechanism -preventing reentrant calls of Tramp.") - -;; Avoid recursive loading of tramp.el. If `non-essential' is -;; non-nil, we must load tramp.el, in order to get the real definition -;; of `tramp-completion-file-name-handler'. -;;;###autoload(defun tramp-completion-file-name-handler (operation &rest args) -;;;###autoload (if (tramp-completion-mode-p) -;;;###autoload (apply 'tramp-autoload-file-name-handler operation args) -;;;###autoload (tramp-completion-run-real-handler operation args))) - +;;;###autoload (defun tramp-completion-file-name-handler (operation &rest args) "Invoke Tramp file name completion handler. Falls back to normal file name handler if no Tramp file name handler exists." (let ((fn (assoc operation tramp-completion-file-name-handler-alist))) - (if (and fn tramp-mode (tramp-completion-mode-p)) + (if (and fn tramp-mode) (save-match-data (apply (cdr fn) args)) - (tramp-completion-run-real-handler operation args)))) + (tramp-run-real-handler operation args)))) ;;;###autoload (progn (defun tramp-autoload-file-name-handler (operation &rest args) "Load Tramp file name handler, and perform OPERATION." - (if (and - ;; Do not load tramp.el just for "/". - (not (and (stringp (car args)) (string-equal (car args) "/"))) - ;; Avoid recursive loading of tramp.el. - (let ((default-directory temporary-file-directory)) - (and (null load-in-progress) (load "tramp" 'noerror 'nomessage)))) - (apply operation args) - ;; tramp.el not needed or not available for loading, fall back. - (tramp-completion-run-real-handler operation args)))) + (let ((default-directory temporary-file-directory)) + (load "tramp" 'noerror 'nomessage)) + (apply operation args))) ;; `tramp-autoload-file-name-handler' must be registered before ;; evaluation of site-start and init files, because there might exist -;; remote files already, f.e. files kept via recentf-mode. We cannot -;; autoload `tramp-file-name-handler', because it would result in -;; recursive loading of tramp.el when `default-directory' is set to -;; remote. +;; remote files already, f.e. files kept via recentf-mode. ;;;###autoload (progn (defun tramp-register-autoload-file-name-handlers () "Add Tramp file name handlers to `file-name-handler-alist' during autoload." (add-to-list 'file-name-handler-alist - (cons tramp-file-name-regexp + (cons tramp-initial-file-name-regexp 'tramp-autoload-file-name-handler)) (put 'tramp-autoload-file-name-handler 'safe-magic t) + (add-to-list 'file-name-handler-alist - (cons tramp-completion-file-name-regexp + (cons tramp-initial-completion-file-name-regexp 'tramp-completion-file-name-handler)) - (put 'tramp-completion-file-name-handler 'safe-magic t))) + (put 'tramp-completion-file-name-handler 'safe-magic t) + ;; Mark `operations' the handler is responsible for. + (put 'tramp-completion-file-name-handler 'operations + (mapcar 'car tramp-completion-file-name-handler-alist)))) ;;;###autoload (tramp-register-autoload-file-name-handlers) +(defun tramp-use-absolute-autoload-file-names () + "Change Tramp autoload objects to use absolute file names. +This avoids problems during autoload, when `load-path' contains +remote file names." + ;; We expect all other Tramp files in the same directory as tramp.el. + (let* ((dir (expand-file-name (file-name-directory (locate-library "tramp")))) + (files-regexp + (format + "^%s$" + (regexp-opt + (mapcar + 'file-name-sans-extension + (directory-files dir nil "^tramp.+\\.elc?$")) + 'paren)))) + (mapatoms + (lambda (atom) + (when (and (functionp atom) + (autoloadp (symbol-function atom)) + (string-match files-regexp (cadr (symbol-function atom)))) + (ignore-errors + (setf (cadr (symbol-function atom)) + (expand-file-name (cadr (symbol-function atom)) dir)))))))) + +(eval-after-load 'tramp (tramp-use-absolute-autoload-file-names)) + (defun tramp-register-file-name-handlers () "Add Tramp file name handlers to `file-name-handler-alist'." ;; Remove autoloaded handlers from file name handler alist. Useful, @@ -2204,18 +2267,22 @@ Falls back to normal file name handler if no Tramp file name handler exists." tramp-autoload-file-name-handler)) (let ((a1 (rassq fnh file-name-handler-alist))) (setq file-name-handler-alist (delq a1 file-name-handler-alist)))) - ;; The initial value of `tramp-file-name-regexp' is too simple - ;; minded, but we cannot give it the real value in the autoload - ;; pattern. See Bug#24889. - (setq tramp-file-name-regexp (car tramp-file-name-structure)) - ;; Add the handlers. + + ;; Add the handlers. We do not add anything to the `operations' + ;; property of `tramp-file-name-handler', this shall be done by the + ;; respective foreign handlers. (add-to-list 'file-name-handler-alist - (cons tramp-file-name-regexp 'tramp-file-name-handler)) + (cons (tramp-file-name-regexp) 'tramp-file-name-handler)) (put 'tramp-file-name-handler 'safe-magic t) + (add-to-list 'file-name-handler-alist - (cons tramp-completion-file-name-regexp + (cons (tramp-completion-file-name-regexp) 'tramp-completion-file-name-handler)) (put 'tramp-completion-file-name-handler 'safe-magic t) + ;; Mark `operations' the handler is responsible for. + (put 'tramp-completion-file-name-handler 'operations + (mapcar 'car tramp-completion-file-name-handler-alist)) + ;; If jka-compr or epa-file are already loaded, move them to the ;; front of `file-name-handler-alist'. (dolist (fnh '(epa-file-handler jka-compr-handler)) @@ -2226,6 +2293,24 @@ Falls back to normal file name handler if no Tramp file name handler exists." (eval-after-load 'tramp (tramp-register-file-name-handlers)) +;;;###tramp-autoload +(progn (defun tramp-register-foreign-file-name-handler + (func handler &optional append) + "Register (FUNC . HANDLER) in `tramp-foreign-file-name-handler-alist'. +FUNC is the function, which determines whether HANDLER is to be called. +Add operations defined in `HANDLER-alist' to `tramp-file-name-handler'." + (add-to-list + 'tramp-foreign-file-name-handler-alist `(,func . ,handler) append) + ;; Mark `operations' the handler is responsible for. + (put 'tramp-file-name-handler + 'operations + (delete-dups + (append + (get 'tramp-file-name-handler 'operations) + (mapcar + 'car + (symbol-value (intern (concat (symbol-name handler) "-alist"))))))))) + (defun tramp-exists-file-name-handler (operation &rest args) "Check, whether OPERATION runs a file name handler." ;; The file name handler is determined on base of either an @@ -2249,12 +2334,10 @@ Falls back to normal file name handler if no Tramp file name handler exists." ;;;###autoload (defun tramp-unload-file-name-handlers () "Unload Tramp file name handlers from `file-name-handler-alist'." - (setq file-name-handler-alist - (delete (rassoc 'tramp-file-name-handler - file-name-handler-alist) - (delete (rassoc 'tramp-completion-file-name-handler - file-name-handler-alist) - file-name-handler-alist)))) + (dolist (fnh '(tramp-file-name-handler + tramp-completion-file-name-handler)) + (let ((a1 (rassq fnh file-name-handler-alist))) + (setq file-name-handler-alist (delq a1 file-name-handler-alist))))) (add-hook 'tramp-unload-hook 'tramp-unload-file-name-handlers) @@ -2262,34 +2345,16 @@ Falls back to normal file name handler if no Tramp file name handler exists." ;;;###autoload (defvar tramp-completion-mode nil - "If non-nil, external packages signal that they are in file name completion. - -This is necessary, because Tramp uses a heuristic depending on last -input event. This fails when external packages use other characters -but , or ?\\? for file name completion. This variable -should never be set globally, the intention is to let-bind it.") + "If non-nil, external packages signal that they are in file name completion.") (make-obsolete-variable 'tramp-completion-mode 'non-essential "26.1") -;; Necessary because `tramp-file-name-regexp-unified' and -;; `tramp-completion-file-name-regexp-unified' aren't different. If -;; nil is returned, `tramp-completion-run-real-handler' is called -;; (i.e. forwarding to `tramp-file-name-handler'). Otherwise, it -;; takes `tramp-run-real-handler'. Using `last-input-event' is a -;; little bit risky, because completing a file might require loading -;; other files, like "~/.netrc", and for them it shouldn't be decided -;; based on that variable. On the other hand, those files shouldn't -;; have partial Tramp file name syntax. -;;;###autoload -(progn (defun tramp-completion-mode-p () +(defun tramp-completion-mode-p () "Check, whether method / user name / host name completion is active." (or - ;; Signal from outside. `non-essential' has been introduced in Emacs 24. - (and (boundp 'non-essential) (symbol-value 'non-essential)) + ;; Signal from outside. + non-essential ;; This variable has been obsoleted in Emacs 26. - tramp-completion-mode - ;; Fallback. Some completion packages still don't support - ;; `non-essential' sufficiently. - (equal last-input-event 'tab)))) + tramp-completion-mode)) (defun tramp-connectable-p (filename) "Check, whether it is possible to connect the remote host w/o side-effects. @@ -2298,22 +2363,13 @@ not in completion mode." (let (tramp-verbose) (and (tramp-tramp-file-p filename) (or (not (tramp-completion-mode-p)) - (tramp-compat-process-live-p + (process-live-p (tramp-get-connection-process (tramp-dissect-file-name filename))))))) -(defun tramp-completion-handle-expand-file-name (name &optional dir) - "Like `expand-file-name' for Tramp files." - ;; If DIR is not given, use `default-directory' or "/". - (setq dir (or dir default-directory "/")) - (cond - ((file-name-absolute-p name) name) - ((zerop (length name)) dir) - (t (concat (file-name-as-directory dir) name)))) - ;; Method, host name and user name completion. ;; `tramp-completion-dissect-file-name' returns a list of -;; tramp-file-name structures. For all of them we return possible completions. +;; tramp-file-name structures. For all of them we return possible completions. (defun tramp-completion-handle-file-name-all-completions (filename directory) "Like `file-name-all-completions' for partial Tramp files." @@ -2324,8 +2380,8 @@ not in completion mode." ;; Suppress hop from completion. (when (string-match (concat - tramp-prefix-regexp - "\\(" "\\(" tramp-remote-file-name-spec-regexp + (tramp-prefix-regexp) + "\\(" "\\(" (tramp-remote-file-name-spec-regexp) tramp-postfix-hop-regexp "\\)+" "\\)") fullname) @@ -2370,20 +2426,19 @@ not in completion mode." ;; Unify list, add hop, remove nil elements. (dolist (elt result) (when elt - (string-match tramp-prefix-regexp elt) - (setq elt (replace-match (concat tramp-prefix-format hop) nil nil elt)) - (add-to-list - 'result1 - (substring elt (length (tramp-drop-volume-letter directory)))))) + (string-match (tramp-prefix-regexp) elt) + (setq elt + (replace-match (concat (tramp-prefix-format) hop) nil nil elt)) + (push + (substring elt (length (tramp-drop-volume-letter directory))) + result1))) ;; Complete local parts. (append result1 (ignore-errors - (apply (if (tramp-connectable-p fullname) - 'tramp-completion-run-real-handler - 'tramp-run-real-handler) - 'file-name-all-completions (list (list filename directory))))))) + (tramp-run-real-handler + 'file-name-all-completions (list filename directory)))))) ;; Method, host name and user name completion for a file. (defun tramp-completion-handle-file-name-completion @@ -2404,117 +2459,88 @@ not in completion mode." ;; Expected results: -;; "/x" "/[x" "/x@" "/[x@" "/x@y" "/[x@y" -;; [nil nil "x" nil] [nil "x" nil nil] [nil "x" "y" nil] -;; [nil "x" nil nil] +;; "/x" "/[x" ;; ["x" nil nil nil] -;; "/x:" "/x:y" "/x:y:" -;; [nil nil "x" ""] [nil nil "x" "y"] ["x" nil "y" ""] -;; "/[x/" "/[x/y" -;; ["x" nil "" nil] ["x" nil "y" nil] +;; "/x:" "/[x/" "/x:y" "/[x/y" "/x:y:" "/[x/y]" +;; ["x" nil "" nil] ["x" nil "y" nil] ["x" nil "y" ""] ;; ["x" "" nil nil] ["x" "y" nil nil] -;; "/x:y@" "/x:y@z" "/x:y@z:" -;; [nil nil "x" "y@"] [nil nil "x" "y@z"] ["x" "y" "z" ""] -;; "/[x/y@" "/[x/y@z" -;; ["x" nil "y" nil] ["x" "y" "z" nil] +;; "/x:y@""/[x/y@" "/x:y@z" "/[x/y@z" "/x:y@z:" "/[x/y@z]" +;;["x" "y" nil nil] ["x" "y" "z" nil] ["x" "y" "z" ""] (defun tramp-completion-dissect-file-name (name) "Returns a list of `tramp-file-name' structures. They are collected by `tramp-completion-dissect-file-name1'." - (let* ((result) - (x-nil "\\|\\(\\)") + (let* ((x-nil "\\|\\(\\)") (tramp-completion-ipv6-regexp (format "[^%s]*" - (if (zerop (length tramp-postfix-ipv6-format)) - tramp-postfix-host-format - tramp-postfix-ipv6-format))) + (if (zerop (length (tramp-postfix-ipv6-format))) + (tramp-postfix-host-format) + (tramp-postfix-ipv6-format)))) ;; "/method" "/[method" (tramp-completion-file-name-structure1 - (list (concat tramp-prefix-regexp "\\(" tramp-method-regexp x-nil "\\)$") - 1 nil nil nil)) - ;; "/user" "/[user" - (tramp-completion-file-name-structure2 - (list (concat tramp-prefix-regexp "\\(" tramp-user-regexp x-nil "\\)$") - nil 1 nil nil)) - ;; "/host" "/[host" - (tramp-completion-file-name-structure3 - (list (concat tramp-prefix-regexp "\\(" tramp-host-regexp x-nil "\\)$") - nil nil 1 nil)) - ;; "/[ipv6" "/[ipv6" - (tramp-completion-file-name-structure4 - (list (concat tramp-prefix-regexp - tramp-prefix-ipv6-regexp - "\\(" tramp-completion-ipv6-regexp x-nil "\\)$") - nil nil 1 nil)) - ;; "/user@host" "/[user@host" - (tramp-completion-file-name-structure5 - (list (concat tramp-prefix-regexp - "\\(" tramp-user-regexp "\\)" tramp-postfix-user-regexp - "\\(" tramp-host-regexp x-nil "\\)$") - nil 1 2 nil)) - ;; "/user@[ipv6" "/[user@ipv6" - (tramp-completion-file-name-structure6 - (list (concat tramp-prefix-regexp - "\\(" tramp-user-regexp "\\)" tramp-postfix-user-regexp - tramp-prefix-ipv6-regexp - "\\(" tramp-completion-ipv6-regexp x-nil "\\)$") - nil 1 2 nil)) + (list + (concat + (tramp-prefix-regexp) + "\\(" (tramp-method-regexp) x-nil "\\)$") + 1 nil nil nil)) ;; "/method:user" "/[method/user" - (tramp-completion-file-name-structure7 - (list (concat tramp-prefix-regexp - "\\(" tramp-method-regexp "\\)" tramp-postfix-method-regexp - "\\(" tramp-user-regexp x-nil "\\)$") - 1 2 nil nil)) + (tramp-completion-file-name-structure2 + (list + (concat + (tramp-prefix-regexp) + "\\(" (tramp-method-regexp) "\\)" (tramp-postfix-method-regexp) + "\\(" tramp-user-regexp x-nil "\\)$") + 1 2 nil nil)) ;; "/method:host" "/[method/host" - (tramp-completion-file-name-structure8 - (list (concat tramp-prefix-regexp - "\\(" tramp-method-regexp "\\)" tramp-postfix-method-regexp - "\\(" tramp-host-regexp x-nil "\\)$") - 1 nil 2 nil)) + (tramp-completion-file-name-structure3 + (list + (concat + (tramp-prefix-regexp) + "\\(" (tramp-method-regexp) "\\)" (tramp-postfix-method-regexp) + "\\(" tramp-host-regexp x-nil "\\)$") + 1 nil 2 nil)) ;; "/method:[ipv6" "/[method/ipv6" - (tramp-completion-file-name-structure9 - (list (concat tramp-prefix-regexp - "\\(" tramp-method-regexp "\\)" tramp-postfix-method-regexp - tramp-prefix-ipv6-regexp - "\\(" tramp-completion-ipv6-regexp x-nil "\\)$") - 1 nil 2 nil)) + (tramp-completion-file-name-structure4 + (list + (concat + (tramp-prefix-regexp) + "\\(" (tramp-method-regexp) "\\)" (tramp-postfix-method-regexp) + (tramp-prefix-ipv6-regexp) + "\\(" tramp-completion-ipv6-regexp x-nil "\\)$") + 1 nil 2 nil)) ;; "/method:user@host" "/[method/user@host" - (tramp-completion-file-name-structure10 - (list (concat tramp-prefix-regexp - "\\(" tramp-method-regexp "\\)" tramp-postfix-method-regexp - "\\(" tramp-user-regexp "\\)" tramp-postfix-user-regexp - "\\(" tramp-host-regexp x-nil "\\)$") - 1 2 3 nil)) + (tramp-completion-file-name-structure5 + (list + (concat + (tramp-prefix-regexp) + "\\(" (tramp-method-regexp) "\\)" (tramp-postfix-method-regexp) + "\\(" tramp-user-regexp "\\)" tramp-postfix-user-regexp + "\\(" tramp-host-regexp x-nil "\\)$") + 1 2 3 nil)) ;; "/method:user@[ipv6" "/[method/user@ipv6" - (tramp-completion-file-name-structure11 - (list (concat tramp-prefix-regexp - "\\(" tramp-method-regexp "\\)" tramp-postfix-method-regexp - "\\(" tramp-user-regexp "\\)" tramp-postfix-user-regexp - tramp-prefix-ipv6-regexp - "\\(" tramp-completion-ipv6-regexp x-nil "\\)$") - 1 2 3 nil))) - - (mapc (lambda (structure) - (add-to-list 'result - (tramp-completion-dissect-file-name1 structure name))) + (tramp-completion-file-name-structure6 + (list + (concat + (tramp-prefix-regexp) + "\\(" (tramp-method-regexp) "\\)" (tramp-postfix-method-regexp) + "\\(" tramp-user-regexp "\\)" tramp-postfix-user-regexp + (tramp-prefix-ipv6-regexp) + "\\(" tramp-completion-ipv6-regexp x-nil "\\)$") + 1 2 3 nil))) + (delq + nil + (mapcar + (lambda (structure) (tramp-completion-dissect-file-name1 structure name)) (list tramp-completion-file-name-structure1 tramp-completion-file-name-structure2 tramp-completion-file-name-structure3 tramp-completion-file-name-structure4 tramp-completion-file-name-structure5 - tramp-completion-file-name-structure6 - tramp-completion-file-name-structure7 - tramp-completion-file-name-structure8 - tramp-completion-file-name-structure9 - tramp-completion-file-name-structure10 - tramp-completion-file-name-structure11 - tramp-file-name-structure)) - - (delq nil result))) + tramp-completion-file-name-structure6))))) (defun tramp-completion-dissect-file-name1 (structure name) "Returns a `tramp-file-name' structure matching STRUCTURE. @@ -2523,15 +2549,13 @@ remote host and localname (filename on remote host)." (save-match-data (when (string-match (nth 0 structure) name) - (let ((method (and (nth 1 structure) - (match-string (nth 1 structure) name))) - (user (and (nth 2 structure) - (match-string (nth 2 structure) name))) - (host (and (nth 3 structure) - (match-string (nth 3 structure) name))) - (localname (and (nth 4 structure) - (match-string (nth 4 structure) name)))) - (vector method user host localname nil))))) + (make-tramp-file-name + :method (and (nth 1 structure) + (match-string (nth 1 structure) name)) + :user (and (nth 2 structure) + (match-string (nth 2 structure) name)) + :host (and (nth 3 structure) + (match-string (nth 3 structure) name)))))) ;; This function returns all possible method completions, adding the ;; trailing method delimiter. @@ -2606,7 +2630,7 @@ User is always nil." (with-temp-buffer (insert-file-contents filename) (goto-char (point-min)) - (loop while (not (eobp)) collect (funcall function)))))) + (cl-loop while (not (eobp)) collect (funcall function)))))) ;;;###tramp-autoload (defun tramp-parse-rhosts (filename) @@ -2658,9 +2682,10 @@ User is always nil." ;; `default-directory' is remote. (let* ((default-directory (tramp-compat-temporary-file-directory)) (files (and (file-directory-p dirname) (directory-files dirname)))) - (loop for f in files - when (and (not (string-match "^\\.\\.?$" f)) (string-match regexp f)) - collect (list nil (match-string 1 f))))) + (cl-loop + for f in files + when (and (not (string-match "^\\.\\.?$" f)) (string-match regexp f)) + collect (list nil (match-string 1 f))))) ;;;###tramp-autoload (defun tramp-parse-shostkeys (dirname) @@ -2698,8 +2723,8 @@ Host is always \"localhost\"." (with-temp-buffer (when (zerop (tramp-call-process nil "getent" nil t nil "passwd")) (goto-char (point-min)) - (loop while (not (eobp)) collect - (tramp-parse-etc-group-group)))) + (cl-loop while (not (eobp)) collect + (tramp-parse-etc-group-group)))) (tramp-parse-file filename 'tramp-parse-passwd-group)))) (defun tramp-parse-passwd-group () @@ -2721,8 +2746,8 @@ Host is always \"localhost\"." (with-temp-buffer (when (zerop (tramp-call-process nil "getent" nil t nil "group")) (goto-char (point-min)) - (loop while (not (eobp)) collect - (tramp-parse-etc-group-group)))) + (cl-loop while (not (eobp)) collect + (tramp-parse-etc-group-group)))) (tramp-parse-file filename 'tramp-parse-etc-group-group)))) (defun tramp-parse-etc-group-group () @@ -2764,8 +2789,8 @@ User is always nil." (when (zerop (tramp-call-process nil "reg" nil t nil "query" registry-or-dirname)) (goto-char (point-min)) - (loop while (not (eobp)) collect - (tramp-parse-putty-group registry-or-dirname))))) + (cl-loop while (not (eobp)) collect + (tramp-parse-putty-group registry-or-dirname))))) ;; UNIX case. (tramp-parse-shostkeys-sknownhosts registry-or-dirname (concat "^\\(" tramp-host-regexp "\\)$")))) @@ -2877,9 +2902,11 @@ User is always nil." (tramp-make-tramp-file-name (tramp-file-name-method v) (tramp-file-name-user v) + (tramp-file-name-domain v) (tramp-file-name-host v) - (if (and (tramp-completion-mode-p) - (zerop (length (tramp-file-name-localname v)))) + (tramp-file-name-port v) + (if (and (zerop (length (tramp-file-name-localname v))) + (not (tramp-connectable-p file))) "" (tramp-run-real-handler 'file-name-as-directory (list (or (tramp-file-name-localname v) "")))) @@ -2897,40 +2924,47 @@ User is always nil." (tramp-get-method-parameter v 'tramp-case-insensitive) ;; There isn't. So we must check, in case there's a connection already. - (and (tramp-connectable-p filename) + (and (file-remote-p filename nil 'connected) (with-tramp-connection-property v "case-insensitive" - ;; The idea is to compare a file with lower case letters - ;; with the same file with upper case letters. - (let ((candidate - (tramp-compat-file-name-unquote - (directory-file-name filename))) - tmpfile) - ;; Check, whether we find an existing file with lower case - ;; letters. This avoids us to create a temporary file. - (while (and (string-match - "[a-z]" (file-remote-p candidate 'localname)) - (not (file-exists-p candidate))) - (setq candidate - (directory-file-name (file-name-directory candidate)))) - ;; Nothing found, so we must use a temporary file for - ;; comparison. `make-nearby-temp-file' is added to - ;; Emacs 26+ like `file-name-case-insensitive-p', so - ;; there is no compatibility problem calling it. - (unless - (string-match "[a-z]" (file-remote-p candidate 'localname)) - (setq tmpfile - (let ((default-directory (file-name-directory filename))) - (tramp-compat-funcall 'make-nearby-temp-file "tramp.")) - candidate tmpfile)) - ;; Check for the existence of the same file with upper - ;; case letters. - (unwind-protect - (file-exists-p - (concat - (file-remote-p candidate) - (upcase (file-remote-p candidate 'localname)))) - ;; Cleanup. - (when tmpfile (delete-file tmpfile))))))))) + (ignore-errors + (with-tramp-progress-reporter v 5 "Checking case-insensitive" + ;; The idea is to compare a file with lower case + ;; letters with the same file with upper case letters. + (let ((candidate + (tramp-compat-file-name-unquote + (directory-file-name filename))) + tmpfile) + ;; Check, whether we find an existing file with + ;; lower case letters. This avoids us to create a + ;; temporary file. + (while (and (string-match + "[a-z]" (file-remote-p candidate 'localname)) + (not (file-exists-p candidate))) + (setq candidate + (directory-file-name + (file-name-directory candidate)))) + ;; Nothing found, so we must use a temporary file + ;; for comparison. `make-nearby-temp-file' is added + ;; to Emacs 26+ like `file-name-case-insensitive-p', + ;; so there is no compatibility problem calling it. + (unless + (string-match + "[a-z]" (file-remote-p candidate 'localname)) + (setq tmpfile + (let ((default-directory + (file-name-directory filename))) + (tramp-compat-funcall + 'make-nearby-temp-file "tramp.")) + candidate tmpfile)) + ;; Check for the existence of the same file with + ;; upper case letters. + (unwind-protect + (file-exists-p + (concat + (file-remote-p candidate) + (upcase (file-remote-p candidate 'localname)))) + ;; Cleanup. + (when tmpfile (delete-file tmpfile))))))))))) (defun tramp-handle-file-name-completion (filename directory &optional predicate) @@ -2966,7 +3000,9 @@ User is always nil." (tramp-make-tramp-file-name (tramp-file-name-method v) (tramp-file-name-user v) + (tramp-file-name-domain v) (tramp-file-name-host v) + (tramp-file-name-port v) (tramp-run-real-handler 'file-name-directory (list (or (tramp-file-name-localname v) ""))) (tramp-file-name-hop v)))) @@ -3000,7 +3036,7 @@ User is always nil." (when (tramp-tramp-file-p filename) (let* ((v (tramp-dissect-file-name filename)) (p (tramp-get-connection-process v)) - (c (and (tramp-compat-process-live-p p) + (c (and (process-live-p p) (tramp-get-connection-property p "connected" nil)))) ;; We expand the file name only, if there is already a connection. (with-parsed-tramp-file-name @@ -3008,11 +3044,13 @@ User is always nil." (and (or (not connected) c) (cond ((eq identification 'method) method) - ((eq identification 'user) user) - ((eq identification 'host) host) + ;; Domain and port are appended. + ((eq identification 'user) (tramp-file-name-user-domain v)) + ((eq identification 'host) (tramp-file-name-host-port v)) ((eq identification 'localname) localname) ((eq identification 'hop) hop) - (t (tramp-make-tramp-file-name method user host "" hop))))))))) + (t (tramp-make-tramp-file-name + method user domain host port "" hop))))))))) (defun tramp-handle-file-symlink-p (filename) "Like `file-symlink-p' for Tramp files." @@ -3020,7 +3058,7 @@ User is always nil." (let ((x (tramp-compat-file-attribute-type (file-attributes filename)))) (when (stringp x) (if (file-name-absolute-p x) - (tramp-make-tramp-file-name method user host x) + (tramp-make-tramp-file-name method user domain host port x) x))))) (defun tramp-handle-find-backup-file-name (filename) @@ -3035,7 +3073,8 @@ User is always nil." (if (and (stringp (cdr x)) (file-name-absolute-p (cdr x)) (not (tramp-file-name-p (cdr x)))) - (tramp-make-tramp-file-name method user host (cdr x)) + (tramp-make-tramp-file-name + method user domain host port (cdr x)) (cdr x)))) tramp-backup-directory-alist) backup-directory-alist))) @@ -3140,7 +3179,7 @@ User is always nil." ((stringp remote-copy) (file-local-copy (tramp-make-tramp-file-name - method user host remote-copy))) + method user domain host port remote-copy))) ((stringp tramp-temp-buffer-file-name) (copy-file filename tramp-temp-buffer-file-name 'ok) @@ -3185,7 +3224,8 @@ User is always nil." (delete-file local-copy)) (when (stringp remote-copy) (delete-file - (tramp-make-tramp-file-name method user host remote-copy))))) + (tramp-make-tramp-file-name + method user domain host port remote-copy))))) ;; Result. (list (expand-file-name filename) @@ -3409,7 +3449,7 @@ of." (defun tramp-handle-file-notify-valid-p (proc) "Like `file-notify-valid-p' for Tramp files." - (and (tramp-compat-process-live-p proc) + (and (process-live-p proc) ;; Sometimes, the process is still in status `run' when the ;; file or directory to be watched is deleted already. (with-current-buffer (process-buffer proc) @@ -3504,14 +3544,14 @@ The terminal type can be configured with `tramp-terminal-type'." (defun tramp-action-process-alive (proc _vec) "Check, whether a process has finished." - (unless (tramp-compat-process-live-p proc) + (unless (process-live-p proc) (throw 'tramp-action 'process-died))) (defun tramp-action-out-of-band (proc vec) "Check, whether an out-of-band copy has finished." ;; There might be pending output for the exit status. (tramp-accept-process-output proc 0.1) - (cond ((and (not (tramp-compat-process-live-p proc)) + (cond ((and (not (process-live-p proc)) (zerop (process-exit-status proc))) (tramp-message vec 3 "Process has finished.") (throw 'tramp-action 'ok)) @@ -3558,13 +3598,14 @@ The terminal type can be configured with `tramp-terminal-type'." PROC and VEC indicate the remote connection to be used. POS, if set, is the starting point of the region to be deleted in the connection buffer." - ;; Enable `auth-source'. We must use tramp-current-* variables in - ;; case we have several hops. + ;; Enable `auth-source', unless "emacs -Q" has been called. We must + ;; use `tramp-current-*' variables in case we have several hops. (tramp-set-connection-property - (tramp-dissect-file-name - (tramp-make-tramp-file-name - tramp-current-method tramp-current-user tramp-current-host "")) - "first-password-request" t) + (make-tramp-file-name + :method tramp-current-method :user tramp-current-user + :domain tramp-current-domain :host tramp-current-host + :port tramp-current-port) + "first-password-request" tramp-cache-read-persistent-data) (save-restriction (with-tramp-progress-reporter proc 3 "Waiting for prompts from remote shell" @@ -3613,31 +3654,17 @@ connection buffer." "Like `accept-process-output' for Tramp processes. This is needed in order to hide `last-coding-system-used', which is set for process communication also." - ;; FIXME: There are problems, when an asynchronous process runs in - ;; parallel, and also timers are active. See - ;; . - (when (and timer-event-last - (string-prefix-p "*tramp/" (process-name proc)) - (let (result) - (maphash - (lambda (key _value) - (and (processp key) - (not (string-prefix-p "*tramp/" (process-name key))) - (tramp-compat-process-live-p key) - (setq result t))) - tramp-cache-data) - result)) - (sit-for 0.01 'nodisp)) (with-current-buffer (process-buffer proc) (let (buffer-read-only last-coding-system-used) - ;; Under Windows XP, accept-process-output doesn't return + ;; Under Windows XP, `accept-process-output' doesn't return ;; sometimes. So we add an additional timeout. JUST-THIS-ONE - ;; is set due to Bug#12145. + ;; is set due to Bug#12145. It is an integer, in order to avoid + ;; running timers as well. (tramp-message proc 10 "%s %s %s\n%s" proc (process-status proc) (with-timeout (timeout) - (accept-process-output proc timeout nil t)) + (accept-process-output proc timeout nil 0)) (buffer-string))))) (defun tramp-check-for-regexp (proc regexp) @@ -3687,14 +3714,14 @@ nil." (with-timeout (timeout) (while (not found) (tramp-accept-process-output proc 1) - (unless (tramp-compat-process-live-p proc) + (unless (process-live-p proc) (tramp-error-with-buffer nil proc 'file-error "Process has died")) (setq found (tramp-check-for-regexp proc regexp))))) (t (while (not found) (tramp-accept-process-output proc 1) - (unless (tramp-compat-process-live-p proc) + (unless (process-live-p proc) (tramp-error-with-buffer nil proc 'file-error "Process has died")) (setq found (tramp-check-for-regexp proc regexp))))) @@ -3948,7 +3975,9 @@ be granted." (tramp-make-tramp-file-name (tramp-file-name-method vec) (tramp-file-name-user vec) + (tramp-file-name-domain vec) (tramp-file-name-host vec) + (tramp-file-name-port vec) (tramp-file-name-localname vec) (tramp-file-name-hop vec)) (intern suffix)))) @@ -3994,12 +4023,13 @@ be granted." ;;;###tramp-autoload (defun tramp-local-host-p (vec) "Return t if this points to the local host, nil otherwise." - ;; We cannot use `tramp-file-name-real-host'. A port is an - ;; indication for an ssh tunnel or alike. - (let ((host (tramp-file-name-host vec))) + (let ((host (tramp-file-name-host vec)) + (port (tramp-file-name-port vec))) (and (stringp host) (string-match tramp-local-host-regexp host) + ;; A port is an indication for an ssh tunnel or alike. + (null port) ;; The method shall be applied to one of the shell file name ;; handlers. `tramp-local-host-p' is also called for "smb" and ;; alike, where it must fail. @@ -4009,7 +4039,8 @@ be granted." (tramp-make-tramp-file-name (tramp-file-name-method vec) (tramp-file-name-user vec) - host + (tramp-file-name-domain vec) + host port (tramp-compat-temporary-file-directory))) ;; On some systems, chown runs only for root. (or (zerop (user-uid)) @@ -4023,7 +4054,9 @@ be granted." (let ((dir (tramp-make-tramp-file-name (tramp-file-name-method vec) (tramp-file-name-user vec) + (tramp-file-name-domain vec) (tramp-file-name-host vec) + (tramp-file-name-port vec) (or (tramp-get-method-parameter vec 'tramp-tmpdir) "/tmp") (tramp-file-name-hop vec)))) (or (and (file-directory-p dir) (file-writable-p dir) @@ -4139,8 +4172,10 @@ PROGRAM is nil is trapped also, returning 1. Furthermore, traces are written with verbosity of 6." (let ((default-directory (tramp-compat-temporary-file-directory)) (v (or vec - (vector tramp-current-method tramp-current-user - tramp-current-host nil nil))) + (make-tramp-file-name + :method tramp-current-method :user tramp-current-user + :domain tramp-current-domain :host tramp-current-host + :port tramp-current-port))) (destination (if (eq destination t) (current-buffer) destination)) output error result) (tramp-message @@ -4174,8 +4209,10 @@ PROGRAM is nil is trapped also, returning 1. Furthermore, traces are written with verbosity of 6." (let ((default-directory (tramp-compat-temporary-file-directory)) (v (or vec - (vector tramp-current-method tramp-current-user - tramp-current-host nil nil))) + (make-tramp-file-name + :method tramp-current-method :user tramp-current-user + :domain tramp-current-domain :host tramp-current-host + :port tramp-current-port))) (buffer (if (eq buffer t) (current-buffer) buffer)) result) (tramp-message @@ -4206,8 +4243,8 @@ Consults the auth-source package. Invokes `password-read' if available, `read-passwd' else." (let* ((case-fold-search t) (key (tramp-make-tramp-file-name - tramp-current-method tramp-current-user - tramp-current-host "")) + tramp-current-method tramp-current-user tramp-current-domain + tramp-current-host tramp-current-port "")) (pw-prompt (or prompt (with-current-buffer (process-buffer proc) @@ -4222,32 +4259,36 @@ Invokes `password-read' if available, `read-passwd' else." (prog1 (or ;; See if auth-sources contains something useful. - ;; `auth-source-user-or-password' is an obsoleted - ;; function since Emacs 24.1, it has been replaced by - ;; `auth-source-search'. (ignore-errors (and (tramp-get-connection-property v "first-password-request" nil) ;; Try with Tramp's current method. - (if (fboundp 'auth-source-search) - (setq auth-info - (auth-source-search - :max 1 - (and tramp-current-user :user) - tramp-current-user - :host tramp-current-host - :port tramp-current-method - :require - (cons - :secret (and tramp-current-user '(:user)))) - auth-passwd (plist-get - (nth 0 auth-info) :secret) - auth-passwd (if (functionp auth-passwd) - (funcall auth-passwd) - auth-passwd)) - (tramp-compat-funcall - 'auth-source-user-or-password - "password" tramp-current-host tramp-current-method)))) + (setq auth-info + (auth-source-search + :max 1 + (and tramp-current-user :user) + (if tramp-current-domain + (format + "%s%s%s" + tramp-current-user tramp-prefix-domain-format + tramp-current-domain) + tramp-current-user) + :host + (if tramp-current-port + (format + "%s%s%s" + tramp-current-host tramp-prefix-port-format + tramp-current-port) + tramp-current-host) + :port tramp-current-method + :require + (cons + :secret (and tramp-current-user '(:user)))) + auth-passwd (plist-get + (nth 0 auth-info) :secret) + auth-passwd (if (functionp auth-passwd) + (funcall auth-passwd) + auth-passwd)))) ;; Try the password cache. (let ((password (password-read pw-prompt key))) (password-cache-add key password) @@ -4263,25 +4304,26 @@ Invokes `password-read' if available, `read-passwd' else." "Clear password cache for connection related to VEC." (let ((method (tramp-file-name-method vec)) (user (tramp-file-name-user vec)) + (domain (tramp-file-name-domain vec)) + (user-domain (tramp-file-name-user-domain vec)) (host (tramp-file-name-host vec)) + (port (tramp-file-name-port vec)) + (host-port (tramp-file-name-host-port vec)) (hop (tramp-file-name-hop vec))) (when hop ;; Clear also the passwords of the hops. (tramp-clear-passwd (tramp-dissect-file-name (concat - tramp-prefix-format + (tramp-prefix-format) (replace-regexp-in-string (concat tramp-postfix-hop-regexp "$") - tramp-postfix-host-format hop))))) - ;; `auth-source-forget-user-or-password' is an obsoleted function - ;; since Emacs 24.1, it has been replaced by `auth-source-forget'. - (if (fboundp 'auth-source-forget) - (auth-source-forget - `(:max 1 ,(and user :user) ,user :host ,host :port ,method)) - (tramp-compat-funcall - 'auth-source-forget-user-or-password "password" host method)) - (password-cache-remove (tramp-make-tramp-file-name method user host "")))) + (tramp-postfix-host-format) hop))))) + (auth-source-forget + `(:max 1 ,(and user-domain :user) ,user-domain + :host ,host-port :port ,method)) + (password-cache-remove + (tramp-make-tramp-file-name method user domain host port "")))) ;; Snarfed code from time-date.el. @@ -4320,10 +4362,6 @@ T1 and T2 are time values (as returned by `current-time' for example)." ;; ;; Thanks to Mario DeWeerd for the hint that it is sufficient for this ;; function to work with Bourne-like shells. -;; -;; CCC: This function should be rewritten so that -;; `shell-quote-argument' is not used. This way, we are safe from -;; changes in `shell-quote-argument'. ;;;###tramp-autoload (defun tramp-shell-quote-argument (s) "Similar to `shell-quote-argument', but groks newlines. @@ -4412,10 +4450,6 @@ Only works for Bourne-like shells." ;; . ;; (Bug#6850) ;; -;; * Use also port to distinguish connections. This is needed for -;; different hosts sitting behind a single router (distinguished by -;; different port numbers). (Tzvi Edelman) -;; ;; * Refactor code from different handlers. Start with ;; *-process-file. One idea is to generalize `tramp-send-command' ;; and friends, for most of the handlers this is the major diff --git a/lisp/net/trampver.el b/lisp/net/trampver.el index 14d224142dc..527630d747c 100644 --- a/lisp/net/trampver.el +++ b/lisp/net/trampver.el @@ -1,12 +1,13 @@ -;;; trampver.el --- Transparent Remote Access, Multiple Protocol +;;; trampver.el --- Transparent Remote Access, Multiple Protocol -*- lexical-binding:t -*- ;;; lisp/trampver.el. Generated from trampver.el.in by configure. ;; Copyright (C) 2003-2017 Free Software Foundation, Inc. ;; Author: Kai Großjohann +;; Maintainer: Michael Albinus ;; Keywords: comm, processes ;; Package: tramp -;; Version: 2.3.2-pre +;; Version: 2.3.3-pre ;; This file is part of GNU Emacs. @@ -32,7 +33,7 @@ ;; should be changed only there. ;;;###tramp-autoload -(defconst tramp-version "2.3.2-pre" +(defconst tramp-version "2.3.3-pre" "This version of Tramp.") ;;;###tramp-autoload @@ -52,13 +53,23 @@ (replace-regexp-in-string "\n" "" (buffer-string)))))))) ;; Check for Emacs version. -(let ((x (if (>= emacs-major-version 23) +(let ((x (if (>= emacs-major-version 24) "ok" - (format "Tramp 2.3.2-pre is not fit for %s" + (format "Tramp 2.3.3-pre is not fit for %s" (when (string-match "^.*$" (emacs-version)) (match-string 0 (emacs-version))))))) (unless (string-match "\\`ok\\'" x) (error "%s" x))) +;; Tramp versions integrated into Emacs. +(add-to-list + 'customize-package-emacs-version-alist + '(Tramp ("2.0.55" . "22.1") ("2.0.57" . "22.2") ("2.0.58-pre" . "22.3") + ("2.1.15" . "23.1") ("2.1.18-23.2" . "23.2") + ("2.1.20" . "23.3") ("2.1.21-pre" . "23.4") + ("2.2.3-24.1" . "24.1") ("2.2.3-24.1" . "24.2") ("2.2.6-24.3" . "24.3") + ("2.2.9-24.4" . "24.4") ("2.2.11-24.5" . "24.5") + ("2.2.13.25.1" . "25.1") ("2.2.13.25.2" . "25.2"))) + (add-hook 'tramp-unload-hook (lambda () (unload-feature 'trampver 'force))) diff --git a/lisp/newcomment.el b/lisp/newcomment.el index 4b261c34c65..8772b52376d 100644 --- a/lisp/newcomment.el +++ b/lisp/newcomment.el @@ -142,9 +142,10 @@ Should be an empty string if comments are terminated by end-of-line.") ;;;###autoload (defvar comment-indent-function 'comment-indent-default "Function to compute desired indentation for a comment. -This function is called with no args with point at the beginning of -the comment's starting delimiter and should return either the desired -column indentation or nil. +This function is called with no args with point at the beginning +of the comment's starting delimiter and should return either the +desired column indentation, a range of acceptable +indentation (MIN . MAX), or nil. If nil is returned, indentation is delegated to `indent-according-to-mode'.") ;;;###autoload @@ -649,13 +650,20 @@ The criteria are (in this order): - prefer INDENT (or `comment-column' if nil). Point is expected to be at the start of the comment." (unless indent (setq indent comment-column)) - ;; Avoid moving comments past the fill-column. - (let ((max (+ (current-column) - (- (or comment-fill-column fill-column) - (save-excursion (end-of-line) (current-column))))) - (other nil) - (min (save-excursion (skip-chars-backward " \t") - (if (bolp) 0 (+ comment-inline-offset (current-column)))))) + (let ((other nil) + min max) + (pcase indent + (`(,lo . ,hi) (setq min lo) (setq max hi) + (setq indent comment-column)) + (_ ;; Avoid moving comments past the fill-column. + (setq max (+ (current-column) + (- (or comment-fill-column fill-column) + (save-excursion (end-of-line) (current-column))))) + (setq min (save-excursion + (skip-chars-backward " \t") + ;; Leave at least `comment-inline-offset' space after + ;; other nonwhite text on the line. + (if (bolp) 0 (+ comment-inline-offset (current-column))))))) ;; Fix up the range. (if (< max min) (setq max min)) ;; Don't move past the fill column. @@ -750,13 +758,6 @@ If CONTINUE is non-nil, use the `comment-continue' markers if any." ;; If the comment is at the right of code, adjust the indentation. (unless (save-excursion (skip-chars-backward " \t") (bolp)) (setq indent (comment-choose-indent indent))) - ;; Update INDENT to leave at least one space - ;; after other nonwhite text on the line. - (save-excursion - (skip-chars-backward " \t") - (unless (bolp) - (setq indent (max indent - (+ (current-column) comment-inline-offset))))) ;; If that's different from comment's current position, change it. (unless (= (current-column) indent) (delete-region (point) (progn (skip-chars-backward " \t") (point))) @@ -815,7 +816,7 @@ N defaults to 0. If N is `re', a regexp is returned instead, that would match the string for any N." (setq n (or n 0)) - (when (and (stringp str) (not (string= "" str))) + (when (and (stringp str) (string-match "\\S-" str)) ;; Separate the actual string from any leading/trailing padding (string-match "\\`\\s-*\\(.*?\\)\\s-*\\'" str) (let ((s (match-string 1 str)) ;actual string diff --git a/lisp/nxml/xsd-regexp.el b/lisp/nxml/xsd-regexp.el index 6acb1ff9d41..d56960c9fa9 100644 --- a/lisp/nxml/xsd-regexp.el +++ b/lisp/nxml/xsd-regexp.el @@ -621,7 +621,7 @@ whose value is a range-list." (defun xsdre-parse-escape () (let ((ch (car xsdre-current-regexp))) (xsdre-advance) - (cond ((memq ch '(?\\ ?| ?. ?- ?^ ?* ?+ ?( ?) ?{ ?} ?[ ?])) ch) + (cond ((memq ch '(?\\ ?| ?. ?- ?^ ?* ?+ ?\( ?\) ?{ ?} ?\[ ?\])) ch) ((eq ch ?r) ?\r) ((eq ch ?n) ?\n) ((eq ch ?t) ?\t) diff --git a/lisp/obarray.el b/lisp/obarray.el index aaffe00a072..b1160ebea43 100644 --- a/lisp/obarray.el +++ b/lisp/obarray.el @@ -37,6 +37,10 @@ (make-vector size 0) (signal 'wrong-type-argument '(size 0))))) +(defun obarray-size (ob) + "Return the number of slots of obarray OB." + (length ob)) + (defun obarrayp (object) "Return t if OBJECT is an obarray." (and (vectorp object) diff --git a/lisp/obsolete/complete.el b/lisp/obsolete/complete.el index a6c21bce87c..6a7fdc59c22 100644 --- a/lisp/obsolete/complete.el +++ b/lisp/obsolete/complete.el @@ -570,7 +570,7 @@ GOTO-END is non-nil, however, it instead replaces up to END." (substring regex (1+ p))) p (+ p (length PC-ndelims-regex) (length PC-delim-regex))) (let ((bump (if (memq (aref regex p) - '(?$ ?^ ?\. ?* ?+ ?? ?[ ?] ?\\)) + '(?$ ?^ ?\. ?* ?+ ?? ?\[ ?\] ?\\)) -1 0))) (setq regex (concat (substring regex 0 (+ p bump)) PC-ndelims-regex diff --git a/lisp/net/html2text.el b/lisp/obsolete/html2text.el similarity index 99% rename from lisp/net/html2text.el rename to lisp/obsolete/html2text.el index 87c71dc504a..27560a70c63 100644 --- a/lisp/net/html2text.el +++ b/lisp/obsolete/html2text.el @@ -3,6 +3,7 @@ ;; Copyright (C) 2002-2017 Free Software Foundation, Inc. ;; Author: Joakim Hove +;; Obsolete-since: 26.1 ;; This file is part of GNU Emacs. @@ -29,6 +30,8 @@ ;; ;; The main function is `html2text'. +;; This package was obsoleted by shr.el. + ;;; Code: ;; diff --git a/lisp/obsolete/sregex.el b/lisp/obsolete/sregex.el index beca41cadbf..f57befa5043 100644 --- a/lisp/obsolete/sregex.el +++ b/lisp/obsolete/sregex.el @@ -3,7 +3,7 @@ ;; Copyright (C) 1997-1998, 2000-2017 Free Software Foundation, Inc. ;; Author: Bob Glickstein -;; Maintainer: Bob Glickstein +;; Maintainer: emacs-devel@gnu.org ;; Keywords: extensions ;; Obsolete-since: 24.1 diff --git a/lisp/obsolete/vi.el b/lisp/obsolete/vi.el index 081b229ebca..a7a98d0ca55 100644 --- a/lisp/obsolete/vi.el +++ b/lisp/obsolete/vi.el @@ -1128,7 +1128,7 @@ text as lines. If the optional after-p is given, put after/below the cursor." (progn (forward-line 1) (beginning-of-line)) (beginning-of-line)) (if after-p (forward-char 1))) - (push-mark (point)) + (push-mark) (insert put-text) (exchange-point-and-mark) ;; (back-to-indentation) ; this is not allowed if we allow yank-pop @@ -1444,10 +1444,10 @@ Currently, CHAR could be [,{,(,\",',`,<,*, etc." (vi-set-last-change-command 'vi-quote-words arg char) (if (not (looking-at "\\<")) (forward-word -1)) (insert char) - (cond ((char-equal char ?[) (setq char ?])) + (cond ((char-equal char ?\[) (setq char ?\])) ((char-equal char ?{) (setq char ?})) ((char-equal char ?<) (setq char ?>)) - ((char-equal char ?() (setq char ?))) + ((char-equal char ?\() (setq char ?\))) ((char-equal char ?`) (setq char ?'))) (vi-end-of-word arg) (forward-char 1) diff --git a/lisp/obsolete/vip.el b/lisp/obsolete/vip.el index ca0bfe712cb..4d70d6a5dfc 100644 --- a/lisp/obsolete/vip.el +++ b/lisp/obsolete/vip.el @@ -2596,7 +2596,7 @@ a token has type \(command, address, end-mark\) and value." "ex goto command" (if (null ex-addresses) (setq ex-addresses (cons (point) nil))) - (push-mark (point)) + (push-mark) (goto-char (car ex-addresses)) (beginning-of-line)) diff --git a/lisp/org/ob-C.el b/lisp/org/ob-C.el index 8738824aa7a..2bdda68d583 100644 --- a/lisp/org/ob-C.el +++ b/lisp/org/ob-C.el @@ -1,8 +1,9 @@ -;;; ob-C.el --- org-babel functions for C and similar languages +;;; ob-C.el --- Babel Functions for C and Similar Languages -*- lexical-binding: t; -*- ;; Copyright (C) 2010-2017 Free Software Foundation, Inc. ;; Author: Eric Schulte +;; Thierry Banel ;; Keywords: literate programming, reproducible research ;; Homepage: http://orgmode.org @@ -23,37 +24,57 @@ ;;; Commentary: -;; Org-Babel support for evaluating C code. +;; Org-Babel support for evaluating C, C++, D code. ;; ;; very limited implementation: ;; - currently only support :results output ;; - not much in the way of error feedback ;;; Code: -(eval-when-compile - (require 'cl)) -(require 'ob) + (require 'cc-mode) +(require 'ob) -(declare-function org-entry-get "org" - (pom property &optional inherit literal-nil)) +(declare-function org-entry-get "org" (pom property &optional inherit literal-nil)) +(declare-function org-remove-indentation "org" (code &optional n)) +(declare-function org-trim "org" (s &optional keep-lead)) (defvar org-babel-tangle-lang-exts) (add-to-list 'org-babel-tangle-lang-exts '("C++" . "cpp")) +(add-to-list 'org-babel-tangle-lang-exts '("D" . "d")) (defvar org-babel-default-header-args:C '()) -(defvar org-babel-C-compiler "gcc" - "Command used to compile a C source code file into an -executable.") - -(defvar org-babel-C++-compiler "g++" - "Command used to compile a C++ source code file into an -executable.") +(defcustom org-babel-C-compiler "gcc" + "Command used to compile a C source code file into an executable. +May be either a command in the path, like gcc +or an absolute path name, like /usr/local/bin/gcc +parameter may be used, like gcc -v" + :group 'org-babel + :version "24.3" + :type 'string) + +(defcustom org-babel-C++-compiler "g++" + "Command used to compile a C++ source code file into an executable. +May be either a command in the path, like g++ +or an absolute path name, like /usr/local/bin/g++ +parameter may be used, like g++ -v" + :group 'org-babel + :version "24.3" + :type 'string) + +(defcustom org-babel-D-compiler "rdmd" + "Command used to compile and execute a D source code file. +May be either a command in the path, like rdmd +or an absolute path name, like /usr/local/bin/rdmd +parameter may be used, like rdmd --chatty" + :group 'org-babel + :version "24.3" + :type 'string) (defvar org-babel-c-variant nil - "Internal variable used to hold which type of C (e.g. C or C++) + "Internal variable used to hold which type of C (e.g. C or C++ or D) is currently being evaluated.") (defun org-babel-execute:cpp (body params) @@ -61,88 +82,189 @@ is currently being evaluated.") This function calls `org-babel-execute:C++'." (org-babel-execute:C++ body params)) +(defun org-babel-expand-body:cpp (body params) + "Expand a block of C++ code with org-babel according to its +header arguments." + (org-babel-expand-body:C++ body params)) + (defun org-babel-execute:C++ (body params) "Execute a block of C++ code with org-babel. This function is called by `org-babel-execute-src-block'." (let ((org-babel-c-variant 'cpp)) (org-babel-C-execute body params))) (defun org-babel-expand-body:C++ (body params) - "Expand a block of C++ code with org-babel according to it's -header arguments (calls `org-babel-C-expand')." - (let ((org-babel-c-variant 'cpp)) (org-babel-C-expand body params))) + "Expand a block of C++ code with org-babel according to its +header arguments." + (let ((org-babel-c-variant 'cpp)) (org-babel-C-expand-C++ body params))) + +(defun org-babel-execute:D (body params) + "Execute a block of D code with org-babel. +This function is called by `org-babel-execute-src-block'." + (let ((org-babel-c-variant 'd)) (org-babel-C-execute body params))) + +(defun org-babel-expand-body:D (body params) + "Expand a block of D code with org-babel according to its +header arguments." + (let ((org-babel-c-variant 'd)) (org-babel-C-expand-D body params))) (defun org-babel-execute:C (body params) "Execute a block of C code with org-babel. This function is called by `org-babel-execute-src-block'." (let ((org-babel-c-variant 'c)) (org-babel-C-execute body params))) -(defun org-babel-expand-body:c (body params) - "Expand a block of C code with org-babel according to it's -header arguments (calls `org-babel-C-expand')." - (let ((org-babel-c-variant 'c)) (org-babel-C-expand body params))) +(defun org-babel-expand-body:C (body params) + "Expand a block of C code with org-babel according to its +header arguments." + (let ((org-babel-c-variant 'c)) (org-babel-C-expand-C body params))) (defun org-babel-C-execute (body params) "This function should only be called by `org-babel-execute:C' -or `org-babel-execute:C++'." +or `org-babel-execute:C++' or `org-babel-execute:D'." (let* ((tmp-src-file (org-babel-temp-file "C-src-" - (cond - ((equal org-babel-c-variant 'c) ".c") - ((equal org-babel-c-variant 'cpp) ".cpp")))) - (tmp-bin-file (org-babel-temp-file "C-bin-" org-babel-exeext)) - (cmdline (cdr (assoc :cmdline params))) - (flags (cdr (assoc :flags params))) - (full-body (org-babel-C-expand body params)) - (compile - (progn - (with-temp-file tmp-src-file (insert full-body)) - (org-babel-eval - (format "%s -o %s %s %s" - (cond - ((equal org-babel-c-variant 'c) org-babel-C-compiler) - ((equal org-babel-c-variant 'cpp) org-babel-C++-compiler)) - (org-babel-process-file-name tmp-bin-file) - (mapconcat 'identity - (if (listp flags) flags (list flags)) " ") - (org-babel-process-file-name tmp-src-file)) "")))) + (pcase org-babel-c-variant + (`c ".c") (`cpp ".cpp") (`d ".d")))) + (tmp-bin-file ;not used for D + (org-babel-process-file-name + (org-babel-temp-file "C-bin-" org-babel-exeext))) + (cmdline (cdr (assq :cmdline params))) + (cmdline (if cmdline (concat " " cmdline) "")) + (flags (cdr (assq :flags params))) + (flags (mapconcat 'identity + (if (listp flags) flags (list flags)) " ")) + (libs (org-babel-read + (or (cdr (assq :libs params)) + (org-entry-get nil "libs" t)) + nil)) + (libs (mapconcat #'identity + (if (listp libs) libs (list libs)) + " ")) + (full-body + (pcase org-babel-c-variant + (`c (org-babel-C-expand-C body params)) + (`cpp (org-babel-C-expand-C++ body params)) + (`d (org-babel-C-expand-D body params))))) + (with-temp-file tmp-src-file (insert full-body)) + (pcase org-babel-c-variant + ((or `c `cpp) + (org-babel-eval + (format "%s -o %s %s %s %s" + (pcase org-babel-c-variant + (`c org-babel-C-compiler) + (`cpp org-babel-C++-compiler)) + tmp-bin-file + flags + (org-babel-process-file-name tmp-src-file) + libs) + "")) + (`d nil)) ;; no separate compilation for D (let ((results - (org-babel-trim - (org-babel-eval - (concat tmp-bin-file (if cmdline (concat " " cmdline) "")) "")))) - (org-babel-reassemble-table - (org-babel-result-cond (cdr (assoc :result-params params)) - (org-babel-read results) - (let ((tmp-file (org-babel-temp-file "c-"))) - (with-temp-file tmp-file (insert results)) - (org-babel-import-elisp-from-file tmp-file))) - (org-babel-pick-name - (cdr (assoc :colname-names params)) (cdr (assoc :colnames params))) - (org-babel-pick-name - (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params))))) - )) - -(defun org-babel-C-expand (body params) + (org-babel-eval + (pcase org-babel-c-variant + ((or `c `cpp) + (concat tmp-bin-file cmdline)) + (`d + (format "%s %s %s %s" + org-babel-D-compiler + flags + (org-babel-process-file-name tmp-src-file) + cmdline))) + ""))) + (when results + (setq results (org-trim (org-remove-indentation results))) + (org-babel-reassemble-table + (org-babel-result-cond (cdr (assq :result-params params)) + (org-babel-read results t) + (let ((tmp-file (org-babel-temp-file "c-"))) + (with-temp-file tmp-file (insert results)) + (org-babel-import-elisp-from-file tmp-file))) + (org-babel-pick-name + (cdr (assq :colname-names params)) (cdr (assq :colnames params))) + (org-babel-pick-name + (cdr (assq :rowname-names params)) (cdr (assq :rownames params))))) + ))) + +(defun org-babel-C-expand-C++ (body params) "Expand a block of C or C++ code with org-babel according to -it's header arguments." - (let ((vars (mapcar #'cdr (org-babel-get-header params :var))) - (main-p (not (string= (cdr (assoc :main params)) "no"))) - (includes (or (cdr (assoc :includes params)) - (org-babel-read (org-entry-get nil "includes" t)))) - (defines (org-babel-read - (or (cdr (assoc :defines params)) - (org-babel-read (org-entry-get nil "defines" t)))))) +its header arguments." + (org-babel-C-expand-C body params)) + +(defun org-babel-C-expand-C (body params) + "Expand a block of C or C++ code with org-babel according to +its header arguments." + (let ((vars (org-babel--get-vars params)) + (colnames (cdr (assq :colname-names params))) + (main-p (not (string= (cdr (assq :main params)) "no"))) + (includes (org-babel-read + (or (cdr (assq :includes params)) + (org-entry-get nil "includes" t)) + nil)) + (defines (org-babel-read + (or (cdr (assq :defines params)) + (org-entry-get nil "defines" t)) + nil))) + (when (stringp includes) + (setq includes (split-string includes))) + (when (stringp defines) + (let ((y nil) + (result (list t))) + (dolist (x (split-string defines)) + (if (null y) + (setq y x) + (nconc result (list (concat y " " x))) + (setq y nil))) + (setq defines (cdr result)))) (mapconcat 'identity (list ;; includes (mapconcat (lambda (inc) (format "#include %s" inc)) - (if (listp includes) includes (list includes)) "\n") + includes "\n") ;; defines (mapconcat (lambda (inc) (format "#define %s" inc)) (if (listp defines) defines (list defines)) "\n") ;; variables (mapconcat 'org-babel-C-var-to-C vars "\n") + ;; table sizes + (mapconcat 'org-babel-C-table-sizes-to-C vars "\n") + ;; tables headers utility + (when colnames + (org-babel-C-utility-header-to-C)) + ;; tables headers + (mapconcat 'org-babel-C-header-to-C colnames "\n") + ;; body + (if main-p + (org-babel-C-ensure-main-wrap body) + body) "\n") "\n"))) + +(defun org-babel-C-expand-D (body params) + "Expand a block of D code with org-babel according to +its header arguments." + (let ((vars (org-babel--get-vars params)) + (colnames (cdr (assq :colname-names params))) + (main-p (not (string= (cdr (assq :main params)) "no"))) + (imports (or (cdr (assq :imports params)) + (org-babel-read (org-entry-get nil "imports" t))))) + (when (stringp imports) + (setq imports (split-string imports))) + (setq imports (append imports '("std.stdio" "std.conv"))) + (mapconcat 'identity + (list + "module mmm;" + ;; imports + (mapconcat + (lambda (inc) (format "import %s;" inc)) + imports "\n") + ;; variables + (mapconcat 'org-babel-C-var-to-C vars "\n") + ;; table sizes + (mapconcat 'org-babel-C-table-sizes-to-C vars "\n") + ;; tables headers utility + (when colnames + (org-babel-C-utility-header-to-C)) + ;; tables headers + (mapconcat 'org-babel-C-header-to-C colnames "\n") ;; body (if main-p (org-babel-C-ensure-main-wrap body) @@ -154,15 +276,15 @@ it's header arguments." body (format "int main() {\n%s\nreturn 0;\n}\n" body))) -(defun org-babel-prep-session:C (session params) +(defun org-babel-prep-session:C (_session _params) "This function does nothing as C is a compiled language with no support for sessions" - (error "C is a compiled languages -- no support for sessions")) + (error "C is a compiled language -- no support for sessions")) -(defun org-babel-load-session:C (session body params) +(defun org-babel-load-session:C (_session _body _params) "This function does nothing as C is a compiled language with no support for sessions" - (error "C is a compiled languages -- no support for sessions")) + (error "C is a compiled language -- no support for sessions")) ;; helper functions @@ -177,58 +299,79 @@ support for sessions" "Determine the type of VAL. Return a list (TYPE-NAME FORMAT). TYPE-NAME should be the name of the type. FORMAT can be either a format string or a function which is called with VAL." + (let* ((basetype (org-babel-C-val-to-base-type val)) + (type + (pcase basetype + (`integerp '("int" "%d")) + (`floatp '("double" "%f")) + (`stringp + (list + (if (eq org-babel-c-variant 'd) "string" "const char*") + "\"%s\"")) + (_ (error "unknown type %S" basetype))))) + (cond + ((integerp val) type) ;; an integer declared in the #+begin_src line + ((floatp val) type) ;; a numeric declared in the #+begin_src line + ((and (listp val) (listp (car val))) ;; a table + `(,(car type) + (lambda (val) + (cons + (format "[%d][%d]" (length val) (length (car val))) + (concat + (if (eq org-babel-c-variant 'd) "[\n" "{\n") + (mapconcat + (lambda (v) + (concat + (if (eq org-babel-c-variant 'd) " [" " {") + (mapconcat (lambda (w) (format ,(cadr type) w)) v ",") + (if (eq org-babel-c-variant 'd) "]" "}"))) + val + ",\n") + (if (eq org-babel-c-variant 'd) "\n]" "\n}")))))) + ((or (listp val) (vectorp val)) ;; a list declared in the #+begin_src line + `(,(car type) + (lambda (val) + (cons + (format "[%d]" (length val)) + (concat + (if (eq org-babel-c-variant 'd) "[" "{") + (mapconcat (lambda (v) (format ,(cadr type) v)) val ",") + (if (eq org-babel-c-variant 'd) "]" "}")))))) + (t ;; treat unknown types as string + type)))) + +(defun org-babel-C-val-to-base-type (val) + "Determine the base type of VAL which may be +`integerp' if all base values are integers +`floatp' if all base values are either floating points or integers +`stringp' otherwise." (cond - ((integerp val) '("int" "%d")) - ((floatp val) '("double" "%f")) + ((integerp val) 'integerp) + ((floatp val) 'floatp) ((or (listp val) (vectorp val)) - (lexical-let ((type (org-babel-C-val-to-C-list-type val))) - (list (car type) - (lambda (val) - (cons - (format "[%d]%s" - (length val) - (car (org-babel-C-format-val type (elt val 0)))) - (concat "{ " - (mapconcat (lambda (v) - (cdr (org-babel-C-format-val type v))) - val - ", ") - " }")))))) - (t ;; treat unknown types as string - '("char" (lambda (val) - (let ((s (format "%s" val))) ;; convert to string for unknown types - (cons (format "[%d]" (1+ (length s))) - (concat "\"" s "\"")))))))) - -(defun org-babel-C-val-to-C-list-type (val) - "Determine the C array type of a VAL." - (let (type) - (mapc - #'(lambda (i) - (let* ((tmp-type (org-babel-C-val-to-C-type i)) - (type-name (car type)) - (tmp-type-name (car tmp-type))) - (when (and type (not (string= type-name tmp-type-name))) - (if (and (member type-name '("int" "double" "int32_t")) - (member tmp-type-name '("int" "double" "int32_t"))) - (setq tmp-type '("double" "" "%f")) - (error "Only homogeneous lists are supported by C. You can not mix %s and %s" - type-name - tmp-type-name))) - (setq type tmp-type))) - val) - type)) + (let ((type nil)) + (mapc (lambda (v) + (pcase (org-babel-C-val-to-base-type v) + (`stringp (setq type 'stringp)) + (`floatp + (if (or (not type) (eq type 'integerp)) + (setq type 'floatp))) + (`integerp + (unless type (setq type 'integerp))))) + val) + type)) + (t 'stringp))) (defun org-babel-C-var-to-C (pair) "Convert an elisp val into a string of C code specifying a var of the same value." ;; TODO list support (let ((var (car pair)) - (val (cdr pair))) + (val (cdr pair))) (when (symbolp val) (setq val (symbol-name val)) (when (= (length val) 1) - (setq val (string-to-char val)))) + (setq val (string-to-char val)))) (let* ((type-data (org-babel-C-val-to-C-type val)) (type (car type-data)) (formated (org-babel-C-format-val type-data val)) @@ -240,6 +383,66 @@ of the same value." suffix data)))) +(defun org-babel-C-table-sizes-to-C (pair) + "Create constants of table dimensions, if PAIR is a table." + (when (listp (cdr pair)) + (cond + ((listp (cadr pair)) ;; a table + (concat + (format "const int %s_rows = %d;" (car pair) (length (cdr pair))) + "\n" + (format "const int %s_cols = %d;" (car pair) (length (cadr pair))))) + (t ;; a list declared in the #+begin_src line + (format "const int %s_cols = %d;" (car pair) (length (cdr pair))))))) + +(defun org-babel-C-utility-header-to-C () + "Generate a utility function to convert a column name +into a column number." + (pcase org-babel-c-variant + ((or `c `cpp) + "int get_column_num (int nbcols, const char** header, const char* column) +{ + int c; + for (c=0; c. + +;;; Commentary: + +;; Org-Babel support for evaluating J code. +;; +;; Session interaction depends on `j-console' from package `j-mode' +;; (available in MELPA). + +;;; Code: + +(require 'ob) + +(declare-function org-trim "org" (s &optional keep-lead)) +(declare-function j-console-ensure-session "ext:j-console" ()) + +(defcustom org-babel-J-command "jconsole" + "Command to call J." + :group 'org-babel + :version "26.1" + :package-version '(Org . "9.0") + :type 'string) + +(defun org-babel-expand-body:J (body _params &optional _processed-params) + "Expand BODY according to PARAMS, return the expanded body. +PROCESSED-PARAMS isn't used yet." + (org-babel-J-interleave-echos-except-functions body)) + +(defun org-babel-J-interleave-echos (body) + "Interleave echo',' between each source line of BODY." + (mapconcat #'identity (split-string body "\n") "\necho','\n")) + +(defun org-babel-J-interleave-echos-except-functions (body) + "Interleave echo',' between source lines of BODY that aren't functions." + (if (obj-string-match-m "\\(?:^\\|\n\\)[^\n]*\\(?:0\\|1\\|2\\|3\\|4\\|dyad\\) : 0\n.*\n)\\(?:\n\\|$\\)" body) + (let ((s1 (substring body 0 (match-beginning 0))) + (s2 (match-string 0 body)) + (s3 (substring body (match-end 0)))) + (concat + (if (string= s1 "") + "" + (concat (org-babel-J-interleave-echos s1) + "\necho','\n")) + s2 + "\necho','\n" + (org-babel-J-interleave-echos-except-functions s3))) + (org-babel-J-interleave-echos body))) + +(defalias 'org-babel-execute:j 'org-babel-execute:J) + +(defun org-babel-execute:J (body params) + "Execute a block of J code BODY. +PARAMS are given by org-babel. +This function is called by `org-babel-execute-src-block'" + (message "executing J source code block") + (let* ((processed-params (org-babel-process-params params)) + (sessionp (cdr (assq :session params))) + (full-body (org-babel-expand-body:J + body params processed-params)) + (tmp-script-file (org-babel-temp-file "J-src"))) + (org-babel-j-initiate-session sessionp) + (org-babel-J-strip-whitespace + (if (string= sessionp "none") + (progn + (with-temp-file tmp-script-file + (insert full-body)) + (org-babel-eval (format "%s < %s" org-babel-J-command tmp-script-file) "")) + (org-babel-J-eval-string full-body))))) + +(defun org-babel-J-eval-string (str) + "Sends STR to the `j-console-cmd' session and executes it." + (let ((session (j-console-ensure-session))) + (with-current-buffer (process-buffer session) + (goto-char (point-max)) + (insert (format "\n%s\n" str)) + (let ((beg (point))) + (comint-send-input) + (sit-for .1) + (buffer-substring-no-properties + beg (point-max)))))) + +(defun org-babel-J-strip-whitespace (str) + "Remove whitespace from jconsole output STR." + (mapconcat + #'identity + (delete "" (mapcar + #'org-babel-J-print-block + (split-string str "^ *,\n" t))) + "\n\n")) + +(defun obj-get-string-alignment (str) + "Return a number to describe STR alignment. +STR represents a table. +Positive/negative/zero result means right/left/undetermined. +Don't trust first line." + (let* ((str (org-trim str)) + (lines (split-string str "\n" t)) + n1 n2) + (cond ((<= (length lines) 1) + 0) + ((= (length lines) 2) + ;; numbers are right-aligned + (if (and + (numberp (read (car lines))) + (numberp (read (cadr lines))) + (setq n1 (obj-match-second-space-right (nth 0 lines))) + (setq n2 (obj-match-second-space-right (nth 1 lines)))) + n2 + 0)) + ((not (obj-match-second-space-left (nth 0 lines))) + 0) + ((and + (setq n1 (obj-match-second-space-left (nth 1 lines))) + (setq n2 (obj-match-second-space-left (nth 2 lines))) + (= n1 n2)) + n1) + ((and + (setq n1 (obj-match-second-space-right (nth 1 lines))) + (setq n2 (obj-match-second-space-right (nth 2 lines))) + (= n1 n2)) + (- n1)) + (t 0)))) + +(defun org-babel-J-print-block (x) + "Prettify jconsole output X." + (let* ((x (org-trim x)) + (a (obj-get-string-alignment x)) + (lines (split-string x "\n" t)) + b) + (cond ((< a 0) + (setq b (obj-match-second-space-right (nth 0 lines))) + (concat (make-string (+ a b) ? ) x)) + ((> a 0) + (setq b (obj-match-second-space-left (nth 0 lines))) + (concat (make-string (- a b) ? ) x)) + (t x)))) + +(defun obj-match-second-space-left (s) + "Return position of leftmost space in second space block of S or nil." + (and (string-match "^ *[^ ]+\\( \\)" s) + (match-beginning 1))) + +(defun obj-match-second-space-right (s) + "Return position of rightmost space in second space block of S or nil." + (and (string-match "^ *[^ ]+ *\\( \\)[^ ]" s) + (match-beginning 1))) + +(defun obj-string-match-m (regexp string &optional start) + "Call (string-match REGEXP STRING START). +REGEXP is modified so that .* matches newlines as well." + (string-match + (replace-regexp-in-string "\\.\\*" "[\0-\377[:nonascii:]]*" regexp) + string + start)) + +(defun org-babel-j-initiate-session (&optional session) + "Initiate a J session. +SESSION is a parameter given by org-babel." + (unless (string= session "none") + (require 'j-console) + (j-console-ensure-session))) + +(provide 'ob-J) + +;;; ob-J.el ends here diff --git a/lisp/org/ob-R.el b/lisp/org/ob-R.el index 51d342702ce..3accade49f5 100644 --- a/lisp/org/ob-R.el +++ b/lisp/org/ob-R.el @@ -1,4 +1,4 @@ -;;; ob-R.el --- org-babel functions for R code evaluation +;;; ob-R.el --- Babel Functions for R -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -27,16 +27,17 @@ ;; Org-Babel support for evaluating R code ;;; Code: + +(require 'cl-lib) (require 'ob) -(eval-when-compile (require 'cl)) (declare-function orgtbl-to-tsv "org-table" (table params)) (declare-function R "ext:essd-r" (&optional start-args)) (declare-function inferior-ess-send-input "ext:ess-inf" ()) (declare-function ess-make-buffer-current "ext:ess-inf" ()) (declare-function ess-eval-buffer "ext:ess-inf" (vis)) -(declare-function org-number-sequence "org-compat" (from &optional to inc)) -(declare-function org-remove-if-not "org" (predicate seq)) +(declare-function ess-wait-for-process "ext:ess-inf" + (&optional proc sec-prompt wait force-redisplay)) (defconst org-babel-header-args:R '((width . :any) @@ -60,12 +61,25 @@ (useDingbats . :any) (horizontal . :any) (results . ((file list vector table scalar verbatim) - (raw org html latex code pp wrap) - (replace silent append prepend) + (raw html latex org code pp drawer) + (replace silent none append prepend) (output value graphics)))) "R-specific header arguments.") +(defconst ob-R-safe-header-args + (append org-babel-safe-header-args + '(:width :height :bg :units :pointsize :antialias :quality + :compression :res :type :family :title :fonts + :version :paper :encoding :pagecentre :colormodel + :useDingbats :horizontal)) + "Header args which are safe for R babel blocks. + +See `org-babel-safe-header-args' for documentation of the format of +this variable.") + (defvar org-babel-default-header-args:R '()) +(put 'org-babel-default-header-args:R 'safe-local-variable + (org-babel-header-args-safe-fn ob-R-safe-header-args)) (defcustom org-babel-R-command "R --slave --no-save" "Name of command to use for executing R code." @@ -73,56 +87,103 @@ :version "24.1" :type 'string) -(defvar ess-local-process-name) ; dynamically scoped +(defvar ess-current-process-name) ; dynamically scoped +(defvar ess-local-process-name) ; dynamically scoped (defun org-babel-edit-prep:R (info) - (let ((session (cdr (assoc :session (nth 2 info))))) - (when (and session (string-match "^\\*\\(.+?\\)\\*$" session)) - (save-match-data (org-babel-R-initiate-session session nil))))) - -(defun org-babel-expand-body:R (body params &optional graphics-file) + (let ((session (cdr (assq :session (nth 2 info))))) + (when (and session + (string-prefix-p "*" session) + (string-suffix-p "*" session)) + (org-babel-R-initiate-session session nil)))) + +;; The usage of utils::read.table() ensures that the command +;; read.table() can be found even in circumstances when the utils +;; package is not in the search path from R. +(defconst ob-R-transfer-variable-table-with-header + "%s <- local({ + con <- textConnection( + %S + ) + res <- utils::read.table( + con, + header = %s, + row.names = %s, + sep = \"\\t\", + as.is = TRUE + ) + close(con) + res + })" + "R code used to transfer a table defined as a variable from org to R. + +This function is used when the table contains a header.") + +(defconst ob-R-transfer-variable-table-without-header + "%s <- local({ + con <- textConnection( + %S + ) + res <- utils::read.table( + con, + header = %s, + row.names = %s, + sep = \"\\t\", + as.is = TRUE, + fill = TRUE, + col.names = paste(\"V\", seq_len(%d), sep =\"\") + ) + close(con) + res + })" + "R code used to transfer a table defined as a variable from org to R. + +This function is used when the table does not contain a header.") + +(defun org-babel-expand-body:R (body params &optional _graphics-file) "Expand BODY according to PARAMS, return the expanded body." - (let ((graphics-file - (or graphics-file (org-babel-R-graphical-output-file params)))) - (mapconcat - #'identity - (let ((inside - (append - (when (cdr (assoc :prologue params)) - (list (cdr (assoc :prologue params)))) - (org-babel-variable-assignments:R params) - (list body) - (when (cdr (assoc :epilogue params)) - (list (cdr (assoc :epilogue params))))))) - (if graphics-file - (append - (list (org-babel-R-construct-graphics-device-call - graphics-file params)) - inside - (list "dev.off()")) - inside)) - "\n"))) + (mapconcat 'identity + (append + (when (cdr (assq :prologue params)) + (list (cdr (assq :prologue params)))) + (org-babel-variable-assignments:R params) + (list body) + (when (cdr (assq :epilogue params)) + (list (cdr (assq :epilogue params))))) + "\n")) (defun org-babel-execute:R (body params) "Execute a block of R code. This function is called by `org-babel-execute-src-block'." (save-excursion - (let* ((result-params (cdr (assoc :result-params params))) - (result-type (cdr (assoc :result-type params))) + (let* ((result-params (cdr (assq :result-params params))) + (result-type (cdr (assq :result-type params))) (session (org-babel-R-initiate-session - (cdr (assoc :session params)) params)) - (colnames-p (cdr (assoc :colnames params))) - (rownames-p (cdr (assoc :rownames params))) - (graphics-file (org-babel-R-graphical-output-file params)) - (full-body (org-babel-expand-body:R body params graphics-file)) + (cdr (assq :session params)) params)) + (colnames-p (cdr (assq :colnames params))) + (rownames-p (cdr (assq :rownames params))) + (graphics-file (and (member "graphics" (assq :result-params params)) + (org-babel-graphical-output-file params))) + (full-body + (let ((inside + (list (org-babel-expand-body:R body params graphics-file)))) + (mapconcat 'identity + (if graphics-file + (append + (list (org-babel-R-construct-graphics-device-call + graphics-file params)) + inside + (list "},error=function(e){plot(x=-1:1, y=-1:1, type='n', xlab='', ylab='', axes=FALSE); text(x=0, y=0, labels=e$message, col='red'); paste('ERROR', e$message, sep=' : ')}); dev.off()")) + inside) + "\n"))) (result (org-babel-R-evaluate session full-body result-type result-params (or (equal "yes" colnames-p) (org-babel-pick-name - (cdr (assoc :colname-names params)) colnames-p)) + (cdr (assq :colname-names params)) colnames-p)) (or (equal "yes" rownames-p) (org-babel-pick-name - (cdr (assoc :rowname-names params)) rownames-p))))) + (cdr (assq :rowname-names params)) rownames-p))))) (if graphics-file nil result)))) (defun org-babel-prep-session:R (session params) @@ -148,21 +209,21 @@ This function is called by `org-babel-execute-src-block'." (defun org-babel-variable-assignments:R (params) "Return list of R statements assigning the block's variables." - (let ((vars (mapcar #'cdr (org-babel-get-header params :var)))) + (let ((vars (org-babel--get-vars params))) (mapcar (lambda (pair) (org-babel-R-assign-elisp (car pair) (cdr pair) - (equal "yes" (cdr (assoc :colnames params))) - (equal "yes" (cdr (assoc :rownames params))))) + (equal "yes" (cdr (assq :colnames params))) + (equal "yes" (cdr (assq :rownames params))))) (mapcar (lambda (i) (cons (car (nth i vars)) (org-babel-reassemble-table (cdr (nth i vars)) - (cdr (nth i (cdr (assoc :colname-names params)))) - (cdr (nth i (cdr (assoc :rowname-names params))))))) - (org-number-sequence 0 (1- (length vars))))))) + (cdr (nth i (cdr (assq :colname-names params)))) + (cdr (nth i (cdr (assq :rowname-names params))))))) + (number-sequence 0 (1- (length vars))))))) (defun org-babel-R-quote-tsv-field (s) "Quote field S for export to R." @@ -173,35 +234,25 @@ This function is called by `org-babel-execute-src-block'." (defun org-babel-R-assign-elisp (name value colnames-p rownames-p) "Construct R code assigning the elisp VALUE to a variable named NAME." (if (listp value) - (let* ((lengths (mapcar 'length (org-remove-if-not 'sequencep value))) + (let* ((lengths (mapcar 'length (cl-remove-if-not 'sequencep value))) (max (if lengths (apply 'max lengths) 0)) - (min (if lengths (apply 'min lengths) 0)) - (transition-file (org-babel-temp-file "R-import-"))) + (min (if lengths (apply 'min lengths) 0))) ;; Ensure VALUE has an orgtbl structure (depth of at least 2). (unless (listp (car value)) (setq value (list value))) - (with-temp-file transition-file - (insert - (orgtbl-to-tsv value '(:fmt org-babel-R-quote-tsv-field)) - "\n")) - (let ((file (org-babel-process-file-name transition-file 'noquote)) + (let ((file (orgtbl-to-tsv value '(:fmt org-babel-R-quote-tsv-field))) (header (if (or (eq (nth 1 value) 'hline) colnames-p) "TRUE" "FALSE")) (row-names (if rownames-p "1" "NULL"))) (if (= max min) - (format "%s <- read.table(\"%s\", - header=%s, - row.names=%s, - sep=\"\\t\", - as.is=TRUE)" name file header row-names) - (format "%s <- read.table(\"%s\", - header=%s, - row.names=%s, - sep=\"\\t\", - as.is=TRUE, - fill=TRUE, - col.names = paste(\"V\", seq_len(%d), sep =\"\"))" + (format ob-R-transfer-variable-table-with-header + name file header row-names) + (format ob-R-transfer-variable-table-without-header name file header row-names max)))) - (format "%s <- %s" name (org-babel-R-quote-tsv-field value)))) + (cond ((integerp value) (format "%s <- %s" name (concat (number-to-string value) "L"))) + ((floatp value) (format "%s <- %s" name value)) + ((stringp value) (format "%s <- %S" name (org-no-properties value))) + (t (format "%s <- %S" name (prin1-to-string value)))))) + (defvar ess-ask-for-ess-directory) ; dynamically scoped (defun org-babel-R-initiate-session (session params) @@ -209,8 +260,9 @@ This function is called by `org-babel-execute-src-block'." (unless (string= session "none") (let ((session (or session "*R*")) (ess-ask-for-ess-directory - (and (and (boundp 'ess-ask-for-ess-directory) ess-ask-for-ess-directory) - (not (cdr (assoc :dir params)))))) + (and (boundp 'ess-ask-for-ess-directory) + ess-ask-for-ess-directory + (not (cdr (assq :dir params)))))) (if (org-babel-comint-buffer-livep session) session (save-window-excursion @@ -218,6 +270,10 @@ This function is called by `org-babel-execute-src-block'." ;; Session buffer exists, but with dead process (set-buffer session)) (require 'ess) (R) + (let ((R-proc (get-process (or ess-local-process-name + ess-current-process-name)))) + (while (process-get R-proc 'callbacks) + (ess-wait-for-process R-proc))) (rename-buffer (if (bufferp session) (buffer-name session) @@ -234,11 +290,6 @@ current code buffer." (process-name (get-buffer-process session))) (ess-make-buffer-current)) -(defun org-babel-R-graphical-output-file (params) - "Name of file to which R should send graphical output." - (and (member "graphics" (cdr (assq :result-params params))) - (cdr (assq :file params)))) - (defvar org-babel-R-graphics-devices '((:bmp "bmp" "filename") (:jpg "jpeg" "filename") @@ -265,8 +316,7 @@ Each member of this list is a list with three members: :type :family :title :fonts :version :paper :encoding :pagecentre :colormodel :useDingbats :horizontal)) - (device (and (string-match ".+\\.\\([^.]+\\)" out-file) - (match-string 1 out-file))) + (device (file-name-extension out-file)) (device-info (or (assq (intern (concat ":" device)) org-babel-R-graphics-devices) (assq :png org-babel-R-graphics-devices))) @@ -280,14 +330,43 @@ Each member of this list is a list with three members: (substring (symbol-name (car pair)) 1) (cdr pair)) "")) params "")) - (format "%s(%s=\"%s\"%s%s%s)" + (format "%s(%s=\"%s\"%s%s%s); tryCatch({" device filearg out-file args (if extra-args "," "") (or extra-args "")))) -(defvar org-babel-R-eoe-indicator "'org_babel_R_eoe'") -(defvar org-babel-R-eoe-output "[1] \"org_babel_R_eoe\"") - -(defvar org-babel-R-write-object-command "{function(object,transfer.file){object;invisible(if(inherits(try({tfile<-tempfile();write.table(object,file=tfile,sep=\"\\t\",na=\"nil\",row.names=%s,col.names=%s,quote=FALSE);file.rename(tfile,transfer.file)},silent=TRUE),\"try-error\")){if(!file.exists(transfer.file))file.create(transfer.file)})}}(object=%s,transfer.file=\"%s\")") +(defconst org-babel-R-eoe-indicator "'org_babel_R_eoe'") +(defconst org-babel-R-eoe-output "[1] \"org_babel_R_eoe\"") + +(defconst org-babel-R-write-object-command "{ + function(object,transfer.file) { + object + invisible( + if ( + inherits( + try( + { + tfile<-tempfile() + write.table(object, file=tfile, sep=\"\\t\", + na=\"nil\",row.names=%s,col.names=%s, + quote=FALSE) + file.rename(tfile,transfer.file) + }, + silent=TRUE), + \"try-error\")) + { + if(!file.exists(transfer.file)) + file.create(transfer.file) + } + ) + } +}(object=%s,transfer.file=\"%s\")" + "A template for an R command to evaluate a block of code and write the result to a file. + +Has four %s escapes to be filled in: +1. Row names, \"TRUE\" or \"FALSE\" +2. Column names, \"TRUE\" or \"FALSE\" +3. The code to be run (must be an expression, not a statement) +4. The name of the file to write to") (defun org-babel-R-evaluate (session body result-type result-params column-names-p row-names-p) @@ -299,12 +378,12 @@ Each member of this list is a list with three members: body result-type result-params column-names-p row-names-p))) (defun org-babel-R-evaluate-external-process - (body result-type result-params column-names-p row-names-p) + (body result-type result-params column-names-p row-names-p) "Evaluate BODY in external R process. -If RESULT-TYPE equals 'output then return standard output as a -string. If RESULT-TYPE equals 'value then return the value of the +If RESULT-TYPE equals `output' then return standard output as a +string. If RESULT-TYPE equals `value' then return the value of the last statement in BODY, as elisp." - (case result-type + (cl-case result-type (value (let ((tmp-file (org-babel-temp-file "R-"))) (org-babel-eval org-babel-R-command @@ -319,7 +398,7 @@ last statement in BODY, as elisp." (org-babel-result-cond result-params (with-temp-buffer (insert-file-contents tmp-file) - (buffer-string)) + (org-babel-chomp (buffer-string) "\n")) (org-babel-import-elisp-from-file tmp-file '(16))) column-names-p))) (output (org-babel-eval org-babel-R-command body)))) @@ -327,12 +406,12 @@ last statement in BODY, as elisp." (defvar ess-eval-visibly-p) (defun org-babel-R-evaluate-session - (session body result-type result-params column-names-p row-names-p) + (session body result-type result-params column-names-p row-names-p) "Evaluate BODY in SESSION. -If RESULT-TYPE equals 'output then return standard output as a -string. If RESULT-TYPE equals 'value then return the value of the +If RESULT-TYPE equals `output' then return standard output as a +string. If RESULT-TYPE equals `value' then return the value of the last statement in BODY, as elisp." - (case result-type + (cl-case result-type (value (with-temp-buffer (insert (org-babel-chomp body)) @@ -353,12 +432,12 @@ last statement in BODY, as elisp." (org-babel-result-cond result-params (with-temp-buffer (insert-file-contents tmp-file) - (buffer-string)) + (org-babel-chomp (buffer-string) "\n")) (org-babel-import-elisp-from-file tmp-file '(16))) column-names-p))) (output (mapconcat - #'org-babel-chomp + 'org-babel-chomp (butlast (delq nil (mapcar @@ -366,11 +445,12 @@ last statement in BODY, as elisp." (mapcar (lambda (line) ;; cleanup extra prompts left in output (if (string-match - "^\\([ ]*[>+\\.][ ]?\\)+\\([[0-9]+\\|[ ]\\)" line) + "^\\([>+.]\\([ ][>.+]\\)*[ ]\\)" + (car (split-string line "\n"))) (substring line (match-end 1)) line)) (org-babel-comint-with-output (session org-babel-R-eoe-output) - (insert (mapconcat #'org-babel-chomp + (insert (mapconcat 'org-babel-chomp (list body org-babel-R-eoe-indicator) "\n")) (inferior-ess-send-input)))))) "\n")))) diff --git a/lisp/org/ob-abc.el b/lisp/org/ob-abc.el new file mode 100644 index 00000000000..9fbe35b7d83 --- /dev/null +++ b/lisp/org/ob-abc.el @@ -0,0 +1,90 @@ +;;; ob-abc.el --- Org Babel Functions for ABC -*- lexical-binding: t; -*- + +;; Copyright (C) 2013-2017 Free Software Foundation, Inc. + +;; Author: William Waites +;; Keywords: literate programming, music +;; Homepage: http://www.tardis.ed.ac.uk/wwaites +;; Version: 0.01 + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;;; This file adds support to Org Babel for music in ABC notation. +;;; It requires that the abcm2ps program is installed. +;;; See http://moinejf.free.fr/ + +(require 'ob) + +;; optionally define a file extension for this language +(add-to-list 'org-babel-tangle-lang-exts '("abc" . "abc")) + +;; optionally declare default header arguments for this language +(defvar org-babel-default-header-args:abc + '((:results . "file") (:exports . "results")) + "Default arguments to use when evaluating an ABC source block.") + +(defun org-babel-expand-body:abc (body params) + "Expand BODY according to PARAMS, return the expanded body." + (let ((vars (org-babel--get-vars params))) + (mapc + (lambda (pair) + (let ((name (symbol-name (car pair))) + (value (cdr pair))) + (setq body + (replace-regexp-in-string + (concat "\$" (regexp-quote name)) + (if (stringp value) value (format "%S" value)) + body)))) + vars) + body)) + +(defun org-babel-execute:abc (body params) + "Execute a block of ABC code with org-babel. This function is + called by `org-babel-execute-src-block'" + (message "executing Abc source code block") + (let* ((cmdline (cdr (assq :cmdline params))) + (out-file (let ((file (cdr (assq :file params)))) + (if file (replace-regexp-in-string "\.pdf$" ".ps" file) + (error "abc code block requires :file header argument")))) + (in-file (org-babel-temp-file "abc-")) + (render (concat "abcm2ps" " " cmdline + " -O " (org-babel-process-file-name out-file) + " " (org-babel-process-file-name in-file)))) + (with-temp-file in-file (insert (org-babel-expand-body:abc body params))) + (org-babel-eval render "") + ;;; handle where abcm2ps changes the file name (to support multiple files + (when (or (string= (file-name-extension out-file) "eps") + (string= (file-name-extension out-file) "svg")) + (rename-file (concat + (file-name-sans-extension out-file) "001." + (file-name-extension out-file)) + out-file t)) + ;;; if we were asked for a pdf... + (when (string= (file-name-extension (cdr (assq :file params))) "pdf") + (org-babel-eval (concat "ps2pdf" " " out-file " " (cdr (assq :file params))) "")) + ;;; indicate that the file has been written + nil)) + +;; This function should be used to assign any variables in params in +;; the context of the session environment. +(defun org-babel-prep-session:abc (_session _params) + "Return an error because abc does not support sessions." + (error "ABC does not support sessions")) + +(provide 'ob-abc) +;;; ob-abc.el ends here diff --git a/lisp/org/ob-asymptote.el b/lisp/org/ob-asymptote.el index e3b73c19ac9..1dbf48427f9 100644 --- a/lisp/org/ob-asymptote.el +++ b/lisp/org/ob-asymptote.el @@ -1,4 +1,4 @@ -;;; ob-asymptote.el --- org-babel functions for asymptote evaluation +;;; ob-asymptote.el --- Babel Functions for Asymptote -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -43,11 +43,6 @@ ;;; Code: (require 'ob) -(eval-when-compile (require 'cl)) - -(declare-function orgtbl-to-generic "org-table" - (table params &optional backend)) -(declare-function org-combine-plists "org" (&rest plists)) (defvar org-babel-tangle-lang-exts) (add-to-list 'org-babel-tangle-lang-exts '("asymptote" . "asy")) @@ -59,13 +54,10 @@ (defun org-babel-execute:asymptote (body params) "Execute a block of Asymptote code. This function is called by `org-babel-execute-src-block'." - (let* ((result-params (split-string (or (cdr (assoc :results params)) ""))) - (out-file (cdr (assoc :file params))) - (format (or (and out-file - (string-match ".+\\.\\(.+\\)" out-file) - (match-string 1 out-file)) + (let* ((out-file (cdr (assq :file params))) + (format (or (file-name-extension out-file) "pdf")) - (cmdline (cdr (assoc :cmdline params))) + (cmdline (cdr (assq :cmdline params))) (in-file (org-babel-temp-file "asymptote-")) (cmd (concat "asy " @@ -83,7 +75,7 @@ This function is called by `org-babel-execute-src-block'." (message cmd) (shell-command cmd) nil)) ;; signal that output has already been written to file -(defun org-babel-prep-session:asymptote (session params) +(defun org-babel-prep-session:asymptote (_session _params) "Return an error if the :session header argument is set. Asymptote does not support sessions" (error "Asymptote does not support sessions")) @@ -91,7 +83,7 @@ Asymptote does not support sessions" (defun org-babel-variable-assignments:asymptote (params) "Return list of asymptote statements assigning the block's variables." (mapcar #'org-babel-asymptote-var-to-asymptote - (mapcar #'cdr (org-babel-get-header params :var)))) + (org-babel--get-vars params))) (defun org-babel-asymptote-var-to-asymptote (pair) "Convert an elisp value into an Asymptote variable. @@ -128,21 +120,17 @@ a variable of the same value." DATA is a list. Return type as a symbol. -The type is `string' if any element in DATA is -a string. Otherwise, it is either `real', if some elements are -floats, or `int'." - (let* ((type 'int) - find-type ; for byte-compiler - (find-type - (function - (lambda (row) - (catch 'exit - (mapc (lambda (el) - (cond ((listp el) (funcall find-type el)) - ((stringp el) (throw 'exit (setq type 'string))) - ((floatp el) (setq type 'real)))) - row)))))) - (funcall find-type data) type)) +The type is `string' if any element in DATA is a string. +Otherwise, it is either `real', if some elements are floats, or +`int'." + (letrec ((type 'int) + (find-type + (lambda (row) + (dolist (e row type) + (cond ((listp e) (setq type (funcall find-type e))) + ((stringp e) (throw 'exit 'string)) + ((floatp e) (setq type 'real))))))) + (catch 'exit (funcall find-type data)) type)) (provide 'ob-asymptote) diff --git a/lisp/org/ob-awk.el b/lisp/org/ob-awk.el index c2ac5cac3bf..2db4eeae946 100644 --- a/lisp/org/ob-awk.el +++ b/lisp/org/ob-awk.el @@ -1,4 +1,4 @@ -;;; ob-awk.el --- org-babel functions for awk evaluation +;;; ob-awk.el --- Babel Functions for Awk -*- lexical-binding: t; -*- ;; Copyright (C) 2011-2017 Free Software Foundation, Inc. @@ -27,17 +27,15 @@ ;; ;; - :in-file takes a path to a file of data to be processed by awk ;; -;; - :stdin takes an Org-mode data or code block reference, the value -;; of which will be passed to the awk process through STDIN +;; - :stdin takes an Org data or code block reference, the value of +;; which will be passed to the awk process through STDIN ;;; Code: (require 'ob) (require 'org-compat) -(eval-when-compile (require 'cl)) (declare-function org-babel-ref-resolve "ob-ref" (ref)) -(declare-function orgtbl-to-generic "org-table" - (table params &optional backend)) +(declare-function orgtbl-to-generic "org-table" (table params)) (defvar org-babel-tangle-lang-exts) (add-to-list 'org-babel-tangle-lang-exts '("awk" . "awk")) @@ -45,34 +43,38 @@ (defvar org-babel-awk-command "awk" "Name of the awk executable command.") -(defun org-babel-expand-body:awk (body params) +(defun org-babel-expand-body:awk (body _params) "Expand BODY according to PARAMS, return the expanded body." - (dolist (pair (mapcar #'cdr (org-babel-get-header params :var))) - (setf body (replace-regexp-in-string - (regexp-quote (format "$%s" (car pair))) (cdr pair) body))) body) (defun org-babel-execute:awk (body params) "Execute a block of Awk code with org-babel. This function is called by `org-babel-execute-src-block'" (message "executing Awk source code block") - (let* ((result-params (cdr (assoc :result-params params))) - (cmd-line (cdr (assoc :cmd-line params))) - (in-file (cdr (assoc :in-file params))) + (let* ((result-params (cdr (assq :result-params params))) + (cmd-line (cdr (assq :cmd-line params))) + (in-file (cdr (assq :in-file params))) (full-body (org-babel-expand-body:awk body params)) (code-file (let ((file (org-babel-temp-file "awk-"))) (with-temp-file file (insert full-body)) file)) - (stdin (let ((stdin (cdr (assoc :stdin params)))) + (stdin (let ((stdin (cdr (assq :stdin params)))) (when stdin (let ((tmp (org-babel-temp-file "awk-stdin-")) (res (org-babel-ref-resolve stdin))) (with-temp-file tmp (insert (org-babel-awk-var-to-awk res))) tmp)))) - (cmd (mapconcat #'identity (remove nil (list org-babel-awk-command - "-f" code-file - cmd-line - in-file)) + (cmd (mapconcat #'identity + (append + (list org-babel-awk-command + "-f" code-file cmd-line) + (mapcar (lambda (pair) + (format "-v %s='%s'" + (car pair) + (org-babel-awk-var-to-awk + (cdr pair)))) + (org-babel--get-vars params)) + (list in-file)) " "))) (org-babel-reassemble-table (let ((results @@ -88,9 +90,9 @@ called by `org-babel-execute-src-block'" (with-temp-file tmp (insert results)) (org-babel-import-elisp-from-file tmp))))) (org-babel-pick-name - (cdr (assoc :colname-names params)) (cdr (assoc :colnames params))) + (cdr (assq :colname-names params)) (cdr (assq :colnames params))) (org-babel-pick-name - (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params)))))) + (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))) (defun org-babel-awk-var-to-awk (var &optional sep) "Return a printed value of VAR suitable for parsing with awk." @@ -102,11 +104,6 @@ called by `org-babel-execute-src-block'" (mapconcat echo-var var "\n")) (t (funcall echo-var var))))) -(defun org-babel-awk-table-or-string (results) - "If the results look like a table, then convert them into an -Emacs-lisp table, otherwise return the results as a string." - (org-babel-script-escape results)) - (provide 'ob-awk) diff --git a/lisp/org/ob-calc.el b/lisp/org/ob-calc.el index 6298bba522a..d4b7260c57f 100644 --- a/lisp/org/ob-calc.el +++ b/lisp/org/ob-calc.el @@ -1,4 +1,4 @@ -;;; ob-calc.el --- org-babel functions for calc code evaluation +;;; ob-calc.el --- Babel Functions for Calc -*- lexical-binding: t; -*- ;; Copyright (C) 2010-2017 Free Software Foundation, Inc. @@ -28,18 +28,18 @@ ;;; Code: (require 'ob) (require 'calc) -(unless (featurep 'xemacs) - (require 'calc-trail) - (require 'calc-store)) +(require 'calc-trail) +(require 'calc-store) (declare-function calc-store-into "calc-store" (&optional var)) (declare-function calc-recall "calc-store" (&optional var)) (declare-function math-evaluate-expr "calc-ext" (x)) +(declare-function org-trim "org" (s &optional keep-lead)) (defvar org-babel-default-header-args:calc nil "Default arguments for evaluating an calc source block.") -(defun org-babel-expand-body:calc (body params) +(defun org-babel-expand-body:calc (body _params) "Expand BODY according to PARAMS, return the expanded body." body) (defvar org--var-syms) ; Dynamically scoped from org-babel-execute:calc @@ -48,7 +48,7 @@ "Execute a block of calc code with Babel." (unless (get-buffer "*Calculator*") (save-window-excursion (calc) (calc-quit))) - (let* ((vars (mapcar #'cdr (org-babel-get-header params :var))) + (let* ((vars (org-babel--get-vars params)) (org--var-syms (mapcar #'car vars)) (var-names (mapcar #'symbol-name org--var-syms))) (mapc @@ -85,15 +85,17 @@ ;; parse line into calc objects (car (math-read-exprs line))))))))) )))))) - (mapcar #'org-babel-trim + (mapcar #'org-trim (split-string (org-babel-expand-body:calc body params) "[\n\r]")))) (save-excursion (with-current-buffer (get-buffer "*Calculator*") - (calc-eval (calc-top 1))))) + (prog1 + (calc-eval (calc-top 1)) + (calc-pop 1))))) (defun org-babel-calc-maybe-resolve-var (el) (if (consp el) - (if (and (equal 'var (car el)) (member (cadr el) org--var-syms)) + (if (and (eq 'var (car el)) (member (cadr el) org--var-syms)) (progn (calc-recall (cadr el)) (prog1 (calc-top 1) diff --git a/lisp/org/ob-clojure.el b/lisp/org/ob-clojure.el index b9af45adfeb..39561572a59 100644 --- a/lisp/org/ob-clojure.el +++ b/lisp/org/ob-clojure.el @@ -1,9 +1,9 @@ -;;; ob-clojure.el --- org-babel functions for clojure evaluation +;;; ob-clojure.el --- Babel Functions for Clojure -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. -;; Author: Joel Boehland -;; Eric Schulte +;; Author: Joel Boehland, Eric Schulte, Oleh Krehel +;; ;; Keywords: literate programming, reproducible research ;; Homepage: http://orgmode.org @@ -24,21 +24,30 @@ ;;; Commentary: -;; Support for evaluating clojure code, relies on slime for all eval. +;; Support for evaluating clojure code -;;; Requirements: +;; Requirements: ;; - clojure (at least 1.2.0) ;; - clojure-mode -;; - slime +;; - either cider or SLIME -;; By far, the best way to install these components is by following +;; For Cider, see https://github.com/clojure-emacs/cider + +;; For SLIME, the best way to install these components is by following ;; the directions as set out by Phil Hagelberg (Technomancy) on the ;; web page: http://technomancy.us/126 ;;; Code: +(require 'cl-lib) (require 'ob) +(declare-function cider-current-connection "ext:cider-client" (&optional type)) +(declare-function cider-current-session "ext:cider-client" ()) +(declare-function nrepl-dict-get "ext:nrepl-client" (dict key)) +(declare-function nrepl-sync-request:eval "ext:nrepl-client" + (input connection session &optional ns)) +(declare-function org-trim "org" (s &optional keep-lead)) (declare-function slime-eval "ext:slime" (sexp &optional package)) (defvar org-babel-tangle-lang-exts) @@ -47,49 +56,63 @@ (defvar org-babel-default-header-args:clojure '()) (defvar org-babel-header-args:clojure '((package . :any))) +(defcustom org-babel-clojure-backend + (cond ((featurep 'cider) 'cider) + (t 'slime)) + "Backend used to evaluate Clojure code blocks." + :group 'org-babel + :type '(choice + (const :tag "cider" cider) + (const :tag "SLIME" slime))) + (defun org-babel-expand-body:clojure (body params) "Expand BODY according to PARAMS, return the expanded body." - (let* ((vars (mapcar #'cdr (org-babel-get-header params :var))) - (result-params (cdr (assoc :result-params params))) + (let* ((vars (org-babel--get-vars params)) + (result-params (cdr (assq :result-params params))) (print-level nil) (print-length nil) - (body (org-babel-trim - (if (> (length vars) 0) - (concat "(let [" - (mapconcat - (lambda (var) - (format "%S (quote %S)" (car var) (cdr var))) - vars "\n ") - "]\n" body ")") - body)))) - (cond ((or (member "code" result-params) (member "pp" result-params)) - (format (concat "(let [org-mode-print-catcher (java.io.StringWriter.)] " - "(clojure.pprint/with-pprint-dispatch clojure.pprint/%s-dispatch " - "(clojure.pprint/pprint (do %s) org-mode-print-catcher) " - "(str org-mode-print-catcher)))") - (if (member "code" result-params) "code" "simple") body)) - ;; if (:results output), collect printed output - ((member "output" result-params) - (format "(clojure.core/with-out-str %s)" body)) - (t body)))) + (body (org-trim + (if (null vars) (org-trim body) + (concat "(let [" + (mapconcat + (lambda (var) + (format "%S (quote %S)" (car var) (cdr var))) + vars "\n ") + "]\n" body ")"))))) + (if (or (member "code" result-params) + (member "pp" result-params)) + (format "(clojure.pprint/pprint (do %s))" body) + body))) (defun org-babel-execute:clojure (body params) "Execute a block of Clojure code with Babel." - (require 'slime) - (with-temp-buffer - (insert (org-babel-expand-body:clojure body params)) - (let ((result - (slime-eval - `(swank:eval-and-grab-output - ,(buffer-substring-no-properties (point-min) (point-max))) - (cdr (assoc :package params))))) - (let ((result-params (cdr (assoc :result-params params)))) - (org-babel-result-cond result-params - result - (condition-case nil (org-babel-script-escape result) - (error result))))))) + (let ((expanded (org-babel-expand-body:clojure body params)) + result) + (cl-case org-babel-clojure-backend + (cider + (require 'cider) + (let ((result-params (cdr (assq :result-params params)))) + (setq result + (nrepl-dict-get + (nrepl-sync-request:eval + expanded (cider-current-connection) (cider-current-session)) + (if (or (member "output" result-params) + (member "pp" result-params)) + "out" + "value"))))) + (slime + (require 'slime) + (with-temp-buffer + (insert expanded) + (setq result + (slime-eval + `(swank:eval-and-grab-output + ,(buffer-substring-no-properties (point-min) (point-max))) + (cdr (assq :package params))))))) + (org-babel-result-cond (cdr (assq :result-params params)) + result + (condition-case nil (org-babel-script-escape result) + (error result))))) (provide 'ob-clojure) - - ;;; ob-clojure.el ends here diff --git a/lisp/org/ob-comint.el b/lisp/org/ob-comint.el index 78c5021b1b2..cc60f4e4a73 100644 --- a/lisp/org/ob-comint.el +++ b/lisp/org/ob-comint.el @@ -1,4 +1,4 @@ -;;; ob-comint.el --- org-babel functions for interaction with comint buffers +;;; ob-comint.el --- Babel Functions for Interaction with Comint Buffers -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -33,10 +33,7 @@ (require 'ob-core) (require 'org-compat) (require 'comint) -(eval-when-compile (require 'cl)) -(declare-function with-parsed-tramp-file-name "tramp" - (filename var &rest body) t) -(declare-function tramp-flush-directory-property "tramp-cache" (key directory)) +(require 'tramp) (defun org-babel-comint-buffer-livep (buffer) "Check if BUFFER is a comint buffer with a live process." @@ -49,12 +46,14 @@ BUFFER is checked with `org-babel-comint-buffer-livep'. BODY is executed inside the protection of `save-excursion' and `save-match-data'." (declare (indent 1)) - `(save-excursion + `(progn + (unless (org-babel-comint-buffer-livep ,buffer) + (error "Buffer %s does not exist or has no process" ,buffer)) (save-match-data - (unless (org-babel-comint-buffer-livep ,buffer) - (error "Buffer %s does not exist or has no process" ,buffer)) - (set-buffer ,buffer) - ,@body))) + (with-current-buffer ,buffer + (save-excursion + (let ((comint-input-filter (lambda (_input) nil))) + ,@body)))))) (def-edebug-spec org-babel-comint-in-buffer (form body)) (defmacro org-babel-comint-with-output (meta &rest body) @@ -70,53 +69,49 @@ elements are optional. This macro ensures that the filter is removed in case of an error or user `keyboard-quit' during execution of body." (declare (indent 1)) - (let ((buffer (car meta)) - (eoe-indicator (cadr meta)) - (remove-echo (cadr (cdr meta))) - (full-body (cadr (cdr (cdr meta))))) + (let ((buffer (nth 0 meta)) + (eoe-indicator (nth 1 meta)) + (remove-echo (nth 2 meta)) + (full-body (nth 3 meta))) `(org-babel-comint-in-buffer ,buffer - (let ((string-buffer "") dangling-text raw) - ;; setup filter - (setq comint-output-filter-functions + (let* ((string-buffer "") + (comint-output-filter-functions (cons (lambda (text) (setq string-buffer (concat string-buffer text))) comint-output-filter-functions)) - (unwind-protect - (progn - ;; got located, and save dangling text - (goto-char (process-mark (get-buffer-process (current-buffer)))) - (let ((start (point)) - (end (point-max))) - (setq dangling-text (buffer-substring start end)) - (delete-region start end)) - ;; pass FULL-BODY to process - ,@body - ;; wait for end-of-evaluation indicator - (while (progn - (goto-char comint-last-input-end) - (not (save-excursion - (and (re-search-forward - (regexp-quote ,eoe-indicator) nil t) - (re-search-forward - comint-prompt-regexp nil t))))) - (accept-process-output (get-buffer-process (current-buffer))) - ;; thought the following this would allow async - ;; background running, but I was wrong... - ;; (run-with-timer .5 .5 'accept-process-output - ;; (get-buffer-process (current-buffer))) - ) - ;; replace cut dangling text - (goto-char (process-mark (get-buffer-process (current-buffer)))) - (insert dangling-text)) - ;; remove filter - (setq comint-output-filter-functions - (cdr comint-output-filter-functions))) + dangling-text) + ;; got located, and save dangling text + (goto-char (process-mark (get-buffer-process (current-buffer)))) + (let ((start (point)) + (end (point-max))) + (setq dangling-text (buffer-substring start end)) + (delete-region start end)) + ;; pass FULL-BODY to process + ,@body + ;; wait for end-of-evaluation indicator + (while (progn + (goto-char comint-last-input-end) + (not (save-excursion + (and (re-search-forward + (regexp-quote ,eoe-indicator) nil t) + (re-search-forward + comint-prompt-regexp nil t))))) + (accept-process-output (get-buffer-process (current-buffer))) + ;; thought the following this would allow async + ;; background running, but I was wrong... + ;; (run-with-timer .5 .5 'accept-process-output + ;; (get-buffer-process (current-buffer))) + ) + ;; replace cut dangling text + (goto-char (process-mark (get-buffer-process (current-buffer)))) + (insert dangling-text) + ;; remove echo'd FULL-BODY from input - (if (and ,remove-echo ,full-body - (string-match - (replace-regexp-in-string - "\n" "[\r\n]+" (regexp-quote (or ,full-body ""))) - string-buffer)) - (setq raw (substring string-buffer (match-end 0)))) + (when (and ,remove-echo ,full-body + (string-match + (replace-regexp-in-string + "\n" "[\r\n]+" (regexp-quote (or ,full-body ""))) + string-buffer)) + (setq string-buffer (substring string-buffer (match-end 0)))) (split-string string-buffer comint-prompt-regexp))))) (def-edebug-spec org-babel-comint-with-output (sexp body)) @@ -149,15 +144,14 @@ Don't return until FILE exists. Code in STRING must ensure that FILE exists at end of evaluation." (unless (org-babel-comint-buffer-livep buffer) (error "Buffer %s does not exist or has no process" buffer)) - (if (file-exists-p file) (delete-file file)) + (when (file-exists-p file) (delete-file file)) (process-send-string (get-buffer-process buffer) - (if (string-match "\n$" string) string (concat string "\n"))) + (if (= (aref string (1- (length string))) ?\n) string (concat string "\n"))) ;; From Tramp 2.1.19 the following cache flush is not necessary - (if (file-remote-p default-directory) - (let (v) - (with-parsed-tramp-file-name default-directory nil - (tramp-flush-directory-property v "")))) + (when (file-remote-p default-directory) + (with-parsed-tramp-file-name default-directory nil + (tramp-flush-directory-property v ""))) (while (not (file-exists-p file)) (sit-for (or period 0.25)))) (provide 'ob-comint) diff --git a/lisp/org/ob-coq.el b/lisp/org/ob-coq.el new file mode 100644 index 00000000000..93d2b1f7135 --- /dev/null +++ b/lisp/org/ob-coq.el @@ -0,0 +1,78 @@ +;;; ob-coq.el --- Babel Functions for Coq -*- lexical-binding: t; -*- + +;; Copyright (C) 2010-2017 Free Software Foundation, Inc. + +;; Author: Eric Schulte +;; Keywords: literate programming, reproducible research +;; Homepage: http://orgmode.org + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; Rudimentary support for evaluating Coq code blocks. Currently only +;; session evaluation is supported. Requires both coq.el and +;; coq-inferior.el, both of which are distributed with Coq. +;; +;; http://coq.inria.fr/ + +;;; Code: +(require 'ob) + +(declare-function run-coq "ext:coq-inferior.el" (cmd)) +(declare-function coq-proc "ext:coq-inferior.el" ()) + +(defvar coq-program-name "coqtop" + "Name of the coq toplevel to run.") + +(defvar org-babel-coq-buffer "*coq*" + "Buffer in which to evaluate coq code blocks.") + +(defun org-babel-coq-clean-prompt (string) + (if (string-match "^[^[:space:]]+ < " string) + (substring string 0 (match-beginning 0)) + string)) + +(defun org-babel-execute:coq (body params) + (let ((full-body (org-babel-expand-body:generic body params)) + (session (org-babel-coq-initiate-session)) + (pt (lambda () + (marker-position + (process-mark (get-buffer-process (current-buffer))))))) + (org-babel-coq-clean-prompt + (org-babel-comint-in-buffer session + (let ((start (funcall pt))) + (with-temp-buffer + (insert full-body) + (comint-send-region (coq-proc) (point-min) (point-max)) + (comint-send-string (coq-proc) + (if (string= (buffer-substring (- (point-max) 1) (point-max)) ".") + "\n" + ".\n"))) + (while (equal start (funcall pt)) (sleep-for 0.1)) + (buffer-substring start (funcall pt))))))) + +(defun org-babel-coq-initiate-session () + "Initiate a coq session. +If there is not a current inferior-process-buffer in SESSION then +create one. Return the initialized session." + (unless (fboundp 'run-coq) + (error "`run-coq' not defined, load coq-inferior.el")) + (save-window-excursion (run-coq coq-program-name)) + (sit-for 0.1) + (get-buffer org-babel-coq-buffer)) + +(provide 'ob-coq) diff --git a/lisp/org/ob-core.el b/lisp/org/ob-core.el index cfbcbe6eced..c630b70f91f 100644 --- a/lisp/org/ob-core.el +++ b/lisp/org/ob-core.el @@ -1,4 +1,4 @@ -;;; ob-core.el --- working with code blocks in org-mode +;;; ob-core.el --- Working with Code Blocks -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -23,8 +23,7 @@ ;; along with GNU Emacs. If not, see . ;;; Code: -(eval-when-compile - (require 'cl)) +(require 'cl-lib) (require 'ob-eval) (require 'org-macs) (require 'org-compat) @@ -33,66 +32,70 @@ (if (memq system-type '(windows-nt cygwin)) ".exe" nil)) -;; dynamically scoped for tramp -(defvar org-babel-call-process-region-original nil) -(defvar org-src-lang-modes) + (defvar org-babel-library-of-babel) -(declare-function outline-show-all "outline" ()) -(declare-function org-every "org" (pred seq)) -(declare-function org-reduce "org" (CL-FUNC CL-SEQ &rest CL-KEYS)) +(defvar org-edit-src-content-indentation) +(defvar org-src-lang-modes) +(defvar org-src-preserve-indentation) + +(declare-function org-at-item-p "org-list" ()) +(declare-function org-at-table-p "org" (&optional table-type)) +(declare-function org-babel-lob-execute-maybe "ob-lob" ()) +(declare-function org-babel-ref-goto-headline-id "ob-ref" (id)) +(declare-function org-babel-ref-headline-body "ob-ref" ()) +(declare-function org-babel-ref-parse "ob-ref" (assignment)) +(declare-function org-babel-ref-resolve "ob-ref" (ref)) +(declare-function org-babel-ref-split-args "ob-ref" (arg-string)) +(declare-function org-babel-tangle-comment-links "ob-tangle" (&optional info)) +(declare-function org-completing-read "org" (&rest args)) +(declare-function org-current-level "org" ()) +(declare-function org-cycle "org" (&optional arg)) +(declare-function org-do-remove-indentation "org" (&optional n)) +(declare-function org-edit-src-code "org-src" (&optional code edit-buffer-name)) +(declare-function org-edit-src-exit "org-src" ()) +(declare-function org-element-at-point "org-element" ()) +(declare-function org-element-context "org-element" (&optional element)) +(declare-function org-element-normalize-string "org-element" (s)) +(declare-function org-element-property "org-element" (property element)) +(declare-function org-element-type "org-element" (element)) +(declare-function org-entry-get "org" (pom property &optional inherit literal-nil)) +(declare-function org-escape-code-in-region "org-src" (beg end)) +(declare-function org-get-indentation "org" (&optional line)) +(declare-function org-get-indentation "org" (&optional line)) +(declare-function org-in-regexp "org" (regexp &optional nlines visually)) +(declare-function org-indent-line "org" ()) +(declare-function org-list-get-list-end "org-list" (item struct prevs)) +(declare-function org-list-prevs-alist "org-list" (struct)) +(declare-function org-list-struct "org-list" ()) +(declare-function org-list-to-generic "org-list" (LIST PARAMS)) +(declare-function org-list-to-lisp "org-list" (&optional delete)) +(declare-function org-macro-escape-arguments "org-macro" (&rest args)) +(declare-function org-make-options-regexp "org" (kwds &optional extra)) (declare-function org-mark-ring-push "org" (&optional pos buffer)) -(declare-function tramp-compat-make-temp-file "tramp-compat" - (filename &optional dir-flag)) -(declare-function org-icompleting-read "org" (&rest args)) -(declare-function org-edit-src-code "org-src" - (&optional context code edit-buffer-name)) -(declare-function org-edit-src-exit "org-src" (&optional context)) -(declare-function org-open-at-point "org" (&optional in-emacs reference-buffer)) -(declare-function org-outline-overlay-data "org" (&optional use-markers)) -(declare-function org-set-outline-overlay-data "org" (data)) (declare-function org-narrow-to-subtree "org" ()) -(declare-function org-split-string "org" (string &optional separators)) -(declare-function org-entry-get "org" - (pom property &optional inherit literal-nil)) -(declare-function org-make-options-regexp "org" (kwds &optional extra)) -(declare-function org-do-remove-indentation "org" (&optional n)) (declare-function org-next-block "org" (arg &optional backward block-regexp)) +(declare-function org-number-sequence "org-compat" (from &optional to inc)) +(declare-function org-open-at-point "org" (&optional in-emacs reference-buffer)) +(declare-function org-outline-overlay-data "org" (&optional use-markers)) (declare-function org-previous-block "org" (arg &optional block-regexp)) +(declare-function org-remove-indentation "org" (code &optional n)) +(declare-function org-reverse-string "org" (string)) +(declare-function org-set-outline-overlay-data "org" (data)) (declare-function org-show-context "org" (&optional key)) -(declare-function org-at-table-p "org" (&optional table-type)) -(declare-function org-cycle "org" (&optional arg)) -(declare-function org-uniquify "org" (list)) -(declare-function org-current-level "org" ()) -(declare-function org-table-import "org-table" (file arg)) -(declare-function org-add-hook "org-compat" - (hook function &optional append local)) +(declare-function org-split-string "org" (string &optional separators)) +(declare-function org-src-coderef-format "org-src" (element)) +(declare-function org-src-coderef-regexp "org-src" (fmt &optional label)) (declare-function org-table-align "org-table" ()) (declare-function org-table-end "org-table" (&optional table-type)) -(declare-function orgtbl-to-generic "org-table" - (table params &optional backend)) -(declare-function orgtbl-to-orgtbl "org-table" (table params)) -(declare-function org-babel-tangle-comment-links "ob-tangle" (&optional info)) -(declare-function org-babel-lob-get-info "ob-lob" nil) -(declare-function org-babel-ref-split-args "ob-ref" (arg-string)) -(declare-function org-babel-ref-parse "ob-ref" (assignment)) -(declare-function org-babel-ref-resolve "ob-ref" (ref)) -(declare-function org-babel-ref-goto-headline-id "ob-ref" (id)) -(declare-function org-babel-ref-headline-body "ob-ref" ()) -(declare-function org-babel-lob-execute-maybe "ob-lob" ()) -(declare-function org-number-sequence "org-compat" (from &optional to inc)) -(declare-function org-at-item-p "org-list" ()) -(declare-function org-list-parse-list "org-list" (&optional delete)) -(declare-function org-list-to-generic "org-list" (LIST PARAMS)) -(declare-function org-list-struct "org-list" ()) -(declare-function org-list-prevs-alist "org-list" (struct)) -(declare-function org-list-get-list-end "org-list" (item struct prevs)) -(declare-function org-remove-if "org" (predicate seq)) -(declare-function org-completing-read "org" (&rest args)) -(declare-function org-escape-code-in-region "org-src" (beg end)) -(declare-function org-unescape-code-in-string "org-src" (s)) +(declare-function org-table-import "org-table" (file arg)) (declare-function org-table-to-lisp "org-table" (&optional txt)) -(declare-function org-reverse-string "org" (string)) -(declare-function org-element-context "org-element" (&optional ELEMENT)) +(declare-function org-trim "org" (s &optional keep-lead)) +(declare-function org-unescape-code-in-string "org-src" (s)) +(declare-function org-uniquify "org" (list)) +(declare-function orgtbl-to-generic "org-table" (table params)) +(declare-function orgtbl-to-orgtbl "org-table" (table params)) +(declare-function outline-show-all "outline" ()) +(declare-function tramp-compat-make-temp-file "tramp-compat" (filename &optional dir-flag)) (defgroup org-babel nil "Code block evaluation and management in `org-mode' documents." @@ -101,11 +104,12 @@ (defcustom org-confirm-babel-evaluate t "Confirm before evaluation. +\\\ Require confirmation before interactively evaluating code -blocks in Org-mode buffers. The default value of this variable -is t, meaning confirmation is required for any code block -evaluation. This variable can be set to nil to inhibit any -future confirmation requests. This variable can also be set to a +blocks in Org buffers. The default value of this variable is t, +meaning confirmation is required for any code block evaluation. +This variable can be set to nil to inhibit any future +confirmation requests. This variable can also be set to a function which takes two arguments the language of the code block and the body of the code block. Such a function should then return a non-nil value if the user should be prompted for @@ -113,10 +117,11 @@ execution or nil if no prompt is required. Warning: Disabling confirmation may result in accidental evaluation of potentially harmful code. It may be advisable -remove code block execution from C-c C-c as further protection +remove code block execution from `\\[org-ctrl-c-ctrl-c]' \ +as further protection against accidental code block evaluation. The `org-babel-no-eval-on-ctrl-c-ctrl-c' variable can be used to -remove code block execution from the C-c C-c keybinding." +remove code block execution from the `\\[org-ctrl-c-ctrl-c]' keybinding." :group 'org-babel :version "24.1" :type '(choice boolean function)) @@ -124,19 +129,24 @@ remove code block execution from the C-c C-c keybinding." (put 'org-confirm-babel-evaluate 'safe-local-variable (lambda (x) (eq x t))) (defcustom org-babel-no-eval-on-ctrl-c-ctrl-c nil - "Remove code block evaluation from the C-c C-c key binding." + "\\\ +Remove code block evaluation from the `\\[org-ctrl-c-ctrl-c]' key binding." :group 'org-babel :version "24.1" :type 'boolean) (defcustom org-babel-results-keyword "RESULTS" "Keyword used to name results generated by code blocks. -Should be either RESULTS or NAME however any capitalization may -be used." +It should be \"RESULTS\". However any capitalization may be +used." :group 'org-babel :version "24.4" :package-version '(Org . "8.0") - :type 'string) + :type 'string + :safe (lambda (v) + (and (stringp v) + (eq (compare-strings "RESULTS" nil nil v nil nil t) + t)))) (defcustom org-babel-noweb-wrap-start "<<" "String used to begin a noweb reference in a code block. @@ -155,6 +165,19 @@ See also `org-babel-noweb-wrap-start'." This string must include a \"%s\" which will be replaced by the results." :group 'org-babel :type 'string) +(put 'org-babel-inline-result-wrap + 'safe-local-variable + (lambda (value) + (and (stringp value) + (string-match-p "%s" value)))) + +(defcustom org-babel-hash-show-time nil + "Non-nil means show the time the code block was evaluated in the result hash." + :group 'org-babel + :type 'boolean + :version "26.1" + :package-version '(Org . "9.0") + :safe #'booleanp) (defun org-babel-noweb-wrap (&optional regexp) (concat org-babel-noweb-wrap-start @@ -169,14 +192,6 @@ This string must include a \"%s\" which will be replaced by the results." "^[ \t]*#\\+headers?:[ \t]*\\([^\n]*\\)$" "Regular expression used to match multi-line header arguments.") -(defvar org-babel-src-name-w-name-regexp - (concat org-babel-src-name-regexp - "\\(" - org-babel-multi-line-header-regexp - "\\)*" - "\\([^ ()\f\t\n\r\v]+\\)") - "Regular expression matching source name lines with a name.") - (defvar org-babel-src-block-regexp (concat ;; (1) indentation (2) lang @@ -189,168 +204,100 @@ This string must include a \"%s\" which will be replaced by the results." "\\([^\000]*?\n\\)??[ \t]*#\\+end_src") "Regexp used to identify code blocks.") -(defvar org-babel-inline-src-block-regexp - (concat - ;; (1) replacement target (2) lang - "\\(?:^\\|[^-[:alnum:]]\\)\\(src_\\([^ \f\t\n\r\v]+\\)" - ;; (3,4) (unused, headers) - "\\(\\|\\[\\(.*?\\)\\]\\)" - ;; (5) body - "{\\([^\f\n\r\v]+?\\)}\\)") - "Regexp used to identify inline src-blocks.") - -(defun org-babel-get-header (params key &optional others) - "Select only header argument of type KEY from a list. -Optional argument OTHERS indicates that only the header that do -not match KEY should be returned." - (delq nil - (mapcar - (lambda (p) (when (funcall (if others #'not #'identity) (eq (car p) key)) p)) - params))) - -(defun org-babel-get-inline-src-block-matches() - "Set match data if within body of an inline source block. -Returns non-nil if match-data set" - (let ((src-at-0-p (save-excursion - (beginning-of-line 1) - (string= "src" (thing-at-point 'word)))) - (first-line-p (= (line-beginning-position) (point-min))) - (orig (point))) - (let ((search-for (cond ((and src-at-0-p first-line-p "src_")) - (first-line-p "[[:punct:] \t]src_") - (t "[[:punct:] \f\t\n\r\v]src_"))) - (lower-limit (if first-line-p - nil - (- (point-at-bol) 1)))) - (save-excursion - (when (or (and src-at-0-p (bobp)) - (and (re-search-forward "}" (point-at-eol) t) - (re-search-backward search-for lower-limit t) - (> orig (point)))) - (when (looking-at org-babel-inline-src-block-regexp) - t )))))) - -(defvar org-babel-inline-lob-one-liner-regexp) -(defun org-babel-get-lob-one-liner-matches() - "Set match data if on line of an lob one liner. -Returns non-nil if match-data set" - (save-excursion - (unless (= (point) (point-at-bol)) ;; move before inline block - (re-search-backward "[ \f\t\n\r\v]" nil t)) - (if (looking-at org-babel-inline-lob-one-liner-regexp) - t - nil))) - -(defun org-babel-get-src-block-info (&optional light) - "Get information on the current source block. - -Optional argument LIGHT does not resolve remote variable -references; a process which could likely result in the execution -of other code blocks. +(defun org-babel--get-vars (params) + "Return the babel variable assignments in PARAMS. + +PARAMS is a quasi-alist of header args, which may contain +multiple entries for the key `:var'. This function returns a +list of the cdr of all the `:var' entries." + (mapcar #'cdr + (cl-remove-if-not (lambda (x) (eq (car x) :var)) params))) + +(defvar org-babel-exp-reference-buffer nil + "Buffer containing original contents of the exported buffer. +This is used by Babel to resolve references in source blocks. +Its value is dynamically bound during export.") + +(defun org-babel-check-confirm-evaluate (info) + "Check whether INFO allows code block evaluation. + +Returns nil if evaluation is disallowed, t if it is +unconditionally allowed, and the symbol `query' if the user +should be asked whether to allow evaluation." + (let* ((headers (nth 2 info)) + (eval (or (cdr (assq :eval headers)) + (when (assq :noeval headers) "no"))) + (eval-no (member eval '("no" "never"))) + (export org-babel-exp-reference-buffer) + (eval-no-export (and export (member eval '("no-export" "never-export")))) + (noeval (or eval-no eval-no-export)) + (query (or (equal eval "query") + (and export (equal eval "query-export")) + (if (functionp org-confirm-babel-evaluate) + (save-excursion + (goto-char (nth 5 info)) + (funcall org-confirm-babel-evaluate + ;; language, code block body + (nth 0 info) (nth 1 info))) + org-confirm-babel-evaluate)))) + (cond + (noeval nil) + (query 'query) + (t t)))) -Returns a list - (language body header-arguments-alist switches name indent block-head)." - (let ((case-fold-search t) head info name indent) - ;; full code block - (if (setq head (org-babel-where-is-src-block-head)) - (save-excursion - (goto-char head) - (setq info (org-babel-parse-src-block-match)) - (setq indent (car (last info))) - (setq info (butlast info)) - (while (and (forward-line -1) - (looking-at org-babel-multi-line-header-regexp)) - (setf (nth 2 info) - (org-babel-merge-params - (nth 2 info) - (org-babel-parse-header-arguments (match-string 1))))) - (when (looking-at org-babel-src-name-w-name-regexp) - (setq name (org-no-properties (match-string 3))))) - ;; inline source block - (when (org-babel-get-inline-src-block-matches) - (setq info (org-babel-parse-inline-src-block-match)))) - ;; resolve variable references and add summary parameters - (when (and info (not light)) - (setf (nth 2 info) (org-babel-process-params (nth 2 info)))) - (when info (append info (list name indent head))))) - -(defvar org-current-export-file) ; dynamically bound -(defmacro org-babel-check-confirm-evaluate (info &rest body) - "Evaluate BODY with special execution confirmation variables set. - -Specifically; NOEVAL will indicate if evaluation is allowed, -QUERY will indicate if a user query is required, CODE-BLOCK will -hold the language of the code block, and BLOCK-NAME will hold the -name of the code block." - (declare (indent defun)) - (org-with-gensyms - (lang block-body headers name eval eval-no export eval-no-export) - `(let* ((,lang (nth 0 ,info)) - (,block-body (nth 1 ,info)) - (,headers (nth 2 ,info)) - (,name (nth 4 ,info)) - (,eval (or (cdr (assoc :eval ,headers)) - (when (assoc :noeval ,headers) "no"))) - (,eval-no (or (equal ,eval "no") - (equal ,eval "never"))) - (,export (org-bound-and-true-p org-current-export-file)) - (,eval-no-export (and ,export (or (equal ,eval "no-export") - (equal ,eval "never-export")))) - (noeval (or ,eval-no ,eval-no-export)) - (query (or (equal ,eval "query") - (and ,export (equal ,eval "query-export")) - (if (functionp org-confirm-babel-evaluate) - (funcall org-confirm-babel-evaluate - ,lang ,block-body) - org-confirm-babel-evaluate))) - (code-block (if ,info (format " %s " ,lang) " ")) - (block-name (if ,name (format " (%s) " ,name) " "))) - ;; Silence byte-compiler is `body' doesn't use those vars. - (ignore noeval query) - ,@body))) - -(defsubst org-babel-check-evaluate (info) +(defun org-babel-check-evaluate (info) "Check if code block INFO should be evaluated. -Do not query the user." - (org-babel-check-confirm-evaluate info - (not (when noeval - (message "Evaluation of this%scode-block%sis disabled." - code-block block-name))))) - - ;; dynamically scoped for asynchronous export +Do not query the user, but do display an informative message if +evaluation is blocked. Returns non-nil if evaluation is not blocked." + (let ((confirmed (org-babel-check-confirm-evaluate info))) + (unless confirmed + (message "Evaluation of this %s code block%sis disabled." + (nth 0 info) + (let ((name (nth 4 info))) + (if name (format " (%s) " name) " ")))) + confirmed)) + +;; Dynamically scoped for asynchronous export. (defvar org-babel-confirm-evaluate-answer-no) -(defsubst org-babel-confirm-evaluate (info) +(defun org-babel-confirm-evaluate (info) "Confirm evaluation of the code block INFO. -If the variable `org-babel-confirm-evaluate-answer-no' is bound -to a non-nil value, auto-answer with \"no\". - This query can also be suppressed by setting the value of `org-confirm-babel-evaluate' to nil, in which case all future interactive code block evaluations will proceed without any confirmation from the user. Note disabling confirmation may result in accidental evaluation -of potentially harmful code." - (org-babel-check-confirm-evaluate info - (not (when query - (unless - (and (not (org-bound-and-true-p +of potentially harmful code. + +The variable `org-babel-confirm-evaluate-answer-no' is used by +the async export process, which requires a non-interactive +environment, to override this check." + (let* ((evalp (org-babel-check-confirm-evaluate info)) + (lang (nth 0 info)) + (name (nth 4 info)) + (name-string (if name (format " (%s) " name) " "))) + (pcase evalp + (`nil nil) + (`t t) + (`query (or + (and (not (bound-and-true-p org-babel-confirm-evaluate-answer-no)) (yes-or-no-p - (format "Evaluate this%scode block%son your system? " - code-block block-name))) - (message "Evaluation of this%scode-block%sis aborted." - code-block block-name)))))) + (format "Evaluate this %s code block%son your system? " + lang name-string))) + (progn + (message "Evaluation of this %s code block%sis aborted." + lang name-string) + nil))) + (x (error "Unexpected value `%s' from `org-babel-check-confirm-evaluate'" x))))) ;;;###autoload (defun org-babel-execute-safely-maybe () (unless org-babel-no-eval-on-ctrl-c-ctrl-c (org-babel-execute-maybe))) -(add-hook 'org-ctrl-c-ctrl-c-hook 'org-babel-execute-safely-maybe) - ;;;###autoload (defun org-babel-execute-maybe () (interactive) @@ -361,8 +308,8 @@ of potentially harmful code." "Execute BODY if point is in a source block and return t. Otherwise do nothing and return nil." - `(if (or (org-babel-where-is-src-block-head) - (org-babel-get-inline-src-block-matches)) + `(if (memq (org-element-type (org-element-context)) + '(inline-src-block src-block)) (progn ,@body t) @@ -394,12 +341,16 @@ a window into the `org-babel-get-src-block-info' function." (header-args (nth 2 info))) (when name (funcall printf "Name: %s\n" name)) (when lang (funcall printf "Lang: %s\n" lang)) + (funcall printf "Properties:\n") + (funcall printf "\t:header-args \t%s\n" (org-entry-get (point) "header-args" t)) + (funcall printf "\t:header-args:%s \t%s\n" lang (org-entry-get (point) (concat "header-args:" lang) t)) + (when (funcall full switches) (funcall printf "Switches: %s\n" switches)) (funcall printf "Header Arguments:\n") (dolist (pair (sort header-args (lambda (a b) (string< (symbol-name (car a)) (symbol-name (car b)))))) - (when (funcall full (cdr pair)) + (when (funcall full (format "%s" (cdr pair))) (funcall printf "\t%S%s\t%s\n" (car pair) (if (> (length (format "%S" (car pair))) 7) "" "\t") @@ -442,11 +393,13 @@ then run `org-babel-switch-to-session'." (colnames . ((nil no yes))) (comments . ((no link yes org both noweb))) (dir . :any) - (eval . ((never query))) + (eval . ((yes no no-export strip-export never-export eval never + query))) (exports . ((code results both none))) (epilogue . :any) (file . :any) (file-desc . :any) + (file-ext . :any) (hlines . ((no yes))) (mkdirp . ((yes no))) (no-expand) @@ -454,6 +407,7 @@ then run `org-babel-switch-to-session'." (noweb . ((yes no tangle no-export strip-export))) (noweb-ref . :any) (noweb-sep . :any) + (output-dir . :any) (padline . ((yes no))) (post . :any) (prologue . :any) @@ -476,31 +430,76 @@ then run `org-babel-switch-to-session'." Note that individual languages may define their own language specific header arguments as well.") +(defconst org-babel-safe-header-args + '(:cache :colnames :comments :exports :epilogue :hlines :noeval + :noweb :noweb-ref :noweb-sep :padline :prologue :rownames + :sep :session :tangle :wrap + (:eval . ("never" "query")) + (:results . (lambda (str) (not (string-match "file" str))))) + "A list of safe header arguments for babel source blocks. + +The list can have entries of the following forms: +- :ARG -> :ARG is always a safe header arg +- (:ARG . (VAL1 VAL2 ...)) -> :ARG is safe as a header arg if it is + `equal' to one of the VALs. +- (:ARG . FN) -> :ARG is safe as a header arg if the function FN + returns non-nil. FN is passed one + argument, the value of the header arg + (as a string).") + +(defmacro org-babel-header-args-safe-fn (safe-list) + "Return a function that determines whether a list of header args are safe. + +Intended usage is: +\(put \\='org-babel-default-header-args \\='safe-local-variable + (org-babel-header-args-safe-p org-babel-safe-header-args) + +This allows org-babel languages to extend the list of safe values for +their `org-babel-default-header-args:foo' variable. + +For the format of SAFE-LIST, see `org-babel-safe-header-args'." + `(lambda (value) + (and (listp value) + (cl-every + (lambda (pair) + (and (consp pair) + (org-babel-one-header-arg-safe-p pair ,safe-list))) + value)))) + (defvar org-babel-default-header-args '((:session . "none") (:results . "replace") (:exports . "code") (:cache . "no") (:noweb . "no") (:hlines . "no") (:tangle . "no")) "Default arguments to use when evaluating a source block.") +(put 'org-babel-default-header-args 'safe-local-variable + (org-babel-header-args-safe-fn org-babel-safe-header-args)) (defvar org-babel-default-inline-header-args - '((:session . "none") (:results . "replace") (:exports . "results")) + '((:session . "none") (:results . "replace") + (:exports . "results") (:hlines . "yes")) "Default arguments to use when evaluating an inline source block.") - -(defvar org-babel-data-names '("tblname" "results" "name")) - -(defvar org-babel-result-regexp - (concat "^[ \t]*#\\+" - (regexp-opt org-babel-data-names t) - "\\(\\[\\(" - ;; FIXME The string below is `org-ts-regexp' - "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^\r\n>]*?\\)>" - " \\)?\\([[:alnum:]]+\\)\\]\\)?\\:[ \t]*") +(put 'org-babel-default-inline-header-args 'safe-local-variable + (org-babel-header-args-safe-fn org-babel-safe-header-args)) + +(defconst org-babel-name-regexp + (format "^[ \t]*#\\+%s:[ \t]*" + ;; FIXME: TBLNAME is for backward compatibility. + (regexp-opt '("NAME" "TBLNAME"))) + "Regexp matching a NAME keyword.") + +(defconst org-babel-result-regexp + (format "^[ \t]*#\\+%s\\(?:\\[\\(?:%s \\)?\\([[:alnum:]]+\\)\\]\\)?:[ \t]*" + org-babel-results-keyword + ;; <%Y-%m-%d %H:%M:%S> + "<\\(?:[0-9]\\{4\\}-[0-1][0-9]-[0-3][0-9] \ +[0-2][0-9]\\(?::[0-5][0-9]\\)\\{2\\}\\)>") "Regular expression used to match result lines. If the results are associated with a hash key then the hash will -be saved in the second match data.") +be saved in match group 1.") -(defvar org-babel-result-w-name-regexp - (concat org-babel-result-regexp - "\\([^ ()\f\t\n\r\v]+\\)\\((\\(.*\\))\\|\\)")) +(defconst org-babel-result-w-name-regexp + (concat org-babel-result-regexp "\\(?9:[^ \t\n\r\v\f]+\\)") + "Regexp matching a RESULTS keyword with a name. +Name is saved in match group 9.") (defvar org-babel-min-lines-for-block-output 10 "The minimum number of lines for block output. @@ -510,33 +509,58 @@ block. Otherwise the output is marked as literal by inserting colons at the starts of the lines. This variable only takes effect if the :results output option is in effect.") +(defvar org-babel-noweb-error-all-langs nil + "Raise errors when noweb references don't resolve. +Also see `org-babel-noweb-error-langs' to control noweb errors on +a language by language bases.") + (defvar org-babel-noweb-error-langs nil "Languages for which Babel will raise literate programming errors. List of languages for which errors should be raised when the source code block satisfying a noweb reference in this language -can not be resolved.") +can not be resolved. Also see `org-babel-noweb-error-all-langs' +to raise errors for all languages.") (defvar org-babel-hash-show 4 "Number of initial characters to show of a hidden results hash.") -(defvar org-babel-hash-show-time nil - "Non-nil means show the time the code block was evaluated in the result hash.") - (defvar org-babel-after-execute-hook nil "Hook for functions to be called after `org-babel-execute-src-block'") -(defun org-babel-named-src-block-regexp-for-name (name) - "This generates a regexp used to match a src block named NAME." - (concat org-babel-src-name-regexp (regexp-quote name) - "[ \t(]*[\r\n]\\(?:^#.*[\r\n]\\)*" +(defun org-babel-named-src-block-regexp-for-name (&optional name) + "This generates a regexp used to match a src block named NAME. +If NAME is nil, match any name. Matched name is then put in +match group 9. Other match groups are defined in +`org-babel-src-block-regexp'." + (concat org-babel-src-name-regexp + (concat (if name (regexp-quote name) "\\(?9:.*?\\)") "[ \t]*" ) + "\\(?:\n[ \t]*#\\+\\S-+:.*\\)*?" + "\n" (substring org-babel-src-block-regexp 1))) (defun org-babel-named-data-regexp-for-name (name) "This generates a regexp used to match data named NAME." - (concat org-babel-result-regexp (regexp-quote name) "\\([ \t]\\|$\\)")) + (concat org-babel-name-regexp (regexp-quote name) "[ \t]*$")) + +(defun org-babel--normalize-body (datum) + "Normalize body for element or object DATUM. +DATUM is a source block element or an inline source block object. +Remove final newline character and spurious indentation." + (let* ((value (org-element-property :value datum)) + (body (if (string-suffix-p "\n" value) + (substring value 0 -1) + value))) + (cond ((eq (org-element-type datum) 'inline-src-block) + ;; Newline characters and indentation in an inline + ;; src-block are not meaningful, since they could come from + ;; some paragraph filling. Treat them as a white space. + (replace-regexp-in-string "\n[ \t]*" " " body)) + ((or org-src-preserve-indentation + (org-element-property :preserve-indent datum)) + body) + (t (org-remove-indentation body))))) ;;; functions -(defvar call-process-region) (defvar org-babel-current-src-block-location nil "Marker pointing to the src block currently being executed. This may also point to a call line or an inline code block. If @@ -546,6 +570,56 @@ the outer-most code block.") (defvar *this*) +(defun org-babel-get-src-block-info (&optional light datum) + "Extract information from a source block or inline source block. + +Optional argument LIGHT does not resolve remote variable +references; a process which could likely result in the execution +of other code blocks. + +By default, consider the block at point. However, when optional +argument DATUM is provided, extract information from that parsed +object instead. + +Return nil if point is not on a source block. Otherwise, return +a list with the following pattern: + + (language body arguments switches name start coderef)" + (let* ((datum (or datum (org-element-context))) + (type (org-element-type datum)) + (inline (eq type 'inline-src-block))) + (when (memq type '(inline-src-block src-block)) + (let* ((lang (org-element-property :language datum)) + (lang-headers (intern + (concat "org-babel-default-header-args:" lang))) + (name (org-element-property :name datum)) + (info + (list + lang + (org-babel--normalize-body datum) + (apply #'org-babel-merge-params + (if inline org-babel-default-inline-header-args + org-babel-default-header-args) + (and (boundp lang-headers) (eval lang-headers t)) + (append + ;; If DATUM is provided, make sure we get node + ;; properties applicable to its location within + ;; the document. + (org-with-point-at (org-element-property :begin datum) + (org-babel-params-from-properties lang)) + (mapcar #'org-babel-parse-header-arguments + (cons (org-element-property :parameters datum) + (org-element-property :header datum))))) + (or (org-element-property :switches datum) "") + name + (org-element-property (if inline :begin :post-affiliated) + datum) + (and (not inline) (org-src-coderef-format datum))))) + (unless light + (setf (nth 2 info) (org-babel-process-params (nth 2 info)))) + (setf (nth 2 info) (org-babel-generate-file-param name (nth 2 info))) + info)))) + ;;;###autoload (defun org-babel-execute-src-block (&optional arg info params) "Execute the current source code block. @@ -565,110 +639,91 @@ block." (interactive) (let* ((org-babel-current-src-block-location (or org-babel-current-src-block-location - (nth 6 info) + (nth 5 info) (org-babel-where-is-src-block-head))) - (info (if info - (copy-tree info) - (org-babel-get-src-block-info))) - (merged-params (org-babel-merge-params (nth 2 info) params))) - (when (org-babel-check-evaluate - (let ((i info)) (setf (nth 2 i) merged-params) i)) - (let* ((params (if params - (org-babel-process-params merged-params) - (nth 2 info))) - (cachep (and (not arg) (cdr (assoc :cache params)) - (string= "yes" (cdr (assoc :cache params))))) - (new-hash (when cachep (org-babel-sha1-hash info))) - (old-hash (when cachep (org-babel-current-result-hash))) - (cache-current-p (and (not arg) new-hash - (equal new-hash old-hash)))) + (info (if info (copy-tree info) (org-babel-get-src-block-info)))) + ;; Merge PARAMS with INFO before considering source block + ;; evaluation since both could disagree. + (cl-callf org-babel-merge-params (nth 2 info) params) + (when (org-babel-check-evaluate info) + (cl-callf org-babel-process-params (nth 2 info)) + (let* ((params (nth 2 info)) + (cache (let ((c (cdr (assq :cache params)))) + (and (not arg) c (string= "yes" c)))) + (new-hash (and cache (org-babel-sha1-hash info))) + (old-hash (and cache (org-babel-current-result-hash))) + (current-cache (and new-hash (equal new-hash old-hash)))) (cond - (cache-current-p - (save-excursion ;; return cached result + (current-cache + (save-excursion ;Return cached result. (goto-char (org-babel-where-is-src-block-result nil info)) - (end-of-line 1) (forward-char 1) + (forward-line) + (skip-chars-forward " \t") (let ((result (org-babel-read-result))) - (message (replace-regexp-in-string - "%" "%%" (format "%S" result))) - result))) - ((org-babel-confirm-evaluate - (let ((i info)) (setf (nth 2 i) merged-params) i)) + (message (replace-regexp-in-string "%" "%%" (format "%S" result))) + result))) + ((org-babel-confirm-evaluate info) (let* ((lang (nth 0 info)) - (result-params (cdr (assoc :result-params params))) - (body (setf (nth 1 info) - (if (org-babel-noweb-p params :eval) - (org-babel-expand-noweb-references info) - (nth 1 info)))) - (dir (cdr (assoc :dir params))) + (result-params (cdr (assq :result-params params))) + ;; Expand noweb references in BODY and remove any + ;; coderef. + (body + (let ((coderef (nth 6 info)) + (expand + (if (org-babel-noweb-p params :eval) + (org-babel-expand-noweb-references info) + (nth 1 info)))) + (if (not coderef) expand + (replace-regexp-in-string + (org-src-coderef-regexp coderef) "" expand nil nil 1)))) + (dir (cdr (assq :dir params))) (default-directory (or (and dir (file-name-as-directory (expand-file-name dir))) default-directory)) - (org-babel-call-process-region-original ;; for tramp handler - (or (org-bound-and-true-p - org-babel-call-process-region-original) - (symbol-function 'call-process-region))) - (indent (nth 5 info)) - result cmd) - (unwind-protect - (let ((call-process-region - (lambda (&rest args) - (apply 'org-babel-tramp-handle-call-process-region - args)))) - (let ((lang-check - (lambda (f) - (let ((f (intern (concat "org-babel-execute:" f)))) - (when (fboundp f) f))))) - (setq cmd - (or (funcall lang-check lang) - (funcall lang-check - (symbol-name - (cdr (assoc lang org-src-lang-modes)))) - (error "No org-babel-execute function for %s!" - lang)))) - (message "executing %s code block%s..." - (capitalize lang) - (if (nth 4 info) (format " (%s)" (nth 4 info)) "")) - (if (member "none" result-params) - (progn - (funcall cmd body params) - (message "result silenced") - (setq result nil)) - (setq result - (let ((result (funcall cmd body params))) - (if (and (eq (cdr (assoc :result-type params)) - 'value) - (or (member "vector" result-params) - (member "table" result-params)) - (not (listp result))) - (list (list result)) result))) - ;; If non-empty result and :file then write to :file. - (when (cdr (assoc :file params)) - (when result - (with-temp-file (cdr (assoc :file params)) - (insert - (org-babel-format-result - result (cdr (assoc :sep (nth 2 info))))))) - (setq result (cdr (assoc :file params)))) - ;; Possibly perform post process provided its appropriate. - (when (cdr (assoc :post params)) - (let ((*this* (if (cdr (assoc :file params)) - (org-babel-result-to-file - (cdr (assoc :file params)) - (when (assoc :file-desc params) - (or (cdr (assoc :file-desc params)) - result))) - result))) - (setq result (org-babel-ref-resolve - (cdr (assoc :post params)))) - (when (cdr (assoc :file params)) - (setq result-params - (remove "file" result-params))))) - (org-babel-insert-result - result result-params info new-hash indent lang)) - (run-hooks 'org-babel-after-execute-hook) - result) - (setq call-process-region - 'org-babel-call-process-region-original))))))))) + (cmd (intern (concat "org-babel-execute:" lang))) + result) + (unless (fboundp cmd) + (error "No org-babel-execute function for %s!" lang)) + (message "executing %s code block%s..." + (capitalize lang) + (let ((name (nth 4 info))) + (if name (format " (%s)" name) ""))) + (if (member "none" result-params) + (progn (funcall cmd body params) + (message "result silenced")) + (setq result + (let ((r (funcall cmd body params))) + (if (and (eq (cdr (assq :result-type params)) 'value) + (or (member "vector" result-params) + (member "table" result-params)) + (not (listp r))) + (list (list r)) + r))) + (let ((file (cdr (assq :file params)))) + ;; If non-empty result and :file then write to :file. + (when file + (when result + (with-temp-file file + (insert (org-babel-format-result + result (cdr (assq :sep params)))))) + (setq result file)) + ;; Possibly perform post process provided its + ;; appropriate. Dynamically bind "*this*" to the + ;; actual results of the block. + (let ((post (cdr (assq :post params)))) + (when post + (let ((*this* (if (not file) result + (org-babel-result-to-file + file + (let ((desc (assq :file-desc params))) + (and desc (or (cdr desc) result))))))) + (setq result (org-babel-ref-resolve post)) + (when file + (setq result-params (remove "file" result-params)))))) + (org-babel-insert-result + result result-params info new-hash lang))) + (run-hooks 'org-babel-after-execute-hook) + result))))))) (defun org-babel-expand-body:generic (body params &optional var-lines) "Expand BODY with PARAMS. @@ -676,8 +731,8 @@ Expand a block of code with org-babel according to its header arguments. This generic implementation of body expansion is called for languages which have not defined their own specific org-babel-expand-body:lang function." - (let ((pro (cdr (assoc :prologue params))) - (epi (cdr (assoc :epilogue params)))) + (let ((pro (cdr (assq :prologue params))) + (epi (cdr (assq :epilogue params)))) (mapconcat #'identity (append (when pro (list pro)) var-lines @@ -708,10 +763,9 @@ arguments and pop open the results in a preview buffer." (org-babel-expand-body:generic body params (and (fboundp assignments-cmd) (funcall assignments-cmd params)))))) - (if (org-called-interactively-p 'any) + (if (called-interactively-p 'any) (org-edit-src-code - nil expanded - (concat "*Org-Babel Preview " (buffer-name) "[ " lang " ]*")) + expanded (concat "*Org-Babel Preview " (buffer-name) "[ " lang " ]*")) expanded))) (defun org-babel-edit-distance (s1 s2) @@ -742,7 +796,7 @@ arguments and pop open the results in a preview buffer." (dolist (arg-pair new-list) (let ((header (car arg-pair))) (setq results - (cons arg-pair (org-remove-if + (cons arg-pair (cl-remove-if (lambda (pair) (equal header (car pair))) results)))))) results)) @@ -770,37 +824,43 @@ arguments and pop open the results in a preview buffer." (message "No suspicious header arguments found."))) ;;;###autoload -(defun org-babel-insert-header-arg () +(defun org-babel-insert-header-arg (&optional header-arg value) "Insert a header argument selecting from lists of common args and values." (interactive) - (let* ((lang (car (org-babel-get-src-block-info 'light))) + (let* ((info (org-babel-get-src-block-info 'light)) + (lang (car info)) + (begin (nth 5 info)) (lang-headers (intern (concat "org-babel-header-args:" lang))) (headers (org-babel-combine-header-arg-lists org-babel-common-header-args-w-values - (when (boundp lang-headers) (eval lang-headers)))) - (arg (org-icompleting-read - "Header Arg: " - (mapcar - (lambda (header-spec) (symbol-name (car header-spec))) - headers)))) - (insert ":" arg) - (let ((vals (cdr (assoc (intern arg) headers)))) - (when vals - (insert - " " - (cond - ((eq vals :any) - (read-from-minibuffer "value: ")) - ((listp vals) - (mapconcat - (lambda (group) - (let ((arg (org-icompleting-read - "value: " - (cons "default" (mapcar #'symbol-name group))))) - (if (and arg (not (string= "default" arg))) - (concat arg " ") - ""))) - vals "")))))))) + (when (boundp lang-headers) (eval lang-headers t)))) + (header-arg (or header-arg + (completing-read + "Header Arg: " + (mapcar + (lambda (header-spec) (symbol-name (car header-spec))) + headers)))) + (vals (cdr (assoc (intern header-arg) headers))) + (value (or value + (cond + ((eq vals :any) + (read-from-minibuffer "value: ")) + ((listp vals) + (mapconcat + (lambda (group) + (let ((arg (completing-read + "Value: " + (cons "default" + (mapcar #'symbol-name group))))) + (if (and arg (not (string= "default" arg))) + (concat arg " ") + ""))) + vals "")))))) + (save-excursion + (goto-char begin) + (goto-char (point-at-eol)) + (unless (= (char-before (point)) ?\ ) (insert " ")) + (insert ":" header-arg) (when value (insert " " value))))) ;; Add support for completing-read insertion of header arguments after ":" (defun org-babel-header-arg-expand () @@ -811,7 +871,7 @@ arguments and pop open the results in a preview buffer." (defun org-babel-enter-header-arg-w-completion (&optional lang) "Insert header argument appropriate for LANG with completion." (let* ((lang-headers-var (intern (concat "org-babel-header-args:" lang))) - (lang-headers (when (boundp lang-headers-var) (eval lang-headers-var))) + (lang-headers (when (boundp lang-headers-var) (eval lang-headers-var t))) (headers-w-values (org-babel-combine-header-arg-lists org-babel-common-header-args-w-values lang-headers)) (headers (mapcar #'symbol-name (mapcar #'car headers-w-values))) @@ -842,8 +902,8 @@ session." (if (org-babel-noweb-p params :eval) (org-babel-expand-noweb-references info) (nth 1 info))))) - (session (cdr (assoc :session params))) - (dir (cdr (assoc :dir params))) + (session (cdr (assq :session params))) + (dir (cdr (assq :dir params))) (default-directory (or (and dir (file-name-as-directory dir)) default-directory)) (cmd (intern (concat "org-babel-load-session:" lang)))) @@ -863,17 +923,17 @@ the session. Copy the body of the code block to the kill ring." (lang (nth 0 info)) (body (nth 1 info)) (params (nth 2 info)) - (session (cdr (assoc :session params))) - (dir (cdr (assoc :dir params))) + (session (cdr (assq :session params))) + (dir (cdr (assq :dir params))) (default-directory (or (and dir (file-name-as-directory dir)) default-directory)) (init-cmd (intern (format "org-babel-%s-initiate-session" lang))) (prep-cmd (intern (concat "org-babel-prep-session:" lang)))) - (if (and (stringp session) (string= session "none")) - (error "This block is not using a session!")) + (when (and (stringp session) (string= session "none")) + (error "This block is not using a session!")) (unless (fboundp init-cmd) (error "No org-babel-initiate-session function for %s!" lang)) - (with-temp-buffer (insert (org-babel-trim body)) + (with-temp-buffer (insert (org-trim body)) (copy-region-as-kill (point-min) (point-max))) (when arg (unless (fboundp prep-cmd) @@ -912,15 +972,15 @@ with a prefix argument then this is passed on to (org-edit-src-code) (funcall swap-windows))) +;;;###autoload (defmacro org-babel-do-in-edit-buffer (&rest body) "Evaluate BODY in edit buffer if there is a code block at point. Return t if a code block was found at point, nil otherwise." `(let ((org-src-window-setup 'switch-invisibly)) (when (and (org-babel-where-is-src-block-head) - (org-edit-src-code nil nil nil)) + (org-edit-src-code)) (unwind-protect (progn ,@body) - (if (org-bound-and-true-p org-edit-src-from-org-mode) - (org-edit-src-exit))) + (org-edit-src-exit)) t))) (def-edebug-spec org-babel-do-in-edit-buffer (body)) @@ -928,10 +988,10 @@ Return t if a code block was found at point, nil otherwise." "Read key sequence and execute the command in edit buffer. Enter a key sequence to be executed in the language major-mode edit buffer. For example, TAB will alter the contents of the -Org-mode code block according to the effect of TAB in the -language major-mode buffer. For languages that support -interactive sessions, this can be used to send code from the Org -buffer to the session for evaluation using the native major-mode +Org code block according to the effect of TAB in the language +major mode buffer. For languages that support interactive +sessions, this can be used to send code from the Org buffer +to the session for evaluation using the native major mode evaluation mechanisms." (interactive "kEnter key-sequence to execute in edit buffer: ") (org-babel-do-in-edit-buffer @@ -941,7 +1001,7 @@ evaluation mechanisms." (defvar org-bracket-link-regexp) (defun org-babel-active-location-p () - (memq (car (save-match-data (org-element-context))) + (memq (org-element-type (save-match-data (org-element-context))) '(babel-call inline-babel-call inline-src-block src-block))) ;;;###autoload @@ -965,7 +1025,7 @@ results already exist." ;; file results (org-open-at-point) (let ((r (org-babel-format-result - (org-babel-read-result) (cdr (assoc :sep (nth 2 info)))))) + (org-babel-read-result) (cdr (assq :sep (nth 2 info)))))) (pop-to-buffer (get-buffer-create "*Org-Babel Results*")) (delete-region (point-min) (point-max)) (insert r))) @@ -995,7 +1055,8 @@ beg-body --------- point at the beginning of the body end-body --------- point at the end of the body" (declare (indent 1)) (let ((tempvar (make-symbol "file"))) - `(let* ((,tempvar ,file) + `(let* ((case-fold-search t) + (,tempvar ,file) (visited-p (or (null ,tempvar) (get-file-buffer (expand-file-name ,tempvar)))) (point (point)) to-be-removed) @@ -1035,80 +1096,91 @@ end-body --------- point at the end of the body" ;;;###autoload (defmacro org-babel-map-inline-src-blocks (file &rest body) - "Evaluate BODY forms on each inline source-block in FILE. + "Evaluate BODY forms on each inline source block in FILE. If FILE is nil evaluate BODY forms on source blocks in current buffer." - (declare (indent 1)) - (let ((tempvar (make-symbol "file"))) - `(let* ((,tempvar ,file) - (visited-p (or (null ,tempvar) + (declare (indent 1) (debug (form body))) + (org-with-gensyms (datum end point tempvar to-be-removed visitedp) + `(let* ((case-fold-search t) + (,tempvar ,file) + (,visitedp (or (null ,tempvar) (get-file-buffer (expand-file-name ,tempvar)))) - (point (point)) to-be-removed) + (,point (point)) + ,to-be-removed) (save-window-excursion (when ,tempvar (find-file ,tempvar)) - (setq to-be-removed (current-buffer)) + (setq ,to-be-removed (current-buffer)) (goto-char (point-min)) - (while (re-search-forward org-babel-inline-src-block-regexp nil t) - (when (org-babel-active-location-p) - (goto-char (match-beginning 1)) - (save-match-data ,@body)) - (goto-char (match-end 0)))) - (unless visited-p (kill-buffer to-be-removed)) - (goto-char point)))) -(def-edebug-spec org-babel-map-inline-src-blocks (form body)) - -(defvar org-babel-lob-one-liner-regexp) + (while (re-search-forward "src_\\S-" nil t) + (let ((,datum (save-match-data (org-element-context)))) + (when (eq (org-element-type ,datum) 'inline-src-block) + (goto-char (match-beginning 0)) + (let ((,end (copy-marker (org-element-property :end ,datum)))) + ,@body + (goto-char ,end) + (set-marker ,end nil)))))) + (unless ,visitedp (kill-buffer ,to-be-removed)) + (goto-char ,point)))) ;;;###autoload (defmacro org-babel-map-call-lines (file &rest body) "Evaluate BODY forms on each call line in FILE. If FILE is nil evaluate BODY forms on source blocks in current buffer." - (declare (indent 1)) - (let ((tempvar (make-symbol "file"))) - `(let* ((,tempvar ,file) - (visited-p (or (null ,tempvar) + (declare (indent 1) (debug (form body))) + (org-with-gensyms (datum end point tempvar to-be-removed visitedp) + `(let* ((case-fold-search t) + (,tempvar ,file) + (,visitedp (or (null ,tempvar) (get-file-buffer (expand-file-name ,tempvar)))) - (point (point)) to-be-removed) + (,point (point)) + ,to-be-removed) (save-window-excursion (when ,tempvar (find-file ,tempvar)) - (setq to-be-removed (current-buffer)) + (setq ,to-be-removed (current-buffer)) (goto-char (point-min)) - (while (re-search-forward org-babel-lob-one-liner-regexp nil t) - (when (org-babel-active-location-p) - (goto-char (match-beginning 1)) - (save-match-data ,@body)) - (goto-char (match-end 0)))) - (unless visited-p (kill-buffer to-be-removed)) - (goto-char point)))) -(def-edebug-spec org-babel-map-call-lines (form body)) + (while (re-search-forward "call_\\S-\\|^[ \t]*#\\+CALL:" nil t) + (let ((,datum (save-match-data (org-element-context)))) + (when (memq (org-element-type ,datum) + '(babel-call inline-babel-call)) + (goto-char (match-beginning 0)) + (let ((,end (copy-marker (org-element-property :end ,datum)))) + ,@body + (goto-char ,end) + (set-marker ,end nil)))))) + (unless ,visitedp (kill-buffer ,to-be-removed)) + (goto-char ,point)))) ;;;###autoload (defmacro org-babel-map-executables (file &rest body) - (declare (indent 1)) - (let ((tempvar (make-symbol "file")) - (rx (make-symbol "rx"))) - `(let* ((,tempvar ,file) - (,rx (concat "\\(" org-babel-src-block-regexp - "\\|" org-babel-inline-src-block-regexp - "\\|" org-babel-lob-one-liner-regexp "\\)")) - (visited-p (or (null ,tempvar) + "Evaluate BODY forms on each active Babel code in FILE. +If FILE is nil evaluate BODY forms on source blocks in current +buffer." + (declare (indent 1) (debug (form body))) + (org-with-gensyms (datum end point tempvar to-be-removed visitedp) + `(let* ((case-fold-search t) + (,tempvar ,file) + (,visitedp (or (null ,tempvar) (get-file-buffer (expand-file-name ,tempvar)))) - (point (point)) to-be-removed) + (,point (point)) + ,to-be-removed) (save-window-excursion (when ,tempvar (find-file ,tempvar)) - (setq to-be-removed (current-buffer)) + (setq ,to-be-removed (current-buffer)) (goto-char (point-min)) - (while (re-search-forward ,rx nil t) - (when (org-babel-active-location-p) - (goto-char (match-beginning 1)) - (when (looking-at org-babel-inline-src-block-regexp) - (forward-char 1)) - (save-match-data ,@body)) - (goto-char (match-end 0)))) - (unless visited-p (kill-buffer to-be-removed)) - (goto-char point)))) -(def-edebug-spec org-babel-map-executables (form body)) + (while (re-search-forward + "\\(call\\|src\\)_\\|^[ \t]*#\\+\\(BEGIN_SRC\\|CALL:\\)" nil t) + (let ((,datum (save-match-data (org-element-context)))) + (when (memq (org-element-type ,datum) + '(babel-call inline-babel-call inline-src-block + src-block)) + (goto-char (match-beginning 0)) + (let ((,end (copy-marker (org-element-property :end ,datum)))) + ,@body + (goto-char ,end) + (set-marker ,end nil)))))) + (unless ,visitedp (kill-buffer ,to-be-removed)) + (goto-char ,point)))) ;;;###autoload (defun org-babel-execute-buffer (&optional arg) @@ -1119,7 +1191,8 @@ the current buffer." (org-babel-eval-wipe-error-buffer) (org-save-outline-visibility t (org-babel-map-executables nil - (if (looking-at org-babel-lob-one-liner-regexp) + (if (memq (org-element-type (org-element-context)) + '(babel-call inline-babel-call)) (org-babel-lob-execute-maybe) (org-babel-execute-src-block arg))))) @@ -1164,7 +1237,20 @@ the current subtree." (member (car arg) '(:results :exports))) (mapconcat #'identity (sort (funcall rm (split-string v)) #'string<) " ")) - (t v))))))) + (t v)))))) + ;; expanded body + (lang (nth 0 info)) + (params (nth 2 info)) + (body (if (org-babel-noweb-p params :eval) + (org-babel-expand-noweb-references info) (nth 1 info))) + (expand-cmd (intern (concat "org-babel-expand-body:" lang))) + (assignments-cmd (intern (concat "org-babel-variable-assignments:" + lang))) + (expanded + (if (fboundp expand-cmd) (funcall expand-cmd body params) + (org-babel-expand-body:generic + body params (and (fboundp assignments-cmd) + (funcall assignments-cmd params)))))) (let* ((it (format "%s-%s" (mapconcat #'identity @@ -1173,26 +1259,32 @@ the current subtree." (when normalized (format "%S" normalized)))) (nth 2 info))) ":") - (nth 1 info))) + expanded)) (hash (sha1 it))) - (when (org-called-interactively-p 'interactive) (message hash)) + (when (called-interactively-p 'interactive) (message hash)) hash)))) -(defun org-babel-current-result-hash () +(defun org-babel-current-result-hash (&optional info) "Return the current in-buffer hash." - (org-babel-where-is-src-block-result) - (org-no-properties (match-string 5))) + (let ((result (org-babel-where-is-src-block-result nil info))) + (when result + (org-with-wide-buffer + (goto-char result) + (looking-at org-babel-result-regexp) + (match-string-no-properties 1))))) -(defun org-babel-set-current-result-hash (hash) +(defun org-babel-set-current-result-hash (hash info) "Set the current in-buffer hash to HASH." - (org-babel-where-is-src-block-result) - (save-excursion (goto-char (match-beginning 5)) - (mapc #'delete-overlay (overlays-at (point))) - (forward-char org-babel-hash-show) - (mapc #'delete-overlay (overlays-at (point))) - (replace-match hash nil nil nil 5) - (goto-char (point-at-bol)) - (org-babel-hide-hash))) + (org-with-wide-buffer + (goto-char (org-babel-where-is-src-block-result nil info)) + (looking-at org-babel-result-regexp) + (goto-char (match-beginning 1)) + (mapc #'delete-overlay (overlays-at (point))) + (forward-char org-babel-hash-show) + (mapc #'delete-overlay (overlays-at (point))) + (replace-match hash nil nil nil 1) + (beginning-of-line) + (org-babel-hide-hash))) (defun org-babel-hide-hash () "Hide the hash in the current results line. @@ -1201,11 +1293,11 @@ will remain visible." (add-to-invisibility-spec '(org-babel-hide-hash . t)) (save-excursion (when (and (re-search-forward org-babel-result-regexp nil t) - (match-string 5)) - (let* ((start (match-beginning 5)) + (match-string 1)) + (let* ((start (match-beginning 1)) (hide-start (+ org-babel-hash-show start)) - (end (match-end 5)) - (hash (match-string 5)) + (end (match-end 1)) + (hash (match-string 1)) ov1 ov2) (setq ov1 (make-overlay start hide-start)) (setq ov2 (make-overlay hide-start end)) @@ -1227,14 +1319,14 @@ the `org-mode-hook'." (defun org-babel-hash-at-point (&optional point) "Return the value of the hash at POINT. +\\\ The hash is also added as the last element of the kill ring. -This can be called with C-c C-c." +This can be called with `\\[org-ctrl-c-ctrl-c]'." (interactive) (let ((hash (car (delq nil (mapcar (lambda (ol) (overlay-get ol 'babel-hash)) (overlays-at (or point (point)))))))) (when hash (kill-new hash) (message hash)))) -(add-hook 'org-ctrl-c-ctrl-c-hook 'org-babel-hash-at-point) (defun org-babel-result-hide-spec () "Hide portions of results lines. @@ -1288,15 +1380,15 @@ portions of results lines." (eq (overlay-get overlay 'invisible) 'org-babel-hide-result)) (overlays-at start))) - (if (or (not force) (eq force 'off)) - (mapc (lambda (ov) - (when (member ov org-babel-hide-result-overlays) - (setq org-babel-hide-result-overlays - (delq ov org-babel-hide-result-overlays))) - (when (eq (overlay-get ov 'invisible) - 'org-babel-hide-result) - (delete-overlay ov))) - (overlays-at start))) + (when (or (not force) (eq force 'off)) + (mapc (lambda (ov) + (when (member ov org-babel-hide-result-overlays) + (setq org-babel-hide-result-overlays + (delq ov org-babel-hide-result-overlays))) + (when (eq (overlay-get ov 'invisible) + 'org-babel-hide-result) + (delete-overlay ov))) + (overlays-at start))) (setq ov (make-overlay start end)) (overlay-put ov 'invisible 'org-babel-hide-result) ;; make the block accessible to isearch @@ -1316,8 +1408,8 @@ portions of results lines." (add-hook 'org-tab-first-hook 'org-babel-hide-result-toggle-maybe) ;; Remove overlays when changing major mode (add-hook 'org-mode-hook - (lambda () (org-add-hook 'change-major-mode-hook - 'org-babel-show-result-all 'append 'local))) + (lambda () (add-hook 'change-major-mode-hook + 'org-babel-show-result-all 'append 'local))) (defvar org-file-properties) (defun org-babel-params-from-properties (&optional lang) @@ -1326,122 +1418,98 @@ Return a list of association lists of source block params specified in the properties of the current outline entry." (save-match-data (list - ;; DEPRECATED header arguments specified as separate property at - ;; point of definition - (let (val sym) - (org-babel-parse-multiple-vars - (delq nil - (mapcar - (lambda (header-arg) - (and (setq val (org-entry-get (point) header-arg t)) - (cons (intern (concat ":" header-arg)) - (org-babel-read val)))) - (mapcar - #'symbol-name - (mapcar - #'car - (org-babel-combine-header-arg-lists - org-babel-common-header-args-w-values - (progn - (setq sym (intern (concat "org-babel-header-args:" lang))) - (and (boundp sym) (eval sym)))))))))) ;; header arguments specified with the header-args property at - ;; point of call + ;; point of call. (org-babel-parse-header-arguments (org-entry-get org-babel-current-src-block-location - "header-args" 'inherit)) - (when lang ;; language-specific header arguments at point of call - (org-babel-parse-header-arguments - (org-entry-get org-babel-current-src-block-location - (concat "header-args:" lang) 'inherit)))))) - -(defvar org-src-preserve-indentation) ;; declare defcustom from org-src -(defun org-babel-parse-src-block-match () - "Parse the results from a match of the `org-babel-src-block-regexp'." - (let* ((block-indentation (length (match-string 1))) - (lang (org-no-properties (match-string 2))) - (lang-headers (intern (concat "org-babel-default-header-args:" lang))) - (switches (match-string 3)) - (body (org-no-properties - (let* ((body (match-string 5)) - (sub-length (- (length body) 1))) - (if (and (> sub-length 0) - (string= "\n" (substring body sub-length))) - (substring body 0 sub-length) - (or body ""))))) - (preserve-indentation (or org-src-preserve-indentation - (save-match-data - (string-match "-i\\>" switches))))) - (list lang - ;; get block body less properties, protective commas, and indentation - (with-temp-buffer - (save-match-data - (insert (org-unescape-code-in-string body)) - (unless preserve-indentation (org-do-remove-indentation)) - (buffer-string))) - (apply #'org-babel-merge-params - org-babel-default-header-args - (when (boundp lang-headers) (eval lang-headers)) - (append - (org-babel-params-from-properties lang) - (list (org-babel-parse-header-arguments - (org-no-properties (or (match-string 4) "")))))) - switches - block-indentation))) - -(defun org-babel-parse-inline-src-block-match () - "Parse the results from a match of the `org-babel-inline-src-block-regexp'." - (let* ((lang (org-no-properties (match-string 2))) - (lang-headers (intern (concat "org-babel-default-header-args:" lang)))) - (list lang - (org-unescape-code-in-string (org-no-properties (match-string 5))) - (apply #'org-babel-merge-params - org-babel-default-inline-header-args - (if (boundp lang-headers) (eval lang-headers) nil) - (append - (org-babel-params-from-properties lang) - (list (org-babel-parse-header-arguments - (org-no-properties (or (match-string 4) ""))))))))) + "header-args" + 'inherit)) + (and lang ; language-specific header arguments at point of call + (org-babel-parse-header-arguments + (org-entry-get org-babel-current-src-block-location + (concat "header-args:" lang) + 'inherit)))))) (defun org-babel-balanced-split (string alts) "Split STRING on instances of ALTS. -ALTS is a cons of two character options where each option may be -either the numeric code of a single character or a list of -character alternatives. For example to split on balanced -instances of \"[ \t]:\" set ALTS to ((32 9) . 58)." - (let* ((matches (lambda (ch spec) (if (listp spec) (member ch spec) (equal spec ch)))) - (matched (lambda (ch last) - (if (consp alts) - (and (funcall matches ch (cdr alts)) - (funcall matches last (car alts))) - (funcall matches ch alts)))) - (balance 0) (last 0) - quote partial lst) - (mapc (lambda (ch) ; split on [], (), "" balanced instances of [ \t]: - (setq balance (+ balance - (cond ((or (equal 91 ch) (equal 40 ch)) 1) - ((or (equal 93 ch) (equal 41 ch)) -1) - (t 0)))) - (when (and (equal 34 ch) (not (equal 92 last))) - (setq quote (not quote))) - (setq partial (cons ch partial)) - (when (and (= balance 0) (not quote) (funcall matched ch last)) - (setq lst (cons (apply #'string (nreverse - (if (consp alts) - (cddr partial) - (cdr partial)))) - lst)) - (setq partial nil)) - (setq last ch)) - (string-to-list string)) - (nreverse (cons (apply #'string (nreverse partial)) lst)))) +ALTS is a character, or cons of two character options where each +option may be either the numeric code of a single character or +a list of character alternatives. For example, to split on +balanced instances of \"[ \t]:\", set ALTS to ((32 9) . 58)." + (with-temp-buffer + (insert string) + (goto-char (point-min)) + (let ((splitp (lambda (past next) + ;; Non-nil when there should be a split after NEXT + ;; character. PAST is the character before NEXT. + (pcase alts + (`(,(and first (pred consp)) . ,(and second (pred consp))) + (and (memq past first) (memq next second))) + (`(,first . ,(and second (pred consp))) + (and (eq past first) (memq next second))) + (`(,(and first (pred consp)) . ,second) + (and (memq past first) (eq next second))) + (`(,first . ,second) + (and (eq past first) (eq next second))) + ((pred (eq next)) t) + (_ nil)))) + (partial nil) + (result nil)) + (while (not (eobp)) + (cond + ((funcall splitp (char-before) (char-after)) + ;; There is a split after point. If ALTS is two-folds, + ;; remove last parsed character as it belongs to ALTS. + (when (consp alts) (pop partial)) + ;; Include elements parsed so far in RESULTS and flush + ;; partial parsing. + (when partial + (push (apply #'string (nreverse partial)) result) + (setq partial nil)) + (forward-char)) + ((memq (char-after) '(?\( ?\[)) + ;; Include everything between balanced brackets. + (let* ((origin (point)) + (after (char-after)) + (openings (list after))) + (forward-char) + (while (and openings (re-search-forward "[]()]" nil t)) + (pcase (char-before) + ((and match (or ?\[ ?\()) (push match openings)) + (?\] (when (eq ?\[ (car openings)) (pop openings))) + (_ (when (eq ?\( (car openings)) (pop openings))))) + (if (null openings) + (setq partial + (nconc (nreverse (string-to-list + (buffer-substring origin (point)))) + partial)) + ;; Un-balanced bracket. Backtrack. + (push after partial) + (goto-char (1+ origin))))) + ((and (eq ?\" (char-after)) (not (eq ?\\ (char-before)))) + ;; Include everything from current double quote to next + ;; non-escaped double quote. + (let ((origin (point))) + (if (re-search-forward "[^\\]\"" nil t) + (setq partial + (nconc (nreverse (string-to-list + (buffer-substring origin (point)))) + partial)) + ;; No closing double quote. Backtrack. + (push ?\" partial) + (forward-char)))) + (t (push (char-after) partial) + (forward-char)))) + ;; Add pending parsing and return result. + (when partial (push (apply #'string (nreverse partial)) result)) + (nreverse result)))) (defun org-babel-join-splits-near-ch (ch list) "Join splits where \"=\" is on either end of the split." (let ((last= (lambda (str) (= ch (aref str (1- (length str)))))) (first= (lambda (str) (= ch (aref str 0))))) (reverse - (org-reduce (lambda (acc el) + (cl-reduce (lambda (acc el) (let ((head (car acc))) (if (and head (or (funcall last= head) (funcall first= el))) (cons (concat head el) (cdr acc)) @@ -1474,7 +1542,7 @@ shown below. (let (results) (mapc (lambda (pair) (if (eq (car pair) :var) - (mapcar (lambda (v) (push (cons :var (org-babel-trim v)) results)) + (mapcar (lambda (v) (push (cons :var (org-trim v)) results)) (org-babel-join-splits-near-ch 61 (org-babel-balanced-split (cdr pair) 32))) (push pair results))) @@ -1484,48 +1552,52 @@ shown below. (defun org-babel-process-params (params) "Expand variables in PARAMS and add summary parameters." (let* ((processed-vars (mapcar (lambda (el) - (if (consp (cdr el)) - (cdr el) - (org-babel-ref-parse (cdr el)))) - (org-babel-get-header params :var))) - (vars-and-names (if (and (assoc :colname-names params) - (assoc :rowname-names params)) + (if (consp el) + el + (org-babel-ref-parse el))) + (org-babel--get-vars params))) + (vars-and-names (if (and (assq :colname-names params) + (assq :rowname-names params)) (list processed-vars) (org-babel-disassemble-tables processed-vars - (cdr (assoc :hlines params)) - (cdr (assoc :colnames params)) - (cdr (assoc :rownames params))))) - (raw-result (or (cdr (assoc :results params)) "")) - (result-params (append - (split-string (if (stringp raw-result) - raw-result - (eval raw-result))) - (cdr (assoc :result-params params))))) + (cdr (assq :hlines params)) + (cdr (assq :colnames params)) + (cdr (assq :rownames params))))) + (raw-result (or (cdr (assq :results params)) "")) + (result-params (delete-dups + (append + (split-string (if (stringp raw-result) + raw-result + (eval raw-result t))) + (cdr (assq :result-params params)))))) (append (mapcar (lambda (var) (cons :var var)) (car vars-and-names)) (list - (cons :colname-names (or (cdr (assoc :colname-names params)) + (cons :colname-names (or (cdr (assq :colname-names params)) (cadr vars-and-names))) - (cons :rowname-names (or (cdr (assoc :rowname-names params)) - (caddr vars-and-names))) + (cons :rowname-names (or (cdr (assq :rowname-names params)) + (cl-caddr vars-and-names))) (cons :result-params result-params) (cons :result-type (cond ((member "output" result-params) 'output) ((member "value" result-params) 'value) (t 'value)))) - (org-babel-get-header params :var 'other)))) + (cl-remove-if + (lambda (x) (memq (car x) '(:colname-names :rowname-names :result-params + :result-type :var))) + params)))) ;; row and column names (defun org-babel-del-hlines (table) "Remove all `hline's from TABLE." - (remove 'hline table)) + (remq 'hline table)) (defun org-babel-get-colnames (table) "Return the column names of TABLE. Return a cons cell, the `car' of which contains the TABLE less colnames, and the `cdr' of which contains a list of the column names." - (if (equal 'hline (nth 1 table)) + (if (eq 'hline (nth 1 table)) (cons (cddr table) (car table)) (cons (cdr table) (car table)))) @@ -1583,7 +1655,7 @@ of the vars, cnames and rnames." (lambda (var) (when (listp (cdr var)) (when (and (not (equal colnames "no")) - (or colnames (and (equal (nth 1 (cdr var)) 'hline) + (or colnames (and (eq (nth 1 (cdr var)) 'hline) (not (member 'hline (cddr (cdr var))))))) (let ((both (org-babel-get-colnames (cdr var)))) (setq cnames (cons (cons (car var) (cdr both)) @@ -1612,35 +1684,26 @@ to the table for reinsertion to org-mode." (org-babel-put-colnames table colnames) table)) table)) -(defun org-babel-where-is-src-block-head () +(defun org-babel-where-is-src-block-head (&optional src-block) "Find where the current source block begins. -Return the point at the beginning of the current source -block. Specifically at the beginning of the #+BEGIN_SRC line. + +If optional argument SRC-BLOCK is `src-block' type element, find +its current beginning instead. + +Return the point at the beginning of the current source block. +Specifically at the beginning of the #+BEGIN_SRC line. Also set +match-data relatively to `org-babel-src-block-regexp', which see. If the point is not on a source block then return nil." - (let ((initial (point)) (case-fold-search t) top bottom) - (or - (save-excursion ;; on a source name line or a #+header line - (beginning-of-line 1) - (and (or (looking-at org-babel-src-name-regexp) - (looking-at org-babel-multi-line-header-regexp)) - (progn - (while (and (forward-line 1) - (or (looking-at org-babel-src-name-regexp) - (looking-at org-babel-multi-line-header-regexp)))) - (looking-at org-babel-src-block-regexp)) - (point))) - (save-excursion ;; on a #+begin_src line - (beginning-of-line 1) - (and (looking-at org-babel-src-block-regexp) - (point))) - (save-excursion ;; inside a src block - (and - (re-search-backward "^[ \t]*#\\+begin_src" nil t) (setq top (point)) - (re-search-forward "^[ \t]*#\\+end_src" nil t) (setq bottom (point)) - (< top initial) (< initial bottom) - (progn (goto-char top) (beginning-of-line 1) - (looking-at org-babel-src-block-regexp)) - (point-marker)))))) + (let ((element (or src-block (org-element-at-point)))) + (when (eq (org-element-type element) 'src-block) + (let ((end (org-element-property :end element))) + (org-with-wide-buffer + ;; Ensure point is not on a blank line after the block. + (beginning-of-line) + (skip-chars-forward " \r\t\n" end) + (when (< (point) end) + (prog1 (goto-char (org-element-property :post-affiliated element)) + (looking-at org-babel-src-block-regexp)))))))) ;;;###autoload (defun org-babel-goto-src-block-head () @@ -1655,56 +1718,52 @@ If the point is not on a source block then return nil." (interactive (let ((completion-ignore-case t) (case-fold-search t) - (under-point (thing-at-point 'line))) - (list (org-icompleting-read - "source-block name: " (org-babel-src-block-names) nil t - (cond - ;; noweb - ((string-match (org-babel-noweb-wrap) under-point) - (let ((block-name (match-string 1 under-point))) - (string-match "[^(]*" block-name) - (match-string 0 block-name))) - ;; #+call: - ((string-match org-babel-lob-one-liner-regexp under-point) - (let ((source-info (car (org-babel-lob-get-info)))) - (if (string-match "^\\([^\\[]+?\\)\\(\\[.*\\]\\)?(" source-info) - (let ((source-name (match-string 1 source-info))) - source-name)))) - ;; #+results: - ((string-match (concat "#\\+" org-babel-results-keyword - "\\:\s+\\([^\\(]*\\)") under-point) - (match-string 1 under-point)) - ;; symbol-at-point - ((and (thing-at-point 'symbol)) - (org-babel-find-named-block (thing-at-point 'symbol)) - (thing-at-point 'symbol)) - ("")))))) + (all-block-names (org-babel-src-block-names))) + (list (completing-read + "source-block name: " all-block-names nil t + (let* ((context (org-element-context)) + (type (org-element-type context)) + (noweb-ref + (and (memq type '(inline-src-block src-block)) + (org-in-regexp (org-babel-noweb-wrap))))) + (cond + (noweb-ref + (buffer-substring + (+ (car noweb-ref) (length org-babel-noweb-wrap-start)) + (- (cdr noweb-ref) (length org-babel-noweb-wrap-end)))) + ((memq type '(babel-call inline-babel-call)) ;#+CALL: + (org-element-property :call context)) + ((car (org-element-property :results context))) ;#+RESULTS: + ((let ((symbol (thing-at-point 'symbol))) ;Symbol. + (and symbol + (member-ignore-case symbol all-block-names) + symbol))) + (t ""))))))) (let ((point (org-babel-find-named-block name))) (if point - ;; taken from `org-open-at-point' + ;; Taken from `org-open-at-point'. (progn (org-mark-ring-push) (goto-char point) (org-show-context)) (message "source-code block `%s' not found in this buffer" name)))) (defun org-babel-find-named-block (name) "Find a named source-code block. Return the location of the source block identified by source -NAME, or nil if no such block exists. Set match data according to -org-babel-named-src-block-regexp." +NAME, or nil if no such block exists. Set match data according +to `org-babel-named-src-block-regexp'." (save-excursion - (let ((case-fold-search t) - (regexp (org-babel-named-src-block-regexp-for-name name))) - (goto-char (point-min)) - (when (or (re-search-forward regexp nil t) - (re-search-backward regexp nil t)) - (match-beginning 0))))) + (goto-char (point-min)) + (ignore-errors + (org-next-block 1 nil (org-babel-named-src-block-regexp-for-name name))))) (defun org-babel-src-block-names (&optional file) "Returns the names of source blocks in FILE or the current buffer." + (when file (find-file file)) (save-excursion - (when file (find-file file)) (goto-char (point-min)) - (let ((case-fold-search t) names) - (while (re-search-forward org-babel-src-name-w-name-regexp nil t) - (setq names (cons (match-string 3) names))) + (goto-char (point-min)) + (let ((re (org-babel-named-src-block-regexp-for-name)) + names) + (while (ignore-errors (org-next-block 1 nil re)) + (push (match-string-no-properties 9) names)) names))) ;;;###autoload @@ -1712,33 +1771,31 @@ org-babel-named-src-block-regexp." "Go to a named result." (interactive (let ((completion-ignore-case t)) - (list (org-icompleting-read "source-block name: " - (org-babel-result-names) nil t)))) + (list (completing-read "Source-block name: " + (org-babel-result-names) nil t)))) (let ((point (org-babel-find-named-result name))) (if point ;; taken from `org-open-at-point' (progn (goto-char point) (org-show-context)) (message "result `%s' not found in this buffer" name)))) -(defun org-babel-find-named-result (name &optional point) +(defun org-babel-find-named-result (name) "Find a named result. Return the location of the result named NAME in the current buffer or nil if no such result exists." (save-excursion - (let ((case-fold-search t)) - (goto-char (or point (point-min))) - (catch 'is-a-code-block - (when (re-search-forward - (concat org-babel-result-regexp - "[ \t]" (regexp-quote name) "[ \t]*[\n\f\v\r]") - nil t) - (when (and (string= "name" (downcase (match-string 1))) - (or (beginning-of-line 1) - (looking-at org-babel-src-block-regexp) - (looking-at org-babel-multi-line-header-regexp) - (looking-at org-babel-lob-one-liner-regexp))) - (throw 'is-a-code-block (org-babel-find-named-result name (point)))) - (beginning-of-line 0) (point)))))) + (goto-char (point-min)) + (let ((case-fold-search t) + (re (format "^[ \t]*#\\+%s.*?:[ \t]*%s[ \t]*$" + org-babel-results-keyword + (regexp-quote name)))) + (catch :found + (while (re-search-forward re nil t) + (let ((element (org-element-at-point))) + (when (or (eq (org-element-type element) 'keyword) + (< (point) + (org-element-property :post-affiliated element))) + (throw :found (line-beginning-position))))))))) (defun org-babel-result-names (&optional file) "Returns the names of results in FILE or the current buffer." @@ -1746,7 +1803,7 @@ buffer or nil if no such result exists." (when file (find-file file)) (goto-char (point-min)) (let ((case-fold-search t) names) (while (re-search-forward org-babel-result-w-name-regexp nil t) - (setq names (cons (match-string 4) names))) + (setq names (cons (match-string-no-properties 9) names))) names))) ;;;###autoload @@ -1784,26 +1841,31 @@ split. When called from outside of a code block a new code block is created. In both cases if the region is demarcated and if the region is not active then the point is demarcated." (interactive "P") - (let ((info (org-babel-get-src-block-info 'light)) - (headers (progn (org-babel-where-is-src-block-head) - (match-string 4))) - (stars (concat (make-string (or (org-current-level) 1) ?*) " "))) + (let* ((info (org-babel-get-src-block-info 'light)) + (start (org-babel-where-is-src-block-head)) + (block (and start (match-string 0))) + (headers (and start (match-string 4))) + (stars (concat (make-string (or (org-current-level) 1) ?*) " ")) + (lower-case-p (and block + (let (case-fold-search) + (string-match-p "#\\+begin_src" block))))) (if info (mapc (lambda (place) (save-excursion (goto-char place) (let ((lang (nth 0 info)) - (indent (make-string (nth 5 info) ? ))) + (indent (make-string (org-get-indentation) ?\s))) (when (string-match "^[[:space:]]*$" (buffer-substring (point-at-bol) (point-at-eol))) (delete-region (point-at-bol) (point-at-eol))) (insert (concat (if (looking-at "^") "" "\n") - indent "#+end_src\n" + indent (funcall (if lower-case-p 'downcase 'upcase) "#+end_src\n") (if arg stars indent) "\n" - indent "#+begin_src " lang + indent (funcall (if lower-case-p 'downcase 'upcase) "#+begin_src ") + lang (if (> (length headers) 1) (concat " " headers) headers) (if (looking-at "[\n\r]") @@ -1812,7 +1874,7 @@ region is not active then the point is demarcated." (move-end-of-line 2)) (sort (if (org-region-active-p) (list (mark) (point)) (list (point))) #'>)) (let ((start (point)) - (lang (org-icompleting-read + (lang (completing-read "Lang: " (mapcar #'symbol-name (delete-dups @@ -1823,134 +1885,222 @@ region is not active then the point is demarcated." (if (org-region-active-p) (mark) (point)) (point)))) (insert (concat (if (looking-at "^") "" "\n") (if arg (concat stars "\n") "") - "#+begin_src " lang "\n" + (funcall (if lower-case-p 'downcase 'upcase) "#+begin_src ") + lang "\n" body (if (or (= (length body) 0) - (string-match "[\r\n]$" body)) "" "\n") - "#+end_src\n")) + (string-suffix-p "\r" body) + (string-suffix-p "\n" body)) "" "\n") + (funcall (if lower-case-p 'downcase 'upcase) "#+end_src\n"))) (goto-char start) (move-end-of-line 1))))) -(defvar org-babel-lob-one-liner-regexp) -(defun org-babel-where-is-src-block-result (&optional insert info hash indent) +(defun org-babel--insert-results-keyword (name hash) + "Insert RESULTS keyword with NAME value at point. +If NAME is nil, results are anonymous. HASH is a string used as +the results hash, or nil. Leave point before the keyword." + (save-excursion (insert "\n")) ;open line to indent. + (org-indent-line) + (delete-char 1) + (insert (concat "#+" org-babel-results-keyword + (cond ((not hash) nil) + (org-babel-hash-show-time + (format "[%s %s]" + (format-time-string "<%F %T>") + hash)) + (t (format "[%s]" hash))) + ":" + (when name (concat " " name)) + "\n")) + ;; Make sure results are going to be followed by at least one blank + ;; line so they do not get merged with the next element, e.g., + ;; + ;; #+results: + ;; : 1 + ;; + ;; : fixed-width area, unrelated to the above. + (unless (looking-at "^[ \t]*$") (save-excursion (insert "\n"))) + (beginning-of-line 0) + (when hash (org-babel-hide-hash))) + +(defun org-babel--clear-results-maybe (hash) + "Clear results when hash doesn't match HASH. + +When results hash does not match HASH, remove RESULTS keyword at +point, along with related contents. Do nothing if HASH is nil. + +Return a non-nil value if results were cleared. In this case, +leave point where new results should be inserted." + (when hash + (looking-at org-babel-result-regexp) + (unless (string= (match-string 1) hash) + (let* ((e (org-element-at-point)) + (post (copy-marker (org-element-property :post-affiliated e)))) + ;; Delete contents. + (delete-region post + (save-excursion + (goto-char (org-element-property :end e)) + (skip-chars-backward " \t\n") + (line-beginning-position 2))) + ;; Delete RESULT keyword. However, if RESULTS keyword is + ;; orphaned, ignore this part. The deletion above already + ;; took care of it. + (unless (= (point) post) + (delete-region (line-beginning-position) + (line-beginning-position 2))) + (goto-char post) + (set-marker post nil) + t)))) + +(defun org-babel-where-is-src-block-result (&optional insert _info hash) "Find where the current source block results begin. + Return the point at the beginning of the result of the current -source block. Specifically at the beginning of the results line. -If no result exists for this block then create a results line -following the source block." - (save-excursion - (let* ((case-fold-search t) - (on-lob-line (save-excursion - (beginning-of-line 1) - (looking-at org-babel-lob-one-liner-regexp))) - (inlinep (when (org-babel-get-inline-src-block-matches) - (match-end 0))) - (name (nth 4 (or info (org-babel-get-src-block-info 'light)))) - (head (unless on-lob-line (org-babel-where-is-src-block-head))) - found beg end) - (when head (goto-char head)) +source block, specifically at the beginning of the results line. + +If no result exists for this block return nil, unless optional +argument INSERT is non-nil. In this case, create a results line +following the source block and return the position at its +beginning. In the case of inline code, remove the results part +instead. + +If optional argument HASH is a string, remove contents related to +RESULTS keyword if its hash is different. Then update the latter +to HASH." + (let ((context (org-element-context))) + (catch :found (org-with-wide-buffer - (setq - found ;; was there a result (before we potentially insert one) - (or - inlinep - (and - ;; named results: - ;; - return t if it is found, else return nil - ;; - if it does not need to be rebuilt, then don't set end - ;; - if it does need to be rebuilt then do set end - name (setq beg (org-babel-find-named-result name)) - (prog1 beg - (when (and hash (not (string= hash (match-string 5)))) - (goto-char beg) (setq end beg) ;; beginning of result - (forward-line 1) - (delete-region end (org-babel-result-end)) nil))) - (and - ;; unnamed results: - ;; - return t if it is found, else return nil - ;; - if it is found, and the hash doesn't match, delete and set end - (or on-lob-line (re-search-forward "^[ \t]*#\\+end_src" nil t)) - (progn (end-of-line 1) - (if (eobp) (insert "\n") (forward-char 1)) - (setq end (point)) - (or (and - (not name) - (progn ;; unnamed results line already exists - (catch 'non-comment - (while (re-search-forward "[^ \f\t\n\r\v]" nil t) - (beginning-of-line 1) - (cond - ((looking-at (concat org-babel-result-regexp "\n")) - (throw 'non-comment t)) - ((looking-at "^[ \t]*#") (end-of-line 1)) - (t (throw 'non-comment nil)))))) - (let ((this-hash (match-string 5))) - (prog1 (point) - ;; must remove and rebuild if hash!=old-hash - (if (and hash (not (string= hash this-hash))) - (prog1 nil - (forward-line 1) - (delete-region - end (org-babel-result-end))) - (setq end nil))))))))))) - (if (not (and insert end)) found - (goto-char end) - (unless beg - (if (looking-at "[\n\r]") (forward-char 1) (insert "\n"))) - (insert (concat - (when (wholenump indent) (make-string indent ? )) - "#+" org-babel-results-keyword - (when hash - (if org-babel-hash-show-time - (concat - "["(format-time-string "<%Y-%m-%d %H:%M:%S>")" "hash"]") - (concat "["hash"]"))) - ":" - (when name (concat " " name)) "\n")) - (unless beg (insert "\n") (backward-char)) - (beginning-of-line 0) - (if hash (org-babel-hide-hash)) - (point))))) - -(defvar org-block-regexp) + (pcase (org-element-type context) + ((or `inline-babel-call `inline-src-block) + ;; Results for inline objects are located right after them. + ;; There is no RESULTS line to insert either. + (let ((limit (org-element-property + :contents-end (org-element-property :parent context)))) + (goto-char (org-element-property :end context)) + (skip-chars-forward " \t\n" limit) + (throw :found + (and + (< (point) limit) + (let ((result (org-element-context))) + (and (eq (org-element-type result) 'macro) + (string= (org-element-property :key result) + "results") + (if (not insert) (point) + (delete-region + (point) + (progn + (goto-char (org-element-property :end result)) + (skip-chars-backward " \t") + (point))) + (point)))))))) + ((or `babel-call `src-block) + (let* ((name (org-element-property :name context)) + (named-results (and name (org-babel-find-named-result name)))) + (goto-char (or named-results (org-element-property :end context))) + (cond + ;; Existing results named after the current source. + (named-results + (when (org-babel--clear-results-maybe hash) + (org-babel--insert-results-keyword name hash)) + (throw :found (point))) + ;; Named results expect but none to be found. + (name) + ;; No possible anonymous results at the very end of + ;; buffer or outside CONTEXT parent. + ((eq (point) + (or (org-element-property + :contents-end (org-element-property :parent context)) + (point-max)))) + ;; Check if next element is an anonymous result below + ;; the current block. + ((let* ((next (org-element-at-point)) + (end (save-excursion + (goto-char + (org-element-property :post-affiliated next)) + (line-end-position))) + (empty-result-re (concat org-babel-result-regexp "$")) + (case-fold-search t)) + (re-search-forward empty-result-re end t)) + (beginning-of-line) + (when (org-babel--clear-results-maybe hash) + (org-babel--insert-results-keyword nil hash)) + (throw :found (point)))))) + ;; Ignore other elements. + (_ (throw :found nil)))) + ;; No result found. Insert a RESULTS keyword below element, if + ;; appropriate. In this case, ensure there is an empty line + ;; after the previous element. + (when insert + (save-excursion + (goto-char (min (org-element-property :end context) (point-max))) + (skip-chars-backward " \t\n") + (forward-line) + (unless (bolp) (insert "\n")) + (insert "\n") + (org-babel--insert-results-keyword + (org-element-property :name context) hash) + (point)))))) + +(defun org-babel-read-element (element) + "Read ELEMENT into emacs-lisp. +Return nil if ELEMENT cannot be read." + (org-with-wide-buffer + (goto-char (org-element-property :post-affiliated element)) + (pcase (org-element-type element) + (`fixed-width + (let ((v (org-trim (org-element-property :value element)))) + (or (org-babel--string-to-number v) v))) + (`table (org-babel-read-table)) + (`plain-list (org-babel-read-list)) + (`example-block + (let ((v (org-element-property :value element))) + (if (or org-src-preserve-indentation + (org-element-property :preserve-indent element)) + v + (org-remove-indentation v)))) + (`export-block + (org-remove-indentation (org-element-property :value element))) + (`paragraph + ;; Treat paragraphs containing a single link specially. + (skip-chars-forward " \t") + (if (and (looking-at org-bracket-link-regexp) + (save-excursion + (goto-char (match-end 0)) + (skip-chars-forward " \r\t\n") + (<= (org-element-property :end element) + (point)))) + (org-babel-read-link) + (buffer-substring-no-properties + (org-element-property :contents-begin element) + (org-element-property :contents-end element)))) + ((or `center-block `quote-block `verse-block `special-block) + (org-remove-indentation + (buffer-substring-no-properties + (org-element-property :contents-begin element) + (org-element-property :contents-end element)))) + (_ nil)))) + (defun org-babel-read-result () - "Read the result at `point' into emacs-lisp." - (let ((case-fold-search t) result-string) - (cond - ((org-at-table-p) (org-babel-read-table)) - ((org-at-item-p) (org-babel-read-list)) - ((looking-at org-bracket-link-regexp) (org-babel-read-link)) - ((looking-at org-block-regexp) (org-babel-trim (match-string 4))) - ((or (looking-at "^[ \t]*: ") (looking-at "^[ \t]*:$")) - (setq result-string - (org-babel-trim - (mapconcat (lambda (line) - (or (and (> (length line) 1) - (string-match "^[ \t]*: ?\\(.+\\)" line) - (match-string 1 line)) - "")) - (split-string - (buffer-substring - (point) (org-babel-result-end)) "[\r\n]+") - "\n"))) - (or (org-babel-number-p result-string) result-string)) - ((looking-at org-babel-result-regexp) - (save-excursion (forward-line 1) (org-babel-read-result)))))) + "Read the result at point into emacs-lisp." + (and (not (save-excursion + (beginning-of-line) + (looking-at-p "[ \t]*$"))) + (org-babel-read-element (org-element-at-point)))) (defun org-babel-read-table () - "Read the table at `point' into emacs-lisp." + "Read the table at point into emacs-lisp." (mapcar (lambda (row) (if (and (symbolp row) (equal row 'hline)) row (mapcar (lambda (el) (org-babel-read el 'inhibit-lisp-eval)) row))) (org-table-to-lisp))) (defun org-babel-read-list () - "Read the list at `point' into emacs-lisp." + "Read the list at point into emacs-lisp." (mapcar (lambda (el) (org-babel-read el 'inhibit-lisp-eval)) - (mapcar #'cadr (cdr (org-list-parse-list))))) + (cdr (org-list-to-lisp)))) (defvar org-link-types-re) (defun org-babel-read-link () - "Read the link at `point' into emacs-lisp. + "Read the link at point into emacs-lisp. If the path of the link is a file path it is expanded using `expand-file-name'." (let* ((case-fold-search t) @@ -1975,204 +2125,320 @@ If the path of the link is a file path it is expanded using ;; scalar result (funcall echo-res result)))) -(defun org-babel-insert-result - (result &optional result-params info hash indent lang) +(defun org-babel-insert-result (result &optional result-params info hash lang) "Insert RESULT into the current buffer. -By default RESULT is inserted after the end of the -current source block. With optional argument RESULT-PARAMS -controls insertion of results in the org-mode file. -RESULT-PARAMS can take the following values: + +By default RESULT is inserted after the end of the current source +block. The RESULT of an inline source block usually will be +wrapped inside a `results' macro and placed on the same line as +the inline source block. The macro is stripped upon export. +Multiline and non-scalar RESULTS from inline source blocks are +not allowed. With optional argument RESULT-PARAMS controls +insertion of results in the Org mode file. RESULT-PARAMS can +take the following values: replace - (default option) insert results after the source block - replacing any previously inserted results + or inline source block replacing any previously + inserted results. -silent -- no results are inserted into the Org-mode buffer but +silent -- no results are inserted into the Org buffer but the results are echoed to the minibuffer and are ingested by Emacs (a potentially time consuming - process) + process). file ---- the results are interpreted as a file path, and are - inserted into the buffer using the Org-mode file syntax + inserted into the buffer using the Org file syntax. -list ---- the results are interpreted as an Org-mode list. +list ---- the results are interpreted as an Org list. -raw ----- results are added directly to the Org-mode file. This - is a good option if you code block will output org-mode +raw ----- results are added directly to the Org file. This is + a good option if you code block will output Org formatted text. -drawer -- results are added directly to the Org-mode file as with - \"raw\", but are wrapped in a RESULTS drawer, allowing - them to later be replaced or removed automatically. +drawer -- results are added directly to the Org file as with + \"raw\", but are wrapped in a RESULTS drawer or results + macro, allowing them to later be replaced or removed + automatically. -org ----- results are added inside of a \"#+BEGIN_SRC org\" block. - They are not comma-escaped when inserted, but Org syntax - here will be discarded when exporting the file. +org ----- results are added inside of a \"src_org{}\" or \"#+BEGIN_SRC + org\" block depending on whether the current source block is + inline or not. They are not comma-escaped when inserted, + but Org syntax here will be discarded when exporting the + file. -html ---- results are added inside of a #+BEGIN_HTML block. This - is a good option if you code block will output html - formatted text. +html ---- results are added inside of a #+BEGIN_EXPORT HTML block + or html export snippet depending on whether the current + source block is inline or not. This is a good option + if your code block will output html formatted text. -latex --- results are added inside of a #+BEGIN_LATEX block. - This is a good option if you code block will output - latex formatted text. +latex --- results are added inside of a #+BEGIN_EXPORT LATEX + block or latex export snippet depending on whether the + current source block is inline or not. This is a good + option if your code block will output latex formatted + text. code ---- the results are extracted in the syntax of the source code of the language being evaluated and are added - inside of a #+BEGIN_SRC block with the source-code - language set appropriately. Note this relies on the - optional LANG argument." - (if (stringp result) - (progn - (setq result (org-no-properties result)) - (when (member "file" result-params) - (setq result (org-babel-result-to-file - result (when (assoc :file-desc (nth 2 info)) - (or (cdr (assoc :file-desc (nth 2 info))) - result)))))) - (unless (listp result) (setq result (format "%S" result)))) + inside of a source block with the source-code language + set appropriately. Also, source block inlining is + preserved in this case. Note this relies on the + optional LANG argument. + +list ---- the results are rendered as a list. This option not + allowed for inline src blocks. + +table --- the results are rendered as a table. This option not + allowed for inline src blocks. + +INFO may provide the values of these header arguments (in the +`header-arguments-alist' see the docstring for +`org-babel-get-src-block-info'): + +:file --- the name of the file to which output should be written. + +:wrap --- the effect is similar to `latex' in RESULT-PARAMS but + using the argument supplied to specify the export block + or snippet type." + (cond ((stringp result) + (setq result (org-no-properties result)) + (when (member "file" result-params) + (setq result (org-babel-result-to-file + result (when (assq :file-desc (nth 2 info)) + (or (cdr (assq :file-desc (nth 2 info))) + result)))))) + ((listp result)) + (t (setq result (format "%S" result)))) (if (and result-params (member "silent" result-params)) - (progn - (message (replace-regexp-in-string "%" "%%" (format "%S" result))) - result) - (save-excursion - (let* ((inlinep - (save-excursion - (when (or (org-babel-get-inline-src-block-matches) - (org-babel-get-lob-one-liner-matches)) - (goto-char (match-end 0)) - (insert (if (listp result) "\n" " ")) - (point)))) - (existing-result (unless inlinep - (org-babel-where-is-src-block-result - t info hash indent))) - (results-switches - (cdr (assoc :results_switches (nth 2 info)))) - (visible-beg (point-min-marker)) - (visible-end (point-max-marker)) - ;; When results exist outside of the current visible - ;; region of the buffer, be sure to widen buffer to - ;; update them. - (outside-scope-p (and existing-result + (progn (message (replace-regexp-in-string "%" "%%" (format "%S" result))) + result) + (let ((inline (let ((context (org-element-context))) + (and (memq (org-element-type context) + '(inline-babel-call inline-src-block)) + context)))) + (when inline + (let ((warning + (or (and (member "table" result-params) "`:results table'") + (and (listp result) "list result") + (and (string-match-p "\n." result) "multiline result") + (and (member "list" result-params) "`:results list'")))) + (when warning + (user-error "Inline error: %s cannot be used" warning)))) + (save-excursion + (let* ((visible-beg (point-min-marker)) + (visible-end (copy-marker (point-max) t)) + (inline (let ((context (org-element-context))) + (and (memq (org-element-type context) + '(inline-babel-call inline-src-block)) + context))) + (existing-result (org-babel-where-is-src-block-result t nil hash)) + (results-switches (cdr (assq :results_switches (nth 2 info)))) + ;; When results exist outside of the current visible + ;; region of the buffer, be sure to widen buffer to + ;; update them. + (outside-scope (and existing-result + (buffer-narrowed-p) (or (> visible-beg existing-result) (<= visible-end existing-result)))) - beg end) - (when (and (stringp result) ; ensure results end in a newline - (not inlinep) - (> (length result) 0) - (not (or (string-equal (substring result -1) "\n") - (string-equal (substring result -1) "\r")))) - (setq result (concat result "\n"))) - (unwind-protect - (progn - (when outside-scope-p (widen)) - (if (not existing-result) - (setq beg (or inlinep (point))) - (goto-char existing-result) - (save-excursion - (re-search-forward "#" nil t) - (setq indent (- (current-column) 1))) - (forward-line 1) + beg end indent) + ;; Ensure non-inline results end in a newline. + (when (and (org-string-nw-p result) + (not inline) + (not (string-equal (substring result -1) "\n"))) + (setq result (concat result "\n"))) + (unwind-protect + (progn + (when outside-scope (widen)) + (if existing-result (goto-char existing-result) + (goto-char (org-element-property :end inline)) + (skip-chars-backward " \t")) + (unless inline + (setq indent (org-get-indentation)) + (forward-line 1)) (setq beg (point)) (cond + (inline + ;; Make sure new results are separated from the + ;; source code by one space. + (unless existing-result + (insert " ") + (setq beg (point)))) ((member "replace" result-params) (delete-region (point) (org-babel-result-end))) ((member "append" result-params) (goto-char (org-babel-result-end)) (setq beg (point-marker))) - ((member "prepend" result-params)))) ; already there - (setq results-switches - (if results-switches (concat " " results-switches) "")) - (let ((wrap (lambda (start finish &optional no-escape) - (goto-char end) (insert (concat finish "\n")) - (goto-char beg) (insert (concat start "\n")) - (unless no-escape - (org-escape-code-in-region (min (point) end) end)) - (goto-char end) (goto-char (point-at-eol)) - (setq end (point-marker)))) - (proper-list-p (lambda (it) (and (listp it) (null (cdr (last it))))))) - ;; insert results based on type - (cond - ;; do nothing for an empty result - ((null result)) - ;; insert a list if preferred - ((member "list" result-params) - (insert - (org-babel-trim - (org-list-to-generic - (cons 'unordered - (mapcar - (lambda (el) (list nil (if (stringp el) el (format "%S" el)))) - (if (listp result) result (split-string result "\n" t)))) - '(:splicep nil :istart "- " :iend "\n"))) - "\n")) - ;; assume the result is a table if it's not a string - ((funcall proper-list-p result) - (goto-char beg) - (insert (concat (orgtbl-to-orgtbl - (if (org-every - (lambda (el) (or (listp el) (eq el 'hline))) - result) - result (list result)) - '(:fmt (lambda (cell) (format "%s" cell)))) "\n")) - (goto-char beg) (when (org-at-table-p) (org-table-align))) - ((and (listp result) (not (funcall proper-list-p result))) - (insert (format "%s\n" result))) - ((member "file" result-params) - (when inlinep (goto-char inlinep)) - (insert result)) - (t (goto-char beg) (insert result))) - (when (funcall proper-list-p result) (goto-char (org-table-end))) - (setq end (point-marker)) - ;; possibly wrap result - (cond - ((assoc :wrap (nth 2 info)) - (let ((name (or (cdr (assoc :wrap (nth 2 info))) "RESULTS"))) - (funcall wrap (concat "#+BEGIN_" name) - (concat "#+END_" (car (org-split-string name)))))) - ((member "html" result-params) - (funcall wrap "#+BEGIN_HTML" "#+END_HTML")) - ((member "latex" result-params) - (funcall wrap "#+BEGIN_LaTeX" "#+END_LaTeX")) - ((member "org" result-params) - (goto-char beg) (if (org-at-table-p) (org-cycle)) - (funcall wrap "#+BEGIN_SRC org" "#+END_SRC")) - ((member "code" result-params) - (funcall wrap (format "#+BEGIN_SRC %s%s" (or lang "none") results-switches) - "#+END_SRC")) - ((member "raw" result-params) - (goto-char beg) (if (org-at-table-p) (org-cycle))) - ((or (member "drawer" result-params) - ;; Stay backward compatible with <7.9.2 - (member "wrap" result-params)) - (goto-char beg) (if (org-at-table-p) (org-cycle)) - (funcall wrap ":RESULTS:" ":END:" 'no-escape)) - ((and (not (funcall proper-list-p result)) - (not (member "file" result-params))) - (org-babel-examplize-region beg end results-switches) - (setq end (point))))) - ;; possibly indent the results to match the #+results line - (when (and (not inlinep) (numberp indent) indent (> indent 0) - ;; in this case `table-align' does the work for us - (not (and (listp result) - (member "append" result-params)))) - (indent-rigidly beg end indent)) - (if (null result) - (if (member "value" result-params) - (message "Code block returned no value.") - (message "Code block produced no output.")) - (message "Code block evaluation complete."))) - (when outside-scope-p (narrow-to-region visible-beg visible-end)) - (set-marker visible-beg nil) - (set-marker visible-end nil)))))) - -(defun org-babel-remove-result (&optional info) + ((member "prepend" result-params))) ; already there + (setq results-switches + (if results-switches (concat " " results-switches) "")) + (let ((wrap (lambda (start finish &optional no-escape no-newlines + inline-start inline-finish) + (when inline + (setq start inline-start) + (setq finish inline-finish) + (setq no-newlines t)) + (goto-char end) + (insert (concat finish (unless no-newlines "\n"))) + (goto-char beg) + (insert (concat start (unless no-newlines "\n"))) + (unless no-escape + (org-escape-code-in-region (min (point) end) end)) + (goto-char end) + (unless no-newlines (goto-char (point-at-eol))) + (setq end (point-marker)))) + (tabulablep + (lambda (r) + ;; Non-nil when result R can be turned into + ;; a table. + (and (listp r) + (null (cdr (last r))) + (cl-every + (lambda (e) (or (atom e) (null (cdr (last e))))) + result))))) + ;; insert results based on type + (cond + ;; Do nothing for an empty result. + ((null result)) + ;; Insert a list if preferred. + ((member "list" result-params) + (insert + (org-trim + (org-list-to-generic + (cons 'unordered + (mapcar + (lambda (e) + (list (if (stringp e) e (format "%S" e)))) + (if (listp result) result + (split-string result "\n" t)))) + '(:splicep nil :istart "- " :iend "\n"))) + "\n")) + ;; Try hard to print RESULT as a table. Give up if + ;; it contains an improper list. + ((funcall tabulablep result) + (goto-char beg) + (insert (concat (orgtbl-to-orgtbl + (if (cl-every + (lambda (e) + (or (eq e 'hline) (listp e))) + result) + result + (list result)) + nil) + "\n")) + (goto-char beg) + (when (org-at-table-p) (org-table-align)) + (goto-char (org-table-end))) + ;; Print verbatim a list that cannot be turned into + ;; a table. + ((listp result) (insert (format "%s\n" result))) + ((member "file" result-params) + (when inline + (setq result (org-macro-escape-arguments result))) + (insert result)) + ((and inline (not (member "raw" result-params))) + (insert (org-macro-escape-arguments + (org-babel-chomp result "\n")))) + (t (goto-char beg) (insert result))) + (setq end (point-marker)) + ;; possibly wrap result + (cond + ((assq :wrap (nth 2 info)) + (let ((name (or (cdr (assq :wrap (nth 2 info))) "RESULTS"))) + (funcall wrap (concat "#+BEGIN_" name) + (concat "#+END_" (car (org-split-string name))) + nil nil (concat "{{{results(@@" name ":") "@@)}}}"))) + ((member "html" result-params) + (funcall wrap "#+BEGIN_EXPORT html" "#+END_EXPORT" nil nil + "{{{results(@@html:" "@@)}}}")) + ((member "latex" result-params) + (funcall wrap "#+BEGIN_EXPORT latex" "#+END_EXPORT" nil nil + "{{{results(@@latex:" "@@)}}}")) + ((member "org" result-params) + (goto-char beg) (when (org-at-table-p) (org-cycle)) + (funcall wrap "#+BEGIN_SRC org" "#+END_SRC" nil nil + "{{{results(src_org{" "})}}}")) + ((member "code" result-params) + (let ((lang (or lang "none"))) + (funcall wrap (format "#+BEGIN_SRC %s%s" lang results-switches) + "#+END_SRC" nil nil + (format "{{{results(src_%s[%s]{" lang results-switches) + "})}}}"))) + ((member "raw" result-params) + (goto-char beg) (when (org-at-table-p) (org-cycle))) + ((or (member "drawer" result-params) + ;; Stay backward compatible with <7.9.2 + (member "wrap" result-params)) + (goto-char beg) (when (org-at-table-p) (org-cycle)) + (funcall wrap ":RESULTS:" ":END:" 'no-escape nil + "{{{results(" ")}}}")) + ((and inline (member "file" result-params)) + (funcall wrap nil nil nil nil "{{{results(" ")}}}")) + ((and (not (funcall tabulablep result)) + (not (member "file" result-params))) + (let ((org-babel-inline-result-wrap + ;; Hard code {{{results(...)}}} on top of customization. + (format "{{{results(%s)}}}" + org-babel-inline-result-wrap))) + (org-babel-examplify-region beg end results-switches inline) + (setq end (point)))))) + ;; Possibly indent results in par with #+results line. + (when (and (not inline) (numberp indent) (> indent 0) + ;; In this case `table-align' does the work + ;; for us. + (not (and (listp result) + (member "append" result-params)))) + (indent-rigidly beg end indent)) + (if (null result) + (if (member "value" result-params) + (message "Code block returned no value.") + (message "Code block produced no output.")) + (message "Code block evaluation complete."))) + (when outside-scope (narrow-to-region visible-beg visible-end)) + (set-marker visible-beg nil) + (set-marker visible-end nil))))))) + +(defun org-babel-remove-result (&optional info keep-keyword) "Remove the result of the current source block." (interactive) - (let ((location (org-babel-where-is-src-block-result nil info)) start) + (let ((location (org-babel-where-is-src-block-result nil info))) (when location - (setq start (- location 1)) (save-excursion - (goto-char location) (forward-line 1) - (delete-region start (org-babel-result-end)))))) + (goto-char location) + (when (looking-at (concat org-babel-result-regexp ".*$")) + (delete-region + (if keep-keyword (1+ (match-end 0)) (1- (match-beginning 0))) + (progn (forward-line 1) (org-babel-result-end)))))))) + +(defun org-babel-remove-inline-result (&optional datum) + "Remove the result of the current inline-src-block or babel call. +The result must be wrapped in a `results' macro to be removed. +Leading white space is trimmed." + (interactive) + (let* ((el (or datum (org-element-context)))) + (when (memq (org-element-type el) '(inline-src-block inline-babel-call)) + (org-with-wide-buffer + (goto-char (org-element-property :end el)) + (skip-chars-backward " \t") + (let ((result (save-excursion + (skip-chars-forward + " \t\n" + (org-element-property + :contents-end (org-element-property :parent el))) + (org-element-context)))) + (when (and (eq (org-element-type result) 'macro) + (string= (org-element-property :key result) "results")) + (delete-region ; And leading whitespace. + (point) + (progn (goto-char (org-element-property :end result)) + (skip-chars-backward " \t\n") + (point))))))))) + +(defun org-babel-remove-result-one-or-many (x) + "Remove the result of the current source block. +If called with a prefix argument, remove all result blocks +in the buffer." + (interactive "P") + (if x + (org-babel-map-src-blocks nil (org-babel-remove-result)) + (org-babel-remove-result))) (defun org-babel-result-end () "Return the point at the end of the current set of results." @@ -2210,29 +2476,26 @@ file's directory then expand relative links." result) (if description (concat "[" description "]") "")))) -(defvar org-babel-capitalize-examplize-region-markers nil +(defvar org-babel-capitalize-example-region-markers nil "Make true to capitalize begin/end example markers inserted by code blocks.") -(defun org-babel-examplize-region (beg end &optional results-switches) +(defun org-babel-examplify-region (beg end &optional results-switches inline) "Comment out region using the inline `==' or `: ' org example quote." (interactive "*r") - (let ((chars-between (lambda (b e) - (not (string-match "^[\\s]*$" (buffer-substring b e))))) - (maybe-cap (lambda (str) (if org-babel-capitalize-examplize-region-markers - (upcase str) str)))) - (if (or (funcall chars-between (save-excursion (goto-char beg) (point-at-bol)) beg) - (funcall chars-between end (save-excursion (goto-char end) (point-at-eol)))) + (let ((maybe-cap + (lambda (str) + (if org-babel-capitalize-example-region-markers (upcase str) str)))) + (if inline (save-excursion (goto-char beg) (insert (format org-babel-inline-result-wrap - (prog1 (buffer-substring beg end) - (delete-region beg end))))) + (delete-and-extract-region beg end)))) (let ((size (count-lines beg end))) (save-excursion (cond ((= size 0)) ; do nothing for an empty result ((< size org-babel-min-lines-for-block-output) (goto-char beg) - (dotimes (n size) + (dotimes (_ size) (beginning-of-line 1) (insert ": ") (forward-line 1))) (t (goto-char beg) @@ -2241,16 +2504,37 @@ file's directory then expand relative links." (funcall maybe-cap "#+begin_example") results-switches) (funcall maybe-cap "#+begin_example\n"))) - (if (markerp end) (goto-char end) (forward-char (- end beg))) + (let ((p (point))) + (if (markerp end) (goto-char end) (forward-char (- end beg))) + (org-escape-code-in-region p (point))) (insert (funcall maybe-cap "#+end_example\n"))))))))) (defun org-babel-update-block-body (new-body) "Update the body of the current code block to NEW-BODY." - (if (not (org-babel-where-is-src-block-head)) - (error "Not in a source block") - (save-match-data - (replace-match (concat (org-babel-trim new-body) "\n") nil t nil 5)) - (indent-rigidly (match-beginning 5) (match-end 5) 2))) + (let ((element (org-element-at-point))) + (unless (eq (org-element-type element) 'src-block) + (error "Not in a source block")) + (goto-char (org-babel-where-is-src-block-head element)) + (let* ((ind (org-get-indentation)) + (body-start (line-beginning-position 2)) + (body (org-element-normalize-string + (if (or org-src-preserve-indentation + (org-element-property :preserve-indent element)) + new-body + (with-temp-buffer + (insert (org-remove-indentation new-body)) + (indent-rigidly + (point-min) + (point-max) + (+ ind org-edit-src-content-indentation)) + (buffer-string)))))) + (delete-region body-start + (org-with-wide-buffer + (goto-char (org-element-property :end element)) + (skip-chars-backward " \t\n") + (line-beginning-position))) + (goto-char body-start) + (insert body)))) (defun org-babel-merge-params (&rest plists) "Combine all parameter association lists in PLISTS. @@ -2259,133 +2543,103 @@ This takes into account some special considerations for certain parameters when merging lists." (let* ((results-exclusive-groups (mapcar (lambda (group) (mapcar #'symbol-name group)) - (cdr (assoc 'results org-babel-common-header-args-w-values)))) + (cdr (assq 'results org-babel-common-header-args-w-values)))) (exports-exclusive-groups (mapcar (lambda (group) (mapcar #'symbol-name group)) - (cdr (assoc 'exports org-babel-common-header-args-w-values)))) - (variable-index 0) - (e-merge (lambda (exclusive-groups &rest result-params) - ;; maintain exclusivity of mutually exclusive parameters - (let (output) - (mapc (lambda (new-params) - (mapc (lambda (new-param) - (mapc (lambda (exclusive-group) - (when (member new-param exclusive-group) - (mapcar (lambda (excluded-param) - (setq output - (delete - excluded-param - output))) - exclusive-group))) - exclusive-groups) - (setq output (org-uniquify - (cons new-param output)))) - new-params)) - result-params) - output))) - params results exports tangle noweb cache vars shebang comments padline - clearnames) - - (mapc - (lambda (plist) - (mapc - (lambda (pair) - (case (car pair) - (:var - (let ((name (if (listp (cdr pair)) - (cadr pair) - (and (string-match "^\\([^= \f\t\n\r\v]+\\)[ \t]*=" - (cdr pair)) - (intern (match-string 1 (cdr pair))))))) - (if name - (setq vars - (append - (if (member name (mapcar #'car vars)) - (progn - (push name clearnames) - (delq nil - (mapcar - (lambda (p) - (unless (equal (car p) name) p)) - vars))) - vars) - (list (cons name pair)))) - ;; if no name is given and we already have named variables - ;; then assign to named variables in order - (if (and vars (nth variable-index vars)) - (let ((name (car (nth variable-index vars)))) - (push name clearnames) ; clear out colnames - ; and rownames - ; for replace vars - (prog1 (setf (cddr (nth variable-index vars)) - (concat (symbol-name name) "=" (cdr pair))) - (incf variable-index))) - (error "Variable \"%s\" must be assigned a default value" - (cdr pair)))))) - (:results - (setq results (funcall e-merge results-exclusive-groups - results - (split-string - (let ((r (cdr pair))) - (if (stringp r) r (eval r))))))) - (:file - (when (cdr pair) - (setq results (funcall e-merge results-exclusive-groups - results '("file"))) - (unless (or (member "both" exports) - (member "none" exports) - (member "code" exports)) - (setq exports (funcall e-merge exports-exclusive-groups - exports '("results")))) - (setq params (cons pair (assq-delete-all (car pair) params))))) - (:exports - (setq exports (funcall e-merge exports-exclusive-groups - exports (split-string (cdr pair))))) - (:tangle ;; take the latest -- always overwrite - (setq tangle (or (list (cdr pair)) tangle))) - (:noweb - (setq noweb (funcall e-merge - '(("yes" "no" "tangle" "no-export" - "strip-export" "eval")) - noweb - (split-string (or (cdr pair) ""))))) - (:cache - (setq cache (funcall e-merge '(("yes" "no")) cache - (split-string (or (cdr pair) ""))))) - (:padline - (setq padline (funcall e-merge '(("yes" "no")) padline - (split-string (or (cdr pair) ""))))) - (:shebang ;; take the latest -- always overwrite - (setq shebang (or (list (cdr pair)) shebang))) - (:comments - (setq comments (funcall e-merge '(("yes" "no")) comments - (split-string (or (cdr pair) ""))))) - (t ;; replace: this covers e.g. :session - (setq params (cons pair (assq-delete-all (car pair) params)))))) - plist)) - plists) - (setq vars (reverse vars)) - (while vars (setq params (cons (cons :var (cddr (pop vars))) params))) - ;; clear out col-names and row-names for replaced variables - (mapc - (lambda (name) - (mapc - (lambda (param) - (when (assoc param params) - (setf (cdr (assoc param params)) - (org-remove-if (lambda (pair) (equal (car pair) name)) - (cdr (assoc param params)))) - (setf params (org-remove-if (lambda (pair) (and (equal (car pair) param) - (null (cdr pair)))) - params)))) - (list :colname-names :rowname-names))) - clearnames) - (mapc - (lambda (hd) - (let ((key (intern (concat ":" (symbol-name hd)))) - (val (eval hd))) - (setf params (cons (cons key (mapconcat 'identity val " ")) params)))) - '(results exports tangle noweb padline cache shebang comments)) + (cdr (assq 'exports org-babel-common-header-args-w-values)))) + (merge + (lambda (exclusive-groups &rest result-params) + ;; Maintain exclusivity of mutually exclusive parameters, + ;; as defined in EXCLUSIVE-GROUPS while merging lists in + ;; RESULT-PARAMS. + (let (output) + (dolist (new-params result-params (delete-dups output)) + (dolist (new-param new-params) + (dolist (exclusive-group exclusive-groups) + (when (member new-param exclusive-group) + (setq output (cl-remove-if + (lambda (o) (member o exclusive-group)) + output)))) + (push new-param output)))))) + (variable-index 0) ;Handle positional arguments. + clearnames + params ;Final parameters list. + ;; Some keywords accept multiple values. We need to treat + ;; them specially. + vars results exports) + (dolist (plist plists) + (dolist (pair plist) + (pcase pair + (`(:var . ,value) + (let ((name (cond + ((listp value) (car value)) + ((string-match "^\\([^= \f\t\n\r\v]+\\)[ \t]*=" value) + (intern (match-string 1 value))) + (t nil)))) + (cond + (name + (setq vars + (append (if (not (assoc name vars)) vars + (push name clearnames) + (cl-remove-if (lambda (p) (equal name (car p))) + vars)) + (list (cons name pair))))) + ((and vars (nth variable-index vars)) + ;; If no name is given and we already have named + ;; variables then assign to named variables in order. + (let ((name (car (nth variable-index vars)))) + ;; Clear out colnames and rownames for replace vars. + (push name clearnames) + (setf (cddr (nth variable-index vars)) + (concat (symbol-name name) "=" value)) + (cl-incf variable-index))) + (t (error "Variable \"%s\" must be assigned a default value" + (cdr pair)))))) + (`(:results . ,value) + (setq results (funcall merge + results-exclusive-groups + results + (split-string + (if (stringp value) value (eval value t)))))) + (`(,(or :file :file-ext) . ,value) + ;; `:file' and `:file-ext' are regular keywords but they + ;; imply a "file" `:results' and a "results" `:exports'. + (when value + (setq results + (funcall merge results-exclusive-groups results '("file"))) + (unless (or (member "both" exports) + (member "none" exports) + (member "code" exports)) + (setq exports + (funcall merge + exports-exclusive-groups exports '("results")))) + (push pair params))) + (`(:exports . ,value) + (setq exports (funcall merge + exports-exclusive-groups + exports + (split-string (or value ""))))) + ;; Regular keywords: any value overwrites the previous one. + (_ (setq params (cons pair (assq-delete-all (car pair) params))))))) + ;; Handle `:var' and clear out colnames and rownames for replaced + ;; variables. + (setq params (nconc (mapcar (lambda (v) (cons :var (cddr v))) vars) + params)) + (dolist (name clearnames) + (dolist (param '(:colname-names :rowname-names)) + (when (assq param params) + (setf (cdr (assq param params)) + (cl-remove-if (lambda (pair) (equal name (car pair))) + (cdr (assq param params)))) + (setq params + (cl-remove-if (lambda (pair) (and (equal (car pair) param) + (null (cdr pair)))) + params))))) + ;; Handle other special keywords, which accept multiple values. + (setq params (nconc (list (cons :results (mapconcat #'identity results " ")) + (cons :exports (mapconcat #'identity exports " "))) + params)) + ;; Return merged params. params)) (defvar org-babel-use-quick-and-dirty-noweb-expansion nil @@ -2397,17 +2651,12 @@ header argument from buffer or subtree wide properties.") (defun org-babel-noweb-p (params context) "Check if PARAMS require expansion in CONTEXT. CONTEXT may be one of :tangle, :export or :eval." - (let* (intersect - (intersect (lambda (as bs) - (when as - (if (member (car as) bs) - (car as) - (funcall intersect (cdr as) bs)))))) - (funcall intersect (case context - (:tangle '("yes" "tangle" "no-export" "strip-export")) - (:eval '("yes" "no-export" "strip-export" "eval")) - (:export '("yes"))) - (split-string (or (cdr (assoc :noweb params)) ""))))) + (let ((allowed-values (cl-case context + (:tangle '("yes" "tangle" "no-export" "strip-export")) + (:eval '("yes" "no-export" "strip-export" "eval")) + (:export '("yes"))))) + (cl-some (lambda (v) (member v allowed-values)) + (split-string (or (cdr (assq :noweb params)) ""))))) (defun org-babel-expand-noweb-references (&optional info parent-buffer) "Expand Noweb references in the body of the current source code block. @@ -2445,7 +2694,7 @@ block but are passed literally to the \"example-block\"." (body (nth 1 info)) (ob-nww-start org-babel-noweb-wrap-start) (ob-nww-end org-babel-noweb-wrap-end) - (comment (string= "noweb" (cdr (assoc :comments (nth 2 info))))) + (comment (string= "noweb" (cdr (assq :comments (nth 2 info))))) (rx-prefix (concat "\\(" org-babel-src-name-regexp "\\|" ":noweb-ref[ \t]+" "\\)")) (new-body "") @@ -2454,11 +2703,11 @@ block but are passed literally to the \"example-block\"." (with-temp-buffer (funcall (intern (concat lang "-mode"))) (comment-region (point) (progn (insert text) (point))) - (org-babel-trim (buffer-string))))) + (org-trim (buffer-string))))) index source-name evaluate prefix) (with-temp-buffer - (org-set-local 'org-babel-noweb-wrap-start ob-nww-start) - (org-set-local 'org-babel-noweb-wrap-end ob-nww-end) + (setq-local org-babel-noweb-wrap-start ob-nww-start) + (setq-local org-babel-noweb-wrap-end ob-nww-end) (insert body) (goto-char (point-min)) (setq index (point)) (while (and (re-search-forward (org-babel-noweb-wrap) nil t)) @@ -2502,7 +2751,7 @@ block but are passed literally to the \"example-block\"." (while (re-search-forward rx nil t) (let* ((i (org-babel-get-src-block-info 'light)) (body (org-babel-expand-noweb-references i)) - (sep (or (cdr (assoc :noweb-sep (nth 2 i))) + (sep (or (cdr (assq :noweb-sep (nth 2 i))) "\n")) (full (if comment (let ((cs (org-babel-tangle-comment-links i))) @@ -2513,11 +2762,11 @@ block but are passed literally to the \"example-block\"." (setq expansion (cons sep (cons full expansion))))) (org-babel-map-src-blocks nil (let ((i (org-babel-get-src-block-info 'light))) - (when (equal (or (cdr (assoc :noweb-ref (nth 2 i))) + (when (equal (or (cdr (assq :noweb-ref (nth 2 i))) (nth 4 i)) source-name) (let* ((body (org-babel-expand-noweb-references i)) - (sep (or (cdr (assoc :noweb-sep (nth 2 i))) + (sep (or (cdr (assq :noweb-sep (nth 2 i))) "\n")) (full (if comment (let ((cs (org-babel-tangle-comment-links i))) @@ -2530,7 +2779,8 @@ block but are passed literally to the \"example-block\"." (and expansion (mapconcat #'identity (nreverse (cdr expansion)) ""))) ;; Possibly raise an error if named block doesn't exist. - (if (member lang org-babel-noweb-error-langs) + (if (or org-babel-noweb-error-all-langs + (member lang org-babel-noweb-error-langs)) (error "%s" (concat (org-babel-noweb-wrap source-name) "could not be resolved (see " @@ -2540,79 +2790,120 @@ block but are passed literally to the \"example-block\"." (funcall nb-add (buffer-substring index (point-max)))) new-body)) +(defun org-babel--script-escape-inner (str) + (let (in-single in-double backslash out) + (mapc + (lambda (ch) + (setq + out + (if backslash + (progn + (setq backslash nil) + (cond + ((and in-single (eq ch ?')) + ;; Escaped single quote inside single quoted string: + ;; emit just a single quote, since we've changed the + ;; outer quotes to double. + (cons ch out)) + ((eq ch ?\") + ;; Escaped double quote + (if in-single + ;; This should be interpreted as backslash+quote, + ;; not an escape. Emit a three backslashes + ;; followed by a quote (because one layer of + ;; quoting will be stripped by `org-babel-read'). + (append (list ch ?\\ ?\\ ?\\) out) + ;; Otherwise we are in a double-quoted string. Emit + ;; a single escaped quote + (append (list ch ?\\) out))) + ((eq ch ?\\) + ;; Escaped backslash: emit a single escaped backslash + (append (list ?\\ ?\\) out)) + ;; Other: emit a quoted backslash followed by whatever + ;; the character was (because one layer of quoting will + ;; be stripped by `org-babel-read'). + (t (append (list ch ?\\ ?\\) out)))) + (cl-case ch + (?\[ (if (or in-double in-single) + (cons ?\[ out) + (cons ?\( out))) + (?\] (if (or in-double in-single) + (cons ?\] out) + (cons ?\) out))) + (?\{ (if (or in-double in-single) + (cons ?\{ out) + (cons ?\( out))) + (?\} (if (or in-double in-single) + (cons ?\} out) + (cons ?\) out))) + (?, (if (or in-double in-single) + (cons ?, out) (cons ?\s out))) + (?\' (if in-double + (cons ?\' out) + (setq in-single (not in-single)) (cons ?\" out))) + (?\" (if in-single + (append (list ?\" ?\\) out) + (setq in-double (not in-double)) (cons ?\" out))) + (?\\ (unless (or in-single in-double) + (error "Can't handle backslash outside string in `org-babel-script-escape'")) + (setq backslash t) + out) + (t (cons ch out)))))) + (string-to-list str)) + (when (or in-single in-double) + (error "Unterminated string in `org-babel-script-escape'")) + (apply #'string (reverse out)))) + (defun org-babel-script-escape (str &optional force) "Safely convert tables into elisp lists." + (unless (stringp str) + (error "`org-babel-script-escape' expects a string")) (let ((escaped - (if (or force - (and (stringp str) - (> (length str) 2) - (or (and (string-equal "[" (substring str 0 1)) - (string-equal "]" (substring str -1))) - (and (string-equal "{" (substring str 0 1)) - (string-equal "}" (substring str -1))) - (and (string-equal "(" (substring str 0 1)) - (string-equal ")" (substring str -1)))))) - (org-babel-read - (concat - "'" - (let (in-single in-double out) - (mapc - (lambda (ch) - (setq - out - (case ch - (91 (if (or in-double in-single) ; [ - (cons 91 out) - (cons 40 out))) - (93 (if (or in-double in-single) ; ] - (cons 93 out) - (cons 41 out))) - (123 (if (or in-double in-single) ; { - (cons 123 out) - (cons 40 out))) - (125 (if (or in-double in-single) ; } - (cons 125 out) - (cons 41 out))) - (44 (if (or in-double in-single) ; , - (cons 44 out) (cons 32 out))) - (39 (if in-double ; ' - (cons 39 out) - (setq in-single (not in-single)) (cons 34 out))) - (34 (if in-single ; " - (append (list 34 32) out) - (setq in-double (not in-double)) (cons 34 out))) - (t (cons ch out))))) - (string-to-list str)) - (apply #'string (reverse out))))) - str))) + (cond + ((and (> (length str) 2) + (or (and (string-equal "[" (substring str 0 1)) + (string-equal "]" (substring str -1))) + (and (string-equal "{" (substring str 0 1)) + (string-equal "}" (substring str -1))) + (and (string-equal "(" (substring str 0 1)) + (string-equal ")" (substring str -1))))) + + (concat "'" (org-babel--script-escape-inner str))) + ((or force + (and (> (length str) 2) + (or (and (string-equal "'" (substring str 0 1)) + (string-equal "'" (substring str -1))) + ;; We need to pass double-quoted strings + ;; through the backslash-twiddling bits, even + ;; though we don't need to change their + ;; delimiters. + (and (string-equal "\"" (substring str 0 1)) + (string-equal "\"" (substring str -1)))))) + (org-babel--script-escape-inner str)) + (t str)))) (condition-case nil (org-babel-read escaped) (error escaped)))) (defun org-babel-read (cell &optional inhibit-lisp-eval) "Convert the string value of CELL to a number if appropriate. -Otherwise if cell looks like lisp (meaning it starts with a -\"(\", \"\\='\", \"\\=`\" or a \"[\") then read it as lisp, -otherwise return it unmodified as a string. Optional argument -NO-LISP-EVAL inhibits lisp evaluation for situations in which is -it not appropriate." - (if (and (stringp cell) (not (equal cell ""))) - (or (org-babel-number-p cell) - (if (and (not inhibit-lisp-eval) - (or (member (substring cell 0 1) '("(" "'" "`" "[")) - (string= cell "*this*"))) - (eval (read cell)) - (if (string= (substring cell 0 1) "\"") - (read cell) - (progn (set-text-properties 0 (length cell) nil cell) cell)))) - cell)) - -(defun org-babel-number-p (string) - "If STRING represents a number return its value." - (if (and (string-match "[0-9]+" string) - (string-match "^-?[0-9]*\\.?[0-9]*$" string) - (= (length (substring string (match-beginning 0) - (match-end 0))) - (length string))) - (string-to-number string))) +Otherwise if CELL looks like lisp (meaning it starts with a +\"(\", \"\\='\", \"\\=`\" or a \"[\") then read and evaluate it as +lisp, otherwise return it unmodified as a string. Optional +argument INHIBIT-LISP-EVAL inhibits lisp evaluation for +situations in which is it not appropriate." + (cond ((not (org-string-nw-p cell)) cell) + ((org-babel--string-to-number cell)) + ((and (not inhibit-lisp-eval) + (or (memq (string-to-char cell) '(?\( ?' ?` ?\[)) + (string= cell "*this*"))) + (eval (read cell) t)) + ((eq (string-to-char cell) ?\") (read cell)) + (t (org-no-properties cell)))) + +(defun org-babel--string-to-number (string) + "If STRING represents a number return its value. +Otherwise return nil." + (and (string-match-p "\\`-?[0-9]*\\.?[0-9]*\\'" string) + (string-to-number string))) (defun org-babel-import-elisp-from-file (file-name &optional separator) "Read the results located at FILE-NAME into an elisp table. @@ -2644,49 +2935,15 @@ If the table is trivial, then return it as a scalar." cell) t)) (defun org-babel-chomp (string &optional regexp) - "Strip trailing spaces and carriage returns from STRING. -Default regexp used is \"[ \f\t\n\r\v]\" but can be -overwritten by specifying a regexp as a second argument." + "Strip a trailing space or carriage return from STRING. +The default regexp used is \"[ \\f\\t\\n\\r\\v]\" but another one +can be specified as the REGEXP argument." (let ((regexp (or regexp "[ \f\t\n\r\v]"))) (while (and (> (length string) 0) (string-match regexp (substring string -1))) (setq string (substring string 0 -1))) string)) -(defun org-babel-trim (string &optional regexp) - "Strip leading and trailing spaces and carriage returns from STRING. -Like `org-babel-chomp' only it runs on both the front and back -of the string." - (org-babel-chomp (org-reverse-string - (org-babel-chomp (org-reverse-string string) regexp)) - regexp)) - -(defun org-babel-tramp-handle-call-process-region - (start end program &optional delete buffer display &rest args) - "Use Tramp to handle `call-process-region'. -Fixes a bug in `tramp-handle-call-process-region'." - (if (file-remote-p default-directory) - (let ((tmpfile (tramp-compat-make-temp-file ""))) - (write-region start end tmpfile) - (when delete (delete-region start end)) - (unwind-protect - ;; (apply 'call-process program tmpfile buffer display args) - ;; bug in tramp - (apply 'process-file program tmpfile buffer display args) - (delete-file tmpfile))) - ;; org-babel-call-process-region-original is the original emacs - ;; definition. It is in scope from the let binding in - ;; org-babel-execute-src-block - (apply org-babel-call-process-region-original - start end program delete buffer display args))) - -(defalias 'org-babel-local-file-name - (if (fboundp 'file-local-name) - 'file-local-name - (lambda (file) - "Return the local name component of FILE." - (or (file-remote-p file 'localname) file)))) - (defun org-babel-process-file-name (name &optional no-quote-p) "Prepare NAME to be used in an external process. If NAME specifies a remote location, the remote portion of the @@ -2694,7 +2951,7 @@ name is removed, since in that case the process will be executing remotely. The file name is then processed by `expand-file-name'. Unless second argument NO-QUOTE-P is non-nil, the file name is additionally processed by `shell-quote-argument'" - (let ((f (expand-file-name (org-babel-local-file-name name)))) + (let ((f (org-babel-local-file-name (expand-file-name name)))) (if no-quote-p f (shell-quote-argument f)))) (defvar org-babel-temporary-directory) @@ -2708,6 +2965,11 @@ additionally processed by `shell-quote-argument'" Used by `org-babel-temp-file'. This directory will be removed on Emacs shutdown.")) +(defcustom org-babel-remote-temporary-directory "/tmp/" + "Directory to hold temporary files on remote hosts." + :group 'org-babel + :type 'string) + (defmacro org-babel-result-cond (result-params scalar-form &rest table-forms) "Call the code to parse raw string results according to RESULT-PARAMS." (declare (indent 1) @@ -2720,6 +2982,7 @@ Emacs shutdown.")) (member "html" ,params) (member "code" ,params) (member "pp" ,params) + (member "file" ,params) (and (or (member "output" ,params) (member "raw" ,params) (member "org" ,params) @@ -2737,7 +3000,8 @@ of `org-babel-temporary-directory'." (if (file-remote-p default-directory) (let ((prefix (concat (file-remote-p default-directory) - (expand-file-name prefix temporary-file-directory)))) + (expand-file-name + prefix org-babel-remote-temporary-directory)))) (make-temp-file prefix nil suffix)) (let ((temporary-file-directory (or (and (boundp 'org-babel-temporary-directory) @@ -2772,6 +3036,96 @@ of `org-babel-temporary-directory'." (add-hook 'kill-emacs-hook 'org-babel-remove-temporary-directory) +(defun org-babel-one-header-arg-safe-p (pair safe-list) + "Determine if the PAIR is a safe babel header arg according to SAFE-LIST. + +For the format of SAFE-LIST, see `org-babel-safe-header-args'." + (and (consp pair) + (keywordp (car pair)) + (stringp (cdr pair)) + (or + (memq (car pair) safe-list) + (let ((entry (assq (car pair) safe-list))) + (and entry + (consp entry) + (cond ((functionp (cdr entry)) + (funcall (cdr entry) (cdr pair))) + ((listp (cdr entry)) + (member (cdr pair) (cdr entry))) + (t nil))))))) + +(defun org-babel-generate-file-param (src-name params) + "Calculate the filename for source block results. + +The directory is calculated from the :output-dir property of the +source block; if not specified, use the current directory. + +If the source block has a #+NAME and the :file parameter does not +contain any period characters, then the :file parameter is +treated as an extension, and the output file name is the +concatenation of the directory (as calculated above), the block +name, a period, and the parameter value as a file extension. +Otherwise, the :file parameter is treated as a full file name, +and the output file name is the directory (as calculated above) +plus the parameter value." + (let* ((file-cons (assq :file params)) + (file-ext-cons (assq :file-ext params)) + (file-ext (cdr-safe file-ext-cons)) + (dir (cdr-safe (assq :output-dir params))) + fname) + ;; create the output-dir if it does not exist + (when dir + (make-directory dir t)) + (if file-cons + ;; :file given; add :output-dir if given + (when dir + (setcdr file-cons (concat (file-name-as-directory dir) (cdr file-cons)))) + ;; :file not given; compute from name and :file-ext if possible + (when (and src-name file-ext) + (if dir + (setq fname (concat (file-name-as-directory (or dir "")) + src-name "." file-ext)) + (setq fname (concat src-name "." file-ext))) + (setq params (cons (cons :file fname) params)))) + params)) + +(defun org-babel-graphical-output-file (params) + "File where a babel block should send graphical output, per PARAMS. +Return nil if no graphical output is expected. Raise an error if +the output file is ill-defined." + (let ((file (cdr (assq :file params)))) + (cond (file (and (member "graphics" (cdr (assq :result-params params))) + file)) + ((assq :file-ext params) + (user-error ":file-ext given but no :file generated; did you forget \ +to name a block?")) + (t (user-error "No :file header argument given; cannot create \ +graphical result"))))) + +(defun org-babel-make-language-alias (new old) + "Make source blocks of type NEW aliases for those of type OLD. + +NEW and OLD should be strings. This function should be called +after the babel API for OLD-type source blocks is fully defined. + +Callers of this function will probably want to add an entry to +`org-src-lang-modes' as well." + (dolist (fn '("execute" "expand-body" "prep-session" + "variable-assignments" "load-session")) + (let ((sym (intern-soft (concat "org-babel-" fn ":" old)))) + (when (and sym (fboundp sym)) + (defalias (intern (concat "org-babel-" fn ":" new)) sym)))) + ;; Technically we don't need a `dolist' for just one variable, but + ;; we keep it for symmetry/ease of future expansion. + (dolist (var '("default-header-args")) + (let ((sym (intern-soft (concat "org-babel-" var ":" old)))) + (when (and sym (boundp sym)) + (defvaralias (intern (concat "org-babel-" var ":" new)) sym))))) + +(defun org-babel-strip-quotes (string) + "Strip \\\"s from around a string, if applicable." + (org-unbracket-string "\"" "\"" string)) + (provide 'ob-core) ;; Local variables: diff --git a/lisp/org/ob-css.el b/lisp/org/ob-css.el index 70c66d46704..4203b1258c3 100644 --- a/lisp/org/ob-css.el +++ b/lisp/org/ob-css.el @@ -1,4 +1,4 @@ -;;; ob-css.el --- org-babel functions for css evaluation +;;; ob-css.el --- Babel Functions for CSS -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -24,19 +24,19 @@ ;;; Commentary: ;; Since CSS can't be executed, this file exists solely for tangling -;; CSS from org-mode files. +;; CSS from Org files. ;;; Code: (require 'ob) (defvar org-babel-default-header-args:css '()) -(defun org-babel-execute:css (body params) +(defun org-babel-execute:css (body _params) "Execute a block of CSS code. This function is called by `org-babel-execute-src-block'." body) -(defun org-babel-prep-session:css (session params) +(defun org-babel-prep-session:css (_session _params) "Return an error if the :session header argument is set. CSS does not support sessions." (error "CSS sessions are nonsensical")) diff --git a/lisp/org/ob-ditaa.el b/lisp/org/ob-ditaa.el index 5eb8e2fdb4b..89b5d2465c2 100644 --- a/lisp/org/ob-ditaa.el +++ b/lisp/org/ob-ditaa.el @@ -1,4 +1,4 @@ -;;; ob-ditaa.el --- org-babel functions for ditaa evaluation +;;; ob-ditaa.el --- Babel Functions for ditaa -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -81,15 +81,21 @@ Do not leave leading or trailing spaces in this string." (defun org-babel-execute:ditaa (body params) "Execute a block of Ditaa code with org-babel. This function is called by `org-babel-execute-src-block'." - (let* ((result-params (split-string (or (cdr (assoc :results params)) ""))) - (out-file (let ((el (cdr (assoc :file params)))) - (or el - (error - "ditaa code block requires :file header argument")))) - (cmdline (cdr (assoc :cmdline params))) - (java (cdr (assoc :java params))) + (let* ((out-file (or (cdr (assq :file params)) + (error + "ditaa code block requires :file header argument"))) + (cmdline (cdr (assq :cmdline params))) + (java (cdr (assq :java params))) (in-file (org-babel-temp-file "ditaa-")) - (eps (cdr (assoc :eps params))) + (eps (cdr (assq :eps params))) + (eps-file (when eps + (org-babel-process-file-name (concat in-file ".eps")))) + (pdf-cmd (when (and (or (string= (file-name-extension out-file) "pdf") + (cdr (assq :pdf params)))) + (concat + "epstopdf" + " " eps-file + " -o=" (org-babel-process-file-name out-file)))) (cmd (concat org-babel-ditaa-java-cmd " " java " " org-ditaa-jar-option " " (shell-quote-argument @@ -97,13 +103,9 @@ This function is called by `org-babel-execute-src-block'." (if eps org-ditaa-eps-jar-path org-ditaa-jar-path))) " " cmdline " " (org-babel-process-file-name in-file) - " " (org-babel-process-file-name out-file))) - (pdf-cmd (when (and (or (string= (file-name-extension out-file) "pdf") - (cdr (assoc :pdf params)))) - (concat - "epstopdf" - " " (org-babel-process-file-name (concat in-file ".eps")) - " -o=" (org-babel-process-file-name out-file))))) + " " (if pdf-cmd + eps-file + (org-babel-process-file-name out-file))))) (unless (file-exists-p org-ditaa-jar-path) (error "Could not find ditaa.jar at %s" org-ditaa-jar-path)) (with-temp-file in-file (insert body)) @@ -111,7 +113,7 @@ This function is called by `org-babel-execute-src-block'." (when pdf-cmd (message pdf-cmd) (shell-command pdf-cmd)) nil)) ;; signal that output has already been written to file -(defun org-babel-prep-session:ditaa (session params) +(defun org-babel-prep-session:ditaa (_session _params) "Return an error because ditaa does not support sessions." (error "Ditaa does not support sessions")) diff --git a/lisp/org/ob-dot.el b/lisp/org/ob-dot.el index aa0445b4ca4..81442bfc1c6 100644 --- a/lisp/org/ob-dot.el +++ b/lisp/org/ob-dot.el @@ -1,4 +1,4 @@ -;;; ob-dot.el --- org-babel functions for dot evaluation +;;; ob-dot.el --- Babel Functions for dot -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -46,7 +46,7 @@ (defun org-babel-expand-body:dot (body params) "Expand BODY according to PARAMS, return the expanded body." - (let ((vars (mapcar #'cdr (org-babel-get-header params :var)))) + (let ((vars (org-babel--get-vars params))) (mapc (lambda (pair) (let ((name (symbol-name (car pair))) @@ -55,19 +55,20 @@ (replace-regexp-in-string (concat "$" (regexp-quote name)) (if (stringp value) value (format "%S" value)) - body)))) + body + t + t)))) vars) body)) (defun org-babel-execute:dot (body params) "Execute a block of Dot code with org-babel. This function is called by `org-babel-execute-src-block'." - (let* ((result-params (cdr (assoc :result-params params))) - (out-file (cdr (or (assoc :file params) + (let* ((out-file (cdr (or (assq :file params) (error "You need to specify a :file parameter")))) - (cmdline (or (cdr (assoc :cmdline params)) + (cmdline (or (cdr (assq :cmdline params)) (format "-T%s" (file-name-extension out-file)))) - (cmd (or (cdr (assoc :cmd params)) "dot")) + (cmd (or (cdr (assq :cmd params)) "dot")) (in-file (org-babel-temp-file "dot-"))) (with-temp-file in-file (insert (org-babel-expand-body:dot body params))) @@ -78,7 +79,7 @@ This function is called by `org-babel-execute-src-block'." " -o " (org-babel-process-file-name out-file)) "") nil)) ;; signal that output has already been written to file -(defun org-babel-prep-session:dot (session params) +(defun org-babel-prep-session:dot (_session _params) "Return an error because Dot does not support sessions." (error "Dot does not support sessions")) diff --git a/lisp/org/ob-ebnf.el b/lisp/org/ob-ebnf.el new file mode 100644 index 00000000000..0fceb5fc6b4 --- /dev/null +++ b/lisp/org/ob-ebnf.el @@ -0,0 +1,81 @@ +;;; ob-ebnf.el --- Babel Functions for EBNF -*- lexical-binding: t; -*- + +;; Copyright (C) 2013-2017 Free Software Foundation, Inc. + +;; Author: Michael Gauland +;; Keywords: literate programming, reproducible research +;; Homepage: http://orgmode.org +;; Version: 1.00 + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;;; Org-Babel support for using ebnf2ps to generate encapsulated postscript +;;; railroad diagrams. It recognizes these arguments: +;;; +;;; :file is required; it must include the extension '.eps.' All the rules +;;; in the block will be drawn in the same file. This is done by +;;; inserting a '[' comment at the start of the block (see the +;;; documentation for ebnf-eps-buffer for more information). +;;; +;;; :style specifies a value in ebnf-style-database. This provides the +;;; ability to customize the output. The style can also specify the +;;; grammar syntax (by setting ebnf-syntax); note that only ebnf, +;;; iso-ebnf, and yacc are supported by this file. + +;;; Requirements: + +;;; Code: +(require 'ob) +(require 'ebnf2ps) + +;; optionally declare default header arguments for this language +(defvar org-babel-default-header-args:ebnf '((:style . nil))) + +;; Use ebnf-eps-buffer to produce an encapsulated postscript file. +;; +(defun org-babel-execute:ebnf (body params) + "Execute a block of Ebnf code with org-babel. This function is +called by `org-babel-execute-src-block'" + (save-excursion + (let* ((dest-file (cdr (assq :file params))) + (dest-dir (file-name-directory dest-file)) + (dest-root (file-name-sans-extension + (file-name-nondirectory dest-file))) + (style (cdr (assq :style params))) + (result nil)) + (with-temp-buffer + (when style (ebnf-push-style style)) + (let ((comment-format + (cond ((string= ebnf-syntax 'yacc) "/*%s*/") + ((string= ebnf-syntax 'ebnf) ";%s") + ((string= ebnf-syntax 'iso-ebnf) "(*%s*)") + (t (setq result + (format "EBNF error: format %s not supported." + ebnf-syntax)))))) + (setq ebnf-eps-prefix dest-dir) + (insert (format comment-format (format "[%s" dest-root))) + (newline) + (insert body) + (newline) + (insert (format comment-format (format "]%s" dest-root))) + (ebnf-eps-buffer) + (when style (ebnf-pop-style)))) + result))) + +(provide 'ob-ebnf) +;;; ob-ebnf.el ends here diff --git a/lisp/org/ob-emacs-lisp.el b/lisp/org/ob-emacs-lisp.el index d95c475c4ee..c0bd12a8793 100644 --- a/lisp/org/ob-emacs-lisp.el +++ b/lisp/org/ob-emacs-lisp.el @@ -1,4 +1,4 @@ -;;; ob-emacs-lisp.el --- org-babel functions for emacs-lisp code evaluation +;;; ob-emacs-lisp.el --- Babel Functions for Emacs-lisp Code -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -28,17 +28,21 @@ ;;; Code: (require 'ob) -(defvar org-babel-default-header-args:emacs-lisp - '((:hlines . "yes") (:colnames . "no")) - "Default arguments for evaluating an emacs-lisp source block.") +(defconst org-babel-header-args:emacs-lisp '((lexical . :any)) + "Emacs-lisp specific header arguments.") -(declare-function orgtbl-to-generic "org-table" - (table params &optional backend)) +(defvar org-babel-default-header-args:emacs-lisp '((:lexical . "no")) + "Default arguments for evaluating an emacs-lisp source block. + +A value of \"yes\" or t causes src blocks to be eval'd using +lexical scoping. It can also be an alist mapping symbols to +their value. It is used as the optional LEXICAL argument to +`eval', which see.") (defun org-babel-expand-body:emacs-lisp (body params) "Expand BODY according to PARAMS, return the expanded body." - (let* ((vars (mapcar #'cdr (org-babel-get-header params :var))) - (result-params (cdr (assoc :result-params params))) + (let* ((vars (org-babel--get-vars params)) + (result-params (cdr (assq :result-params params))) (print-level nil) (print-length nil) (body (if (> (length vars) 0) (concat "(let (" @@ -55,26 +59,33 @@ (defun org-babel-execute:emacs-lisp (body params) "Execute a block of emacs-lisp code with Babel." (save-window-excursion - (let ((result - (eval (read (format (if (member "output" - (cdr (assoc :result-params params))) - "(with-output-to-string %s)" - "(progn %s)") - (org-babel-expand-body:emacs-lisp - body params)))))) - (org-babel-result-cond (cdr (assoc :result-params params)) + (let* ((lexical (cdr (assq :lexical params))) + (result + (eval (read (format (if (member "output" + (cdr (assq :result-params params))) + "(with-output-to-string %s)" + "(progn %s)") + (org-babel-expand-body:emacs-lisp + body params))) + + (if (listp lexical) + lexical + (member lexical '("yes" "t")))))) + (org-babel-result-cond (cdr (assq :result-params params)) (let ((print-level nil) (print-length nil)) - (if (or (member "scalar" (cdr (assoc :result-params params))) - (member "verbatim" (cdr (assoc :result-params params)))) + (if (or (member "scalar" (cdr (assq :result-params params))) + (member "verbatim" (cdr (assq :result-params params)))) (format "%S" result) (format "%s" result))) (org-babel-reassemble-table result - (org-babel-pick-name (cdr (assoc :colname-names params)) - (cdr (assoc :colnames params))) - (org-babel-pick-name (cdr (assoc :rowname-names params)) - (cdr (assoc :rownames params)))))))) + (org-babel-pick-name (cdr (assq :colname-names params)) + (cdr (assq :colnames params))) + (org-babel-pick-name (cdr (assq :rowname-names params)) + (cdr (assq :rownames params)))))))) + +(org-babel-make-language-alias "elisp" "emacs-lisp") (provide 'ob-emacs-lisp) diff --git a/lisp/org/ob-eval.el b/lisp/org/ob-eval.el index 46d21c88e85..324cf5fb27c 100644 --- a/lisp/org/ob-eval.el +++ b/lisp/org/ob-eval.el @@ -1,4 +1,4 @@ -;;; ob-eval.el --- org-babel functions for external code evaluation +;;; ob-eval.el --- Babel Functions for External Code Evaluation -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -28,7 +28,6 @@ ;;; Code: (require 'org-macs) -(eval-when-compile (require 'cl)) (defvar org-babel-error-buffer-name "*Org-Babel Error Output*") (declare-function org-babel-temp-file "ob-core" (prefix &optional suffix)) @@ -57,6 +56,13 @@ STDERR with `org-babel-eval-error-notify'." (progn (with-current-buffer err-buff (org-babel-eval-error-notify exit-code (buffer-string))) + (save-excursion + (when (get-buffer org-babel-error-buffer-name) + (with-current-buffer org-babel-error-buffer-name + (unless (derived-mode-p 'compilation-mode) + (compilation-mode)) + ;; Compilation-mode enforces read-only, but Babel expects the buffer modifiable. + (setq buffer-read-only nil)))) nil) (buffer-string))))) @@ -114,18 +120,18 @@ function in various versions of Emacs. (delete-file input-file)) (when (and error-file (file-exists-p error-file)) - (if (< 0 (nth 7 (file-attributes error-file))) - (with-current-buffer (get-buffer-create error-buffer) - (let ((pos-from-end (- (point-max) (point)))) - (or (bobp) - (insert "\f\n")) - ;; Do no formatting while reading error file, - ;; because that can run a shell command, and we - ;; don't want that to cause an infinite recursion. - (format-insert-file error-file nil) - ;; Put point after the inserted errors. - (goto-char (- (point-max) pos-from-end))) - (current-buffer))) + (when (< 0 (nth 7 (file-attributes error-file))) + (with-current-buffer (get-buffer-create error-buffer) + (let ((pos-from-end (- (point-max) (point)))) + (or (bobp) + (insert "\f\n")) + ;; Do no formatting while reading error file, + ;; because that can run a shell command, and we + ;; don't want that to cause an infinite recursion. + (format-insert-file error-file nil) + ;; Put point after the inserted errors. + (goto-char (- (point-max) pos-from-end))) + (current-buffer))) (delete-file error-file)) exit-status)) diff --git a/lisp/org/ob-exp.el b/lisp/org/ob-exp.el index 2677fe59cb2..f87d0f8e7d3 100644 --- a/lisp/org/ob-exp.el +++ b/lisp/org/ob-exp.el @@ -1,4 +1,4 @@ -;;; ob-exp.el --- Exportation of org-babel source blocks +;;; ob-exp.el --- Exportation of Babel Source Blocks -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -24,81 +24,49 @@ ;;; Code: (require 'ob-core) -(require 'org-src) -(eval-when-compile - (require 'cl)) - -(defvar org-current-export-file) -(defvar org-babel-lob-one-liner-regexp) -(defvar org-babel-ref-split-regexp) -(defvar org-list-forbidden-blocks) - -(declare-function org-babel-lob-get-info "ob-lob" ()) -(declare-function org-babel-eval-wipe-error-buffer "ob-eval" ()) -(declare-function org-between-regexps-p "org" - (start-re end-re &optional lim-up lim-down)) -(declare-function org-get-indentation "org" (&optional line)) -(declare-function org-heading-components "org" ()) -(declare-function org-in-block-p "org" (names)) -(declare-function org-in-verbatim-emphasis "org" ()) -(declare-function org-link-search "org" (s &optional type avoid-pos stealth)) -(declare-function org-fill-template "org" (template alist)) -(declare-function org-split-string "org" (string &optional separators)) -(declare-function org-element-at-point "org-element" (&optional keep-trail)) + +(declare-function org-babel-lob-get-info "ob-lob" (&optional datum)) +(declare-function org-element-at-point "org-element" ()) (declare-function org-element-context "org-element" (&optional element)) (declare-function org-element-property "org-element" (property element)) (declare-function org-element-type "org-element" (element)) (declare-function org-escape-code-in-string "org-src" (s)) +(declare-function org-export-copy-buffer "ox" ()) +(declare-function org-fill-template "org" (template alist)) +(declare-function org-get-indentation "org" (&optional line)) +(declare-function org-in-commented-heading-p "org" (&optional no-inheritance)) + +(defvar org-src-preserve-indentation) (defcustom org-export-babel-evaluate t "Switch controlling code evaluation during export. When set to nil no code will be evaluated as part of the export -process. When set to `inline-only', only inline code blocks will -be executed." +process and no header arguments will be obeyed. When set to +`inline-only', only inline code blocks will be executed. Users +who wish to avoid evaluating code on export should use the header +argument `:eval never-export'." :group 'org-babel :version "24.1" :type '(choice (const :tag "Never" nil) (const :tag "Only inline code" inline-only) (const :tag "Always" t))) -(put 'org-export-babel-evaluate 'safe-local-variable (lambda (x) (eq x nil))) - -(defun org-babel-exp-get-export-buffer () - "Return the current export buffer if possible." - (cond - ((bufferp org-current-export-file) org-current-export-file) - (org-current-export-file (get-file-buffer org-current-export-file)) - ('otherwise - (error "Requested export buffer when `org-current-export-file' is nil")))) - -(defvar org-link-search-inhibit-query) - -(defmacro org-babel-exp-in-export-file (lang &rest body) - (declare (indent 1)) - `(let* ((lang-headers (intern (concat "org-babel-default-header-args:" ,lang))) - (heading (nth 4 (ignore-errors (org-heading-components)))) - (export-buffer (current-buffer)) - (original-buffer (org-babel-exp-get-export-buffer)) results) - (when original-buffer - ;; resolve parameters in the original file so that - ;; headline and file-wide parameters are included, attempt - ;; to go to the same heading in the original file - (set-buffer original-buffer) - (save-restriction - (when heading - (condition-case nil - (let ((org-link-search-inhibit-query t)) - (org-link-search heading)) - (error (when heading - (goto-char (point-min)) - (re-search-forward (regexp-quote heading) nil t))))) - (setq results ,@body)) - (set-buffer export-buffer) - results))) -(def-edebug-spec org-babel-exp-in-export-file (form body)) - -(defun org-babel-exp-src-block (&rest headers) +(put 'org-export-babel-evaluate 'safe-local-variable #'null) + +(defmacro org-babel-exp--at-source (&rest body) + "Evaluate BODY at the source of the Babel block at point. +Source is located in `org-babel-exp-reference-buffer'. The value +returned is the value of the last form in BODY. Assume that +point is at the beginning of the Babel block." + (declare (indent 1) (debug body)) + `(let ((source (get-text-property (point) 'org-reference))) + (with-current-buffer org-babel-exp-reference-buffer + (org-with-wide-buffer + (goto-char source) + ,@body)))) + +(defun org-babel-exp-src-block () "Process source block for export. -Depending on the `export' headers argument, replace the source +Depending on the \":export\" header argument, replace the source code block like this: both ---- display the code and the results @@ -107,29 +75,36 @@ code ---- the default, display the code inside the block but do not process results - just like none only the block is run on export ensuring - that it's results are present in the org-mode buffer + that its results are present in the Org mode buffer none ---- do not display either code or results upon export -Assume point is at the beginning of block's starting line." +Assume point is at block opening line." (interactive) - (unless noninteractive (message "org-babel-exp processing...")) (save-excursion (let* ((info (org-babel-get-src-block-info 'light)) (lang (nth 0 info)) - (raw-params (nth 2 info)) hash) + (raw-params (nth 2 info)) + hash) ;; bail if we couldn't get any info from the block + (unless noninteractive + (message "org-babel-exp process %s at position %d..." + lang + (line-beginning-position))) (when info ;; if we're actually going to need the parameters - (when (member (cdr (assoc :exports (nth 2 info))) '("both" "results")) - (org-babel-exp-in-export-file lang - (setf (nth 2 info) - (org-babel-process-params - (apply #'org-babel-merge-params - org-babel-default-header-args - (if (boundp lang-headers) (eval lang-headers) nil) - (append (org-babel-params-from-properties lang) - (list raw-params)))))) + (when (member (cdr (assq :exports (nth 2 info))) '("both" "results")) + (let ((lang-headers (intern (concat "org-babel-default-header-args:" + lang)))) + (org-babel-exp--at-source + (setf (nth 2 info) + (org-babel-process-params + (apply #'org-babel-merge-params + org-babel-default-header-args + (and (boundp lang-headers) + (symbol-value lang-headers)) + (append (org-babel-params-from-properties lang) + (list raw-params))))))) (setf hash (org-babel-sha1-hash info))) (org-babel-exp-do-export info 'block hash))))) @@ -150,166 +125,180 @@ this template." :group 'org-babel :type 'string) -(defvar org-babel-default-lob-header-args) (defun org-babel-exp-process-buffer () "Execute all Babel blocks in current buffer." (interactive) - (save-window-excursion - (save-excursion + (when org-export-babel-evaluate + (save-window-excursion (let ((case-fold-search t) - (regexp (concat org-babel-inline-src-block-regexp "\\|" - org-babel-lob-one-liner-regexp "\\|" - "^[ \t]*#\\+BEGIN_SRC"))) - (goto-char (point-min)) - (while (re-search-forward regexp nil t) - (let* ((element (save-excursion - ;; If match is inline, point is at its - ;; end. Move backward so - ;; `org-element-context' can get the - ;; object, not the following one. - (backward-char) - (save-match-data (org-element-context)))) - (type (org-element-type element)) - (begin (copy-marker (org-element-property :begin element))) - (end (copy-marker - (save-excursion - (goto-char (org-element-property :end element)) - (skip-chars-backward " \r\t\n") - (point))))) - (case type - (inline-src-block - (let* ((info (org-babel-parse-inline-src-block-match)) - (params (nth 2 info))) - (setf (nth 1 info) - (if (and (cdr (assoc :noweb params)) - (string= "yes" (cdr (assoc :noweb params)))) - (org-babel-expand-noweb-references - info (org-babel-exp-get-export-buffer)) - (nth 1 info))) - (goto-char begin) - (let ((replacement (org-babel-exp-do-export info 'inline))) - (if (equal replacement "") - ;; Replacement code is empty: remove inline src - ;; block, including extra white space that - ;; might have been created when inserting - ;; results. - (delete-region begin - (progn (goto-char end) - (skip-chars-forward " \t") - (point))) - ;; Otherwise: remove inline src block but - ;; preserve following white spaces. Then insert - ;; value. - (delete-region begin end) - (insert replacement))))) - ((babel-call inline-babel-call) - (let* ((lob-info (org-babel-lob-get-info)) - (results - (org-babel-exp-do-export - (list "emacs-lisp" "results" - (apply #'org-babel-merge-params - org-babel-default-header-args - org-babel-default-lob-header-args - (append - (org-babel-params-from-properties) - (list - (org-babel-parse-header-arguments - (org-no-properties - (concat - ":var results=" - (mapconcat 'identity - (butlast lob-info 2) - " "))))))) - "" (nth 3 lob-info) (nth 2 lob-info)) - 'lob)) - (rep (org-fill-template - org-babel-exp-call-line-template - `(("line" . ,(nth 0 lob-info)))))) - ;; If replacement is empty, completely remove the - ;; object/element, including any extra white space - ;; that might have been created when including - ;; results. - (if (equal rep "") - (delete-region - begin - (progn (goto-char end) - (if (not (eq type 'babel-call)) - (progn (skip-chars-forward " \t") (point)) - (skip-chars-forward " \r\t\n") - (line-beginning-position)))) - ;; Otherwise, preserve following white - ;; spaces/newlines and then, insert replacement - ;; string. - (goto-char begin) - (delete-region begin end) - (insert rep)))) - (src-block - (let* ((match-start (copy-marker (match-beginning 0))) - (ind (org-get-indentation)) - (headers - (cons - (org-element-property :language element) - (let ((params (org-element-property :parameters - element))) - (and params (org-split-string params "[ \t]+")))))) - ;; Take care of matched block: compute replacement - ;; string. In particular, a nil REPLACEMENT means - ;; the block should be left as-is while an empty - ;; string should remove the block. - (let ((replacement (progn (goto-char match-start) - (org-babel-exp-src-block headers)))) - (cond ((not replacement) (goto-char end)) - ((equal replacement "") - (goto-char end) - (skip-chars-forward " \r\t\n") - (beginning-of-line) - (delete-region begin (point))) - (t - (goto-char match-start) - (delete-region (point) - (save-excursion (goto-char end) - (line-end-position))) - (insert replacement) - (if (or org-src-preserve-indentation - (org-element-property :preserve-indent - element)) - ;; Indent only the code block markers. - (save-excursion (skip-chars-backward " \r\t\n") - (indent-line-to ind) - (goto-char match-start) - (indent-line-to ind)) - ;; Indent everything. - (indent-rigidly match-start (point) ind))))) - (set-marker match-start nil)))) - (set-marker begin nil) - (set-marker end nil))))))) - -(defun org-babel-in-example-or-verbatim () - "Return true if point is in example or verbatim code. -Example and verbatim code include escaped portions of -an org-mode buffer code that should be treated as normal -org-mode text." - (or (save-match-data - (save-excursion - (goto-char (point-at-bol)) - (looking-at "[ \t]*:[ \t]"))) - (org-in-verbatim-emphasis) - (org-in-block-p org-list-forbidden-blocks) - (org-between-regexps-p "^[ \t]*#\\+begin_src" "^[ \t]*#\\+end_src"))) + (regexp (if (eq org-export-babel-evaluate 'inline-only) + "\\(call\\|src\\)_" + "\\(call\\|src\\)_\\|^[ \t]*#\\+\\(BEGIN_SRC\\|CALL:\\)")) + ;; Get a pristine copy of current buffer so Babel + ;; references are properly resolved and source block + ;; context is preserved. + (org-babel-exp-reference-buffer (org-export-copy-buffer))) + (unwind-protect + (save-excursion + ;; First attach to every source block their original + ;; position, so that they can be retrieved within + ;; `org-babel-exp-reference-buffer', even after heavy + ;; modifications on current buffer. + ;; + ;; False positives are harmless, so we don't check if + ;; we're really at some Babel object. Moreover, + ;; `line-end-position' ensures that we propertize + ;; a noticeable part of the object, without affecting + ;; multiple objects on the same line. + (goto-char (point-min)) + (while (re-search-forward regexp nil t) + (let ((s (match-beginning 0))) + (put-text-property s (line-end-position) 'org-reference s))) + ;; Evaluate from top to bottom every Babel block + ;; encountered. + (goto-char (point-min)) + (while (re-search-forward regexp nil t) + (unless (save-match-data (org-in-commented-heading-p)) + (let* ((object? (match-end 1)) + (element (save-match-data + (if object? (org-element-context) + ;; No deep inspection if we're + ;; just looking for an element. + (org-element-at-point)))) + (type + (pcase (org-element-type element) + ;; Discard block elements if we're looking + ;; for inline objects. False results + ;; happen when, e.g., "call_" syntax is + ;; located within affiliated keywords: + ;; + ;; #+name: call_src + ;; #+begin_src ... + ((and (or `babel-call `src-block) (guard object?)) + nil) + (type type))) + (begin + (copy-marker (org-element-property :begin element))) + (end + (copy-marker + (save-excursion + (goto-char (org-element-property :end element)) + (skip-chars-backward " \r\t\n") + (point))))) + (pcase type + (`inline-src-block + (let* ((info + (org-babel-get-src-block-info nil element)) + (params (nth 2 info))) + (setf (nth 1 info) + (if (and (cdr (assq :noweb params)) + (string= "yes" + (cdr (assq :noweb params)))) + (org-babel-expand-noweb-references + info org-babel-exp-reference-buffer) + (nth 1 info))) + (goto-char begin) + (let ((replacement + (org-babel-exp-do-export info 'inline))) + (if (equal replacement "") + ;; Replacement code is empty: remove + ;; inline source block, including extra + ;; white space that might have been + ;; created when inserting results. + (delete-region begin + (progn (goto-char end) + (skip-chars-forward " \t") + (point))) + ;; Otherwise: remove inline src block but + ;; preserve following white spaces. Then + ;; insert value. + (delete-region begin end) + (insert replacement))))) + ((or `babel-call `inline-babel-call) + (org-babel-exp-do-export (org-babel-lob-get-info element) + 'lob) + (let ((rep + (org-fill-template + org-babel-exp-call-line-template + `(("line" . + ,(org-element-property :value element)))))) + ;; If replacement is empty, completely remove + ;; the object/element, including any extra + ;; white space that might have been created + ;; when including results. + (if (equal rep "") + (delete-region + begin + (progn (goto-char end) + (if (not (eq type 'babel-call)) + (progn (skip-chars-forward " \t") + (point)) + (skip-chars-forward " \r\t\n") + (line-beginning-position)))) + ;; Otherwise, preserve trailing + ;; spaces/newlines and then, insert + ;; replacement string. + (goto-char begin) + (delete-region begin end) + (insert rep)))) + (`src-block + (let ((match-start (copy-marker (match-beginning 0))) + (ind (org-get-indentation))) + ;; Take care of matched block: compute + ;; replacement string. In particular, a nil + ;; REPLACEMENT means the block is left as-is + ;; while an empty string removes the block. + (let ((replacement + (progn (goto-char match-start) + (org-babel-exp-src-block)))) + (cond ((not replacement) (goto-char end)) + ((equal replacement "") + (goto-char end) + (skip-chars-forward " \r\t\n") + (beginning-of-line) + (delete-region begin (point))) + (t + (goto-char match-start) + (delete-region (point) + (save-excursion + (goto-char end) + (line-end-position))) + (insert replacement) + (if (or org-src-preserve-indentation + (org-element-property + :preserve-indent element)) + ;; Indent only code block + ;; markers. + (save-excursion + (skip-chars-backward " \r\t\n") + (indent-line-to ind) + (goto-char match-start) + (indent-line-to ind)) + ;; Indent everything. + (indent-rigidly + match-start (point) ind))))) + (set-marker match-start nil)))) + (set-marker begin nil) + (set-marker end nil))))) + (kill-buffer org-babel-exp-reference-buffer) + (remove-text-properties (point-min) (point-max) '(org-reference))))))) (defun org-babel-exp-do-export (info type &optional hash) "Return a string with the exported content of a code block. The function respects the value of the :exports header argument." - (let ((silently (lambda () (let ((session (cdr (assoc :session (nth 2 info))))) - (when (not (and session (equal "none" session))) - (org-babel-exp-results info type 'silent))))) - (clean (lambda () (unless (eq type 'inline) (org-babel-remove-result info))))) - (case (intern (or (cdr (assoc :exports (nth 2 info))) "code")) - ('none (funcall silently) (funcall clean) "") - ('code (funcall silently) (funcall clean) (org-babel-exp-code info)) - ('results (org-babel-exp-results info type nil hash) "") - ('both (org-babel-exp-results info type nil hash) - (org-babel-exp-code info))))) + (let ((silently (lambda () (let ((session (cdr (assq :session (nth 2 info))))) + (unless (equal "none" session) + (org-babel-exp-results info type 'silent))))) + (clean (lambda () (if (eq type 'inline) + (org-babel-remove-inline-result) + (org-babel-remove-result info))))) + (pcase (or (cdr (assq :exports (nth 2 info))) "code") + ("none" (funcall silently) (funcall clean) "") + ("code" (funcall silently) (funcall clean) (org-babel-exp-code info type)) + ("results" (org-babel-exp-results info type nil hash) "") + ("both" + (org-babel-exp-results info type nil hash) + (org-babel-exp-code info type))))) (defcustom org-babel-exp-code-template "#+BEGIN_SRC %lang%switches%flags\n%body\n#+END_SRC" @@ -331,18 +320,42 @@ replaced with its value." :group 'org-babel :type 'string) -(defun org-babel-exp-code (info) +(defcustom org-babel-exp-inline-code-template + "src_%lang[%switches%flags]{%body}" + "Template used to export the body of inline code blocks. +This template may be customized to include additional information +such as the code block name, or the values of particular header +arguments. The template is filled out using `org-fill-template', +and the following %keys may be used. + + lang ------ the language of the code block + name ------ the name of the code block + body ------ the body of the code block + switches -- the switches associated to the code block + flags ----- the flags passed to the code block + +In addition to the keys mentioned above, every header argument +defined for the code block may be used as a key and will be +replaced with its value." + :group 'org-babel + :type 'string + :version "26.1" + :package-version '(Org . "8.3")) + +(defun org-babel-exp-code (info type) "Return the original code block formatted for export." (setf (nth 1 info) - (if (string= "strip-export" (cdr (assoc :noweb (nth 2 info)))) + (if (string= "strip-export" (cdr (assq :noweb (nth 2 info)))) (replace-regexp-in-string (org-babel-noweb-wrap) "" (nth 1 info)) (if (org-babel-noweb-p (nth 2 info) :export) (org-babel-expand-noweb-references - info (org-babel-exp-get-export-buffer)) + info org-babel-exp-reference-buffer) (nth 1 info)))) (org-fill-template - org-babel-exp-code-template + (if (eq type 'inline) + org-babel-exp-inline-code-template + org-babel-exp-code-template) `(("lang" . ,(nth 0 info)) ("body" . ,(org-escape-code-in-string (nth 1 info))) ("switches" . ,(let ((f (nth 3 info))) @@ -357,48 +370,41 @@ replaced with its value." (defun org-babel-exp-results (info type &optional silent hash) "Evaluate and return the results of the current code block for export. -Results are prepared in a manner suitable for export by org-mode. +Results are prepared in a manner suitable for export by Org mode. This function is called by `org-babel-exp-do-export'. The code block will be evaluated. Optional argument SILENT can be used to inhibit insertion of results into the buffer." - (when (and (or (eq org-export-babel-evaluate t) - (and (eq type 'inline) - (eq org-export-babel-evaluate 'inline-only))) - (not (and hash (equal hash (org-babel-current-result-hash))))) + (unless (and hash (equal hash (org-babel-current-result-hash))) (let ((lang (nth 0 info)) (body (if (org-babel-noweb-p (nth 2 info) :eval) (org-babel-expand-noweb-references - info (org-babel-exp-get-export-buffer)) + info org-babel-exp-reference-buffer) (nth 1 info))) (info (copy-sequence info)) (org-babel-current-src-block-location (point-marker))) - ;; skip code blocks which we can't evaluate + ;; Skip code blocks which we can't evaluate. (when (fboundp (intern (concat "org-babel-execute:" lang))) (org-babel-eval-wipe-error-buffer) - (prog1 nil - (setf (nth 1 info) body) - (setf (nth 2 info) - (org-babel-exp-in-export-file lang - (org-babel-process-params - (org-babel-merge-params - (nth 2 info) - `((:results . ,(if silent "silent" "replace"))))))) - (cond - ((equal type 'block) - (org-babel-execute-src-block nil info)) - ((equal type 'inline) - ;; position the point on the inline source block allowing - ;; `org-babel-insert-result' to check that the block is - ;; inline - (re-search-backward "[ \f\t\n\r\v]" nil t) - (re-search-forward org-babel-inline-src-block-regexp nil t) - (re-search-backward "src_" nil t) + (setf (nth 1 info) body) + (setf (nth 2 info) + (org-babel-exp--at-source + (org-babel-process-params + (org-babel-merge-params + (nth 2 info) + `((:results . ,(if silent "silent" "replace"))))))) + (pcase type + (`block (org-babel-execute-src-block nil info)) + (`inline + ;; Position the point on the inline source block + ;; allowing `org-babel-insert-result' to check that the + ;; block is inline. + (goto-char (nth 5 info)) (org-babel-execute-src-block nil info)) - ((equal type 'lob) - (save-excursion - (re-search-backward org-babel-lob-one-liner-regexp nil t) - (let (org-confirm-babel-evaluate) - (org-babel-execute-src-block nil info)))))))))) + (`lob + (save-excursion + (goto-char (nth 5 info)) + (let (org-confirm-babel-evaluate) + (org-babel-execute-src-block nil info))))))))) (provide 'ob-exp) diff --git a/lisp/org/ob-forth.el b/lisp/org/ob-forth.el new file mode 100644 index 00000000000..152cf727e2b --- /dev/null +++ b/lisp/org/ob-forth.el @@ -0,0 +1,87 @@ +;;; ob-forth.el --- Babel Functions for Forth -*- lexical-binding: t; -*- + +;; Copyright (C) 2014-2017 Free Software Foundation, Inc. + +;; Author: Eric Schulte +;; Keywords: literate programming, reproducible research, forth +;; Homepage: http://orgmode.org + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; Requires the gforth forth compiler and `forth-mode' (see below). +;; https://www.gnu.org/software/gforth/ + +;;; Requirements: + +;; Session evaluation requires the gforth forth compiler as well as +;; `forth-mode' which is distributed with gforth (in gforth.el). + +;;; Code: +(require 'ob) + +(declare-function forth-proc "ext:gforth" ()) +(declare-function org-trim "org" (s &optional keep-lead)) + +(defvar org-babel-default-header-args:forth '((:session . "yes")) + "Default header arguments for forth code blocks.") + +(defun org-babel-execute:forth (body params) + "Execute a block of Forth code with org-babel. +This function is called by `org-babel-execute-src-block'" + (if (string= "none" (cdr (assq :session params))) + (error "Non-session evaluation not supported for Forth code blocks") + (let ((all-results (org-babel-forth-session-execute body params))) + (if (member "output" (cdr (assq :result-params params))) + (mapconcat #'identity all-results "\n") + (car (last all-results)))))) + +(defun org-babel-forth-session-execute (body params) + (require 'forth-mode) + (let ((proc (forth-proc)) + (rx " \\(\n:\\|compiled\n\\\|ok\n\\)") + (result-start)) + (with-current-buffer (process-buffer (forth-proc)) + (mapcar (lambda (line) + (setq result-start (progn (goto-char (process-mark proc)) + (point))) + (comint-send-string proc (concat line "\n")) + ;; wait for forth to say "ok" + (while (not (progn (goto-char result-start) + (re-search-forward rx nil t))) + (accept-process-output proc 0.01)) + (let ((case (match-string 1))) + (cond + ((string= "ok\n" case) + ;; Collect intermediate output. + (buffer-substring (+ result-start 1 (length line)) + (match-beginning 0))) + ((string= "compiled\n" case)) + ;; Ignore partial compilation. + ((string= "\n:" case) + ;; Report errors. + (org-babel-eval-error-notify 1 + (buffer-substring + (+ (match-beginning 0) 1) (point-max))) nil)))) + (split-string (org-trim + (org-babel-expand-body:generic body params)) + "\n" + 'omit-nulls))))) + +(provide 'ob-forth) + +;;; ob-forth.el ends here diff --git a/lisp/org/ob-fortran.el b/lisp/org/ob-fortran.el index 6a6112df9bd..d059245b30c 100644 --- a/lisp/org/ob-fortran.el +++ b/lisp/org/ob-fortran.el @@ -1,4 +1,4 @@ -;;; ob-fortran.el --- org-babel functions for fortran +;;; ob-fortran.el --- Babel Functions for Fortran -*- lexical-binding: t; -*- ;; Copyright (C) 2011-2017 Free Software Foundation, Inc. @@ -29,10 +29,12 @@ ;;; Code: (require 'ob) (require 'cc-mode) +(require 'cl-lib) (declare-function org-entry-get "org" (pom property &optional inherit literal-nil)) -(declare-function org-every "org" (pred seq)) +(declare-function org-remove-indentation "org" (code &optional n)) +(declare-function org-trim "org" (s &optional keep-lead)) (defvar org-babel-tangle-lang-exts) (add-to-list 'org-babel-tangle-lang-exts '("fortran" . "F90")) @@ -47,43 +49,42 @@ "This function should only be called by `org-babel-execute:fortran'" (let* ((tmp-src-file (org-babel-temp-file "fortran-src-" ".F90")) (tmp-bin-file (org-babel-temp-file "fortran-bin-" org-babel-exeext)) - (cmdline (cdr (assoc :cmdline params))) - (flags (cdr (assoc :flags params))) - (full-body (org-babel-expand-body:fortran body params)) - (compile - (progn - (with-temp-file tmp-src-file (insert full-body)) - (org-babel-eval - (format "%s -o %s %s %s" - org-babel-fortran-compiler - (org-babel-process-file-name tmp-bin-file) - (mapconcat 'identity - (if (listp flags) flags (list flags)) " ") - (org-babel-process-file-name tmp-src-file)) "")))) + (cmdline (cdr (assq :cmdline params))) + (flags (cdr (assq :flags params))) + (full-body (org-babel-expand-body:fortran body params))) + (with-temp-file tmp-src-file (insert full-body)) + (org-babel-eval + (format "%s -o %s %s %s" + org-babel-fortran-compiler + (org-babel-process-file-name tmp-bin-file) + (mapconcat 'identity + (if (listp flags) flags (list flags)) " ") + (org-babel-process-file-name tmp-src-file)) "") (let ((results - (org-babel-trim - (org-babel-eval - (concat tmp-bin-file (if cmdline (concat " " cmdline) "")) "")))) + (org-trim + (org-remove-indentation + (org-babel-eval + (concat tmp-bin-file (if cmdline (concat " " cmdline) "")) ""))))) (org-babel-reassemble-table - (org-babel-result-cond (cdr (assoc :result-params params)) + (org-babel-result-cond (cdr (assq :result-params params)) (org-babel-read results) (let ((tmp-file (org-babel-temp-file "f-"))) (with-temp-file tmp-file (insert results)) (org-babel-import-elisp-from-file tmp-file))) (org-babel-pick-name - (cdr (assoc :colname-names params)) (cdr (assoc :colnames params))) + (cdr (assq :colname-names params)) (cdr (assq :colnames params))) (org-babel-pick-name - (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params))))))) + (cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))) (defun org-babel-expand-body:fortran (body params) "Expand a block of fortran or fortran code with org-babel according to -it's header arguments." - (let ((vars (mapcar #'cdr (org-babel-get-header params :var))) - (main-p (not (string= (cdr (assoc :main params)) "no"))) - (includes (or (cdr (assoc :includes params)) +its header arguments." + (let ((vars (org-babel--get-vars params)) + (main-p (not (string= (cdr (assq :main params)) "no"))) + (includes (or (cdr (assq :includes params)) (org-babel-read (org-entry-get nil "includes" t)))) (defines (org-babel-read - (or (cdr (assoc :defines params)) + (or (cdr (assq :defines params)) (org-babel-read (org-entry-get nil "defines" t)))))) (mapconcat 'identity (list @@ -107,17 +108,17 @@ it's header arguments." (defun org-babel-fortran-ensure-main-wrap (body params) "Wrap body in a \"program ... end program\" block if none exists." (if (string-match "^[ \t]*program[ \t]*.*" (capitalize body)) - (let ((vars (mapcar #'cdr (org-babel-get-header params :var)))) + (let ((vars (org-babel--get-vars params))) (if vars (error "Cannot use :vars if `program' statement is present")) body) (format "program main\n%s\nend program main\n" body))) -(defun org-babel-prep-session:fortran (session params) +(defun org-babel-prep-session:fortran (_session _params) "This function does nothing as fortran is a compiled language with no support for sessions" (error "Fortran is a compiled languages -- no support for sessions")) -(defun org-babel-load-session:fortran (session body params) +(defun org-babel-load-session:fortran (_session _body _params) "This function does nothing as fortran is a compiled language with no support for sessions" (error "Fortran is a compiled languages -- no support for sessions")) @@ -145,7 +146,7 @@ of the same value." (format "character(len=%d), parameter :: %S = '%s'\n" (length val) var val)) ;; val is a matrix - ((and (listp val) (org-every #'listp val)) + ((and (listp val) (cl-every #'listp val)) (format "real, parameter :: %S(%d,%d) = transpose( reshape( %s , (/ %d, %d /) ) )\n" var (length val) (length (car val)) (org-babel-fortran-transform-list val) diff --git a/lisp/org/ob-gnuplot.el b/lisp/org/ob-gnuplot.el index 82b103e52cd..400823b2d70 100644 --- a/lisp/org/ob-gnuplot.el +++ b/lisp/org/ob-gnuplot.el @@ -1,4 +1,4 @@ -;;; ob-gnuplot.el --- org-babel functions for gnuplot evaluation +;;; ob-gnuplot.el --- Babel Functions for Gnuplot -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -39,12 +39,10 @@ ;;; Code: (require 'ob) -(eval-when-compile (require 'cl)) (declare-function org-time-string-to-time "org" (s &optional buffer pos)) (declare-function org-combine-plists "org" (&rest plists)) -(declare-function orgtbl-to-generic "org-table" - (table params &optional backend)) +(declare-function orgtbl-to-generic "org-table" (table params)) (declare-function gnuplot-mode "ext:gnuplot-mode" ()) (declare-function gnuplot-send-string-to-gnuplot "ext:gnuplot-mode" (str txt)) (declare-function gnuplot-send-buffer-to-gnuplot "ext:gnuplot-mode" ()) @@ -65,7 +63,7 @@ (term . :any)) "Gnuplot specific header args.") -(defvar org-babel-gnuplot-timestamp-fmt nil) +(defvar org-babel-gnuplot-timestamp-fmt nil) ; Dynamically scoped. (defvar *org-babel-gnuplot-missing* nil) @@ -81,7 +79,7 @@ Dumps all vectors into files and returns an association list of variable names and the related value to be used in the gnuplot code." - (let ((*org-babel-gnuplot-missing* (cdr (assoc :missing params)))) + (let ((*org-babel-gnuplot-missing* (cdr (assq :missing params)))) (mapcar (lambda (pair) (cons @@ -95,38 +93,33 @@ code." (if tablep val (mapcar 'list val))) (org-babel-temp-file "gnuplot-") params) val)))) - (mapcar #'cdr (org-babel-get-header params :var))))) + (org-babel--get-vars params)))) (defun org-babel-expand-body:gnuplot (body params) "Expand BODY according to PARAMS, return the expanded body." (save-window-excursion (let* ((vars (org-babel-gnuplot-process-vars params)) - (out-file (cdr (assoc :file params))) - (prologue (cdr (assoc :prologue params))) - (epilogue (cdr (assoc :epilogue params))) - (term (or (cdr (assoc :term params)) + (out-file (cdr (assq :file params))) + (prologue (cdr (assq :prologue params))) + (epilogue (cdr (assq :epilogue params))) + (term (or (cdr (assq :term params)) (when out-file (let ((ext (file-name-extension out-file))) (or (cdr (assoc (intern (downcase ext)) *org-babel-gnuplot-terms*)) ext))))) - (cmdline (cdr (assoc :cmdline params))) - (title (cdr (assoc :title params))) - (lines (cdr (assoc :line params))) - (sets (cdr (assoc :set params))) - (x-labels (cdr (assoc :xlabels params))) - (y-labels (cdr (assoc :ylabels params))) - (timefmt (cdr (assoc :timefmt params))) - (time-ind (or (cdr (assoc :timeind params)) + (title (cdr (assq :title params))) + (lines (cdr (assq :line params))) + (sets (cdr (assq :set params))) + (x-labels (cdr (assq :xlabels params))) + (y-labels (cdr (assq :ylabels params))) + (timefmt (cdr (assq :timefmt params))) + (time-ind (or (cdr (assq :timeind params)) (when timefmt 1))) - (missing (cdr (assoc :missing params))) - (add-to-body (lambda (text) (setq body (concat text "\n" body)))) - output) + (add-to-body (lambda (text) (setq body (concat text "\n" body))))) ;; append header argument settings to body (when title (funcall add-to-body (format "set title '%s'" title))) (when lines (mapc (lambda (el) (funcall add-to-body el)) lines)) - (when missing - (funcall add-to-body (format "set datafile missing '%s'" missing))) (when sets (mapc (lambda (el) (funcall add-to-body (format "set %s" el))) sets)) (when x-labels @@ -175,9 +168,8 @@ code." "Execute a block of Gnuplot code. This function is called by `org-babel-execute-src-block'." (require 'gnuplot) - (let ((session (cdr (assoc :session params))) - (result-type (cdr (assoc :results params))) - (out-file (cdr (assoc :file params))) + (let ((session (cdr (assq :session params))) + (result-type (cdr (assq :results params))) (body (org-babel-expand-body:gnuplot body params)) output) (save-window-excursion @@ -195,7 +187,7 @@ This function is called by `org-babel-execute-src-block'." script-file (if (member system-type '(cygwin windows-nt ms-dos)) t nil))))) - (message output)) + (message "%s" output)) (with-temp-buffer (insert (concat body "\n")) (gnuplot-mode) @@ -210,10 +202,12 @@ This function is called by `org-babel-execute-src-block'." (var-lines (org-babel-variable-assignments:gnuplot params))) (message "%S" session) (org-babel-comint-in-buffer session - (mapc (lambda (var-line) - (insert var-line) (comint-send-input nil t) - (org-babel-comint-wait-for-output session) - (sit-for .1) (goto-char (point-max))) var-lines)) + (dolist (var-line var-lines) + (insert var-line) + (comint-send-input nil t) + (org-babel-comint-wait-for-output session) + (sit-for .1) + (goto-char (point-max)))) session)) (defun org-babel-load-session:gnuplot (session body params) @@ -232,7 +226,7 @@ This function is called by `org-babel-execute-src-block'." (org-babel-gnuplot-process-vars params))) (defvar gnuplot-buffer) -(defun org-babel-gnuplot-initiate-session (&optional session params) +(defun org-babel-gnuplot-initiate-session (&optional session _params) "Initiate a gnuplot session. If there is not a current inferior-process-buffer in SESSION then create one. Return the initialized session. The current @@ -268,15 +262,13 @@ then create one. Return the initialized session. The current "Export TABLE to DATA-FILE in a format readable by gnuplot. Pass PARAMS through to `orgtbl-to-generic' when exporting TABLE." (with-temp-file data-file - (make-local-variable 'org-babel-gnuplot-timestamp-fmt) - (setq org-babel-gnuplot-timestamp-fmt (or - (plist-get params :timefmt) - "%Y-%m-%d-%H:%M:%S")) - (insert (orgtbl-to-generic - table - (org-combine-plists - '(:sep "\t" :fmt org-babel-gnuplot-quote-tsv-field) - params)))) + (insert (let ((org-babel-gnuplot-timestamp-fmt + (or (plist-get params :timefmt) "%Y-%m-%d-%H:%M:%S"))) + (orgtbl-to-generic + table + (org-combine-plists + '(:sep "\t" :fmt org-babel-gnuplot-quote-tsv-field) + params))))) data-file) (provide 'ob-gnuplot) diff --git a/lisp/org/ob-groovy.el b/lisp/org/ob-groovy.el new file mode 100644 index 00000000000..69993c0f6a6 --- /dev/null +++ b/lisp/org/ob-groovy.el @@ -0,0 +1,116 @@ +;;; ob-groovy.el --- Babel Functions for Groovy -*- lexical-binding: t; -*- + +;; Copyright (C) 2013-2017 Free Software Foundation, Inc. + +;; Author: Miro Bezjak +;; Keywords: literate programming, reproducible research +;; Homepage: http://orgmode.org + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: +;; Currently only supports the external execution. No session support yet. + +;;; Requirements: +;; - Groovy language :: http://groovy.codehaus.org +;; - Groovy major mode :: Can be installed from MELPA or +;; https://github.com/russel/Emacs-Groovy-Mode + +;;; Code: +(require 'ob) + +(defvar org-babel-tangle-lang-exts) ;; Autoloaded +(add-to-list 'org-babel-tangle-lang-exts '("groovy" . "groovy")) +(defvar org-babel-default-header-args:groovy '()) +(defcustom org-babel-groovy-command "groovy" + "Name of the command to use for executing Groovy code. +May be either a command in the path, like groovy +or an absolute path name, like /usr/local/bin/groovy +parameters may be used, like groovy -v" + :group 'org-babel + :version "24.3" + :type 'string) + +(defun org-babel-execute:groovy (body params) + "Execute a block of Groovy code with org-babel. This function is +called by `org-babel-execute-src-block'" + (message "executing Groovy source code block") + (let* ((processed-params (org-babel-process-params params)) + (session (org-babel-groovy-initiate-session (nth 0 processed-params))) + (result-params (nth 2 processed-params)) + (result-type (cdr (assq :result-type params))) + (full-body (org-babel-expand-body:generic + body params)) + (result (org-babel-groovy-evaluate + session full-body result-type result-params))) + + (org-babel-reassemble-table + result + (org-babel-pick-name + (cdr (assq :colname-names params)) (cdr (assq :colnames params))) + (org-babel-pick-name + (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))) + +(defvar org-babel-groovy-wrapper-method + + "class Runner extends Script { + def out = new PrintWriter(new ByteArrayOutputStream()) + def run() { %s } +} + +println(new Runner().run()) +") + + +(defun org-babel-groovy-evaluate + (session body &optional result-type result-params) + "Evaluate BODY in external Groovy process. +If RESULT-TYPE equals `output' then return standard output as a string. +If RESULT-TYPE equals `value' then return the value of the last statement +in BODY as elisp." + (when session (error "Sessions are not (yet) supported for Groovy")) + (pcase result-type + (`output + (let ((src-file (org-babel-temp-file "groovy-"))) + (progn (with-temp-file src-file (insert body)) + (org-babel-eval + (concat org-babel-groovy-command " " src-file) "")))) + (`value + (let* ((src-file (org-babel-temp-file "groovy-")) + (wrapper (format org-babel-groovy-wrapper-method body))) + (with-temp-file src-file (insert wrapper)) + (let ((raw (org-babel-eval + (concat org-babel-groovy-command " " src-file) ""))) + (org-babel-result-cond result-params + raw + (org-babel-script-escape raw))))))) + + +(defun org-babel-prep-session:groovy (_session _params) + "Prepare SESSION according to the header arguments specified in PARAMS." + (error "Sessions are not (yet) supported for Groovy")) + +(defun org-babel-groovy-initiate-session (&optional _session) + "If there is not a current inferior-process-buffer in SESSION +then create. Return the initialized session. Sessions are not +supported in Groovy." + nil) + +(provide 'ob-groovy) + + + +;;; ob-groovy.el ends here diff --git a/lisp/org/ob-haskell.el b/lisp/org/ob-haskell.el index ce6b8edbeb8..ecce6dcd5df 100644 --- a/lisp/org/ob-haskell.el +++ b/lisp/org/ob-haskell.el @@ -1,4 +1,4 @@ -;;; ob-haskell.el --- org-babel functions for haskell evaluation +;;; ob-haskell.el --- Babel Functions for Haskell -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -41,9 +41,9 @@ ;;; Code: (require 'ob) (require 'comint) -(eval-when-compile (require 'cl)) (declare-function org-remove-indentation "org" (code &optional n)) +(declare-function org-trim "org" (s &optional keep-lead)) (declare-function haskell-mode "ext:haskell-mode" ()) (declare-function run-haskell "ext:inf-haskell" (&optional arg)) (declare-function inferior-haskell-load-file @@ -61,42 +61,35 @@ (defun org-babel-execute:haskell (body params) "Execute a block of Haskell code." - (let* ((session (cdr (assoc :session params))) - (vars (mapcar #'cdr (org-babel-get-header params :var))) - (result-type (cdr (assoc :result-type params))) + (let* ((session (cdr (assq :session params))) + (result-type (cdr (assq :result-type params))) (full-body (org-babel-expand-body:generic body params (org-babel-variable-assignments:haskell params))) (session (org-babel-haskell-initiate-session session params)) (raw (org-babel-comint-with-output (session org-babel-haskell-eoe t full-body) - (insert (org-babel-trim full-body)) + (insert (org-trim full-body)) (comint-send-input nil t) (insert org-babel-haskell-eoe) (comint-send-input nil t))) (results (mapcar - #'org-babel-haskell-read-string + #'org-babel-strip-quotes (cdr (member org-babel-haskell-eoe - (reverse (mapcar #'org-babel-trim raw))))))) + (reverse (mapcar #'org-trim raw))))))) (org-babel-reassemble-table (let ((result - (case result-type - (output (mapconcat #'identity (reverse (cdr results)) "\n")) - (value (car results))))) - (org-babel-result-cond (cdr (assoc :result-params params)) - result (org-babel-haskell-table-or-string result))) - (org-babel-pick-name (cdr (assoc :colname-names params)) - (cdr (assoc :colname-names params))) - (org-babel-pick-name (cdr (assoc :rowname-names params)) - (cdr (assoc :rowname-names params)))))) - -(defun org-babel-haskell-read-string (string) - "Strip \\\"s from around a haskell string." - (if (string-match "^\"\\([^\000]+\\)\"$" string) - (match-string 1 string) - string)) - -(defun org-babel-haskell-initiate-session (&optional session params) + (pcase result-type + (`output (mapconcat #'identity (reverse (cdr results)) "\n")) + (`value (car results))))) + (org-babel-result-cond (cdr (assq :result-params params)) + result (org-babel-script-escape result))) + (org-babel-pick-name (cdr (assq :colname-names params)) + (cdr (assq :colname-names params))) + (org-babel-pick-name (cdr (assq :rowname-names params)) + (cdr (assq :rowname-names params)))))) + +(defun org-babel-haskell-initiate-session (&optional _session _params) "Initiate a haskell session. If there is not a current inferior-process-buffer in SESSION then create one. Return the initialized session." @@ -131,13 +124,7 @@ then create one. Return the initialized session." (format "let %s = %s" (car pair) (org-babel-haskell-var-to-haskell (cdr pair)))) - (mapcar #'cdr (org-babel-get-header params :var)))) - -(defun org-babel-haskell-table-or-string (results) - "Convert RESULTS to an Emacs-lisp table or string. -If RESULTS look like a table, then convert them into an -Emacs-lisp table, otherwise return the results as a string." - (org-babel-script-escape results)) + (org-babel--get-vars params))) (defun org-babel-haskell-var-to-haskell (var) "Convert an elisp value VAR into a haskell variable. @@ -157,7 +144,7 @@ specifying a variable of the same value." When called with a prefix argument the resulting .lhs file will be exported to a .tex file. This function will create two new files, base-name.lhs and base-name.tex where -base-name is the name of the current org-mode file. +base-name is the name of the current Org file. Note that all standard Babel literate programming constructs (header arguments, no-web syntax etc...) are ignored." @@ -185,12 +172,12 @@ constructs (header arguments, no-web syntax etc...) are ignored." (save-match-data (setq indentation (length (match-string 1)))) (replace-match (save-match-data (concat - "#+begin_latex\n\\begin{code}\n" + "#+begin_export latex\n\\begin{code}\n" (if (or preserve-indentp (string-match "-i" (match-string 2))) (match-string 3) (org-remove-indentation (match-string 3))) - "\n\\end{code}\n#+end_latex\n")) + "\n\\end{code}\n#+end_export\n")) t t) (indent-code-rigidly (match-beginning 0) (match-end 0) indentation))) (save-excursion diff --git a/lisp/org/ob-io.el b/lisp/org/ob-io.el index 1d3a42aa38a..5dd611098e0 100644 --- a/lisp/org/ob-io.el +++ b/lisp/org/ob-io.el @@ -1,4 +1,4 @@ -;;; ob-io.el --- org-babel functions for Io evaluation +;;; ob-io.el --- Babel Functions for Io -*- lexical-binding: t; -*- ;; Copyright (C) 2012-2017 Free Software Foundation, Inc. @@ -33,7 +33,6 @@ ;;; Code: (require 'ob) -(eval-when-compile (require 'cl)) (defvar org-babel-tangle-lang-exts) ;; Autoloaded (add-to-list 'org-babel-tangle-lang-exts '("io" . "io")) @@ -47,9 +46,8 @@ called by `org-babel-execute-src-block'" (message "executing Io source code block") (let* ((processed-params (org-babel-process-params params)) (session (org-babel-io-initiate-session (nth 0 processed-params))) - (vars (nth 1 processed-params)) (result-params (nth 2 processed-params)) - (result-type (cdr (assoc :result-type params))) + (result-type (cdr (assq :result-type params))) (full-body (org-babel-expand-body:generic body params)) (result (org-babel-io-evaluate @@ -58,17 +56,9 @@ called by `org-babel-execute-src-block'" (org-babel-reassemble-table result (org-babel-pick-name - (cdr (assoc :colname-names params)) (cdr (assoc :colnames params))) + (cdr (assq :colname-names params)) (cdr (assq :colnames params))) (org-babel-pick-name - (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params)))))) - - -(defun org-babel-io-table-or-string (results) - "Convert RESULTS into an appropriate elisp value. -If RESULTS look like a table, then convert them into an -Emacs-lisp table, otherwise return the results as a string." - (org-babel-script-escape results)) - + (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))) (defvar org-babel-io-wrapper-method "( @@ -79,33 +69,33 @@ Emacs-lisp table, otherwise return the results as a string." (defun org-babel-io-evaluate (session body &optional result-type result-params) "Evaluate BODY in external Io process. -If RESULT-TYPE equals 'output then return standard output as a string. -If RESULT-TYPE equals 'value then return the value of the last statement +If RESULT-TYPE equals `output' then return standard output as a string. +If RESULT-TYPE equals `value' then return the value of the last statement in BODY as elisp." (when session (error "Sessions are not (yet) supported for Io")) - (case result-type - (output + (pcase result-type + (`output (if (member "repl" result-params) (org-babel-eval org-babel-io-command body) (let ((src-file (org-babel-temp-file "io-"))) (progn (with-temp-file src-file (insert body)) (org-babel-eval (concat org-babel-io-command " " src-file) ""))))) - (value (let* ((src-file (org-babel-temp-file "io-")) - (wrapper (format org-babel-io-wrapper-method body))) - (with-temp-file src-file (insert wrapper)) - (let ((raw (org-babel-eval - (concat org-babel-io-command " " src-file) ""))) - (org-babel-result-cond result-params - raw - (org-babel-io-table-or-string raw))))))) + (`value (let* ((src-file (org-babel-temp-file "io-")) + (wrapper (format org-babel-io-wrapper-method body))) + (with-temp-file src-file (insert wrapper)) + (let ((raw (org-babel-eval + (concat org-babel-io-command " " src-file) ""))) + (org-babel-result-cond result-params + raw + (org-babel-script-escape raw))))))) -(defun org-babel-prep-session:io (session params) +(defun org-babel-prep-session:io (_session _params) "Prepare SESSION according to the header arguments specified in PARAMS." (error "Sessions are not (yet) supported for Io")) -(defun org-babel-io-initiate-session (&optional session) +(defun org-babel-io-initiate-session (&optional _session) "If there is not a current inferior-process-buffer in SESSION then create. Return the initialized session. Sessions are not supported in Io." diff --git a/lisp/org/ob-java.el b/lisp/org/ob-java.el index 70a10e0131a..7e720231e48 100644 --- a/lisp/org/ob-java.el +++ b/lisp/org/ob-java.el @@ -1,4 +1,4 @@ -;;; ob-java.el --- org-babel functions for java evaluation +;;; ob-java.el --- Babel Functions for Java -*- lexical-binding: t; -*- ;; Copyright (C) 2011-2017 Free Software Foundation, Inc. @@ -32,41 +32,51 @@ (defvar org-babel-tangle-lang-exts) (add-to-list 'org-babel-tangle-lang-exts '("java" . "java")) -(defvar org-babel-java-command "java" - "Name of the java command.") - -(defvar org-babel-java-compiler "javac" - "Name of the java compiler.") +(defcustom org-babel-java-command "java" + "Name of the java command. +May be either a command in the path, like java +or an absolute path name, like /usr/local/bin/java +parameters may be used, like java -verbose" + :group 'org-babel + :version "24.3" + :type 'string) + +(defcustom org-babel-java-compiler "javac" + "Name of the java compiler. +May be either a command in the path, like javac +or an absolute path name, like /usr/local/bin/javac +parameters may be used, like javac -verbose" + :group 'org-babel + :version "24.3" + :type 'string) (defun org-babel-execute:java (body params) - (let* ((classname (or (cdr (assoc :classname params)) + (let* ((classname (or (cdr (assq :classname params)) (error "Can't compile a java block without a classname"))) (packagename (file-name-directory classname)) (src-file (concat classname ".java")) - (cmpflag (or (cdr (assoc :cmpflag params)) "")) - (cmdline (or (cdr (assoc :cmdline params)) "")) - (full-body (org-babel-expand-body:generic body params)) - (compile - (progn (with-temp-file src-file (insert full-body)) - (org-babel-eval - (concat org-babel-java-compiler - " " cmpflag " " src-file) "")))) + (cmpflag (or (cdr (assq :cmpflag params)) "")) + (cmdline (or (cdr (assq :cmdline params)) "")) + (full-body (org-babel-expand-body:generic body params))) + (with-temp-file src-file (insert full-body)) + (org-babel-eval + (concat org-babel-java-compiler " " cmpflag " " src-file) "") ;; created package-name directories if missing (unless (or (not packagename) (file-exists-p packagename)) (make-directory packagename 'parents)) (let ((results (org-babel-eval (concat org-babel-java-command " " cmdline " " classname) ""))) (org-babel-reassemble-table - (org-babel-result-cond (cdr (assoc :result-params params)) + (org-babel-result-cond (cdr (assq :result-params params)) (org-babel-read results) (let ((tmp-file (org-babel-temp-file "c-"))) (with-temp-file tmp-file (insert results)) (org-babel-import-elisp-from-file tmp-file))) (org-babel-pick-name - (cdr (assoc :colname-names params)) (cdr (assoc :colnames params))) + (cdr (assq :colname-names params)) (cdr (assq :colnames params))) (org-babel-pick-name - (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params))))))) + (cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))) (provide 'ob-java) diff --git a/lisp/org/ob-js.el b/lisp/org/ob-js.el index f4f8116dfd7..91be6b07359 100644 --- a/lisp/org/ob-js.el +++ b/lisp/org/ob-js.el @@ -1,4 +1,4 @@ -;;; ob-js.el --- org-babel functions for Javascript +;;; ob-js.el --- Babel Functions for Javascript -*- lexical-binding: t; -*- ;; Copyright (C) 2010-2017 Free Software Foundation, Inc. @@ -39,7 +39,6 @@ ;;; Code: (require 'ob) -(eval-when-compile (require 'cl)) (declare-function run-mozilla "ext:moz" (arg)) @@ -56,20 +55,20 @@ :type 'string) (defvar org-babel-js-function-wrapper - "require('sys').print(require('sys').inspect(function(){%s}()));" + "require('sys').print(require('sys').inspect(function(){\n%s\n}()));" "Javascript code to print value of body.") (defun org-babel-execute:js (body params) "Execute a block of Javascript code with org-babel. This function is called by `org-babel-execute-src-block'" - (let* ((org-babel-js-cmd (or (cdr (assoc :cmd params)) org-babel-js-cmd)) - (result-type (cdr (assoc :result-type params))) + (let* ((org-babel-js-cmd (or (cdr (assq :cmd params)) org-babel-js-cmd)) + (result-type (cdr (assq :result-type params))) (full-body (org-babel-expand-body:generic body params (org-babel-variable-assignments:js params))) - (result (if (not (string= (cdr (assoc :session params)) "none")) + (result (if (not (string= (cdr (assq :session params)) "none")) ;; session evaluation (let ((session (org-babel-prep-session:js - (cdr (assoc :session params)) params))) + (cdr (assq :session params)) params))) (nth 1 (org-babel-comint-with-output (session (format "%S" org-babel-js-eoe) t body) @@ -89,7 +88,7 @@ This function is called by `org-babel-execute-src-block'" (org-babel-eval (format "%s %s" org-babel-js-cmd (org-babel-process-file-name script-file)) ""))))) - (org-babel-result-cond (cdr (assoc :result-params params)) + (org-babel-result-cond (cdr (assq :result-params params)) result (org-babel-js-read result)))) (defun org-babel-js-read (results) @@ -97,14 +96,17 @@ This function is called by `org-babel-execute-src-block'" If RESULTS look like a table, then convert them into an Emacs-lisp table, otherwise return the results as a string." (org-babel-read - (if (and (stringp results) (string-match "^\\[.+\\]$" results)) + (if (and (stringp results) + (string-prefix-p "[" results) + (string-suffix-p "]" results)) (org-babel-read (concat "'" (replace-regexp-in-string "\\[" "(" (replace-regexp-in-string "\\]" ")" (replace-regexp-in-string - ", " " " (replace-regexp-in-string - "'" "\"" results)))))) + ",[[:space:]]" " " + (replace-regexp-in-string + "'" "\"" results)))))) results))) (defun org-babel-js-var-to-js (var) @@ -113,7 +115,7 @@ Convert an elisp value into a string of js source code specifying a variable of the same value." (if (listp var) (concat "[" (mapconcat #'org-babel-js-var-to-js var ", ") "]") - (format "%S" var))) + (replace-regexp-in-string "\n" "\\\\n" (format "%S" var)))) (defun org-babel-prep-session:js (session params) "Prepare SESSION according to the header arguments specified in PARAMS." @@ -133,7 +135,7 @@ specifying a variable of the same value." (mapcar (lambda (pair) (format "var %s=%s;" (car pair) (org-babel-js-var-to-js (cdr pair)))) - (mapcar #'cdr (org-babel-get-header params :var)))) + (org-babel--get-vars params))) (defun org-babel-js-initiate-session (&optional session) "If there is not a current inferior-process-buffer in SESSION diff --git a/lisp/org/ob-keys.el b/lisp/org/ob-keys.el index b71fba416f7..f5fb9101236 100644 --- a/lisp/org/ob-keys.el +++ b/lisp/org/ob-keys.el @@ -1,4 +1,4 @@ -;;; ob-keys.el --- key bindings for org-babel +;;; ob-keys.el --- Key Bindings for Babel -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -23,8 +23,8 @@ ;;; Commentary: -;; Add org-babel keybindings to the org-mode keymap for exposing -;; org-babel functions. These will all share a common prefix. See +;; Add Org Babel keybindings to the Org mode keymap for exposing +;; Org Babel functions. These will all share a common prefix. See ;; the value of `org-babel-key-bindings' for a list of interactive ;; functions and their associated keys. @@ -89,6 +89,7 @@ functions which are assigned key bindings, and see ("h" . org-babel-describe-bindings) ("\C-x" . org-babel-do-key-sequence-in-edit-buffer) ("x" . org-babel-do-key-sequence-in-edit-buffer) + ("k" . org-babel-remove-result-one-or-many) ("\C-\M-h" . org-babel-mark-block)) "Alist of key bindings and interactive Babel functions. This list associates interactive Babel functions diff --git a/lisp/org/ob-latex.el b/lisp/org/ob-latex.el index d00827645ef..763ffb16ff4 100644 --- a/lisp/org/ob-latex.el +++ b/lisp/org/ob-latex.el @@ -1,4 +1,4 @@ -;;; ob-latex.el --- org-babel functions for latex "evaluation" +;;; ob-latex.el --- Babel Functions for LaTeX -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -32,12 +32,11 @@ ;;; Code: (require 'ob) -(declare-function org-create-formula-image "org" - (string tofile options buffer &optional type)) -(declare-function org-splice-latex-header "org" - (tpl def-pkg pkg snippets-p &optional extra)) -(declare-function org-latex-guess-inputenc "ox-latex" (header)) +(declare-function org-create-formula-image "org" (string tofile options buffer &optional type)) (declare-function org-latex-compile "ox-latex" (texfile &optional snippet)) +(declare-function org-latex-guess-inputenc "ox-latex" (header)) +(declare-function org-splice-latex-header "org" (tpl def-pkg pkg snippets-p &optional extra)) +(declare-function org-trim "org" (s &optional keep-lead)) (defvar org-babel-tangle-lang-exts) (add-to-list 'org-babel-tangle-lang-exts '("latex" . "tex")) @@ -51,7 +50,22 @@ '((:results . "latex") (:exports . "results")) "Default arguments to use when evaluating a LaTeX source block.") -(defcustom org-babel-latex-htlatex "" +(defconst org-babel-header-args:latex + '((border . :any) + (fit . :any) + (imagemagick . ((nil t))) + (iminoptions . :any) + (imoutoptions . :any) + (packages . :any) + (pdfheight . :any) + (pdfpng . :any) + (pdfwidth . :any) + (headers . :any) + (packages . :any) + (buffer . ((yes no)))) + "LaTeX-specific header arguments.") + +(defcustom org-babel-latex-htlatex "htlatex" "The htlatex command to enable conversion of latex to SVG or HTML." :group 'org-babel :type 'string) @@ -70,37 +84,82 @@ (regexp-quote (format "%S" (car pair))) (if (stringp (cdr pair)) (cdr pair) (format "%S" (cdr pair))) - body))) (mapcar #'cdr (org-babel-get-header params :var))) - (org-babel-trim body)) + body))) (org-babel--get-vars params)) + (org-trim body)) (defun org-babel-execute:latex (body params) "Execute a block of Latex code with Babel. This function is called by `org-babel-execute-src-block'." (setq body (org-babel-expand-body:latex body params)) - (if (cdr (assoc :file params)) - (let* ((out-file (cdr (assoc :file params))) + (if (cdr (assq :file params)) + (let* ((out-file (cdr (assq :file params))) + (extension (file-name-extension out-file)) (tex-file (org-babel-temp-file "latex-" ".tex")) - (border (cdr (assoc :border params))) - (imagemagick (cdr (assoc :imagemagick params))) - (im-in-options (cdr (assoc :iminoptions params))) - (im-out-options (cdr (assoc :imoutoptions params))) - (pdfpng (cdr (assoc :pdfpng params))) - (fit (or (cdr (assoc :fit params)) border)) - (height (and fit (cdr (assoc :pdfheight params)))) - (width (and fit (cdr (assoc :pdfwidth params)))) - (headers (cdr (assoc :headers params))) - (in-buffer (not (string= "no" (cdr (assoc :buffer params))))) + (border (cdr (assq :border params))) + (imagemagick (cdr (assq :imagemagick params))) + (im-in-options (cdr (assq :iminoptions params))) + (im-out-options (cdr (assq :imoutoptions params))) + (fit (or (cdr (assq :fit params)) border)) + (height (and fit (cdr (assq :pdfheight params)))) + (width (and fit (cdr (assq :pdfwidth params)))) + (headers (cdr (assq :headers params))) + (in-buffer (not (string= "no" (cdr (assq :buffer params))))) (org-latex-packages-alist - (append (cdr (assoc :packages params)) org-latex-packages-alist))) + (append (cdr (assq :packages params)) org-latex-packages-alist))) (cond - ((and (string-match "\\.png$" out-file) (not imagemagick)) + ((and (string-suffix-p ".png" out-file) (not imagemagick)) (org-create-formula-image body out-file org-format-latex-options in-buffer)) - ((string-match "\\.tikz$" out-file) + ((string-suffix-p ".tikz" out-file) (when (file-exists-p out-file) (delete-file out-file)) (with-temp-file out-file (insert body))) - ((or (string-match "\\.pdf$" out-file) imagemagick) + ((and (or (string= "svg" extension) + (string= "html" extension)) + (executable-find org-babel-latex-htlatex)) + ;; TODO: this is a very different way of generating the + ;; frame latex document than in the pdf case. Ideally, both + ;; would be unified. This would prevent bugs creeping in + ;; such as the one fixed on Aug 16 2014 whereby :headers was + ;; not included in the SVG/HTML case. + (with-temp-file tex-file + (insert (concat + "\\documentclass[preview]{standalone} +\\def\\pgfsysdriver{pgfsys-tex4ht.def} +" + (mapconcat (lambda (pkg) + (concat "\\usepackage" pkg)) + org-babel-latex-htlatex-packages + "\n") + (if headers + (concat "\n" + (if (listp headers) + (mapconcat #'identity headers "\n") + headers) "\n") + "") + "\\begin{document}" + body + "\\end{document}"))) + (when (file-exists-p out-file) (delete-file out-file)) + (let ((default-directory (file-name-directory tex-file))) + (shell-command (format "%s %s" org-babel-latex-htlatex tex-file))) + (cond + ((file-exists-p (concat (file-name-sans-extension tex-file) "-1.svg")) + (if (string-suffix-p ".svg" out-file) + (progn + (shell-command "pwd") + (shell-command (format "mv %s %s" + (concat (file-name-sans-extension tex-file) "-1.svg") + out-file))) + (error "SVG file produced but HTML file requested"))) + ((file-exists-p (concat (file-name-sans-extension tex-file) ".html")) + (if (string-suffix-p ".html" out-file) + (shell-command "mv %s %s" + (concat (file-name-sans-extension tex-file) + ".html") + out-file) + (error "HTML file produced but SVG file requested"))))) + ((or (string= "pdf" extension) imagemagick) (with-temp-file tex-file (require 'ox-latex) (insert @@ -133,54 +192,20 @@ This function is called by `org-babel-execute-src-block'." (when (file-exists-p out-file) (delete-file out-file)) (let ((transient-pdf-file (org-babel-latex-tex-to-pdf tex-file))) (cond - ((string-match "\\.pdf$" out-file) + ((string= "pdf" extension) (rename-file transient-pdf-file out-file)) (imagemagick - (convert-pdf + (org-babel-latex-convert-pdf transient-pdf-file out-file im-in-options im-out-options) (when (file-exists-p transient-pdf-file) - (delete-file transient-pdf-file)))))) - ((and (or (string-match "\\.svg$" out-file) - (string-match "\\.html$" out-file)) - (not (string= "" org-babel-latex-htlatex))) - (with-temp-file tex-file - (insert (concat - "\\documentclass[preview]{standalone} -\\def\\pgfsysdriver{pgfsys-tex4ht.def} -" - (mapconcat (lambda (pkg) - (concat "\\usepackage" pkg)) - org-babel-latex-htlatex-packages - "\n") - "\\begin{document}" - body - "\\end{document}"))) - (when (file-exists-p out-file) (delete-file out-file)) - (let ((default-directory (file-name-directory tex-file))) - (shell-command (format "%s %s" org-babel-latex-htlatex tex-file))) - (cond - ((file-exists-p (concat (file-name-sans-extension tex-file) "-1.svg")) - (if (string-match "\\.svg$" out-file) - (progn - (shell-command "pwd") - (shell-command (format "mv %s %s" - (concat (file-name-sans-extension tex-file) "-1.svg") - out-file))) - (error "SVG file produced but HTML file requested."))) - ((file-exists-p (concat (file-name-sans-extension tex-file) ".html")) - (if (string-match "\\.html$" out-file) - (shell-command "mv %s %s" - (concat (file-name-sans-extension tex-file) - ".html") - out-file) - (error "HTML file produced but SVG file requested."))))) - ((string-match "\\.\\([^\\.]+\\)$" out-file) - (error "Can not create %s files, please specify a .png or .pdf file or try the :imagemagick header argument" - (match-string 1 out-file)))) + (delete-file transient-pdf-file))) + (t + (error "Can not create %s files, please specify a .png or .pdf file or try the :imagemagick header argument" + extension)))))) nil) ;; signal that output has already been written to file body)) -(defun convert-pdf (pdffile out-file im-in-options im-out-options) +(defun org-babel-latex-convert-pdf (pdffile out-file im-in-options im-out-options) "Generate a file from a pdf file using imagemagick." (let ((cmd (concat "convert " im-in-options " " pdffile " " im-out-options " " out-file))) @@ -192,7 +217,7 @@ This function is called by `org-babel-execute-src-block'." (require 'ox-latex) (org-latex-compile file)) -(defun org-babel-prep-session:latex (session params) +(defun org-babel-prep-session:latex (_session _params) "Return an error because LaTeX doesn't support sessions." (error "LaTeX does not support sessions")) diff --git a/lisp/org/ob-ledger.el b/lisp/org/ob-ledger.el index 154e75c0e05..c02069e2835 100644 --- a/lisp/org/ob-ledger.el +++ b/lisp/org/ob-ledger.el @@ -1,4 +1,4 @@ -;;; ob-ledger.el --- org-babel functions for ledger evaluation +;;; ob-ledger.el --- Babel Functions for Ledger -*- lexical-binding: t; -*- ;; Copyright (C) 2010-2017 Free Software Foundation, Inc. @@ -46,8 +46,7 @@ "Execute a block of Ledger entries with org-babel. This function is called by `org-babel-execute-src-block'." (message "executing Ledger source code block") - (let ((result-params (split-string (or (cdr (assoc :results params)) ""))) - (cmdline (cdr (assoc :cmdline params))) + (let ((cmdline (cdr (assq :cmdline params))) (in-file (org-babel-temp-file "ledger-")) (out-file (org-babel-temp-file "ledger-output-"))) (with-temp-file in-file (insert body)) @@ -61,7 +60,7 @@ called by `org-babel-execute-src-block'." " > " (org-babel-process-file-name out-file)))) (with-temp-buffer (insert-file-contents out-file) (buffer-string)))) -(defun org-babel-prep-session:ledger (session params) +(defun org-babel-prep-session:ledger (_session _params) (error "Ledger does not support sessions")) (provide 'ob-ledger) diff --git a/lisp/org/ob-lilypond.el b/lisp/org/ob-lilypond.el index b37ecd87a7b..37a7a6b57ef 100644 --- a/lisp/org/ob-lilypond.el +++ b/lisp/org/ob-lilypond.el @@ -1,4 +1,4 @@ -;;; ob-lilypond.el --- org-babel functions for lilypond evaluation +;;; ob-lilypond.el --- Babel Functions for Lilypond -*- lexical-binding: t; -*- ;; Copyright (C) 2010-2017 Free Software Foundation, Inc. @@ -28,6 +28,8 @@ ;; ;; Lilypond documentation can be found at ;; http://lilypond.org/manuals.html +;; +;; This depends on epstopdf --- See http://www.ctan.org/pkg/epstopdf. ;;; Code: (require 'ob) @@ -60,51 +62,68 @@ org-babel-lilypond-play-midi-post-tangle determines whether to automate the playing of the resultant midi file. If the value is nil, the midi file is not automatically played. Default value is t") -(defvar org-babel-lilypond-OSX-ly-path - "/Applications/lilypond.app/Contents/Resources/bin/lilypond") -(defvar org-babel-lilypond-OSX-pdf-path "open") -(defvar org-babel-lilypond-OSX-midi-path "open") - -(defvar org-babel-lilypond-nix-ly-path "/usr/bin/lilypond") -(defvar org-babel-lilypond-nix-pdf-path "evince") -(defvar org-babel-lilypond-nix-midi-path "timidity") - -(defvar org-babel-lilypond-w32-ly-path "lilypond") -(defvar org-babel-lilypond-w32-pdf-path "") -(defvar org-babel-lilypond-w32-midi-path "") +(defvar org-babel-lilypond-ly-command "" + "Command to execute lilypond on your system. +Do not set it directly. Customize `org-babel-lilypond-commands' instead.") +(defvar org-babel-lilypond-pdf-command "" + "Command to show a PDF file on your system. +Do not set it directly. Customize `org-babel-lilypond-commands' instead.") +(defvar org-babel-lilypond-midi-command "" + "Command to play a MIDI file on your system. +Do not set it directly. Customize `org-babel-lilypond-commands' instead.") +(defcustom org-babel-lilypond-commands + (cond + ((eq system-type 'darwin) + '("/Applications/lilypond.app/Contents/Resources/bin/lilypond" "open" "open")) + ((eq system-type 'windows-nt) + '("lilypond" "" "")) + (t + '("lilypond" "xdg-open" "xdg-open"))) + "Commands to run lilypond and view or play the results. +These should be executables that take a filename as an argument. +On some system it is possible to specify the filename directly +and the viewer or player will be determined from the file type; +you can leave the string empty on this case." + :group 'org-babel + :type '(list + (string :tag "Lilypond ") + (string :tag "PDF Viewer ") + (string :tag "MIDI Player")) + :version "24.3" + :package-version '(Org . "8.2.7") + :set + (lambda (_symbol value) + (setq + org-babel-lilypond-ly-command (nth 0 value) + org-babel-lilypond-pdf-command (nth 1 value) + org-babel-lilypond-midi-command (nth 2 value)))) (defvar org-babel-lilypond-gen-png nil - "Image generation (png) can be turned on by default by setting -ORG-BABEL-LILYPOND-GEN-PNG to t") + "Non-nil means image generation (PNG) is turned on by default.") (defvar org-babel-lilypond-gen-svg nil - "Image generation (SVG) can be turned on by default by setting -ORG-BABEL-LILYPOND-GEN-SVG to t") + "Non-nil means image generation (SVG) is be turned on by default.") (defvar org-babel-lilypond-gen-html nil - "HTML generation can be turned on by default by setting -ORG-BABEL-LILYPOND-GEN-HTML to t") + "Non-nil means HTML generation is turned on by default.") (defvar org-babel-lilypond-gen-pdf nil - "PDF generation can be turned on by default by setting -ORG-BABEL-LILYPOND-GEN-PDF to t") + "Non-nil means PDF generation is be turned on by default.") (defvar org-babel-lilypond-use-eps nil - "You can force the compiler to use the EPS backend by setting -ORG-BABEL-LILYPOND-USE-EPS to t") + "Non-nil forces the compiler to use the EPS backend.") (defvar org-babel-lilypond-arrange-mode nil - "Arrange mode is turned on by setting ORG-BABEL-LILYPOND-ARRANGE-MODE -to t. In Arrange mode the following settings are altered -from default... + "Non-nil turns Arrange mode on. +In Arrange mode the following settings are altered from default: :tangle yes, :noweb yes :results silent :comments yes. In addition lilypond block execution causes tangling of all lilypond -blocks") +blocks.") (defun org-babel-expand-body:lilypond (body params) "Expand BODY according to PARAMS, return the expanded body." - (let ((vars (mapcar #'cdr (org-babel-get-header params :var)))) + (let ((vars (org-babel--get-vars params))) (mapc (lambda (pair) (let ((name (symbol-name (car pair))) @@ -138,9 +157,8 @@ specific arguments to =org-babel-tangle=" (defun org-babel-lilypond-process-basic (body params) "Execute a lilypond block in basic mode." - (let* ((result-params (cdr (assoc :result-params params))) - (out-file (cdr (assoc :file params))) - (cmdline (or (cdr (assoc :cmdline params)) + (let* ((out-file (cdr (assq :file params))) + (cmdline (or (cdr (assq :cmdline params)) "")) (in-file (org-babel-temp-file "lilypond-"))) @@ -148,7 +166,7 @@ specific arguments to =org-babel-tangle=" (insert (org-babel-expand-body:generic body params))) (org-babel-eval (concat - (org-babel-lilypond-determine-ly-path) + org-babel-lilypond-ly-command " -dbackend=eps " "-dno-gs-load-fonts " "-dinclude-eps-fonts " @@ -163,7 +181,7 @@ specific arguments to =org-babel-tangle=" cmdline in-file) "")) nil) -(defun org-babel-prep-session:lilypond (session params) +(defun org-babel-prep-session:lilypond (_session _params) "Return an error because LilyPond exporter does not support sessions." (error "Sorry, LilyPond does not currently support sessions!")) @@ -175,29 +193,27 @@ If error in compilation, attempt to mark the error in lilypond org file" (buffer-file-name) ".lilypond")) (org-babel-lilypond-temp-file (org-babel-lilypond-switch-extension (buffer-file-name) ".ly"))) - (if (file-exists-p org-babel-lilypond-tangled-file) - (progn - (when (file-exists-p org-babel-lilypond-temp-file) - (delete-file org-babel-lilypond-temp-file)) - (rename-file org-babel-lilypond-tangled-file - org-babel-lilypond-temp-file)) - (error "Error: Tangle Failed!") t) + (if (not (file-exists-p org-babel-lilypond-tangled-file)) + (error "Error: Tangle Failed!") + (when (file-exists-p org-babel-lilypond-temp-file) + (delete-file org-babel-lilypond-temp-file)) + (rename-file org-babel-lilypond-tangled-file + org-babel-lilypond-temp-file)) (switch-to-buffer-other-window "*lilypond*") (erase-buffer) (org-babel-lilypond-compile-lilyfile org-babel-lilypond-temp-file) (goto-char (point-min)) - (if (not (org-babel-lilypond-check-for-compile-error org-babel-lilypond-temp-file)) - (progn - (other-window -1) - (org-babel-lilypond-attempt-to-open-pdf org-babel-lilypond-temp-file) - (org-babel-lilypond-attempt-to-play-midi org-babel-lilypond-temp-file)) - (error "Error in Compilation!")))) nil) + (if (org-babel-lilypond-check-for-compile-error org-babel-lilypond-temp-file) + (error "Error in Compilation!") + (other-window -1) + (org-babel-lilypond-attempt-to-open-pdf org-babel-lilypond-temp-file) + (org-babel-lilypond-attempt-to-play-midi org-babel-lilypond-temp-file))))) (defun org-babel-lilypond-compile-lilyfile (file-name &optional test) "Compile lilypond file and check for compile errors FILE-NAME is full path to lilypond (.ly) file" (message "Compiling LilyPond...") - (let ((arg-1 (org-babel-lilypond-determine-ly-path)) ;program + (let ((arg-1 org-babel-lilypond-ly-command) ;program (arg-2 nil) ;infile (arg-3 "*lilypond*") ;buffer (arg-4 t) ;display @@ -223,11 +239,10 @@ FILE-NAME is full path to lilypond file. If TEST is t just return nil if no error found, and pass nil as file-name since it is unused in this context" (let ((is-error (search-forward "error:" nil t))) - (if (not test) - (if (not is-error) - nil - (org-babel-lilypond-process-compile-error file-name)) - is-error))) + (if test + is-error + (when is-error + (org-babel-lilypond-process-compile-error file-name))))) (defun org-babel-lilypond-process-compile-error (file-name) "Process the compilation error that has occurred. @@ -249,32 +264,26 @@ LINE is the erroneous line" (setq case-fold-search nil) (if (search-forward line nil t) (progn - (show-all) + (outline-show-all) (set-mark (point)) (goto-char (- (point) (length line)))) (goto-char temp)))) (defun org-babel-lilypond-parse-line-num (&optional buffer) "Extract error line number." - (when buffer - (set-buffer buffer)) + (when buffer (set-buffer buffer)) (let ((start (and (search-backward ":" nil t) (search-backward ":" nil t) (search-backward ":" nil t) - (search-backward ":" nil t))) - (num nil)) - (if start - (progn - (forward-char) - (let ((num (buffer-substring - (+ 1 start) - (- (search-forward ":" nil t) 1)))) - (setq num (string-to-number num)) - (if (numberp num) - num - nil))) - nil))) + (search-backward ":" nil t)))) + (when start + (forward-char) + (let ((num (string-to-number + (buffer-substring + (+ 1 start) + (- (search-forward ":" nil t) 1))))) + (and (numberp num) num))))) (defun org-babel-lilypond-parse-error-line (file-name lineNo) "Extract the erroneous line from the tangled .ly file @@ -298,13 +307,13 @@ If TEST is non-nil, the shell command is returned and is not run" (let ((pdf-file (org-babel-lilypond-switch-extension file-name ".pdf"))) (if (file-exists-p pdf-file) (let ((cmd-string - (concat (org-babel-lilypond-determine-pdf-path) " " pdf-file))) + (concat org-babel-lilypond-pdf-command " " pdf-file))) (if test cmd-string (start-process "\"Audition pdf\"" "*lilypond*" - (org-babel-lilypond-determine-pdf-path) + org-babel-lilypond-pdf-command pdf-file))) (message "No pdf file generated so can't display!"))))) @@ -316,49 +325,16 @@ If TEST is non-nil, the shell command is returned and is not run" (let ((midi-file (org-babel-lilypond-switch-extension file-name ".midi"))) (if (file-exists-p midi-file) (let ((cmd-string - (concat (org-babel-lilypond-determine-midi-path) " " midi-file))) + (concat org-babel-lilypond-midi-command " " midi-file))) (if test cmd-string (start-process "\"Audition midi\"" "*lilypond*" - (org-babel-lilypond-determine-midi-path) + org-babel-lilypond-midi-command midi-file))) (message "No midi file generated so can't play!"))))) -(defun org-babel-lilypond-determine-ly-path (&optional test) - "Return correct path to ly binary depending on OS -If TEST is non-nil, it contains a simulation of the OS for test purposes" - (let ((sys-type - (or test system-type))) - (cond ((string= sys-type "darwin") - org-babel-lilypond-OSX-ly-path) - ((string= sys-type "windows-nt") - org-babel-lilypond-w32-ly-path) - (t org-babel-lilypond-nix-ly-path)))) - -(defun org-babel-lilypond-determine-pdf-path (&optional test) - "Return correct path to pdf viewer depending on OS -If TEST is non-nil, it contains a simulation of the OS for test purposes" - (let ((sys-type - (or test system-type))) - (cond ((string= sys-type "darwin") - org-babel-lilypond-OSX-pdf-path) - ((string= sys-type "windows-nt") - org-babel-lilypond-w32-pdf-path) - (t org-babel-lilypond-nix-pdf-path)))) - -(defun org-babel-lilypond-determine-midi-path (&optional test) - "Return correct path to midi player depending on OS -If TEST is non-nil, it contains a simulation of the OS for test purposes" - (let ((sys-type - (or test test system-type))) - (cond ((string= sys-type "darwin") - org-babel-lilypond-OSX-midi-path) - ((string= sys-type "windows-nt") - org-babel-lilypond-w32-midi-path) - (t org-babel-lilypond-nix-midi-path)))) - (defun org-babel-lilypond-toggle-midi-play () "Toggle whether midi will be played following a successful compilation." (interactive) diff --git a/lisp/org/ob-lisp.el b/lisp/org/ob-lisp.el index 2f66549fc3d..1e381d0ce2f 100644 --- a/lisp/org/ob-lisp.el +++ b/lisp/org/ob-lisp.el @@ -1,4 +1,4 @@ -;;; ob-lisp.el --- org-babel functions for common lisp evaluation +;;; ob-lisp.el --- Babel Functions for Common Lisp -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -25,17 +25,22 @@ ;;; Commentary: -;;; support for evaluating common lisp code, relies on slime for all eval +;;; Support for evaluating Common Lisp code, relies on SLY or SLIME +;;; for all eval. ;;; Requirements: -;; Requires SLIME (Superior Lisp Interaction Mode for Emacs.) -;; See http://common-lisp.net/project/slime/ +;; Requires SLY (Sylvester the Cat's Common Lisp IDE) or SLIME +;; (Superior Lisp Interaction Mode for Emacs). See: +;; - https://github.com/capitaomorte/sly +;; - http://common-lisp.net/project/slime/ ;;; Code: (require 'ob) +(declare-function sly-eval "ext:sly" (sexp &optional package)) (declare-function slime-eval "ext:slime" (sexp &optional package)) +(declare-function org-trim "org" (s &optional keep-lead)) (defvar org-babel-tangle-lang-exts) (add-to-list 'org-babel-tangle-lang-exts '("lisp" . "lisp")) @@ -43,8 +48,16 @@ (defvar org-babel-default-header-args:lisp '()) (defvar org-babel-header-args:lisp '((package . :any))) +(defcustom org-babel-lisp-eval-fn #'slime-eval + "The function to be called to evaluate code on the Lisp side. +Valid values include `slime-eval' and `sly-eval'." + :group 'org-babel + :version "26.1" + :package-version '(Org . "9.0") + :type 'function) + (defcustom org-babel-lisp-dir-fmt - "(let ((*default-pathname-defaults* #P%S)) %%s)" + "(let ((*default-pathname-defaults* #P%S\n)) %%s\n)" "Format string used to wrap code bodies to set the current directory. For example a value of \"(progn ;; %s\\n %%s)\" would ignore the current directory string." @@ -54,49 +67,54 @@ current directory string." (defun org-babel-expand-body:lisp (body params) "Expand BODY according to PARAMS, return the expanded body." - (let* ((vars (mapcar #'cdr (org-babel-get-header params :var))) - (result-params (cdr (assoc :result-params params))) + (let* ((vars (org-babel--get-vars params)) + (result-params (cdr (assq :result-params params))) (print-level nil) (print-length nil) - (body (org-babel-trim - (if (> (length vars) 0) - (concat "(let (" - (mapconcat - (lambda (var) - (format "(%S (quote %S))" (car var) (cdr var))) - vars "\n ") - ")\n" body ")") - body)))) + (body (if (null vars) (org-trim body) + (concat "(let (" + (mapconcat + (lambda (var) + (format "(%S (quote %S))" (car var) (cdr var))) + vars "\n ") + ")\n" body ")")))) (if (or (member "code" result-params) (member "pp" result-params)) (format "(pprint %s)" body) body))) (defun org-babel-execute:lisp (body params) - "Execute a block of Common Lisp code with Babel." - (require 'slime) + "Execute a block of Common Lisp code with Babel. +BODY is the contents of the block, as a string. PARAMS is +a property list containing the parameters of the block." + (require (pcase org-babel-lisp-eval-fn + (`slime-eval 'slime) + (`sly-eval 'sly))) (org-babel-reassemble-table (let ((result - (with-temp-buffer - (insert (org-babel-expand-body:lisp body params)) - (slime-eval `(swank:eval-and-grab-output - ,(let ((dir (if (assoc :dir params) - (cdr (assoc :dir params)) - default-directory))) - (format - (if dir (format org-babel-lisp-dir-fmt dir) - "(progn %s)") - (buffer-substring-no-properties - (point-min) (point-max))))) - (cdr (assoc :package params)))))) - (org-babel-result-cond (cdr (assoc :result-params params)) - (car result) + (funcall (if (member "output" (cdr (assq :result-params params))) + #'car #'cadr) + (with-temp-buffer + (insert (org-babel-expand-body:lisp body params)) + (funcall org-babel-lisp-eval-fn + `(swank:eval-and-grab-output + ,(let ((dir (if (assq :dir params) + (cdr (assq :dir params)) + default-directory))) + (format + (if dir (format org-babel-lisp-dir-fmt dir) + "(progn %s\n)") + (buffer-substring-no-properties + (point-min) (point-max))))) + (cdr (assq :package params))))))) + (org-babel-result-cond (cdr (assq :result-params params)) + result (condition-case nil - (read (org-babel-lisp-vector-to-list (cadr result))) - (error (cadr result))))) - (org-babel-pick-name (cdr (assoc :colname-names params)) - (cdr (assoc :colnames params))) - (org-babel-pick-name (cdr (assoc :rowname-names params)) - (cdr (assoc :rownames params))))) + (read (org-babel-lisp-vector-to-list result)) + (error result)))) + (org-babel-pick-name (cdr (assq :colname-names params)) + (cdr (assq :colnames params))) + (org-babel-pick-name (cdr (assq :rowname-names params)) + (cdr (assq :rownames params))))) (defun org-babel-lisp-vector-to-list (results) ;; TODO: better would be to replace #(...) with [...] diff --git a/lisp/org/ob-lob.el b/lisp/org/ob-lob.el index ddfac2afeed..b6f50d33ed0 100644 --- a/lisp/org/ob-lob.el +++ b/lisp/org/ob-lob.el @@ -1,4 +1,4 @@ -;;; ob-lob.el --- functions supporting the Library of Babel +;;; ob-lob.el --- Functions Supporting the Library of Babel -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -23,27 +23,27 @@ ;; along with GNU Emacs. If not, see . ;;; Code: -(eval-when-compile - (require 'cl)) +(require 'cl-lib) (require 'ob-core) (require 'ob-table) -(declare-function org-babel-in-example-or-verbatim "ob-exp" nil) +(declare-function org-babel-ref-split-args "ob-ref" (arg-string)) +(declare-function org-element-at-point "org-element" ()) +(declare-function org-element-context "org-element" (&optional element)) +(declare-function org-element-property "org-element" (property element)) +(declare-function org-element-type "org-element" (element)) (defvar org-babel-library-of-babel nil "Library of source-code blocks. -This is an association list. Populate the library by adding -files to `org-babel-lob-files'.") - -(defcustom org-babel-lob-files nil - "Files used to populate the `org-babel-library-of-babel'. -To add files to this list use the `org-babel-lob-ingest' command." - :group 'org-babel - :version "24.1" - :type '(repeat file)) +This is an association list. Populate the library by calling +`org-babel-lob-ingest' on files containing source blocks.") (defvar org-babel-default-lob-header-args '((:exports . "results")) - "Default header arguments to use when exporting #+lob/call lines.") + "Default header arguments to use when exporting Babel calls. +By default, a Babel call inherits its arguments from the source +block being called. Header arguments defined in this variable +take precedence over these. It is useful for properties that +should not be inherited from a source block.") (defun org-babel-lob-ingest (&optional file) "Add all named source blocks defined in FILE to `org-babel-library-of-babel'." @@ -62,24 +62,7 @@ To add files to this list use the `org-babel-lob-ingest' command." lob-ingest-count (if (> lob-ingest-count 1) "s" "")) lob-ingest-count)) -(defconst org-babel-block-lob-one-liner-regexp - (concat - "^\\([ \t]*?\\)#\\+call:[ \t]+\\([^()\n]+?\\)\\(\\[\\(.*\\)\\]\\|\\(\\)\\)" - "(\\([^\n]*?\\))\\(\\[.+\\]\\|\\)[ \t]*\\(\\([^\n]*\\)\\)?") - "Regexp to match non-inline calls to predefined source block functions.") - -(defconst org-babel-inline-lob-one-liner-regexp - (concat - "\\([^\n]*?\\)call_\\([^()\n]+?\\)\\(\\[\\(.*?\\)\\]\\|\\(\\)\\)" - "(\\([^\n]*?\\))\\(\\[\\(.*?\\)\\]\\)?") - "Regexp to match inline calls to predefined source block functions.") - -(defconst org-babel-lob-one-liner-regexp - (concat "\\(" org-babel-block-lob-one-liner-regexp - "\\|" org-babel-inline-lob-one-liner-regexp "\\)") - "Regexp to match calls to predefined source block functions.") - -;; functions for executing lob one-liners +;; Functions for executing lob one-liners. ;;;###autoload (defun org-babel-lob-execute-maybe () @@ -88,72 +71,76 @@ Detect if this is context for a Library Of Babel source block and if so then run the appropriate source block from the Library." (interactive) (let ((info (org-babel-lob-get-info))) - (if (and (nth 0 info) (not (org-babel-in-example-or-verbatim))) - (progn (org-babel-lob-execute info) t) - nil))) + (when info + (org-babel-execute-src-block nil info) + t))) + +(defun org-babel-lob--src-info (name) + "Return internal representation for Babel data named NAME. +NAME is a string. This function looks into the current document +for a Babel call or source block. If none is found, it looks +after NAME in the Library of Babel. Eventually, if that also +fails, it returns nil." + ;; During export, look into the pristine copy of the document being + ;; exported instead of the current one, which could miss some data. + (with-current-buffer (or org-babel-exp-reference-buffer (current-buffer)) + (org-with-wide-buffer + (goto-char (point-min)) + (catch :found + (let ((case-fold-search t) + (regexp (org-babel-named-data-regexp-for-name name))) + (while (re-search-forward regexp nil t) + (let ((element (org-element-at-point))) + (when (equal name (org-element-property :name element)) + (throw :found + (pcase (org-element-type element) + (`src-block (org-babel-get-src-block-info t element)) + (`babel-call (org-babel-lob-get-info element)) + ;; Non-executable data found. Since names are + ;; supposed to be unique throughout a document, + ;; bail out. + (_ nil)))))) + ;; No element named NAME in buffer. Try Library of Babel. + (cdr (assoc-string name org-babel-library-of-babel))))))) ;;;###autoload -(defun org-babel-lob-get-info () - "Return a Library of Babel function call as a string." - (let ((case-fold-search t) - (nonempty (lambda (a b) - (let ((it (match-string a))) - (if (= (length it) 0) (match-string b) it))))) - (save-excursion - (beginning-of-line 1) - (when (looking-at org-babel-lob-one-liner-regexp) - (append - (mapcar #'org-no-properties - (list - (format "%s%s(%s)%s" - (funcall nonempty 3 12) - (if (not (= 0 (length (funcall nonempty 5 14)))) - (concat "[" (funcall nonempty 5 14) "]") "") - (or (funcall nonempty 7 16) "") - (or (funcall nonempty 8 19) "")) - (funcall nonempty 9 18))) - (list (length (if (= (length (match-string 12)) 0) - (match-string 2) (match-string 11))) - (save-excursion - (forward-line -1) - (and (looking-at (concat org-babel-src-name-regexp - "\\([^\n]*\\)$")) - (org-no-properties (match-string 1)))))))))) - -(defvar org-babel-default-header-args:emacs-lisp) ; Defined in ob-emacs-lisp.el -(defun org-babel-lob-execute (info) - "Execute the lob call specified by INFO." - (let* ((mkinfo (lambda (p) - (list "emacs-lisp" "results" p nil - (nth 3 info) ;; name - (nth 2 info)))) - (pre-params (apply #'org-babel-merge-params - org-babel-default-header-args - org-babel-default-header-args:emacs-lisp - (append - (org-babel-params-from-properties) - (list - (org-babel-parse-header-arguments - (org-no-properties - (concat - ":var results=" - (mapconcat #'identity (butlast info 2) - " ")))))))) - (pre-info (funcall mkinfo pre-params)) - (cache-p (and (cdr (assoc :cache pre-params)) - (string= "yes" (cdr (assoc :cache pre-params))))) - (new-hash (when cache-p (org-babel-sha1-hash pre-info))) - (old-hash (when cache-p (org-babel-current-result-hash))) - (org-babel-current-src-block-location (point-marker))) - (if (and cache-p (equal new-hash old-hash)) - (save-excursion (goto-char (org-babel-where-is-src-block-result)) - (forward-line 1) - (message "%S" (org-babel-read-result))) - (prog1 (let* ((proc-params (org-babel-process-params pre-params)) - org-confirm-babel-evaluate) - (org-babel-execute-src-block nil (funcall mkinfo proc-params))) - ;; update the hash - (when new-hash (org-babel-set-current-result-hash new-hash)))))) +(defun org-babel-lob-get-info (&optional datum) + "Return internal representation for Library of Babel function call. +Consider DATUM, when provided, or element at point. Return nil +when not on an appropriate location. Otherwise return a list +compatible with `org-babel-get-src-block-info', which see." + (let* ((context (or datum (org-element-context))) + (type (org-element-type context))) + (when (memq type '(babel-call inline-babel-call)) + (pcase (org-babel-lob--src-info (org-element-property :call context)) + (`(,language ,body ,header ,_ ,_ ,_ ,coderef) + (let ((begin (org-element-property (if (eq type 'inline-babel-call) + :begin + :post-affiliated) + context))) + (list language + body + (apply #'org-babel-merge-params + header + org-babel-default-lob-header-args + (append + (org-with-wide-buffer + (goto-char begin) + (org-babel-params-from-properties language)) + (list + (org-babel-parse-header-arguments + (org-element-property :inside-header context)) + (let ((args (org-element-property :arguments context))) + (and args + (mapcar (lambda (ref) (cons :var ref)) + (org-babel-ref-split-args args)))) + (org-babel-parse-header-arguments + (org-element-property :end-header context))))) + nil + (org-element-property :name context) + begin + coderef))) + (_ nil))))) (provide 'ob-lob) diff --git a/lisp/org/ob-lua.el b/lisp/org/ob-lua.el new file mode 100644 index 00000000000..877d895284f --- /dev/null +++ b/lisp/org/ob-lua.el @@ -0,0 +1,403 @@ +;;; ob-lua.el --- Org Babel functions for Lua evaluation -*- lexical-binding: t; -*- + +;; Copyright (C) 2014, 2016-2017 Free Software Foundation, Inc. + +;; Authors: Dieter Schoen +;; Keywords: literate programming, reproducible research +;; Homepage: http://orgmode.org + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;; Requirements: +;; for session support, lua-mode is needed. +;; lua-mode is not part of GNU Emacs/orgmode, but can be obtained +;; from marmalade or melpa. +;; The source repository is here: +;; https://github.com/immerrr/lua-mode + +;; However, sessions are not yet working. + +;; Org-Babel support for evaluating lua source code. + +;;; Code: +(require 'ob) +(require 'cl-lib) + +(declare-function org-remove-indentation "org" (code &optional n)) +(declare-function org-trim "org" (s &optional keep-lead)) +(declare-function lua-shell "ext:lua-mode" (&optional argprompt)) +(declare-function lua-toggle-shells "ext:lua-mode" (arg)) +(declare-function run-lua "ext:lua" (cmd &optional dedicated show)) + +(defvar org-babel-tangle-lang-exts) +(add-to-list 'org-babel-tangle-lang-exts '("lua" . "lua")) + +(defvar org-babel-default-header-args:lua '()) + +(defcustom org-babel-lua-command "lua" + "Name of the command for executing Lua code." + :version "24.5" + :package-version '(Org . "8.3") + :group 'org-babel + :type 'string) + +(defcustom org-babel-lua-mode 'lua-mode + "Preferred lua mode for use in running lua interactively. +This will typically be 'lua-mode." + :group 'org-babel + :version "24.5" + :package-version '(Org . "8.3") + :type 'symbol) + +(defcustom org-babel-lua-hline-to "None" + "Replace hlines in incoming tables with this when translating to lua." + :group 'org-babel + :version "24.5" + :package-version '(Org . "8.3") + :type 'string) + +(defcustom org-babel-lua-None-to 'hline + "Replace 'None' in lua tables with this before returning." + :group 'org-babel + :version "24.5" + :package-version '(Org . "8.3") + :type 'symbol) + +(defun org-babel-execute:lua (body params) + "Execute a block of Lua code with Babel. +This function is called by `org-babel-execute-src-block'." + (let* ((session (org-babel-lua-initiate-session + (cdr (assq :session params)))) + (result-params (cdr (assq :result-params params))) + (result-type (cdr (assq :result-type params))) + (return-val (when (and (eq result-type 'value) (not session)) + (cdr (assq :return params)))) + (preamble (cdr (assq :preamble params))) + (full-body + (org-babel-expand-body:generic + (concat body (if return-val (format "\nreturn %s" return-val) "")) + params (org-babel-variable-assignments:lua params))) + (result (org-babel-lua-evaluate + session full-body result-type result-params preamble))) + (org-babel-reassemble-table + result + (org-babel-pick-name (cdr (assq :colname-names params)) + (cdr (assq :colnames params))) + (org-babel-pick-name (cdr (assq :rowname-names params)) + (cdr (assq :rownames params)))))) + +(defun org-babel-prep-session:lua (session params) + "Prepare SESSION according to the header arguments in PARAMS. +VARS contains resolved variable references" + (let* ((session (org-babel-lua-initiate-session session)) + (var-lines + (org-babel-variable-assignments:lua params))) + (org-babel-comint-in-buffer session + (mapc (lambda (var) + (end-of-line 1) (insert var) (comint-send-input) + (org-babel-comint-wait-for-output session)) var-lines)) + session)) + +(defun org-babel-load-session:lua (session body params) + "Load BODY into SESSION." + (save-window-excursion + (let ((buffer (org-babel-prep-session:lua session params))) + (with-current-buffer buffer + (goto-char (process-mark (get-buffer-process (current-buffer)))) + (insert (org-babel-chomp body))) + buffer))) + +;; helper functions + +(defun org-babel-variable-assignments:lua (params) + "Return a list of Lua statements assigning the block's variables." + (mapcar + (lambda (pair) + (format "%s=%s" + (car pair) + (org-babel-lua-var-to-lua (cdr pair)))) + (org-babel--get-vars params))) + +(defun org-babel-lua-var-to-lua (var) + "Convert an elisp value to a lua variable. +Convert an elisp value, VAR, into a string of lua source code +specifying a variable of the same value." + (if (listp var) + (if (and (= 1 (length var)) (not (listp (car var)))) + (org-babel-lua-var-to-lua (car var)) + (if (and + (= 2 (length var)) + (not (listp (car var)))) + (concat + (substring-no-properties (car var)) + "=" + (org-babel-lua-var-to-lua (cdr var))) + (concat "{" (mapconcat #'org-babel-lua-var-to-lua var ", ") "}"))) + (if (eq var 'hline) + org-babel-lua-hline-to + (format + (if (and (stringp var) (string-match "[\n\r]" var)) "\"\"%S\"\"" "%S") + (if (stringp var) (substring-no-properties var) var))))) + +(defun org-babel-lua-table-or-string (results) + "Convert RESULTS into an appropriate elisp value. +If the results look like a list or tuple, then convert them into an +Emacs-lisp table, otherwise return the results as a string." + (let ((res (org-babel-script-escape results))) + (if (listp res) + (mapcar (lambda (el) (if (eq el 'None) + org-babel-lua-None-to el)) + res) + res))) + +(defvar org-babel-lua-buffers '((:default . "*Lua*"))) + +(defun org-babel-lua-session-buffer (session) + "Return the buffer associated with SESSION." + (cdr (assoc session org-babel-lua-buffers))) + +(defun org-babel-lua-with-earmuffs (session) + (let ((name (if (stringp session) session (format "%s" session)))) + (if (and (string= "*" (substring name 0 1)) + (string= "*" (substring name (- (length name) 1)))) + name + (format "*%s*" name)))) + +(defun org-babel-lua-without-earmuffs (session) + (let ((name (if (stringp session) session (format "%s" session)))) + (if (and (string= "*" (substring name 0 1)) + (string= "*" (substring name (- (length name) 1)))) + (substring name 1 (- (length name) 1)) + name))) + +(defvar lua-default-interpreter) +(defvar lua-which-bufname) +(defvar lua-shell-buffer-name) +(defun org-babel-lua-initiate-session-by-key (&optional session) + "Initiate a lua session. +If there is not a current inferior-process-buffer in SESSION +then create. Return the initialized session." + ;; (require org-babel-lua-mode) + (save-window-excursion + (let* ((session (if session (intern session) :default)) + (lua-buffer (org-babel-lua-session-buffer session)) + ;; (cmd (if (member system-type '(cygwin windows-nt ms-dos)) + ;; (concat org-babel-lua-command " -i") + ;; org-babel-lua-command)) + ) + (cond + ((and (eq 'lua-mode org-babel-lua-mode) + (fboundp 'lua-start-process)) ; lua-mode.el + ;; Make sure that lua-which-bufname is initialized, as otherwise + ;; it will be overwritten the first time a Lua buffer is + ;; created. + ;;(lua-toggle-shells lua-default-interpreter) + ;; `lua-shell' creates a buffer whose name is the value of + ;; `lua-which-bufname' with '*'s at the beginning and end + (let* ((bufname (if (and lua-buffer (buffer-live-p lua-buffer)) + (replace-regexp-in-string ;; zap surrounding * + "^\\*\\([^*]+\\)\\*$" "\\1" (buffer-name lua-buffer)) + (concat "Lua-" (symbol-name session)))) + (lua-which-bufname bufname)) + (lua-start-process) + (setq lua-buffer (org-babel-lua-with-earmuffs bufname)))) + (t + (error "No function available for running an inferior Lua"))) + (setq org-babel-lua-buffers + (cons (cons session lua-buffer) + (assq-delete-all session org-babel-lua-buffers))) + session))) + +(defun org-babel-lua-initiate-session (&optional session _params) + "Create a session named SESSION according to PARAMS." + (unless (string= session "none") + (error "Sessions currently not supported, work in progress") + (org-babel-lua-session-buffer + (org-babel-lua-initiate-session-by-key session)))) + +(defvar org-babel-lua-eoe-indicator "--eoe" + "A string to indicate that evaluation has completed.") + +(defvar org-babel-lua-wrapper-method + " +function main() +%s +end + +fd=io.open(\"%s\", \"w\") +fd:write( main() ) +fd:close()") +(defvar org-babel-lua-pp-wrapper-method + " +-- table to string +function t2s(t, indent) + if indent == nil then + indent = \"\" + end + if type(t) == \"table\" then + ts = \"\" + for k,v in pairs(t) do + if type(v) == \"table\" then + ts = ts .. indent .. t2s(k,indent .. \" \") .. \" = \\n\" .. + t2s(v, indent .. \" \") + else + ts = ts .. indent .. t2s(k,indent .. \" \") .. \" = \" .. + t2s(v, indent .. \" \") .. \"\\n\" + end + end + return ts + else + return tostring(t) + end +end + + +function main() +%s +end + +fd=io.open(\"%s\", \"w\") +fd:write(t2s(main())) +fd:close()") + +(defun org-babel-lua-evaluate + (session body &optional result-type result-params preamble) + "Evaluate BODY as Lua code." + (if session + (org-babel-lua-evaluate-session + session body result-type result-params) + (org-babel-lua-evaluate-external-process + body result-type result-params preamble))) + +(defun org-babel-lua-evaluate-external-process + (body &optional result-type result-params preamble) + "Evaluate BODY in external lua process. +If RESULT-TYPE equals 'output then return standard output as a +string. If RESULT-TYPE equals 'value then return the value of the +last statement in BODY, as elisp." + (let ((raw + (pcase result-type + (`output (org-babel-eval org-babel-lua-command + (concat (if preamble (concat preamble "\n")) + body))) + (`value (let ((tmp-file (org-babel-temp-file "lua-"))) + (org-babel-eval + org-babel-lua-command + (concat + (if preamble (concat preamble "\n") "") + (format + (if (member "pp" result-params) + org-babel-lua-pp-wrapper-method + org-babel-lua-wrapper-method) + (mapconcat + (lambda (line) (format "\t%s" line)) + (split-string + (org-remove-indentation + (org-trim body)) + "[\r\n]") "\n") + (org-babel-process-file-name tmp-file 'noquote)))) + (org-babel-eval-read-file tmp-file)))))) + (org-babel-result-cond result-params + raw + (org-babel-lua-table-or-string (org-trim raw))))) + +(defun org-babel-lua-evaluate-session + (session body &optional result-type result-params) + "Pass BODY to the Lua process in SESSION. +If RESULT-TYPE equals 'output then return standard output as a +string. If RESULT-TYPE equals 'value then return the value of the +last statement in BODY, as elisp." + (let* ((send-wait (lambda () (comint-send-input nil t) (sleep-for 0 5))) + (dump-last-value + (lambda + (tmp-file pp) + (mapc + (lambda (statement) (insert statement) (funcall send-wait)) + (if pp + (list + "-- table to string +function t2s(t, indent) + if indent == nil then + indent = \"\" + end + if type(t) == \"table\" then + ts = \"\" + for k,v in pairs(t) do + if type(v) == \"table\" then + ts = ts .. indent .. t2s(k,indent .. \" \") .. \" = \\n\" .. + t2s(v, indent .. \" \") + else + ts = ts .. indent .. t2s(k,indent .. \" \") .. \" = \" .. + t2s(v, indent .. \" \") .. \"\\n\" + end + end + return ts + else + return tostring(t) + end +end +" + (concat "fd:write(_)) +fd:close()" + (org-babel-process-file-name tmp-file 'noquote))) + (list (format "fd=io.open(\"%s\", \"w\") +fd:write( _ ) +fd:close()" + (org-babel-process-file-name tmp-file + 'noquote))))))) + (input-body (lambda (body) + (mapc (lambda (line) (insert line) (funcall send-wait)) + (split-string body "[\r\n]")) + (funcall send-wait))) + (results + (pcase result-type + (`output + (mapconcat + #'org-trim + (butlast + (org-babel-comint-with-output + (session org-babel-lua-eoe-indicator t body) + (funcall input-body body) + (funcall send-wait) (funcall send-wait) + (insert org-babel-lua-eoe-indicator) + (funcall send-wait)) + 2) "\n")) + (`value + (let ((tmp-file (org-babel-temp-file "lua-"))) + (org-babel-comint-with-output + (session org-babel-lua-eoe-indicator nil body) + (let ((comint-process-echoes nil)) + (funcall input-body body) + (funcall dump-last-value tmp-file + (member "pp" result-params)) + (funcall send-wait) (funcall send-wait) + (insert org-babel-lua-eoe-indicator) + (funcall send-wait))) + (org-babel-eval-read-file tmp-file)))))) + (unless (string= (substring org-babel-lua-eoe-indicator 1 -1) results) + (org-babel-result-cond result-params + results + (org-babel-lua-table-or-string results))))) + +(defun org-babel-lua-read-string (string) + "Strip 's from around Lua string." + (org-unbracket-string "'" "'" string)) + +(provide 'ob-lua) + + + +;;; ob-lua.el ends here diff --git a/lisp/org/ob-makefile.el b/lisp/org/ob-makefile.el index a292800dc17..2aa04fd2af7 100644 --- a/lisp/org/ob-makefile.el +++ b/lisp/org/ob-makefile.el @@ -1,4 +1,4 @@ -;;; ob-makefile.el --- org-babel functions for makefile evaluation +;;; ob-makefile.el --- Babel Functions for Makefile -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -24,19 +24,19 @@ ;;; Commentary: -;; This file exists solely for tangling a Makefile from org-mode files. +;; This file exists solely for tangling a Makefile from Org files. ;;; Code: (require 'ob) (defvar org-babel-default-header-args:makefile '()) -(defun org-babel-execute:makefile (body params) +(defun org-babel-execute:makefile (body _params) "Execute a block of makefile code. This function is called by `org-babel-execute-src-block'." body) -(defun org-babel-prep-session:makefile (session params) +(defun org-babel-prep-session:makefile (_session _params) "Return an error if the :session header argument is set. Make does not support sessions." (error "Makefile sessions are nonsensical")) diff --git a/lisp/org/ob-matlab.el b/lisp/org/ob-matlab.el index 42bbd2b9074..23cfa36d1e0 100644 --- a/lisp/org/ob-matlab.el +++ b/lisp/org/ob-matlab.el @@ -1,4 +1,4 @@ -;;; ob-matlab.el --- org-babel support for matlab evaluation +;;; ob-matlab.el --- Babel support for Matlab -*- lexical-binding: t; -*- ;; Copyright (C) 2010-2017 Free Software Foundation, Inc. diff --git a/lisp/org/ob-maxima.el b/lisp/org/ob-maxima.el index b567fd484a9..0a4d835a3ad 100644 --- a/lisp/org/ob-maxima.el +++ b/lisp/org/ob-maxima.el @@ -1,4 +1,4 @@ -;;; ob-maxima.el --- org-babel functions for maxima evaluation +;;; ob-maxima.el --- Babel Functions for Maxima -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -48,11 +48,11 @@ (defun org-babel-maxima-expand (body params) "Expand a block of Maxima code according to its header arguments." - (let ((vars (mapcar #'cdr (org-babel-get-header params :var)))) + (let ((vars (org-babel--get-vars params))) (mapconcat 'identity (list ;; graphic output - (let ((graphic-file (org-babel-maxima-graphical-output-file params))) + (let ((graphic-file (ignore-errors (org-babel-graphical-output-file params)))) (if graphic-file (format "set_plot_option ([gnuplot_term, png]); set_plot_option ([gnuplot_out_file, %S]);" @@ -69,9 +69,9 @@ "Execute a block of Maxima entries with org-babel. This function is called by `org-babel-execute-src-block'." (message "executing Maxima source code block") - (let ((result-params (split-string (or (cdr (assoc :results params)) ""))) + (let ((result-params (split-string (or (cdr (assq :results params)) ""))) (result - (let* ((cmdline (or (cdr (assoc :cmdline params)) "")) + (let* ((cmdline (or (cdr (assq :cmdline params)) "")) (in-file (org-babel-temp-file "maxima-" ".max")) (cmd (format "%s --very-quiet -r 'batchload(%S)$' %s" org-babel-maxima-command in-file cmdline))) @@ -89,7 +89,7 @@ This function is called by `org-babel-execute-src-block'." (= 0 (length line))) line)) (split-string raw "[\r\n]"))) "\n"))))) - (if (org-babel-maxima-graphical-output-file params) + (if (ignore-errors (org-babel-graphical-output-file params)) nil (org-babel-result-cond result-params result @@ -98,7 +98,7 @@ This function is called by `org-babel-execute-src-block'." (org-babel-import-elisp-from-file tmp-file)))))) -(defun org-babel-prep-session:maxima (session params) +(defun org-babel-prep-session:maxima (_session _params) (error "Maxima does not support sessions")) (defun org-babel-maxima-var-to-maxima (pair) @@ -113,11 +113,6 @@ of the same value." (format "%S: %s$" var (org-babel-maxima-elisp-to-maxima val)))) -(defun org-babel-maxima-graphical-output-file (params) - "Name of file to which maxima should send graphical output." - (and (member "graphics" (cdr (assq :result-params params))) - (cdr (assq :file params)))) - (defun org-babel-maxima-elisp-to-maxima (val) "Return a string of maxima code which evaluates to VAL." (if (listp val) diff --git a/lisp/org/ob-mscgen.el b/lisp/org/ob-mscgen.el index b764475cb2f..5c9dccc67c4 100644 --- a/lisp/org/ob-mscgen.el +++ b/lisp/org/ob-mscgen.el @@ -1,4 +1,4 @@ -;;; ob-msc.el --- org-babel functions for mscgen evaluation +;;; ob-msc.el --- Babel Functions for Mscgen -*- lexical-binding: t; -*- ;; Copyright (C) 2010-2017 Free Software Foundation, Inc. @@ -65,15 +65,15 @@ This function is called by `org-babel-execute-src-block'. Default filetype is png. Modify by setting :filetype parameter to mscgen supported formats." - (let* ((out-file (or (cdr (assoc :file params)) "output.png" )) - (filetype (or (cdr (assoc :filetype params)) "png" ))) - (unless (cdr (assoc :file params)) + (let* ((out-file (or (cdr (assq :file params)) "output.png" )) + (filetype (or (cdr (assq :filetype params)) "png" ))) + (unless (cdr (assq :file params)) (error " ERROR: no output file specified. Add \":file name.png\" to the src header")) (org-babel-eval (concat "mscgen -T " filetype " -o " out-file) body) nil)) ;; signal that output has already been written to file -(defun org-babel-prep-session:mscgen (session params) +(defun org-babel-prep-session:mscgen (_session _params) "Raise an error because Mscgen doesn't support sessions." (error "Mscgen does not support sessions")) diff --git a/lisp/org/ob-ocaml.el b/lisp/org/ob-ocaml.el index 31f0d01d7f6..7997ff03a62 100644 --- a/lisp/org/ob-ocaml.el +++ b/lisp/org/ob-ocaml.el @@ -1,4 +1,4 @@ -;;; ob-ocaml.el --- org-babel functions for ocaml evaluation +;;; ob-ocaml.el --- Babel Functions for Ocaml -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -37,11 +37,11 @@ ;;; Code: (require 'ob) (require 'comint) -(eval-when-compile (require 'cl)) (declare-function tuareg-run-caml "ext:tuareg" ()) (declare-function tuareg-run-ocaml "ext:tuareg" ()) (declare-function tuareg-interactive-send-input "ext:tuareg" ()) +(declare-function org-trim "org" (s &optional keep-lead)) (defvar org-babel-tangle-lang-exts) (add-to-list 'org-babel-tangle-lang-exts '("ocaml" . "ml")) @@ -60,17 +60,17 @@ (defun org-babel-execute:ocaml (body params) "Execute a block of Ocaml code with Babel." - (let* ((vars (mapcar #'cdr (org-babel-get-header params :var))) - (full-body (org-babel-expand-body:generic + (let* ((full-body (org-babel-expand-body:generic body params (org-babel-variable-assignments:ocaml params))) (session (org-babel-prep-session:ocaml - (cdr (assoc :session params)) params)) + (cdr (assq :session params)) params)) (raw (org-babel-comint-with-output - (session org-babel-ocaml-eoe-output t full-body) + (session org-babel-ocaml-eoe-output nil full-body) (insert (concat - (org-babel-chomp full-body)";;\n"org-babel-ocaml-eoe-indicator)) + (org-babel-chomp full-body) ";;\n" + org-babel-ocaml-eoe-indicator)) (tuareg-interactive-send-input))) (clean (car (let ((re (regexp-quote org-babel-ocaml-eoe-output)) out) @@ -79,23 +79,31 @@ (progn (setq out nil) line) (when (string-match re line) (progn (setq out t) nil)))) - (mapcar #'org-babel-trim (reverse raw)))))))) - (org-babel-reassemble-table - (let ((raw (org-babel-trim clean)) - (result-params (cdr (assoc :result-params params)))) + (mapcar #'org-trim (reverse raw))))))) + (raw (org-trim clean)) + (result-params (cdr (assq :result-params params)))) + (string-match + "\\(\\(.*\n\\)*\\)[^:\n]+ : \\([^=\n]+\\) =\\(\n\\| \\)\\(.+\\)$" + raw) + (let ((output (match-string 1 raw)) + (type (match-string 3 raw)) + (value (match-string 5 raw))) + (org-babel-reassemble-table (org-babel-result-cond result-params - ;; strip type information from output unless verbatim is specified - (if (and (not (member "verbatim" result-params)) - (string-match "= \\(.+\\)$" raw)) - (match-string 1 raw) raw) - (org-babel-ocaml-parse-output raw))) - (org-babel-pick-name - (cdr (assoc :colname-names params)) (cdr (assoc :colnames params))) - (org-babel-pick-name - (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params)))))) + (cond + ((member "verbatim" result-params) raw) + ((member "output" result-params) output) + (t raw)) + (if (and value type) + (org-babel-ocaml-parse-output value type) + raw)) + (org-babel-pick-name + (cdr (assq :colname-names params)) (cdr (assq :colnames params))) + (org-babel-pick-name + (cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))) (defvar tuareg-interactive-buffer-name) -(defun org-babel-prep-session:ocaml (session params) +(defun org-babel-prep-session:ocaml (session _params) "Prepare SESSION according to the header arguments in PARAMS." (require 'tuareg) (let ((tuareg-interactive-buffer-name (if (and (not (string= session "none")) @@ -113,7 +121,7 @@ (mapcar (lambda (pair) (format "let %s = %s;;" (car pair) (org-babel-ocaml-elisp-to-ocaml (cdr pair)))) - (mapcar #'cdr (org-babel-get-header params :var)))) + (org-babel--get-vars params))) (defun org-babel-ocaml-elisp-to-ocaml (val) "Return a string of ocaml code which evaluates to VAL." @@ -121,26 +129,29 @@ (concat "[|" (mapconcat #'org-babel-ocaml-elisp-to-ocaml val "; ") "|]") (format "%S" val))) -(defun org-babel-ocaml-parse-output (output) - "Parse OUTPUT. -OUTPUT is string output from an ocaml process." - (let ((regexp "[^:]+ : %s = \\(.+\\)$")) - (cond - ((string-match (format regexp "string") output) - (org-babel-read (match-string 1 output))) - ((or (string-match (format regexp "int") output) - (string-match (format regexp "float") output)) - (string-to-number (match-string 1 output))) - ((string-match (format regexp "list") output) - (org-babel-ocaml-read-list (match-string 1 output))) - ((string-match (format regexp "array") output) - (org-babel-ocaml-read-array (match-string 1 output))) - (t (message "don't recognize type of %s" output) output)))) +(defun org-babel-ocaml-parse-output (value type) + "Parse VALUE of type TYPE. +VALUE and TYPE are string output from an ocaml process." + (cond + ((string= "string" type) + (org-babel-read value)) + ((or (string= "int" type) + (string= "float" type)) + (string-to-number value)) + ((string-match "list" type) + (org-babel-ocaml-read-list value)) + ((string-match "array" type) + (org-babel-ocaml-read-array value)) + (t (message "don't recognize type %s" type) value))) (defun org-babel-ocaml-read-list (results) "Convert RESULTS into an elisp table or string. If the results look like a table, then convert them into an Emacs-lisp table, otherwise return the results as a string." + ;; XXX: This probably does not behave as expected when a semicolon + ;; is in a string in a list. The same comment applies to + ;; `org-babel-ocaml-read-array' below (with even more failure + ;; modes). (org-babel-script-escape (replace-regexp-in-string ";" "," results))) (defun org-babel-ocaml-read-array (results) diff --git a/lisp/org/ob-octave.el b/lisp/org/ob-octave.el index 4a96cdbf033..90735b11fb8 100644 --- a/lisp/org/ob-octave.el +++ b/lisp/org/ob-octave.el @@ -1,4 +1,4 @@ -;;; ob-octave.el --- org-babel functions for octave and matlab evaluation +;;; ob-octave.el --- Babel Functions for Octave and Matlab -*- lexical-binding: t; -*- ;; Copyright (C) 2010-2017 Free Software Foundation, Inc. @@ -30,10 +30,10 @@ ;;; Code: (require 'ob) -(eval-when-compile (require 'cl)) (declare-function matlab-shell "ext:matlab-mode") (declare-function matlab-shell-run-region "ext:matlab-mode") +(declare-function org-trim "org" (s &optional keep-lead)) (defvar org-babel-default-header-args:matlab '()) (defvar org-babel-default-header-args:octave '()) @@ -74,33 +74,31 @@ end") (let* ((session (funcall (intern (format "org-babel-%s-initiate-session" (if matlabp "matlab" "octave"))) - (cdr (assoc :session params)) params)) - (vars (mapcar #'cdr (org-babel-get-header params :var))) - (result-params (cdr (assoc :result-params params))) - (result-type (cdr (assoc :result-type params))) - (out-file (cdr (assoc :file params))) + (cdr (assq :session params)) params)) + (result-type (cdr (assq :result-type params))) (full-body (org-babel-expand-body:generic body params (org-babel-variable-assignments:octave params))) + (gfx-file (ignore-errors (org-babel-graphical-output-file params))) (result (org-babel-octave-evaluate session - (if (org-babel-octave-graphical-output-file params) + (if gfx-file (mapconcat 'identity (list "set (0, \"defaultfigurevisible\", \"off\");" full-body - (format "print -dpng %s" (org-babel-octave-graphical-output-file params))) + (format "print -dpng %s" gfx-file)) "\n") full-body) result-type matlabp))) - (if (org-babel-octave-graphical-output-file params) + (if gfx-file nil (org-babel-reassemble-table result (org-babel-pick-name - (cdr (assoc :colname-names params)) (cdr (assoc :colnames params))) + (cdr (assq :colname-names params)) (cdr (assq :colnames params))) (org-babel-pick-name - (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params))))))) + (cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))) (defun org-babel-prep-session:matlab (session params) "Prepare SESSION according to PARAMS." @@ -113,7 +111,7 @@ end") (format "%s=%s;" (car pair) (org-babel-octave-var-to-octave (cdr pair)))) - (mapcar #'cdr (org-babel-get-header params :var)))) + (org-babel--get-vars params))) (defalias 'org-babel-variable-assignments:matlab 'org-babel-variable-assignments:octave) @@ -147,7 +145,7 @@ If there is not a current inferior-process-buffer in SESSION then create. Return the initialized session." (org-babel-octave-initiate-session session params 'matlab)) -(defun org-babel-octave-initiate-session (&optional session params matlabp) +(defun org-babel-octave-initiate-session (&optional session _params matlabp) "Create an octave inferior process buffer. If there is not a current inferior-process-buffer in SESSION then create. Return the initialized session." @@ -167,8 +165,8 @@ create. Return the initialized session." (defun org-babel-octave-evaluate (session body result-type &optional matlabp) "Pass BODY to the octave process in SESSION. -If RESULT-TYPE equals 'output then return the outputs of the -statements in BODY, if RESULT-TYPE equals 'value then return the +If RESULT-TYPE equals `output' then return the outputs of the +statements in BODY, if RESULT-TYPE equals `value' then return the value of the last statement in BODY, as elisp." (if session (org-babel-octave-evaluate-session session body result-type matlabp) @@ -179,9 +177,9 @@ value of the last statement in BODY, as elisp." (let ((cmd (if matlabp org-babel-matlab-shell-command org-babel-octave-shell-command))) - (case result-type - (output (org-babel-eval cmd body)) - (value (let ((tmp-file (org-babel-temp-file "octave-"))) + (pcase result-type + (`output (org-babel-eval cmd body)) + (`value (let ((tmp-file (org-babel-temp-file "octave-"))) (org-babel-eval cmd (format org-babel-octave-wrapper-method body @@ -190,17 +188,17 @@ value of the last statement in BODY, as elisp." (org-babel-octave-import-elisp-from-file tmp-file)))))) (defun org-babel-octave-evaluate-session - (session body result-type &optional matlabp) + (session body result-type &optional matlabp) "Evaluate BODY in SESSION." (let* ((tmp-file (org-babel-temp-file (if matlabp "matlab-" "octave-"))) (wait-file (org-babel-temp-file "matlab-emacs-link-wait-signal-")) (full-body - (case result-type - (output + (pcase result-type + (`output (mapconcat #'org-babel-chomp (list body org-babel-octave-eoe-indicator) "\n")) - (value + (`value (if (and matlabp org-babel-matlab-with-emacs-link) (concat (format org-babel-matlab-emacs-link-wrapper-method @@ -233,21 +231,20 @@ value of the last statement in BODY, as elisp." org-babel-octave-eoe-output) t full-body) (insert full-body) (comint-send-input nil t)))) results) - (case result-type - (value + (pcase result-type + (`value (org-babel-octave-import-elisp-from-file tmp-file)) - (output - (progn - (setq results - (if matlabp - (cdr (reverse (delq "" (mapcar - #'org-babel-octave-read-string - (mapcar #'org-babel-trim raw))))) - (cdr (member org-babel-octave-eoe-output - (reverse (mapcar - #'org-babel-octave-read-string - (mapcar #'org-babel-trim raw))))))) - (mapconcat #'identity (reverse results) "\n")))))) + (`output + (setq results + (if matlabp + (cdr (reverse (delq "" (mapcar + #'org-babel-strip-quotes + (mapcar #'org-trim raw))))) + (cdr (member org-babel-octave-eoe-output + (reverse (mapcar + #'org-babel-strip-quotes + (mapcar #'org-trim raw))))))) + (mapconcat #'identity (reverse results) "\n"))))) (defun org-babel-octave-import-elisp-from-file (file-name) "Import data from FILE-NAME. @@ -262,17 +259,6 @@ This removes initial blank and comment lines and then calls (delete-region beg end))) (org-babel-import-elisp-from-file temp-file '(16)))) -(defun org-babel-octave-read-string (string) - "Strip \\\"s from around octave string." - (if (string-match "^\"\\([^\000]+\\)\"$" string) - (match-string 1 string) - string)) - -(defun org-babel-octave-graphical-output-file (params) - "Name of file to which maxima should send graphical output." - (and (member "graphics" (cdr (assq :result-params params))) - (cdr (assq :file params)))) - (provide 'ob-octave) diff --git a/lisp/org/ob-org.el b/lisp/org/ob-org.el index 3535891613e..5683b96fca3 100644 --- a/lisp/org/ob-org.el +++ b/lisp/org/ob-org.el @@ -1,4 +1,4 @@ -;;; ob-org.el --- org-babel functions for org code block evaluation +;;; ob-org.el --- Babel Functions for Org Code Blocks -*- lexical-binding: t; -*- ;; Copyright (C) 2010-2017 Free Software Foundation, Inc. @@ -41,7 +41,7 @@ "Default header inserted during export of org blocks.") (defun org-babel-expand-body:org (body params) - (dolist (var (mapcar #'cdr (org-babel-get-header params :var))) + (dolist (var (org-babel--get-vars params)) (setq body (replace-regexp-in-string (regexp-quote (format "$%s" (car var))) (format "%s" (cdr var)) @@ -51,7 +51,7 @@ (defun org-babel-execute:org (body params) "Execute a block of Org code with. This function is called by `org-babel-execute-src-block'." - (let ((result-params (split-string (or (cdr (assoc :results params)) ""))) + (let ((result-params (split-string (or (cdr (assq :results params)) ""))) (body (org-babel-expand-body:org (replace-regexp-in-string "^," "" body) params))) (cond @@ -61,7 +61,7 @@ This function is called by `org-babel-execute-src-block'." ((member "ascii" result-params) (org-export-string-as body 'ascii t)) (t body)))) -(defun org-babel-prep-session:org (session params) +(defun org-babel-prep-session:org (_session _params) "Return an error because org does not support sessions." (error "Org does not support sessions")) diff --git a/lisp/org/ob-perl.el b/lisp/org/ob-perl.el index 4e4407d1762..62df8c555f1 100644 --- a/lisp/org/ob-perl.el +++ b/lisp/org/ob-perl.el @@ -1,4 +1,4 @@ -;;; ob-perl.el --- org-babel functions for perl evaluation +;;; ob-perl.el --- Babel Functions for Perl -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -28,7 +28,6 @@ ;;; Code: (require 'ob) -(eval-when-compile (require 'cl)) (defvar org-babel-tangle-lang-exts) (add-to-list 'org-babel-tangle-lang-exts '("perl" . "pl")) @@ -41,20 +40,20 @@ (defun org-babel-execute:perl (body params) "Execute a block of Perl code with Babel. This function is called by `org-babel-execute-src-block'." - (let* ((session (cdr (assoc :session params))) - (result-params (cdr (assoc :result-params params))) - (result-type (cdr (assoc :result-type params))) + (let* ((session (cdr (assq :session params))) + (result-params (cdr (assq :result-params params))) + (result-type (cdr (assq :result-type params))) (full-body (org-babel-expand-body:generic body params (org-babel-variable-assignments:perl params))) (session (org-babel-perl-initiate-session session))) (org-babel-reassemble-table (org-babel-perl-evaluate session full-body result-type result-params) (org-babel-pick-name - (cdr (assoc :colname-names params)) (cdr (assoc :colnames params))) + (cdr (assq :colname-names params)) (cdr (assq :colnames params))) (org-babel-pick-name - (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params)))))) + (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))) -(defun org-babel-prep-session:perl (session params) +(defun org-babel-prep-session:perl (_session _params) "Prepare SESSION according to the header arguments in PARAMS." (error "Sessions are not supported for Perl")) @@ -63,7 +62,7 @@ This function is called by `org-babel-execute-src-block'." (mapcar (lambda (pair) (org-babel-perl--var-to-perl (cdr pair) (car pair))) - (mapcar #'cdr (org-babel-get-header params :var)))) + (org-babel--get-vars params))) ;; helper functions @@ -76,7 +75,7 @@ This function is called by `org-babel-execute-src-block'." The elisp value, VAR, is converted to a string of perl source code specifying a var of the same value." (if varn - (let ((org-babel-perl--lvl 0) (lvar (listp var)) prefix) + (let ((org-babel-perl--lvl 0) (lvar (listp var))) (concat "my $" (symbol-name varn) "=" (when lvar "\n") (org-babel-perl--var-to-perl var) ";\n")) @@ -92,7 +91,7 @@ specifying a var of the same value." (defvar org-babel-perl-buffers '(:default . nil)) -(defun org-babel-perl-initiate-session (&optional session params) +(defun org-babel-perl-initiate-session (&optional _session _params) "Return nil because sessions are not supported by perl." nil) @@ -127,8 +126,8 @@ specifying a var of the same value." (defun org-babel-perl-evaluate (session ibody &optional result-type result-params) "Pass BODY to the Perl process in SESSION. -If RESULT-TYPE equals 'output then return a list of the outputs -of the statements in BODY, if RESULT-TYPE equals 'value then +If RESULT-TYPE equals `output' then return a list of the outputs +of the statements in BODY, if RESULT-TYPE equals `value' then return the value of the last statement in BODY, as elisp." (when session (error "Sessions are not supported for Perl")) (let* ((body (concat org-babel-perl-preface ibody)) @@ -136,13 +135,13 @@ return the value of the last statement in BODY, as elisp." (tmp-babel-file (org-babel-process-file-name tmp-file 'noquote))) (let ((results - (case result-type - (output + (pcase result-type + (`output (with-temp-file tmp-file (insert (org-babel-eval org-babel-perl-command body)) (buffer-string))) - (value + (`value (org-babel-eval org-babel-perl-command (format org-babel-perl-wrapper-method body tmp-babel-file)))))) diff --git a/lisp/org/ob-picolisp.el b/lisp/org/ob-picolisp.el index a87c15ea977..f5773815578 100644 --- a/lisp/org/ob-picolisp.el +++ b/lisp/org/ob-picolisp.el @@ -1,4 +1,4 @@ -;;; ob-picolisp.el --- org-babel functions for picolisp evaluation +;;; ob-picolisp.el --- Babel Functions for Picolisp -*- lexical-binding: t; -*- ;; Copyright (C) 2010-2017 Free Software Foundation, Inc. @@ -55,7 +55,6 @@ ;;; Code: (require 'ob) (require 'comint) -(eval-when-compile (require 'cl)) (declare-function run-picolisp "ext:inferior-picolisp" (cmd)) (defvar org-babel-tangle-lang-exts) ;; Autoloaded @@ -80,9 +79,9 @@ (defun org-babel-expand-body:picolisp (body params) "Expand BODY according to PARAMS, return the expanded body." - (let ((vars (mapcar #'cdr (org-babel-get-header params :var))) - (result-params (cdr (assoc :result-params params))) - (print-level nil) (print-length nil)) + (let ((vars (org-babel--get-vars params)) + (print-level nil) + (print-length nil)) (if (> (length vars) 0) (concat "(prog (let (" (mapconcat @@ -100,12 +99,11 @@ (message "executing Picolisp source code block") (let* ( ;; Name of the session or "none". - (session-name (cdr (assoc :session params))) + (session-name (cdr (assq :session params))) ;; Set the session if the session variable is non-nil. (session (org-babel-picolisp-initiate-session session-name)) ;; Either OUTPUT or VALUE which should behave as described above. - (result-type (cdr (assoc :result-type params))) - (result-params (cdr (assoc :result-params params))) + (result-params (cdr (assq :result-params params))) ;; Expand the body with `org-babel-expand-body:picolisp'. (full-body (org-babel-expand-body:picolisp body params)) ;; Wrap body appropriately for the type of evaluation and results. diff --git a/lisp/org/ob-plantuml.el b/lisp/org/ob-plantuml.el index e05565e32ce..e90021a52ae 100644 --- a/lisp/org/ob-plantuml.el +++ b/lisp/org/ob-plantuml.el @@ -1,4 +1,4 @@ -;;; ob-plantuml.el --- org-babel functions for plantuml evaluation +;;; ob-plantuml.el --- Babel Functions for Plantuml -*- lexical-binding: t; -*- ;; Copyright (C) 2010-2017 Free Software Foundation, Inc. @@ -49,21 +49,36 @@ (defun org-babel-execute:plantuml (body params) "Execute a block of plantuml code with org-babel. This function is called by `org-babel-execute-src-block'." - (let* ((result-params (split-string (or (cdr (assoc :results params)) ""))) - (out-file (or (cdr (assoc :file params)) + (let* ((out-file (or (cdr (assq :file params)) (error "PlantUML requires a \":file\" header argument"))) - (cmdline (cdr (assoc :cmdline params))) + (cmdline (cdr (assq :cmdline params))) (in-file (org-babel-temp-file "plantuml-")) - (java (or (cdr (assoc :java params)) "")) + (java (or (cdr (assq :java params)) "")) (cmd (if (string= "" org-plantuml-jar-path) (error "`org-plantuml-jar-path' is not set") (concat "java " java " -jar " (shell-quote-argument (expand-file-name org-plantuml-jar-path)) + (if (string= (file-name-extension out-file) "png") + " -tpng" "") (if (string= (file-name-extension out-file) "svg") " -tsvg" "") (if (string= (file-name-extension out-file) "eps") " -teps" "") + (if (string= (file-name-extension out-file) "pdf") + " -tpdf" "") + (if (string= (file-name-extension out-file) "vdx") + " -tvdx" "") + (if (string= (file-name-extension out-file) "xmi") + " -txmi" "") + (if (string= (file-name-extension out-file) "scxml") + " -tscxml" "") + (if (string= (file-name-extension out-file) "html") + " -thtml" "") + (if (string= (file-name-extension out-file) "txt") + " -ttxt" "") + (if (string= (file-name-extension out-file) "utxt") + " -utxt" "") " -p " cmdline " < " (org-babel-process-file-name in-file) " > " @@ -74,7 +89,7 @@ This function is called by `org-babel-execute-src-block'." (message "%s" cmd) (org-babel-eval cmd "") nil)) ;; signal that output has already been written to file -(defun org-babel-prep-session:plantuml (session params) +(defun org-babel-prep-session:plantuml (_session _params) "Return an error because plantuml does not support sessions." (error "Plantuml does not support sessions")) diff --git a/lisp/org/ob-processing.el b/lisp/org/ob-processing.el new file mode 100644 index 00000000000..a18a53cbf1e --- /dev/null +++ b/lisp/org/ob-processing.el @@ -0,0 +1,195 @@ +;;; ob-processing.el --- Babel functions for processing -*- lexical-binding: t; -*- + +;; Copyright (C) 2015-2017 Free Software Foundation, Inc. + +;; Author: Jarmo Hurri (adapted from ob-asymptote.el written by Eric Schulte) +;; Keywords: literate programming, reproducible research +;; Homepage: http://orgmode.org + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; Babel support for evaluating processing source code. +;; +;; This differs from most standard languages in that +;; +;; 1) there is no such thing as a "session" in processing +;; +;; 2) results can only be exported as html; in this case, the +;; processing code is embedded via a file into a javascript block +;; using the processing.js module; the script then draws the +;; resulting output when the web page is viewed in a browser; note +;; that the user is responsible for making sure that processing.js +;; is available on the website +;; +;; 3) it is possible to interactively view the sketch of the +;; Processing code block via Processing 2.0 Emacs mode, using +;; `org-babel-processing-view-sketch'. You can bind this command +;; to, e.g., C-c C-v C-k with +;; +;; (define-key org-babel-map (kbd "C-k") 'org-babel-processing-view-sketch) + + +;;; Requirements: + +;; - processing2-emacs mode :: https://github.com/ptrv/processing2-emacs +;; - Processing.js module :: http://processingjs.org/ + +;;; Code: +(require 'ob) +(require 'sha1) + +(declare-function processing-sketch-run "ext:processing-mode" ()) + +(defvar org-babel-temporary-directory) + +(defvar org-babel-tangle-lang-exts) +(add-to-list 'org-babel-tangle-lang-exts '("processing" . "pde")) + +;; Default header tags depend on whether exporting html or not; if not +;; exporting html, then no results are produced; otherwise results are +;; HTML. +(defvar org-babel-default-header-args:processing + '((:results . "html") (:exports . "results")) + "Default arguments when evaluating a Processing source block.") + +(defvar org-babel-processing-processing-js-filename "processing.js" + "Filename of the processing.js file.") + +(defun org-babel-processing-view-sketch () + "Show the sketch of the Processing block under point in an external viewer." + (interactive) + (require 'processing-mode) + (let ((info (org-babel-get-src-block-info))) + (if (string= (nth 0 info) "processing") + (let* ((body (nth 1 info)) + (params (org-babel-process-params (nth 2 info))) + (sketch-code + (org-babel-expand-body:generic + body + params + (org-babel-variable-assignments:processing params)))) + ;; Note: sketch filename can not contain a hyphen, since it + ;; has to be a valid java class name; for this reason + ;; make-temp-file is repeated until no hyphen is in the + ;; name; also sketch dir name must be the same as the + ;; basename of the sketch file. + (let* ((temporary-file-directory org-babel-temporary-directory) + (sketch-dir + (let (sketch-dir-candidate) + (while + (progn + (setq sketch-dir-candidate + (make-temp-file "processing" t)) + (when (string-match-p + "-" + (file-name-nondirectory sketch-dir-candidate)) + (delete-directory sketch-dir-candidate) + t))) + sketch-dir-candidate)) + (sketch-filename + (concat sketch-dir + "/" + (file-name-nondirectory sketch-dir) + ".pde"))) + (with-temp-file sketch-filename (insert sketch-code)) + (find-file sketch-filename) + (processing-sketch-run) + (kill-buffer))) + (message "Not inside a Processing source block.")))) + +(defun org-babel-execute:processing (body params) + "Execute a block of Processing code. +This function is called by `org-babel-execute-src-block'." + (let ((sketch-code + (org-babel-expand-body:generic + body + params + (org-babel-variable-assignments:processing params)))) + ;; Results are HTML. + (let ((sketch-canvas-id (concat "ob-" (sha1 sketch-code)))) + (concat "\n ")))) + +(defun org-babel-prep-session:processing (_session _params) + "Return an error if the :session header argument is set. +Processing does not support sessions" + (error "Processing does not support sessions")) + +(defun org-babel-variable-assignments:processing (params) + "Return list of processing statements assigning the block's variables." + (mapcar #'org-babel-processing-var-to-processing + (org-babel--get-vars params))) + +(defun org-babel-processing-var-to-processing (pair) + "Convert an elisp value into a Processing variable. +The elisp value PAIR is converted into Processing code specifying +a variable of the same value." + (let ((var (car pair)) + (val (let ((v (cdr pair))) + (if (symbolp v) (symbol-name v) v)))) + (cond + ((integerp val) + (format "int %S=%S;" var val)) + ((floatp val) + (format "float %S=%S;" var val)) + ((stringp val) + (format "String %S=\"%s\";" var val)) + ((and (listp val) (not (listp (car val)))) + (let* ((type (org-babel-processing-define-type val)) + (fmt (if (eq 'String type) "\"%s\"" "%s")) + (vect (mapconcat (lambda (e) (format fmt e)) val ", "))) + (format "%s[] %S={%s};" type var vect))) + ((listp val) + (let* ((type (org-babel-processing-define-type val)) + (fmt (if (eq 'String type) "\"%s\"" "%s")) + (array (mapconcat (lambda (row) + (concat "{" + (mapconcat (lambda (e) (format fmt e)) + row ", ") + "}")) + val ","))) + (format "%S[][] %S={%s};" type var array)))))) + +(defun org-babel-processing-define-type (data) + "Determine type of DATA. + +DATA is a list. Return type as a symbol. + +The type is `String' if any element in DATA is a string. +Otherwise, it is either `float', if some elements are floats, or +`int'." + (letrec ((type 'int) + (find-type + (lambda (row) + (dolist (e row type) + (cond ((listp e) (setq type (funcall find-type e))) + ((stringp e) (throw 'exit 'String)) + ((floatp e) (setq type 'float))))))) + (catch 'exit (funcall find-type data)))) + +(provide 'ob-processing) + +;;; ob-processing.el ends here diff --git a/lisp/org/ob-python.el b/lisp/org/ob-python.el index dfad47bf9e0..302f8bd451e 100644 --- a/lisp/org/ob-python.el +++ b/lisp/org/ob-python.el @@ -1,4 +1,4 @@ -;;; ob-python.el --- org-babel functions for python evaluation +;;; ob-python.el --- Babel Functions for Python -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -28,9 +28,9 @@ ;;; Code: (require 'ob) -(eval-when-compile (require 'cl)) (declare-function org-remove-indentation "org" ) +(declare-function org-trim "org" (s &optional keep-lead)) (declare-function py-shell "ext:python-mode" (&optional argprompt)) (declare-function py-toggle-shells "ext:python-mode" (arg)) (declare-function run-python "ext:python" (&optional cmd dedicated show)) @@ -48,9 +48,9 @@ :type 'string) (defcustom org-babel-python-mode - (if (or (featurep 'xemacs) (featurep 'python-mode)) 'python-mode 'python) + (if (featurep 'python-mode) 'python-mode 'python) "Preferred python mode for use in running python interactively. -This will typically be either 'python or 'python-mode." +This will typically be either `python' or `python-mode'." :group 'org-babel :version "24.4" :package-version '(Org . "8.0") @@ -73,13 +73,16 @@ This will typically be either 'python or 'python-mode." (defun org-babel-execute:python (body params) "Execute a block of Python code with Babel. This function is called by `org-babel-execute-src-block'." - (let* ((session (org-babel-python-initiate-session - (cdr (assoc :session params)))) - (result-params (cdr (assoc :result-params params))) - (result-type (cdr (assoc :result-type params))) + (let* ((org-babel-python-command + (or (cdr (assq :python params)) + org-babel-python-command)) + (session (org-babel-python-initiate-session + (cdr (assq :session params)))) + (result-params (cdr (assq :result-params params))) + (result-type (cdr (assq :result-type params))) (return-val (when (and (eq result-type 'value) (not session)) - (cdr (assoc :return params)))) - (preamble (cdr (assoc :preamble params))) + (cdr (assq :return params)))) + (preamble (cdr (assq :preamble params))) (full-body (org-babel-expand-body:generic (concat body (if return-val (format "\nreturn %s" return-val) "")) @@ -88,10 +91,10 @@ This function is called by `org-babel-execute-src-block'." session full-body result-type result-params preamble))) (org-babel-reassemble-table result - (org-babel-pick-name (cdr (assoc :colname-names params)) - (cdr (assoc :colnames params))) - (org-babel-pick-name (cdr (assoc :rowname-names params)) - (cdr (assoc :rownames params)))))) + (org-babel-pick-name (cdr (assq :colname-names params)) + (cdr (assq :colnames params))) + (org-babel-pick-name (cdr (assq :rowname-names params)) + (cdr (assq :rownames params)))))) (defun org-babel-prep-session:python (session params) "Prepare SESSION according to the header arguments in PARAMS. @@ -123,7 +126,7 @@ VARS contains resolved variable references" (format "%s=%s" (car pair) (org-babel-python-var-to-python (cdr pair)))) - (mapcar #'cdr (org-babel-get-header params :var)))) + (org-babel--get-vars params))) (defun org-babel-python-var-to-python (var) "Convert an elisp value to a python variable. @@ -131,7 +134,7 @@ Convert an elisp value, VAR, into a string of python source code specifying a variable of the same value." (if (listp var) (concat "[" (mapconcat #'org-babel-python-var-to-python var ", ") "]") - (if (equal var 'hline) + (if (eq var 'hline) org-babel-python-hline-to (format (if (and (stringp var) (string-match "[\n\r]" var)) "\"\"%S\"\"" "%S") @@ -143,7 +146,7 @@ If the results look like a list or tuple, then convert them into an Emacs-lisp table, otherwise return the results as a string." (let ((res (org-babel-script-escape results))) (if (listp res) - (mapcar (lambda (el) (if (equal el 'None) + (mapcar (lambda (el) (if (eq el 'None) org-babel-python-None-to el)) res) res))) @@ -214,7 +217,7 @@ then create. Return the initialized session." (assq-delete-all session org-babel-python-buffers))) session))) -(defun org-babel-python-initiate-session (&optional session params) +(defun org-babel-python-initiate-session (&optional session _params) "Create a session named SESSION according to PARAMS." (unless (string= session "none") (org-babel-python-session-buffer @@ -222,13 +225,13 @@ then create. Return the initialized session." (defvar org-babel-python-eoe-indicator "'org_babel_python_eoe'" "A string to indicate that evaluation has completed.") -(defvar org-babel-python-wrapper-method +(defconst org-babel-python-wrapper-method " def main(): %s open('%s', 'w').write( str(main()) )") -(defvar org-babel-python-pp-wrapper-method +(defconst org-babel-python-pp-wrapper-method " import pprint def main(): @@ -246,42 +249,41 @@ open('%s', 'w').write( pprint.pformat(main()) )") body result-type result-params preamble))) (defun org-babel-python-evaluate-external-process - (body &optional result-type result-params preamble) + (body &optional result-type result-params preamble) "Evaluate BODY in external python process. -If RESULT-TYPE equals 'output then return standard output as a -string. If RESULT-TYPE equals 'value then return the value of the +If RESULT-TYPE equals `output' then return standard output as a +string. If RESULT-TYPE equals `value' then return the value of the last statement in BODY, as elisp." (let ((raw - (case result-type - (output (org-babel-eval org-babel-python-command - (concat (if preamble (concat preamble "\n")) - body))) - (value (let ((tmp-file (org-babel-temp-file "python-"))) - (org-babel-eval - org-babel-python-command - (concat - (if preamble (concat preamble "\n") "") - (format - (if (member "pp" result-params) - org-babel-python-pp-wrapper-method - org-babel-python-wrapper-method) - (mapconcat - (lambda (line) (format "\t%s" line)) - (split-string - (org-remove-indentation - (org-babel-trim body)) - "[\r\n]") "\n") - (org-babel-process-file-name tmp-file 'noquote)))) - (org-babel-eval-read-file tmp-file)))))) + (pcase result-type + (`output (org-babel-eval org-babel-python-command + (concat (if preamble (concat preamble "\n")) + body))) + (`value (let ((tmp-file (org-babel-temp-file "python-"))) + (org-babel-eval + org-babel-python-command + (concat + (if preamble (concat preamble "\n") "") + (format + (if (member "pp" result-params) + org-babel-python-pp-wrapper-method + org-babel-python-wrapper-method) + (mapconcat + (lambda (line) (format "\t%s" line)) + (split-string (org-remove-indentation (org-trim body)) + "[\r\n]") + "\n") + (org-babel-process-file-name tmp-file 'noquote)))) + (org-babel-eval-read-file tmp-file)))))) (org-babel-result-cond result-params raw - (org-babel-python-table-or-string (org-babel-trim raw))))) + (org-babel-python-table-or-string (org-trim raw))))) (defun org-babel-python-evaluate-session (session body &optional result-type result-params) "Pass BODY to the Python process in SESSION. -If RESULT-TYPE equals 'output then return standard output as a -string. If RESULT-TYPE equals 'value then return the value of the +If RESULT-TYPE equals `output' then return standard output as a +string. If RESULT-TYPE equals `value' then return the value of the last statement in BODY, as elisp." (let* ((send-wait (lambda () (comint-send-input nil t) (sleep-for 0 5))) (dump-last-value @@ -302,10 +304,10 @@ last statement in BODY, as elisp." (split-string body "[\r\n]")) (funcall send-wait))) (results - (case result-type - (output + (pcase result-type + (`output (mapconcat - #'org-babel-trim + #'org-trim (butlast (org-babel-comint-with-output (session org-babel-python-eoe-indicator t body) @@ -314,7 +316,7 @@ last statement in BODY, as elisp." (insert org-babel-python-eoe-indicator) (funcall send-wait)) 2) "\n")) - (value + (`value (let ((tmp-file (org-babel-temp-file "python-"))) (org-babel-comint-with-output (session org-babel-python-eoe-indicator nil body) @@ -332,9 +334,10 @@ last statement in BODY, as elisp." (org-babel-python-table-or-string results))))) (defun org-babel-python-read-string (string) - "Strip 's from around Python string." - (if (string-match "^'\\([^\000]+\\)'$" string) - (match-string 1 string) + "Strip \\='s from around Python string." + (if (and (string-prefix-p "'" string) + (string-suffix-p "'" string)) + (substring string 1 -1) string)) (provide 'ob-python) diff --git a/lisp/org/ob-ref.el b/lisp/org/ob-ref.el index 58cc2d96a64..f8b9ea45098 100644 --- a/lisp/org/ob-ref.el +++ b/lisp/org/ob-ref.el @@ -1,4 +1,4 @@ -;;; ob-ref.el --- org-babel functions for referencing external data +;;; ob-ref.el --- Babel Functions for Referencing External Data -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -50,19 +50,20 @@ ;;; Code: (require 'ob-core) -(eval-when-compile - (require 'cl)) - -(declare-function org-remove-if-not "org" (predicate seq)) -(declare-function org-at-table-p "org" (&optional table-type)) -(declare-function org-count "org" (CL-ITEM CL-SEQ)) -(declare-function org-at-item-p "org-list" ()) -(declare-function org-narrow-to-subtree "org" ()) -(declare-function org-id-find-id-in-file "org-id" (id file &optional markerp)) +(require 'cl-lib) + +(declare-function org-babel-lob-get-info "ob-lob" (&optional datum)) +(declare-function org-element-at-point "org-element" ()) +(declare-function org-element-property "org-element" (property element)) +(declare-function org-element-type "org-element" (element)) +(declare-function org-end-of-meta-data "org" (&optional full)) +(declare-function org-find-property "org" (property &optional value)) (declare-function org-id-find-id-file "org-id" (id)) +(declare-function org-id-find-id-in-file "org-id" (id file &optional markerp)) +(declare-function org-in-commented-heading-p "org" (&optional no-inheritance)) +(declare-function org-narrow-to-subtree "org" ()) (declare-function org-show-context "org" (&optional key)) -(declare-function org-pop-to-buffer-same-window - "org-compat" (&optional buffer-or-name norecord label)) +(declare-function org-trim "org" (s &optional keep-lead)) (defvar org-babel-ref-split-regexp "[ \f\t\n\r\v]*\\(.+?\\)[ \f\t\n\r\v]*=[ \f\t\n\r\v]*\\(.+\\)[ \f\t\n\r\v]*") @@ -90,35 +91,31 @@ the variable." org-babel-current-src-block-location))) (org-babel-read ref)))) (if (equal out ref) - (if (string-match "^\".*\"$" ref) + (if (and (string-prefix-p "\"" ref) + (string-suffix-p "\"" ref)) (read ref) (org-babel-ref-resolve ref)) out)))))) (defun org-babel-ref-goto-headline-id (id) - (goto-char (point-min)) - (let ((rx (regexp-quote id))) - (or (re-search-forward - (concat "^[ \t]*:CUSTOM_ID:[ \t]+" rx "[ \t]*$") nil t) - (let* ((file (org-id-find-id-file id)) - (m (when file (org-id-find-id-in-file id file 'marker)))) - (when (and file m) - (message "file:%S" file) - (org-pop-to-buffer-same-window (marker-buffer m)) - (goto-char m) - (move-marker m nil) - (org-show-context) - t))))) + (or (let ((h (org-find-property "CUSTOM_ID" id))) + (when h (goto-char h))) + (let* ((file (org-id-find-id-file id)) + (m (when file (org-id-find-id-in-file id file 'marker)))) + (when (and file m) + (message "file:%S" file) + (pop-to-buffer-same-window (marker-buffer m)) + (goto-char m) + (move-marker m nil) + (org-show-context) + t)))) (defun org-babel-ref-headline-body () (save-restriction (org-narrow-to-subtree) (buffer-substring (save-excursion (goto-char (point-min)) - (forward-line 1) - (when (looking-at "[ \t]*:PROPERTIES:") - (re-search-forward ":END:" nil) - (forward-char)) + (org-end-of-meta-data) (point)) (point-max)))) @@ -126,89 +123,82 @@ the variable." (defun org-babel-ref-resolve (ref) "Resolve the reference REF and return its value." (save-window-excursion - (save-excursion - (let ((case-fold-search t) - type args new-refere new-header-args new-referent result - lob-info split-file split-ref index index-row index-col id) - ;; if ref is indexed grab the indices -- beware nested indices - (when (and (string-match "\\[\\([^\\[]+\\)\\]$" ref) - (let ((str (substring ref 0 (match-beginning 0)))) - (= (org-count ?( str) (org-count ?) str)))) - (setq index (match-string 1 ref)) - (setq ref (substring ref 0 (match-beginning 0)))) - ;; assign any arguments to pass to source block - (when (string-match - "^\\(.+?\\)\\(\\[\\(.*\\)\\]\\|\\(\\)\\)(\\(.*\\))$" ref) - (setq new-refere (match-string 1 ref)) - (setq new-header-args (match-string 3 ref)) - (setq new-referent (match-string 5 ref)) - (when (> (length new-refere) 0) - (when (> (length new-referent) 0) - (setq args (mapcar (lambda (ref) (cons :var ref)) - (org-babel-ref-split-args new-referent)))) - (when (> (length new-header-args) 0) - (setq args (append (org-babel-parse-header-arguments - new-header-args) args))) - (setq ref new-refere))) - (when (string-match "^\\(.+\\):\\(.+\\)$" ref) - (setq split-file (match-string 1 ref)) - (setq split-ref (match-string 2 ref)) - (find-file split-file) (setq ref split-ref)) - (save-restriction - (widen) - (goto-char (point-min)) - (if (let ((src-rx (org-babel-named-src-block-regexp-for-name ref)) - (res-rx (org-babel-named-data-regexp-for-name ref))) - ;; goto ref in the current buffer - (or - ;; check for code blocks - (re-search-forward src-rx nil t) - ;; check for named data - (re-search-forward res-rx nil t) - ;; check for local or global headlines by id - (setq id (org-babel-ref-goto-headline-id ref)) - ;; check the Library of Babel - (setq lob-info (cdr (assoc (intern ref) - org-babel-library-of-babel))))) - (unless (or lob-info id) (goto-char (match-beginning 0))) - ;; ;; TODO: allow searching for names in other buffers - ;; (setq id-loc (org-id-find ref 'marker) - ;; buffer (marker-buffer id-loc) - ;; loc (marker-position id-loc)) - ;; (move-marker id-loc nil) - (error "Reference `%s' not found in this buffer" ref)) - (cond - (lob-info (setq type 'lob)) - (id (setq type 'id)) - ((and (looking-at org-babel-src-name-regexp) - (save-excursion - (forward-line 1) - (or (looking-at org-babel-src-block-regexp) - (looking-at org-babel-multi-line-header-regexp)))) - (setq type 'source-block)) - (t (while (not (setq type (org-babel-ref-at-ref-p))) - (forward-line 1) - (beginning-of-line) - (if (or (= (point) (point-min)) (= (point) (point-max))) - (error "Reference not found"))))) - (let ((params (append args '((:results . "silent"))))) - (setq result - (case type - (results-line (org-babel-read-result)) - (table (org-babel-read-table)) - (list (org-babel-read-list)) - (file (org-babel-read-link)) - (source-block (org-babel-execute-src-block - nil nil (if org-babel-update-intermediate - nil params))) - (lob (org-babel-execute-src-block - nil lob-info params)) - (id (org-babel-ref-headline-body))))) - (if (symbolp result) - (format "%S" result) - (if (and index (listp result)) - (org-babel-ref-index-list index result) - result))))))) + (with-current-buffer (or org-babel-exp-reference-buffer (current-buffer)) + (save-excursion + (let ((case-fold-search t) + args new-refere new-header-args new-referent split-file split-ref + index) + ;; if ref is indexed grab the indices -- beware nested indices + (when (and (string-match "\\[\\([^\\[]+\\)\\]$" ref) + (let ((str (substring ref 0 (match-beginning 0)))) + (= (cl-count ?\( str) (cl-count ?\) str)))) + (setq index (match-string 1 ref)) + (setq ref (substring ref 0 (match-beginning 0)))) + ;; assign any arguments to pass to source block + (when (string-match + "^\\(.+?\\)\\(\\[\\(.*\\)\\]\\|\\(\\)\\)(\\(.*\\))$" ref) + (setq new-refere (match-string 1 ref)) + (setq new-header-args (match-string 3 ref)) + (setq new-referent (match-string 5 ref)) + (when (> (length new-refere) 0) + (when (> (length new-referent) 0) + (setq args (mapcar (lambda (ref) (cons :var ref)) + (org-babel-ref-split-args new-referent)))) + (when (> (length new-header-args) 0) + (setq args (append (org-babel-parse-header-arguments + new-header-args) args))) + (setq ref new-refere))) + (when (string-match "^\\(.+\\):\\(.+\\)$" ref) + (setq split-file (match-string 1 ref)) + (setq split-ref (match-string 2 ref)) + (find-file split-file) + (setq ref split-ref)) + (org-with-wide-buffer + (goto-char (point-min)) + (let* ((params (append args '((:results . "silent")))) + (regexp (org-babel-named-data-regexp-for-name ref)) + (result + (catch :found + ;; Check for code blocks or named data. + (while (re-search-forward regexp nil t) + ;; Ignore COMMENTed headings and orphaned + ;; affiliated keywords. + (unless (org-in-commented-heading-p) + (let ((e (org-element-at-point))) + (when (equal (org-element-property :name e) ref) + (goto-char + (org-element-property :post-affiliated e)) + (pcase (org-element-type e) + (`babel-call + (throw :found + (org-babel-execute-src-block + nil (org-babel-lob-get-info e) params))) + (`src-block + (throw :found + (org-babel-execute-src-block + nil nil + (and + (not org-babel-update-intermediate) + params)))) + ((and (let v (org-babel-read-element e)) + (guard v)) + (throw :found v)) + (_ (error "Reference not found"))))))) + ;; Check for local or global headlines by ID. + (when (org-babel-ref-goto-headline-id ref) + (throw :found (org-babel-ref-headline-body))) + ;; Check the Library of Babel. + (let ((info (cdr (assq (intern ref) + org-babel-library-of-babel)))) + (when info + (throw :found + (org-babel-execute-src-block nil info params)))) + (error "Reference `%s' not found in this buffer" ref)))) + (cond + ((symbolp result) (format "%S" result)) + ((and index (listp result)) + (org-babel-ref-index-list index result)) + (t result))))))))) (defun org-babel-ref-index-list (index lis) "Return the subset of LIS indexed by INDEX. @@ -251,21 +241,9 @@ to \"0:-1\"." (defun org-babel-ref-split-args (arg-string) "Split ARG-STRING into top-level arguments of balanced parenthesis." - (mapcar #'org-babel-trim (org-babel-balanced-split arg-string 44))) + (mapcar #'org-trim (org-babel-balanced-split arg-string 44))) -(defvar org-bracket-link-regexp) -(defun org-babel-ref-at-ref-p () - "Return the type of reference located at point. -Return nil if none of the supported reference types are found. -Supported reference types are tables and source blocks." - (cond ((org-at-table-p) 'table) - ((org-at-item-p) 'list) - ((looking-at "^[ \t]*#\\+BEGIN_SRC") 'source-block) - ((looking-at org-bracket-link-regexp) 'file) - ((looking-at org-babel-result-regexp) 'results-line))) (provide 'ob-ref) - - ;;; ob-ref.el ends here diff --git a/lisp/org/ob-ruby.el b/lisp/org/ob-ruby.el index 88a99876964..d055783514e 100644 --- a/lisp/org/ob-ruby.el +++ b/lisp/org/ob-ruby.el @@ -1,4 +1,4 @@ -;;; ob-ruby.el --- org-babel functions for ruby evaluation +;;; ob-ruby.el --- Babel Functions for Ruby -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -37,11 +37,14 @@ ;;; Code: (require 'ob) -(eval-when-compile (require 'cl)) +(declare-function org-trim "org" (s &optional keep-lead)) (declare-function run-ruby "ext:inf-ruby" (&optional command name)) (declare-function xmp "ext:rcodetools" (&optional option)) +(defvar inf-ruby-default-implementation) +(defvar inf-ruby-implementations) + (defvar org-babel-tangle-lang-exts) (add-to-list 'org-babel-tangle-lang-exts '("ruby" . "rb")) @@ -68,16 +71,16 @@ "Execute a block of Ruby code with Babel. This function is called by `org-babel-execute-src-block'." (let* ((session (org-babel-ruby-initiate-session - (cdr (assoc :session params)))) - (result-params (cdr (assoc :result-params params))) - (result-type (cdr (assoc :result-type params))) + (cdr (assq :session params)))) + (result-params (cdr (assq :result-params params))) + (result-type (cdr (assq :result-type params))) (full-body (org-babel-expand-body:generic body params (org-babel-variable-assignments:ruby params))) (result (if (member "xmp" result-params) (with-temp-buffer (require 'rcodetools) (insert full-body) - (xmp (cdr (assoc :xmp-option params))) + (xmp (cdr (assq :xmp-option params))) (buffer-string)) (org-babel-ruby-evaluate session full-body result-type result-params)))) @@ -85,10 +88,10 @@ This function is called by `org-babel-execute-src-block'." (org-babel-result-cond result-params result (org-babel-ruby-table-or-string result)) - (org-babel-pick-name (cdr (assoc :colname-names params)) - (cdr (assoc :colnames params))) - (org-babel-pick-name (cdr (assoc :rowname-names params)) - (cdr (assoc :rownames params)))))) + (org-babel-pick-name (cdr (assq :colname-names params)) + (cdr (assq :colnames params))) + (org-babel-pick-name (cdr (assq :rowname-names params)) + (cdr (assq :rownames params)))))) (defun org-babel-prep-session:ruby (session params) "Prepare SESSION according to the header arguments specified in PARAMS." @@ -121,7 +124,7 @@ This function is called by `org-babel-execute-src-block'." (format "%s=%s" (car pair) (org-babel-ruby-var-to-ruby (cdr pair)))) - (mapcar #'cdr (org-babel-get-header params :var)))) + (org-babel--get-vars params))) (defun org-babel-ruby-var-to-ruby (var) "Convert VAR into a ruby variable. @@ -129,7 +132,7 @@ Convert an elisp value into a string of ruby source code specifying a variable of the same value." (if (listp var) (concat "[" (mapconcat #'org-babel-ruby-var-to-ruby var ", ") "]") - (if (equal var 'hline) + (if (eq var 'hline) org-babel-ruby-hline-to (format "%S" var)))) @@ -139,23 +142,27 @@ If RESULTS look like a table, then convert them into an Emacs-lisp table, otherwise return the results as a string." (let ((res (org-babel-script-escape results))) (if (listp res) - (mapcar (lambda (el) (if (equal el 'nil) - org-babel-ruby-nil-to el)) + (mapcar (lambda (el) (if (not el) + org-babel-ruby-nil-to el)) res) res))) -(defun org-babel-ruby-initiate-session (&optional session params) +(defun org-babel-ruby-initiate-session (&optional session _params) "Initiate a ruby session. If there is not a current inferior-process-buffer in SESSION then create one. Return the initialized session." (unless (string= session "none") (require 'inf-ruby) - (let ((session-buffer (save-window-excursion - (run-ruby nil session) (current-buffer)))) + (let* ((cmd (cdr (assoc inf-ruby-default-implementation + inf-ruby-implementations))) + (buffer (get-buffer (format "*%s*" session))) + (session-buffer (or buffer (save-window-excursion + (run-ruby cmd session) + (current-buffer))))) (if (org-babel-comint-buffer-livep session-buffer) (progn (sit-for .25) session-buffer) - (sit-for .5) - (org-babel-ruby-initiate-session session))))) + (sit-for .5) + (org-babel-ruby-initiate-session session))))) (defvar org-babel-ruby-eoe-indicator ":org_babel_ruby_eoe" "String to indicate that evaluation has completed.") @@ -185,46 +192,53 @@ end ") (defun org-babel-ruby-evaluate - (buffer body &optional result-type result-params) + (buffer body &optional result-type result-params) "Pass BODY to the Ruby process in BUFFER. -If RESULT-TYPE equals 'output then return a list of the outputs -of the statements in BODY, if RESULT-TYPE equals 'value then +If RESULT-TYPE equals `output' then return a list of the outputs +of the statements in BODY, if RESULT-TYPE equals `value' then return the value of the last statement in BODY, as elisp." (if (not buffer) ;; external process evaluation - (case result-type - (output (org-babel-eval org-babel-ruby-command body)) - (value (let ((tmp-file (org-babel-temp-file "ruby-"))) - (org-babel-eval - org-babel-ruby-command - (format (if (member "pp" result-params) - org-babel-ruby-pp-wrapper-method - org-babel-ruby-wrapper-method) - body (org-babel-process-file-name tmp-file 'noquote))) - (let ((raw (org-babel-eval-read-file tmp-file))) - (if (or (member "code" result-params) - (member "pp" result-params)) - raw - (org-babel-ruby-table-or-string raw)))))) + (pcase result-type + (`output (org-babel-eval org-babel-ruby-command body)) + (`value (let ((tmp-file (org-babel-temp-file "ruby-"))) + (org-babel-eval + org-babel-ruby-command + (format (if (member "pp" result-params) + org-babel-ruby-pp-wrapper-method + org-babel-ruby-wrapper-method) + body (org-babel-process-file-name tmp-file 'noquote))) + (org-babel-eval-read-file tmp-file)))) ;; comint session evaluation - (case result-type - (output - (mapconcat - #'identity - (butlast - (split-string - (mapconcat - #'org-babel-trim - (butlast - (org-babel-comint-with-output - (buffer org-babel-ruby-eoe-indicator t body) - (mapc - (lambda (line) - (insert (org-babel-chomp line)) (comint-send-input nil t)) - (list body org-babel-ruby-eoe-indicator)) - (comint-send-input nil t)) 2) - "\n") "[\r\n]")) "\n")) - (value + (pcase result-type + (`output + (let ((eoe-string (format "puts \"%s\"" org-babel-ruby-eoe-indicator))) + ;; Force the session to be ready before the actual session + ;; code is run. There is some problem in comint that will + ;; sometimes show the prompt after the the input has already + ;; been inserted and that throws off the extraction of the + ;; result for Babel. + (org-babel-comint-with-output + (buffer org-babel-ruby-eoe-indicator t eoe-string) + (insert eoe-string) (comint-send-input nil t)) + ;; Now we can start the evaluation. + (mapconcat + #'identity + (butlast + (split-string + (mapconcat + #'org-trim + (org-babel-comint-with-output + (buffer org-babel-ruby-eoe-indicator t body) + (mapc + (lambda (line) + (insert (org-babel-chomp line)) (comint-send-input nil t)) + (list "conf.echo=false;_org_prompt_mode=conf.prompt_mode;conf.prompt_mode=:NULL" + body + "conf.prompt_mode=_org_prompt_mode;conf.echo=true" + eoe-string))) + "\n") "[\r\n]") 4) "\n"))) + (`value (let* ((tmp-file (org-babel-temp-file "ruby-")) (ppp (or (member "code" result-params) (member "pp" result-params)))) @@ -247,12 +261,6 @@ return the value of the last statement in BODY, as elisp." (comint-send-input nil t)) (org-babel-eval-read-file tmp-file)))))) -(defun org-babel-ruby-read-string (string) - "Strip \\\"s from around a ruby string." - (if (string-match "^\"\\([^\000]+\\)\"$" string) - (match-string 1 string) - string)) - (provide 'ob-ruby) diff --git a/lisp/org/ob-sass.el b/lisp/org/ob-sass.el index 847c144e80a..a9a2a9f030b 100644 --- a/lisp/org/ob-sass.el +++ b/lisp/org/ob-sass.el @@ -1,4 +1,4 @@ -;;; ob-sass.el --- org-babel functions for the sass css generation language +;;; ob-sass.el --- Babel Functions for the Sass CSS generation language -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -45,10 +45,9 @@ (defun org-babel-execute:sass (body params) "Execute a block of Sass code with Babel. This function is called by `org-babel-execute-src-block'." - (let* ((result-params (split-string (or (cdr (assoc :results params)) ""))) - (file (cdr (assoc :file params))) + (let* ((file (cdr (assq :file params))) (out-file (or file (org-babel-temp-file "sass-out-"))) - (cmdline (cdr (assoc :cmdline params))) + (cmdline (cdr (assq :cmdline params))) (in-file (org-babel-temp-file "sass-in-")) (cmd (concat "sass " (or cmdline "") " " (org-babel-process-file-name in-file) @@ -60,7 +59,7 @@ This function is called by `org-babel-execute-src-block'." nil ;; signal that output has already been written to file (with-temp-buffer (insert-file-contents out-file) (buffer-string))))) -(defun org-babel-prep-session:sass (session params) +(defun org-babel-prep-session:sass (_session _params) "Raise an error because sass does not support sessions." (error "Sass does not support sessions")) diff --git a/lisp/org/ob-scala.el b/lisp/org/ob-scala.el index 9bddeed6e6f..7d5f299ec62 100644 --- a/lisp/org/ob-scala.el +++ b/lisp/org/ob-scala.el @@ -1,4 +1,4 @@ -;;; ob-scala.el --- org-babel functions for Scala evaluation +;;; ob-scala.el --- Babel Functions for Scala -*- lexical-binding: t; -*- ;; Copyright (C) 2012-2017 Free Software Foundation, Inc. @@ -31,7 +31,6 @@ ;;; Code: (require 'ob) -(eval-when-compile (require 'cl)) (defvar org-babel-tangle-lang-exts) ;; Autoloaded (add-to-list 'org-babel-tangle-lang-exts '("scala" . "scala")) @@ -45,9 +44,8 @@ called by `org-babel-execute-src-block'" (message "executing Scala source code block") (let* ((processed-params (org-babel-process-params params)) (session (org-babel-scala-initiate-session (nth 0 processed-params))) - (vars (nth 1 processed-params)) (result-params (nth 2 processed-params)) - (result-type (cdr (assoc :result-type params))) + (result-type (cdr (assq :result-type params))) (full-body (org-babel-expand-body:generic body params)) (result (org-babel-scala-evaluate @@ -56,17 +54,9 @@ called by `org-babel-execute-src-block'" (org-babel-reassemble-table result (org-babel-pick-name - (cdr (assoc :colname-names params)) (cdr (assoc :colnames params))) + (cdr (assq :colname-names params)) (cdr (assq :colnames params))) (org-babel-pick-name - (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params)))))) - - -(defun org-babel-scala-table-or-string (results) - "Convert RESULTS into an appropriate elisp value. -If RESULTS look like a table, then convert them into an -Emacs-lisp table, otherwise return the results as a string." - (org-babel-script-escape results)) - + (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))) (defvar org-babel-scala-wrapper-method @@ -84,19 +74,19 @@ print(str_result) (defun org-babel-scala-evaluate - (session body &optional result-type result-params) + (session body &optional result-type result-params) "Evaluate BODY in external Scala process. -If RESULT-TYPE equals 'output then return standard output as a string. -If RESULT-TYPE equals 'value then return the value of the last statement +If RESULT-TYPE equals `output' then return standard output as a string. +If RESULT-TYPE equals `value' then return the value of the last statement in BODY as elisp." (when session (error "Sessions are not (yet) supported for Scala")) - (case result-type - (output + (pcase result-type + (`output (let ((src-file (org-babel-temp-file "scala-"))) - (progn (with-temp-file src-file (insert body)) - (org-babel-eval - (concat org-babel-scala-command " " src-file) "")))) - (value + (with-temp-file src-file (insert body)) + (org-babel-eval + (concat org-babel-scala-command " " src-file) ""))) + (`value (let* ((src-file (org-babel-temp-file "scala-")) (wrapper (format org-babel-scala-wrapper-method body))) (with-temp-file src-file (insert wrapper)) @@ -104,14 +94,14 @@ in BODY as elisp." (concat org-babel-scala-command " " src-file) ""))) (org-babel-result-cond result-params raw - (org-babel-scala-table-or-string raw))))))) + (org-babel-script-escape raw))))))) -(defun org-babel-prep-session:scala (session params) +(defun org-babel-prep-session:scala (_session _params) "Prepare SESSION according to the header arguments specified in PARAMS." (error "Sessions are not (yet) supported for Scala")) -(defun org-babel-scala-initiate-session (&optional session) +(defun org-babel-scala-initiate-session (&optional _session) "If there is not a current inferior-process-buffer in SESSION then create. Return the initialized session. Sessions are not supported in Scala." diff --git a/lisp/org/ob-scheme.el b/lisp/org/ob-scheme.el index ae77c7c3edf..cd8c3860e25 100644 --- a/lisp/org/ob-scheme.el +++ b/lisp/org/ob-scheme.el @@ -1,4 +1,4 @@ -;;; ob-scheme.el --- org-babel functions for Scheme +;;; ob-scheme.el --- Babel Functions for Scheme -*- lexical-binding: t; -*- ;; Copyright (C) 2010-2017 Free Software Foundation, Inc. @@ -56,7 +56,7 @@ (defun org-babel-expand-body:scheme (body params) "Expand BODY according to PARAMS, return the expanded body." - (let ((vars (mapcar #'cdr (org-babel-get-header params :var)))) + (let ((vars (org-babel--get-vars params))) (if (> (length vars) 0) (concat "(let (" (mapconcat @@ -119,6 +119,22 @@ org-babel-scheme-execute-with-geiser will use a temporary session." (name)))) result)) +(defmacro org-babel-scheme-capture-current-message (&rest body) + "Capture current message in both interactive and noninteractive mode" + `(if noninteractive + (let ((original-message (symbol-function 'message)) + (current-message nil)) + (unwind-protect + (progn + (defun message (&rest args) + (setq current-message (apply original-message args))) + ,@body + current-message) + (fset 'message original-message))) + (progn + ,@body + (current-message)))) + (defun org-babel-scheme-execute-with-geiser (code output impl repl) "Execute code in specified REPL. If the REPL doesn't exist, create it using the given scheme implementation. @@ -143,10 +159,11 @@ is true; otherwise returns the last value." (current-buffer))))) (setq geiser-repl--repl repl-buffer) (setq geiser-impl--implementation nil) - (geiser-eval-region (point-min) (point-max)) + (setq result (org-babel-scheme-capture-current-message + (geiser-eval-region (point-min) (point-max)))) (setq result - (if (equal (substring (current-message) 0 3) "=> ") - (replace-regexp-in-string "^=> " "" (current-message)) + (if (and (stringp result) (equal (substring result 0 3) "=> ")) + (replace-regexp-in-string "^=> " "" result) "\"An error occurred.\"")) (when (not repl) (save-current-buffer (set-buffer repl-buffer) @@ -156,7 +173,7 @@ is true; otherwise returns the last value." (setq result (if (or (string= result "#") (string= result "#")) nil - (read result))))) + result)))) result)) (defun org-babel-execute:scheme (body params) @@ -168,23 +185,23 @@ This function is called by `org-babel-execute-src-block'" (buffer-name source-buffer)))) (save-excursion (org-babel-reassemble-table - (let* ((result-type (cdr (assoc :result-type params))) - (impl (or (when (cdr (assoc :scheme params)) - (intern (cdr (assoc :scheme params)))) + (let* ((result-type (cdr (assq :result-type params))) + (impl (or (when (cdr (assq :scheme params)) + (intern (cdr (assq :scheme params)))) geiser-default-implementation (car geiser-active-implementations))) (session (org-babel-scheme-make-session-name - source-buffer-name (cdr (assoc :session params)) impl)) + source-buffer-name (cdr (assq :session params)) impl)) (full-body (org-babel-expand-body:scheme body params))) (org-babel-scheme-execute-with-geiser full-body ; code (string= result-type "output") ; output? impl ; implementation (and (not (string= session "none")) session))) ; session - (org-babel-pick-name (cdr (assoc :colname-names params)) - (cdr (assoc :colnames params))) - (org-babel-pick-name (cdr (assoc :rowname-names params)) - (cdr (assoc :rownames params))))))) + (org-babel-pick-name (cdr (assq :colname-names params)) + (cdr (assq :colnames params))) + (org-babel-pick-name (cdr (assq :rowname-names params)) + (cdr (assq :rownames params))))))) (provide 'ob-scheme) diff --git a/lisp/org/ob-screen.el b/lisp/org/ob-screen.el index a15f7f7bd86..554f8c43852 100644 --- a/lisp/org/ob-screen.el +++ b/lisp/org/ob-screen.el @@ -1,4 +1,4 @@ -;;; ob-screen.el --- org-babel support for interactive terminal +;;; ob-screen.el --- Babel Support for Interactive Terminal -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -48,18 +48,17 @@ In case you want to use a different screen than one selected by your $PATH") \"default\" session is used when none is specified." (message "Sending source code block to interactive terminal session...") (save-window-excursion - (let* ((session (cdr (assoc :session params))) + (let* ((session (cdr (assq :session params))) (socket (org-babel-screen-session-socketname session))) (unless socket (org-babel-prep-session:screen session params)) (org-babel-screen-session-execute-string session (org-babel-expand-body:generic body params))))) -(defun org-babel-prep-session:screen (session params) +(defun org-babel-prep-session:screen (_session params) "Prepare SESSION according to the header arguments specified in PARAMS." - (let* ((session (cdr (assoc :session params))) - (socket (org-babel-screen-session-socketname session)) - (cmd (cdr (assoc :cmd params))) - (terminal (cdr (assoc :terminal params))) + (let* ((session (cdr (assq :session params))) + (cmd (cdr (assq :cmd params))) + (terminal (cdr (assq :terminal params))) (process-name (concat "org-babel: terminal (" session ")"))) (apply 'start-process process-name "*Messages*" terminal `("-T" ,(concat "org-babel: " session) "-e" ,org-babel-screen-location @@ -104,7 +103,7 @@ In case you want to use a different screen than one selected by your $PATH") sockets))))) (when match-socket (car (split-string match-socket))))) -(defun org-babel-screen-session-write-temp-file (session body) +(defun org-babel-screen-session-write-temp-file (_session body) "Save BODY in a temp file that is named after SESSION." (let ((tmpfile (org-babel-temp-file "screen-"))) (with-temp-file tmpfile @@ -119,11 +118,10 @@ In case you want to use a different screen than one selected by your $PATH") "Test if the default setup works. The terminal should shortly flicker." (interactive) - (let* ((session "org-babel-testing") - (random-string (format "%s" (random 99999))) + (let* ((random-string (format "%s" (random 99999))) (tmpfile (org-babel-temp-file "ob-screen-test-")) (body (concat "echo '" random-string "' > " tmpfile "\nexit\n")) - process tmp-string) + tmp-string) (org-babel-execute:screen body org-babel-default-header-args:screen) ;; XXX: need to find a better way to do the following (while (not (file-readable-p tmpfile)) diff --git a/lisp/org/ob-sed.el b/lisp/org/ob-sed.el new file mode 100644 index 00000000000..f249d3240ef --- /dev/null +++ b/lisp/org/ob-sed.el @@ -0,0 +1,105 @@ +;;; ob-sed.el --- Babel Functions for Sed Scripts -*- lexical-binding: t; -*- + +;; Copyright (C) 2015-2017 Free Software Foundation, Inc. + +;; Author: Bjarte Johansen +;; Keywords: literate programming, reproducible research +;; Version: 0.1.0 + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; Provides a way to evaluate sed scripts in Org mode. + +;;; Usage: + +;; Add to your Emacs config: + +;; (org-babel-do-load-languages +;; 'org-babel-load-languages +;; '((sed . t))) + +;; In addition to the normal header arguments, ob-sed also provides +;; :cmd-line and :in-file. :cmd-line allows one to pass other flags to +;; the sed command like the "--in-place" flag which makes sed edit the +;; file pass to it instead of outputting to standard out or to a +;; different file. :in-file is a header arguments that allows one to +;; tell Org Babel which file the sed script to act on. + +;;; Code: +(require 'ob) + +(defvar org-babel-sed-command "sed" + "Name of the sed executable command.") + +(defvar org-babel-tangle-lang-exts) +(add-to-list 'org-babel-tangle-lang-exts '("sed" . "sed")) + +(defconst org-babel-header-args:sed + '((:cmd-line . :any) + (:in-file . :any)) + "Sed specific header arguments.") + +(defvar org-babel-default-header-args:sed '() + "Default arguments for evaluating a sed source block.") + +(defun org-babel-execute:sed (body params) + "Execute a block of sed code with Org Babel. +BODY is the source inside a sed source block and PARAMS is an +association list over the source block configurations. This +function is called by `org-babel-execute-src-block'." + (message "executing sed source code block") + (let* ((result-params (cdr (assq :result-params params))) + (cmd-line (cdr (assq :cmd-line params))) + (in-file (cdr (assq :in-file params))) + (code-file (let ((file (org-babel-temp-file "sed-"))) + (with-temp-file file + (insert body)) file)) + (stdin (let ((stdin (cdr (assq :stdin params)))) + (when stdin + (let ((tmp (org-babel-temp-file "sed-stdin-")) + (res (org-babel-ref-resolve stdin))) + (with-temp-file tmp + (insert res)) + tmp)))) + (cmd (mapconcat #'identity + (remq nil + (list org-babel-sed-command + (format "--file=\"%s\"" code-file) + cmd-line + in-file)) + " "))) + (org-babel-reassemble-table + (let ((results + (cond + (stdin (with-temp-buffer + (call-process-shell-command cmd stdin (current-buffer)) + (buffer-string))) + (t (org-babel-eval cmd ""))))) + (when results + (org-babel-result-cond result-params + results + (let ((tmp (org-babel-temp-file "sed-results-"))) + (with-temp-file tmp (insert results)) + (org-babel-import-elisp-from-file tmp))))) + (org-babel-pick-name + (cdr (assq :colname-names params)) (cdr (assq :colnames params))) + (org-babel-pick-name + (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))) + +(provide 'ob-sed) +;;; ob-sed.el ends here diff --git a/lisp/org/ob-sh.el b/lisp/org/ob-sh.el deleted file mode 100644 index 47dbab3f6d9..00000000000 --- a/lisp/org/ob-sh.el +++ /dev/null @@ -1,217 +0,0 @@ -;;; ob-sh.el --- org-babel functions for shell evaluation - -;; Copyright (C) 2009-2017 Free Software Foundation, Inc. - -;; Author: Eric Schulte -;; Keywords: literate programming, reproducible research -;; Homepage: http://orgmode.org - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Org-Babel support for evaluating shell source code. - -;;; Code: -(require 'ob) -(require 'shell) -(eval-when-compile (require 'cl)) - -(declare-function org-babel-comint-wait-for-output "ob-comint" (buffer)) -(declare-function org-babel-comint-buffer-livep "ob-comint" (buffer)) -(declare-function orgtbl-to-generic "org-table" - (table params &optional backend)) - -(defvar org-babel-default-header-args:sh '()) - -(defvar org-babel-sh-command "sh" - "Command used to invoke a shell. -This will be passed to `shell-command-on-region'") - -(defcustom org-babel-sh-var-quote-fmt - "$(cat <<'BABEL_TABLE'\n%s\nBABEL_TABLE\n)" - "Format string used to escape variables when passed to shell scripts." - :group 'org-babel - :type 'string) - -(defun org-babel-execute:sh (body params) - "Execute a block of Shell commands with Babel. -This function is called by `org-babel-execute-src-block'." - (let* ((session (org-babel-sh-initiate-session - (cdr (assoc :session params)))) - (stdin (let ((stdin (cdr (assoc :stdin params)))) - (when stdin (org-babel-sh-var-to-string - (org-babel-ref-resolve stdin))))) - (full-body (org-babel-expand-body:generic - body params (org-babel-variable-assignments:sh params)))) - (org-babel-reassemble-table - (org-babel-sh-evaluate session full-body params stdin) - (org-babel-pick-name - (cdr (assoc :colname-names params)) (cdr (assoc :colnames params))) - (org-babel-pick-name - (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params)))))) - -(defun org-babel-prep-session:sh (session params) - "Prepare SESSION according to the header arguments specified in PARAMS." - (let* ((session (org-babel-sh-initiate-session session)) - (var-lines (org-babel-variable-assignments:sh params))) - (org-babel-comint-in-buffer session - (mapc (lambda (var) - (insert var) (comint-send-input nil t) - (org-babel-comint-wait-for-output session)) var-lines)) - session)) - -(defun org-babel-load-session:sh (session body params) - "Load BODY into SESSION." - (save-window-excursion - (let ((buffer (org-babel-prep-session:sh session params))) - (with-current-buffer buffer - (goto-char (process-mark (get-buffer-process (current-buffer)))) - (insert (org-babel-chomp body))) - buffer))) - -;; helper functions - -(defun org-babel-variable-assignments:sh (params) - "Return list of shell statements assigning the block's variables." - (let ((sep (cdr (assoc :separator params)))) - (mapcar - (lambda (pair) - (format "%s=%s" - (car pair) - (org-babel-sh-var-to-sh (cdr pair) sep))) - (mapcar #'cdr (org-babel-get-header params :var))))) - -(defun org-babel-sh-var-to-sh (var &optional sep) - "Convert an elisp value to a shell variable. -Convert an elisp var into a string of shell commands specifying a -var of the same value." - (format org-babel-sh-var-quote-fmt (org-babel-sh-var-to-string var sep))) - -(defun org-babel-sh-var-to-string (var &optional sep) - "Convert an elisp value to a string." - (let ((echo-var (lambda (v) (if (stringp v) v (format "%S" v))))) - (cond - ((and (listp var) (or (listp (car var)) (equal (car var) 'hline))) - (orgtbl-to-generic var (list :sep (or sep "\t") :fmt echo-var))) - ((listp var) - (mapconcat echo-var var "\n")) - (t (funcall echo-var var))))) - -(defun org-babel-sh-table-or-results (results) - "Convert RESULTS to an appropriate elisp value. -If the results look like a table, then convert them into an -Emacs-lisp table, otherwise return the results as a string." - (org-babel-script-escape results)) - -(defun org-babel-sh-initiate-session (&optional session params) - "Initiate a session named SESSION according to PARAMS." - (when (and session (not (string= session "none"))) - (save-window-excursion - (or (org-babel-comint-buffer-livep session) - (progn - (shell session) - ;; Needed for Emacs 23 since the marker is initially - ;; undefined and the filter functions try to use it without - ;; checking. - (set-marker comint-last-output-start (point)) - (get-buffer (current-buffer))))))) - -(defvar org-babel-sh-eoe-indicator "echo 'org_babel_sh_eoe'" - "String to indicate that evaluation has completed.") -(defvar org-babel-sh-eoe-output "org_babel_sh_eoe" - "String to indicate that evaluation has completed.") - -(defun org-babel-sh-evaluate (session body &optional params stdin) - "Pass BODY to the Shell process in BUFFER. -If RESULT-TYPE equals 'output then return a list of the outputs -of the statements in BODY, if RESULT-TYPE equals 'value then -return the value of the last statement in BODY." - (let ((results - (cond - (stdin ; external shell script w/STDIN - (let ((script-file (org-babel-temp-file "sh-script-")) - (stdin-file (org-babel-temp-file "sh-stdin-")) - (shebang (cdr (assoc :shebang params))) - (padline (not (string= "no" (cdr (assoc :padline params)))))) - (with-temp-file script-file - (when shebang (insert (concat shebang "\n"))) - (when padline (insert "\n")) - (insert body)) - (set-file-modes script-file #o755) - (with-temp-file stdin-file (insert stdin)) - (with-temp-buffer - (call-process-shell-command - (if shebang - script-file - (format "%s %s" org-babel-sh-command script-file)) - stdin-file - (current-buffer)) - (buffer-string)))) - (session ; session evaluation - (mapconcat - #'org-babel-sh-strip-weird-long-prompt - (mapcar - #'org-babel-trim - (butlast - (org-babel-comint-with-output - (session org-babel-sh-eoe-output t body) - (mapc - (lambda (line) - (insert line) - (comint-send-input nil t) - (while (save-excursion - (goto-char comint-last-input-end) - (not (re-search-forward - comint-prompt-regexp nil t))) - (accept-process-output - (get-buffer-process (current-buffer))))) - (append - (split-string (org-babel-trim body) "\n") - (list org-babel-sh-eoe-indicator)))) - 2)) "\n")) - ('otherwise ; external shell script - (if (and (cdr (assoc :shebang params)) - (> (length (cdr (assoc :shebang params))) 0)) - (let ((script-file (org-babel-temp-file "sh-script-")) - (shebang (cdr (assoc :shebang params))) - (padline (not (equal "no" (cdr (assoc :padline params)))))) - (with-temp-file script-file - (when shebang (insert (concat shebang "\n"))) - (when padline (insert "\n")) - (insert body)) - (set-file-modes script-file #o755) - (org-babel-eval script-file "")) - (org-babel-eval org-babel-sh-command (org-babel-trim body))))))) - (when results - (let ((result-params (cdr (assoc :result-params params)))) - (org-babel-result-cond result-params - results - (let ((tmp-file (org-babel-temp-file "sh-"))) - (with-temp-file tmp-file (insert results)) - (org-babel-import-elisp-from-file tmp-file))))))) - -(defun org-babel-sh-strip-weird-long-prompt (string) - "Remove prompt cruft from a string of shell output." - (while (string-match "^% +[\r\n$]+ *" string) - (setq string (substring string (match-end 0)))) - string) - -(provide 'ob-sh) - - - -;;; ob-sh.el ends here diff --git a/lisp/org/ob-shell.el b/lisp/org/ob-shell.el new file mode 100644 index 00000000000..3787c26a192 --- /dev/null +++ b/lisp/org/ob-shell.el @@ -0,0 +1,283 @@ +;;; ob-shell.el --- Babel Functions for Shell Evaluation -*- lexical-binding: t; -*- + +;; Copyright (C) 2009-2017 Free Software Foundation, Inc. + +;; Author: Eric Schulte +;; Keywords: literate programming, reproducible research +;; Homepage: http://orgmode.org + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; Org-Babel support for evaluating shell source code. + +;;; Code: +(require 'ob) +(require 'shell) +(require 'cl-lib) + +(declare-function org-babel-comint-in-buffer "ob-comint" (buffer &rest body) + t) +(declare-function org-babel-comint-wait-for-output "ob-comint" (buffer)) +(declare-function org-babel-comint-buffer-livep "ob-comint" (buffer)) +(declare-function org-babel-comint-with-output "ob-comint" (meta &rest body) + t) +(declare-function org-trim "org" (s &optional keep-lead)) +(declare-function orgtbl-to-generic "org-table" (table params)) + +(defvar org-babel-default-header-args:shell '()) +(defvar org-babel-shell-names) + +(defun org-babel-shell-initialize () + "Define execution functions associated to shell names. +This function has to be called whenever `org-babel-shell-names' +is modified outside the Customize interface." + (interactive) + (dolist (name org-babel-shell-names) + (eval `(defun ,(intern (concat "org-babel-execute:" name)) + (body params) + ,(format "Execute a block of %s commands with Babel." name) + (let ((shell-file-name ,name)) + (org-babel-execute:shell body params)))) + (eval `(defalias ',(intern (concat "org-babel-variable-assignments:" name)) + 'org-babel-variable-assignments:shell + ,(format "Return list of %s statements assigning to the block's \ +variables." + name))))) + +(defcustom org-babel-shell-names + '("sh" "bash" "csh" "ash" "dash" "ksh" "mksh" "posh") + "List of names of shell supported by babel shell code blocks. +Call `org-babel-shell-initialize' when modifying this variable +outside the Customize interface." + :group 'org-babel + :type '(repeat (string :tag "Shell name: ")) + :set (lambda (symbol value) + (set-default symbol value) + (org-babel-shell-initialize))) + +(defun org-babel-execute:shell (body params) + "Execute a block of Shell commands with Babel. +This function is called by `org-babel-execute-src-block'." + (let* ((session (org-babel-sh-initiate-session + (cdr (assq :session params)))) + (stdin (let ((stdin (cdr (assq :stdin params)))) + (when stdin (org-babel-sh-var-to-string + (org-babel-ref-resolve stdin))))) + (cmdline (cdr (assq :cmdline params))) + (full-body (org-babel-expand-body:generic + body params (org-babel-variable-assignments:shell params)))) + (org-babel-reassemble-table + (org-babel-sh-evaluate session full-body params stdin cmdline) + (org-babel-pick-name + (cdr (assq :colname-names params)) (cdr (assq :colnames params))) + (org-babel-pick-name + (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))) + +(defun org-babel-prep-session:shell (session params) + "Prepare SESSION according to the header arguments specified in PARAMS." + (let* ((session (org-babel-sh-initiate-session session)) + (var-lines (org-babel-variable-assignments:shell params))) + (org-babel-comint-in-buffer session + (mapc (lambda (var) + (insert var) (comint-send-input nil t) + (org-babel-comint-wait-for-output session)) var-lines)) + session)) + +(defun org-babel-load-session:shell (session body params) + "Load BODY into SESSION." + (save-window-excursion + (let ((buffer (org-babel-prep-session:shell session params))) + (with-current-buffer buffer + (goto-char (process-mark (get-buffer-process (current-buffer)))) + (insert (org-babel-chomp body))) + buffer))) + + +;;; Helper functions +(defun org-babel--variable-assignments:sh-generic + (varname values &optional sep hline) + "Returns a list of statements declaring the values as a generic variable." + (format "%s=%s" varname (org-babel-sh-var-to-sh values sep hline))) + +(defun org-babel--variable-assignments:bash_array + (varname values &optional sep hline) + "Returns a list of statements declaring the values as a bash array." + (format "unset %s\ndeclare -a %s=( %s )" + varname varname + (mapconcat + (lambda (value) (org-babel-sh-var-to-sh value sep hline)) + values + " "))) + +(defun org-babel--variable-assignments:bash_assoc + (varname values &optional sep hline) + "Returns a list of statements declaring the values as bash associative array." + (format "unset %s\ndeclare -A %s\n%s" + varname varname + (mapconcat + (lambda (items) + (format "%s[%s]=%s" + varname + (org-babel-sh-var-to-sh (car items) sep hline) + (org-babel-sh-var-to-sh (cdr items) sep hline))) + values + "\n"))) + +(defun org-babel--variable-assignments:bash (varname values &optional sep hline) + "Represents the parameters as useful Bash shell variables." + (pcase values + (`((,_ ,_ . ,_) . ,_) ;two-dimensional array + (org-babel--variable-assignments:bash_assoc varname values sep hline)) + (`(,_ . ,_) ;simple list + (org-babel--variable-assignments:bash_array varname values sep hline)) + (_ ;scalar value + (org-babel--variable-assignments:sh-generic varname values sep hline)))) + +(defun org-babel-variable-assignments:shell (params) + "Return list of shell statements assigning the block's variables." + (let ((sep (cdr (assq :separator params))) + (hline (when (string= "yes" (cdr (assq :hlines params))) + (or (cdr (assq :hline-string params)) + "hline")))) + (mapcar + (lambda (pair) + (if (string-suffix-p "bash" shell-file-name) + (org-babel--variable-assignments:bash + (car pair) (cdr pair) sep hline) + (org-babel--variable-assignments:sh-generic + (car pair) (cdr pair) sep hline))) + (org-babel--get-vars params)))) + +(defun org-babel-sh-var-to-sh (var &optional sep hline) + "Convert an elisp value to a shell variable. +Convert an elisp var into a string of shell commands specifying a +var of the same value." + (concat "'" (replace-regexp-in-string + "'" "'\"'\"'" + (org-babel-sh-var-to-string var sep hline)) + "'")) + +(defun org-babel-sh-var-to-string (var &optional sep hline) + "Convert an elisp value to a string." + (let ((echo-var (lambda (v) (if (stringp v) v (format "%S" v))))) + (cond + ((and (listp var) (or (listp (car var)) (eq (car var) 'hline))) + (orgtbl-to-generic var (list :sep (or sep "\t") :fmt echo-var + :hline hline))) + ((listp var) + (mapconcat echo-var var "\n")) + (t (funcall echo-var var))))) + +(defun org-babel-sh-initiate-session (&optional session _params) + "Initiate a session named SESSION according to PARAMS." + (when (and session (not (string= session "none"))) + (save-window-excursion + (or (org-babel-comint-buffer-livep session) + (progn + (shell session) + ;; Needed for Emacs 23 since the marker is initially + ;; undefined and the filter functions try to use it without + ;; checking. + (set-marker comint-last-output-start (point)) + (get-buffer (current-buffer))))))) + +(defvar org-babel-sh-eoe-indicator "echo 'org_babel_sh_eoe'" + "String to indicate that evaluation has completed.") +(defvar org-babel-sh-eoe-output "org_babel_sh_eoe" + "String to indicate that evaluation has completed.") + +(defun org-babel-sh-evaluate (session body &optional params stdin cmdline) + "Pass BODY to the Shell process in BUFFER. +If RESULT-TYPE equals `output' then return a list of the outputs +of the statements in BODY, if RESULT-TYPE equals `value' then +return the value of the last statement in BODY." + (let ((results + (cond + ((or stdin cmdline) ; external shell script w/STDIN + (let ((script-file (org-babel-temp-file "sh-script-")) + (stdin-file (org-babel-temp-file "sh-stdin-")) + (shebang (cdr (assq :shebang params))) + (padline (not (string= "no" (cdr (assq :padline params)))))) + (with-temp-file script-file + (when shebang (insert (concat shebang "\n"))) + (when padline (insert "\n")) + (insert body)) + (set-file-modes script-file #o755) + (with-temp-file stdin-file (insert (or stdin ""))) + (with-temp-buffer + (call-process-shell-command + (concat (if shebang script-file + (format "%s %s" shell-file-name script-file)) + (and cmdline (concat " " cmdline))) + stdin-file + (current-buffer)) + (buffer-string)))) + (session ; session evaluation + (mapconcat + #'org-babel-sh-strip-weird-long-prompt + (mapcar + #'org-trim + (butlast + (org-babel-comint-with-output + (session org-babel-sh-eoe-output t body) + (mapc + (lambda (line) + (insert line) + (comint-send-input nil t) + (while (save-excursion + (goto-char comint-last-input-end) + (not (re-search-forward + comint-prompt-regexp nil t))) + (accept-process-output + (get-buffer-process (current-buffer))))) + (append + (split-string (org-trim body) "\n") + (list org-babel-sh-eoe-indicator)))) + 2)) "\n")) + ('otherwise ; external shell script + (if (and (cdr (assq :shebang params)) + (> (length (cdr (assq :shebang params))) 0)) + (let ((script-file (org-babel-temp-file "sh-script-")) + (shebang (cdr (assq :shebang params))) + (padline (not (equal "no" (cdr (assq :padline params)))))) + (with-temp-file script-file + (when shebang (insert (concat shebang "\n"))) + (when padline (insert "\n")) + (insert body)) + (set-file-modes script-file #o755) + (org-babel-eval script-file "")) + (org-babel-eval shell-file-name (org-trim body))))))) + (when results + (let ((result-params (cdr (assq :result-params params)))) + (org-babel-result-cond result-params + results + (let ((tmp-file (org-babel-temp-file "sh-"))) + (with-temp-file tmp-file (insert results)) + (org-babel-import-elisp-from-file tmp-file))))))) + +(defun org-babel-sh-strip-weird-long-prompt (string) + "Remove prompt cruft from a string of shell output." + (while (string-match "^% +[\r\n$]+ *" string) + (setq string (substring string (match-end 0)))) + string) + +(provide 'ob-shell) + + + +;;; ob-shell.el ends here diff --git a/lisp/org/ob-shen.el b/lisp/org/ob-shen.el index d44a48a6382..6bf36c6437b 100644 --- a/lisp/org/ob-shen.el +++ b/lisp/org/ob-shen.el @@ -1,4 +1,4 @@ -;;; ob-shen.el --- org-babel functions for Shen +;;; ob-shen.el --- Babel Functions for Shen -*- lexical-binding: t; -*- ;; Copyright (C) 2010-2017 Free Software Foundation, Inc. @@ -43,7 +43,7 @@ (defun org-babel-expand-body:shen (body params) "Expand BODY according to PARAMS, return the expanded body." - (let ((vars (mapcar #'cdr (org-babel-get-header params :var)))) + (let ((vars (org-babel--get-vars params))) (if (> (length vars) 0) (concat "(let " (mapconcat (lambda (var) @@ -63,14 +63,13 @@ "Execute a block of Shen code with org-babel. This function is called by `org-babel-execute-src-block'" (require 'inf-shen) - (let* ((result-type (cdr (assoc :result-type params))) - (result-params (cdr (assoc :result-params params))) + (let* ((result-params (cdr (assq :result-params params))) (full-body (org-babel-expand-body:shen body params))) (let ((results (with-temp-buffer (insert full-body) (call-interactively #'shen-eval-defun)))) - (org-babel-result-cond result-params + (org-babel-result-cond result-params results (condition-case nil (org-babel-script-escape results) (error results)))))) diff --git a/lisp/org/ob-sql.el b/lisp/org/ob-sql.el index 17775829cba..6d39e953be4 100644 --- a/lisp/org/ob-sql.el +++ b/lisp/org/ob-sql.el @@ -1,4 +1,4 @@ -;;; ob-sql.el --- org-babel functions for sql evaluation +;;; ob-sql.el --- Babel Functions for SQL -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -36,6 +36,7 @@ ;; - engine ;; - cmdline ;; - dbhost +;; - dbport ;; - dbuser ;; - dbpassword ;; - database @@ -56,11 +57,11 @@ ;;; Code: (require 'ob) -(eval-when-compile (require 'cl)) (declare-function org-table-import "org-table" (file arg)) (declare-function orgtbl-to-csv "org-table" (table params)) (declare-function org-table-to-lisp "org-table" (&optional txt)) +(declare-function cygwin-convert-file-name-to-windows "cygw32.c" (file &optional absolute-p)) (defvar org-babel-default-header-args:sql '()) @@ -68,6 +69,7 @@ '((engine . :any) (out-file . :any) (dbhost . :any) + (dbport . :any) (dbuser . :any) (dbpassword . :any) (database . :any)) @@ -76,98 +78,167 @@ (defun org-babel-expand-body:sql (body params) "Expand BODY according to the values of PARAMS." (org-babel-sql-expand-vars - body (mapcar #'cdr (org-babel-get-header params :var)))) + body (org-babel--get-vars params))) -(defun dbstring-mysql (host user password database) +(defun org-babel-sql-dbstring-mysql (host port user password database) "Make MySQL cmd line args for database connection. Pass nil to omit that arg." (combine-and-quote-strings - (remq nil + (delq nil (list (when host (concat "-h" host)) + (when port (format "-P%d" port)) (when user (concat "-u" user)) (when password (concat "-p" password)) (when database (concat "-D" database)))))) +(defun org-babel-sql-dbstring-postgresql (host port user database) + "Make PostgreSQL command line args for database connection. +Pass nil to omit that arg." + (combine-and-quote-strings + (delq nil + (list (when host (concat "-h" host)) + (when port (format "-p%d" port)) + (when user (concat "-U" user)) + (when database (concat "-d" database)))))) + +(defun org-babel-sql-dbstring-oracle (host port user password database) + "Make Oracle command line args for database connection." + (format "%s/%s@%s:%s/%s" user password host port database)) + +(defun org-babel-sql-dbstring-mssql (host user password database) + "Make sqlcmd command line args for database connection. +`sqlcmd' is the preferred command line tool to access Microsoft +SQL Server on Windows and Linux platform." + (mapconcat #'identity + (delq nil + (list (when host (format "-S \"%s\"" host)) + (when user (format "-U \"%s\"" user)) + (when password (format "-P \"%s\"" password)) + (when database (format "-d \"%s\"" database)))) + " ")) + +(defun org-babel-sql-convert-standard-filename (file) + "Convert FILE to OS standard file name. +If in Cygwin environment, uses Cygwin specific function to +convert the file name. In a Windows-NT environment, do nothing. +Otherwise, use Emacs' standard conversion function." + (cond ((fboundp 'cygwin-convert-file-name-to-windows) + (format "%S" (cygwin-convert-file-name-to-windows file))) + ((string= "windows-nt" system-type) file) + (t (format "%S" (convert-standard-filename file))))) + (defun org-babel-execute:sql (body params) "Execute a block of Sql code with Babel. This function is called by `org-babel-execute-src-block'." - (let* ((result-params (cdr (assoc :result-params params))) - (cmdline (cdr (assoc :cmdline params))) - (dbhost (cdr (assoc :dbhost params))) - (dbuser (cdr (assoc :dbuser params))) - (dbpassword (cdr (assoc :dbpassword params))) - (database (cdr (assoc :database params))) - (engine (cdr (assoc :engine params))) - (colnames-p (not (equal "no" (cdr (assoc :colnames params))))) + (let* ((result-params (cdr (assq :result-params params))) + (cmdline (cdr (assq :cmdline params))) + (dbhost (cdr (assq :dbhost params))) + (dbport (cdr (assq :dbport params))) + (dbuser (cdr (assq :dbuser params))) + (dbpassword (cdr (assq :dbpassword params))) + (database (cdr (assq :database params))) + (engine (cdr (assq :engine params))) + (colnames-p (not (equal "no" (cdr (assq :colnames params))))) (in-file (org-babel-temp-file "sql-in-")) - (out-file (or (cdr (assoc :out-file params)) + (out-file (or (cdr (assq :out-file params)) (org-babel-temp-file "sql-out-"))) (header-delim "") - (command (case (intern engine) - ('dbi (format "dbish --batch %s < %s | sed '%s' > %s" + (command (pcase (intern engine) + (`dbi (format "dbish --batch %s < %s | sed '%s' > %s" (or cmdline "") (org-babel-process-file-name in-file) "/^+/d;s/^|//;s/(NULL)/ /g;$d" (org-babel-process-file-name out-file))) - ('monetdb (format "mclient -f tab %s < %s > %s" - (or cmdline "") - (org-babel-process-file-name in-file) - (org-babel-process-file-name out-file))) - ('msosql (format "osql %s -s \"\t\" -i %s -o %s" - (or cmdline "") - (org-babel-process-file-name in-file) - (org-babel-process-file-name out-file))) - ('mysql (format "mysql %s %s %s < %s > %s" - (dbstring-mysql dbhost dbuser dbpassword database) + (`monetdb (format "mclient -f tab %s < %s > %s" + (or cmdline "") + (org-babel-process-file-name in-file) + (org-babel-process-file-name out-file))) + (`mssql (format "sqlcmd %s -s \"\t\" %s -i %s -o %s" + (or cmdline "") + (org-babel-sql-dbstring-mssql + dbhost dbuser dbpassword database) + (org-babel-sql-convert-standard-filename + (org-babel-process-file-name in-file)) + (org-babel-sql-convert-standard-filename + (org-babel-process-file-name out-file)))) + (`mysql (format "mysql %s %s %s < %s > %s" + (org-babel-sql-dbstring-mysql + dbhost dbport dbuser dbpassword database) (if colnames-p "" "-N") - (or cmdline "") + (or cmdline "") (org-babel-process-file-name in-file) (org-babel-process-file-name out-file))) - ('postgresql (format - "psql -A -P footer=off -F \"\t\" -f %s -o %s %s" + (`postgresql (format + "%spsql --set=\"ON_ERROR_STOP=1\" %s -A -P \ +footer=off -F \"\t\" %s -f %s -o %s %s" + (if dbpassword + (format "PGPASSWORD=%s " dbpassword) + "") + (if colnames-p "" "-t") + (org-babel-sql-dbstring-postgresql + dbhost dbport dbuser database) (org-babel-process-file-name in-file) (org-babel-process-file-name out-file) (or cmdline ""))) - (t (error "No support for the %s SQL engine" engine))))) + (`oracle (format + "sqlplus -s %s < %s > %s" + (org-babel-sql-dbstring-oracle + dbhost dbport dbuser dbpassword database) + (org-babel-process-file-name in-file) + (org-babel-process-file-name out-file))) + (_ (error "No support for the %s SQL engine" engine))))) (with-temp-file in-file (insert - (case (intern engine) - ('dbi "/format partbox\n") - (t "")) + (pcase (intern engine) + (`dbi "/format partbox\n") + (`oracle "SET PAGESIZE 50000 +SET NEWPAGE 0 +SET TAB OFF +SET SPACE 0 +SET LINESIZE 9999 +SET ECHO OFF +SET FEEDBACK OFF +SET VERIFY OFF +SET HEADING ON +SET MARKUP HTML OFF SPOOL OFF +SET COLSEP '|' + +") + (`mssql "SET NOCOUNT ON + +") + (_ "")) (org-babel-expand-body:sql body params))) - (message command) (org-babel-eval command "") (org-babel-result-cond result-params (with-temp-buffer - (progn (insert-file-contents-literally out-file) (buffer-string))) + (progn (insert-file-contents-literally out-file) (buffer-string))) (with-temp-buffer (cond - ((or (eq (intern engine) 'mysql) - (eq (intern engine) 'dbi) - (eq (intern engine) 'postgresql)) - ;; Add header row delimiter after column-names header in first line - (cond - (colnames-p - (with-temp-buffer - (insert-file-contents out-file) - (goto-char (point-min)) - (forward-line 1) - (insert "-\n") - (setq header-delim "-") - (write-file out-file))))) - (t - ;; Need to figure out the delimiter for the header row - (with-temp-buffer - (insert-file-contents out-file) - (goto-char (point-min)) - (when (re-search-forward "^\\(-+\\)[^-]" nil t) - (setq header-delim (match-string-no-properties 1))) - (goto-char (point-max)) - (forward-char -1) - (while (looking-at "\n") - (delete-char 1) - (goto-char (point-max)) - (forward-char -1)) - (write-file out-file)))) + ((memq (intern engine) '(dbi mysql postgresql)) + ;; Add header row delimiter after column-names header in first line + (cond + (colnames-p + (with-temp-buffer + (insert-file-contents out-file) + (goto-char (point-min)) + (forward-line 1) + (insert "-\n") + (setq header-delim "-") + (write-file out-file))))) + (t + ;; Need to figure out the delimiter for the header row + (with-temp-buffer + (insert-file-contents out-file) + (goto-char (point-min)) + (when (re-search-forward "^\\(-+\\)[^-]" nil t) + (setq header-delim (match-string-no-properties 1))) + (goto-char (point-max)) + (forward-char -1) + (while (looking-at "\n") + (delete-char 1) + (goto-char (point-max)) + (forward-char -1)) + (write-file out-file)))) (org-table-import out-file '(16)) (org-babel-reassemble-table (mapcar (lambda (x) @@ -175,10 +246,10 @@ This function is called by `org-babel-execute-src-block'." 'hline x)) (org-table-to-lisp)) - (org-babel-pick-name (cdr (assoc :colname-names params)) - (cdr (assoc :colnames params))) - (org-babel-pick-name (cdr (assoc :rowname-names params)) - (cdr (assoc :rownames params)))))))) + (org-babel-pick-name (cdr (assq :colname-names params)) + (cdr (assq :colnames params))) + (org-babel-pick-name (cdr (assq :rowname-names params)) + (cdr (assq :rownames params)))))))) (defun org-babel-sql-expand-vars (body vars) "Expand the variables held in VARS in BODY." @@ -201,7 +272,7 @@ This function is called by `org-babel-execute-src-block'." vars) body) -(defun org-babel-prep-session:sql (session params) +(defun org-babel-prep-session:sql (_session _params) "Raise an error because Sql sessions aren't implemented." (error "SQL sessions not yet implemented")) diff --git a/lisp/org/ob-sqlite.el b/lisp/org/ob-sqlite.el index 4b165dc4762..8094019d5e2 100644 --- a/lisp/org/ob-sqlite.el +++ b/lisp/org/ob-sqlite.el @@ -1,4 +1,4 @@ -;;; ob-sqlite.el --- org-babel functions for sqlite database interaction +;;; ob-sqlite.el --- Babel Functions for SQLite Databases -*- lexical-binding: t; -*- ;; Copyright (C) 2010-2017 Free Software Foundation, Inc. @@ -53,23 +53,22 @@ (defun org-babel-expand-body:sqlite (body params) "Expand BODY according to the values of PARAMS." (org-babel-sqlite-expand-vars - body (mapcar #'cdr (org-babel-get-header params :var)))) + body (org-babel--get-vars params))) (defvar org-babel-sqlite3-command "sqlite3") (defun org-babel-execute:sqlite (body params) "Execute a block of Sqlite code with Babel. This function is called by `org-babel-execute-src-block'." - (let ((result-params (split-string (or (cdr (assoc :results params)) ""))) - (db (cdr (assoc :db params))) - (separator (cdr (assoc :separator params))) - (nullvalue (cdr (assoc :nullvalue params))) - (headers-p (equal "yes" (cdr (assoc :colnames params)))) + (let ((result-params (split-string (or (cdr (assq :results params)) ""))) + (db (cdr (assq :db params))) + (separator (cdr (assq :separator params))) + (nullvalue (cdr (assq :nullvalue params))) + (headers-p (equal "yes" (cdr (assq :colnames params)))) (others (delq nil (mapcar - (lambda (arg) (car (assoc arg params))) + (lambda (arg) (car (assq arg params))) (list :header :echo :bail :column - :csv :html :line :list)))) - exit-code) + :csv :html :line :list))))) (unless db (error "ob-sqlite: can't evaluate without a database")) (with-temp-buffer (insert @@ -140,7 +139,7 @@ This function is called by `org-babel-execute-src-block'." (equal 1 (length (car result)))) (org-babel-read (caar result)) (mapcar (lambda (row) - (if (equal 'hline row) + (if (eq 'hline row) 'hline (mapcar #'org-babel-string-read row))) result))) @@ -150,7 +149,7 @@ This function is called by `org-babel-execute-src-block'." (cons (car table) (cons 'hline (cdr table))) table)) -(defun org-babel-prep-session:sqlite (session params) +(defun org-babel-prep-session:sqlite (_session _params) "Raise an error because support for SQLite sessions isn't implemented. Prepare SESSION according to the header arguments specified in PARAMS." (error "SQLite sessions not yet implemented")) diff --git a/lisp/org/ob-stan.el b/lisp/org/ob-stan.el new file mode 100644 index 00000000000..40dd0efa380 --- /dev/null +++ b/lisp/org/ob-stan.el @@ -0,0 +1,84 @@ +;;; ob-stan.el --- Babel Functions for Stan -*- lexical-binding: t; -*- + +;; Copyright (C) 2015-2017 Free Software Foundation, Inc. + +;; Author: Kyle Meyer +;; Keywords: literate programming, reproducible research +;; Homepage: http://orgmode.org + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; Org-Babel support for evaluating Stan [1] source code. +;; +;; Evaluating a Stan block can produce two different results. +;; +;; 1) Dump the source code contents to a file. +;; +;; This file can then be used as a variable in other blocks, which +;; allows interfaces like RStan to use the model. +;; +;; 2) Compile the contents to a model file. +;; +;; This provides access to the CmdStan interface. To use this, set +;; `org-babel-stan-cmdstan-directory' and provide a :file argument +;; that does not end in ".stan". +;; +;; For more information and usage examples, visit +;; http://orgmode.org/worg/org-contrib/babel/languages/ob-doc-stan.html +;; +;; [1] http://mc-stan.org/ + +;;; Code: +(require 'ob) +(require 'org-compat) + +(defcustom org-babel-stan-cmdstan-directory nil + "CmdStan source directory. +'make' will be called from this directory to compile the Stan +block. When nil, executing Stan blocks dumps the content to a +plain text file." + :group 'org-babel + :type 'string) + +(defvar org-babel-default-header-args:stan + '((:results . "file"))) + +(defun org-babel-execute:stan (body params) + "Generate Stan file from BODY according to PARAMS. +A :file header argument must be given. If +`org-babel-stan-cmdstan-directory' is non-nil and the file name +does not have a \".stan\" extension, save an intermediate +\".stan\" file and compile the block to the named file. +Otherwise, write the Stan code directly to the named file." + (let ((file (expand-file-name + (or (cdr (assq :file params)) + (user-error "Set :file argument to execute Stan blocks"))))) + (if (or (not org-babel-stan-cmdstan-directory) + (string-match-p "\\.stan\\'" file)) + (with-temp-file file (insert body)) + (with-temp-file (concat file ".stan") (insert body)) + (let ((default-directory org-babel-stan-cmdstan-directory)) + (call-process-shell-command (concat "make " file)))) + nil)) ; Signal that output has been written to file. + +(defun org-babel-prep-session:stan (_session _params) + "Return an error because Stan does not support sessions." + (user-error "Stan does not support sessions")) + +(provide 'ob-stan) +;;; ob-stan.el ends here diff --git a/lisp/org/ob-table.el b/lisp/org/ob-table.el index 1fa9105ee2b..4de8936df1a 100644 --- a/lisp/org/ob-table.el +++ b/lisp/org/ob-table.el @@ -1,4 +1,4 @@ -;;; ob-table.el --- support for calling org-babel functions from tables +;;; ob-table.el --- Support for Calling Babel Functions from Tables -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -23,8 +23,8 @@ ;;; Commentary: -;; Should allow calling functions from org-mode tables using the -;; function `org-sbe' as so... +;; Should allow calling functions from Org tables using the function +;; `org-sbe' as so... ;; #+begin_src emacs-lisp :results silent ;; (defun fibbd (n) (if (< n 2) 1 (+ (fibbd (- n 1)) (fibbd (- n 2))))) @@ -47,38 +47,50 @@ ;; | 7 | | ;; | 8 | | ;; | 9 | | -;; #+TBLFM: $2='(org-sbe 'fibbd (n $1)) +;; #+TBLFM: $2='(org-sbe "fibbd" (n $1)) + +;; NOTE: The quotation marks around the function name, 'fibbd' here, +;; are optional. ;;; Code: (require 'ob-core) +(declare-function org-trim "org" (s &optional keep-lead)) + (defun org-babel-table-truncate-at-newline (string) "Replace newline character with ellipses. If STRING ends in a newline character, then remove the newline character and replace it with ellipses." (if (and (stringp string) (string-match "[\n\r]\\(.\\)?" string)) (concat (substring string 0 (match-beginning 0)) - (if (match-string 1 string) "...")) string)) + (when (match-string 1 string) "...")) string)) (defmacro org-sbe (source-block &rest variables) "Return the results of calling SOURCE-BLOCK with VARIABLES. -Each element of VARIABLES should be a two -element list, whose first element is the name of the variable and -second element is a string of its value. The following call to -`org-sbe' would be equivalent to the following source code block. - (org-sbe \\='source-block (n $2) (m 3)) +Each element of VARIABLES should be a list of two elements: the +first element is the name of the variable and second element is a +string of its value. + +So this `org-sbe' construct + + (org-sbe \"source-block\" (n $2) (m 3)) + +is the equivalent of the following source code block: + + #+begin_src emacs-lisp :var results=source-block(n=val_at_col_2, m=3) :results silent + results + #+end_src -#+begin_src emacs-lisp :var results=source-block(n=val_at_col_2, m=3) :results silent -results -#+end_src +NOTE: The quotation marks around the function name, +'source-block', are optional. -NOTE: by default string variable names are interpreted as +NOTE: By default, string variable names are interpreted as references to source-code blocks, to force interpretation of a cell's value as a string, prefix the identifier a \"$\" (e.g., \"$$2\" instead of \"$2\" or \"$@2$2\" instead of \"@2$2\"). -NOTE: it is also possible to pass header arguments to the code +NOTE: It is also possible to pass header arguments to the code block. In this case a table cell should hold the string value of the header argument which can then be passed before all variables as shown in the example below. @@ -132,7 +144,7 @@ as shown in the example below. nil (list "emacs-lisp" "results" params) '((:results . "silent")))) ""))) - (org-babel-trim (if (stringp result) result (format "%S" result))))))) + (org-trim (if (stringp result) result (format "%S" result))))))) (provide 'ob-table) diff --git a/lisp/org/ob-tangle.el b/lisp/org/ob-tangle.el index 437e0a296c1..3b0533261c6 100644 --- a/lisp/org/ob-tangle.el +++ b/lisp/org/ob-tangle.el @@ -1,4 +1,4 @@ -;;; ob-tangle.el --- extract source code from org-mode files +;;; ob-tangle.el --- Extract Source Code From Org Files -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -26,22 +26,35 @@ ;; Extract the code from source blocks out into raw source-code files. ;;; Code: + +(require 'cl-lib) (require 'org-src) -(eval-when-compile - (require 'cl)) +(declare-function make-directory "files" (dir &optional parents)) +(declare-function org-at-heading-p "org" (&optional ignored)) +(declare-function org-babel-update-block-body "ob-core" (new-body)) +(declare-function org-back-to-heading "org" (&optional invisible-ok)) +(declare-function org-before-first-heading-p "org" ()) (declare-function org-edit-special "org" (&optional arg)) +(declare-function org-element-at-point "org-element" ()) +(declare-function org-element-type "org-element" (element)) +(declare-function org-fill-template "org" (template alist)) +(declare-function org-heading-components "org" ()) +(declare-function org-in-commented-heading-p "org" (&optional no-inheritance)) (declare-function org-link-escape "org" (text &optional table merge)) -(declare-function org-store-link "org" (arg)) (declare-function org-open-link-from-string "org" (s &optional arg reference-buffer)) -(declare-function org-heading-components "org" ()) -(declare-function org-back-to-heading "org" (&optional invisible-ok)) -(declare-function org-fill-template "org" (template alist)) -(declare-function org-babel-update-block-body "ob-core" (new-body)) -(declare-function make-directory "files" (dir &optional parents)) +(declare-function org-remove-indentation "org" (code &optional n)) +(declare-function org-store-link "org" (arg)) +(declare-function org-string-nw-p "org-macs" (s)) +(declare-function org-trim "org" (s &optional keep-lead)) +(declare-function outline-previous-heading "outline" ()) +(declare-function org-id-find "org-id" (id &optional markerp)) + +(defvar org-link-types-re) (defcustom org-babel-tangle-lang-exts - '(("emacs-lisp" . "el")) + '(("emacs-lisp" . "el") + ("elisp" . "el")) "Alist mapping languages to their file extensions. The key is the language name, the value is the string that should be inserted as the extension commonly used to identify files @@ -54,6 +67,11 @@ then the name of the language is used." (string "Language name") (string "File Extension")))) +(defcustom org-babel-tangle-use-relative-file-links t + "Use relative path names in links from tangled source back the Org file." + :group 'org-babel-tangle + :type 'boolean) + (defcustom org-babel-post-tangle-hook nil "Hook run in code files tangled by `org-babel-tangle'." :group 'org-babel @@ -78,9 +96,14 @@ The following format strings can be used to insert special information into the output using `org-fill-template'. %start-line --- the line number at the start of the code block %file --------- the file from which the code block was tangled -%link --------- Org-mode style link to the code block +%link --------- Org style link to the code block %source-name -- name of the code block +Upon insertion the formatted comment will be commented out, and +followed by a newline. To inhibit this post-insertion processing +set the `org-babel-tangle-uncomment-comments' variable to a +non-nil value. + Whether or not comments are inserted during tangling is controlled by the :comments header argument." :group 'org-babel @@ -93,20 +116,33 @@ The following format strings can be used to insert special information into the output using `org-fill-template'. %start-line --- the line number at the start of the code block %file --------- the file from which the code block was tangled -%link --------- Org-mode style link to the code block +%link --------- Org style link to the code block %source-name -- name of the code block +Upon insertion the formatted comment will be commented out, and +followed by a newline. To inhibit this post-insertion processing +set the `org-babel-tangle-uncomment-comments' variable to a +non-nil value. + Whether or not comments are inserted during tangling is controlled by the :comments header argument." :group 'org-babel :version "24.1" :type 'string) -(defcustom org-babel-process-comment-text #'org-babel-trim - "Function called to process raw Org-mode text collected to be +(defcustom org-babel-tangle-uncomment-comments nil + "Inhibits automatic commenting and addition of trailing newline +of tangle comments. Use `org-babel-tangle-comment-format-beg' +and `org-babel-tangle-comment-format-end' to customize the format +of tangled comments." + :group 'org-babel + :type 'boolean) + +(defcustom org-babel-process-comment-text 'org-remove-indentation + "Function called to process raw Org text collected to be inserted as comments in tangled source-code files. The function should take a single string argument and return a string -result. The default value is `org-babel-trim'." +result. The default value is `org-remove-indentation'." :group 'org-babel :version "24.1" :type 'function) @@ -153,12 +189,14 @@ Return a list whose CAR is the tangled file name." (save-window-excursion (find-file file) (setq to-be-removed (current-buffer)) - (org-babel-tangle nil target-file lang)) + (mapcar #'expand-file-name (org-babel-tangle nil target-file lang))) (unless visited-p (kill-buffer to-be-removed))))) (defun org-babel-tangle-publish (_ filename pub-dir) "Tangle FILENAME and place the results in PUB-DIR." + (unless (file-exists-p pub-dir) + (make-directory pub-dir t)) (mapc (lambda (el) (copy-file el pub-dir t)) (org-babel-tangle-file filename))) ;;;###autoload @@ -176,12 +214,12 @@ used to limit the exported source code blocks by language." (run-hooks 'org-babel-pre-tangle-hook) ;; Possibly Restrict the buffer to the current code block (save-restriction - (when (equal arg '(4)) - (let ((head (org-babel-where-is-src-block-head))) + (save-excursion + (when (equal arg '(4)) + (let ((head (org-babel-where-is-src-block-head))) (if head (goto-char head) (user-error "Point is not in a source code block")))) - (save-excursion (let ((block-counter 0) (org-babel-default-header-args (if target-file @@ -190,7 +228,7 @@ used to limit the exported source code blocks by language." org-babel-default-header-args)) (tangle-file (when (equal arg '(16)) - (or (cdr (assoc :tangle (nth 2 (org-babel-get-src-block-info 'light)))) + (or (cdr (assq :tangle (nth 2 (org-babel-get-src-block-info 'light)))) (user-error "Point is not in a source code block")))) path-collector) (mapc ;; map over all languages @@ -216,7 +254,7 @@ used to limit the exported source code blocks by language." (base-name (cond ((string= "yes" tangle) (file-name-sans-extension - (buffer-file-name))) + (nth 1 spec))) ((string= "no" tangle) nil) ((> (length tangle) 0) tangle))) (file-name (when base-name @@ -243,9 +281,13 @@ used to limit the exported source code blocks by language." ;; We avoid append-to-file as it does not work with tramp. (let ((content (buffer-string))) (with-temp-buffer - (if (file-exists-p file-name) - (insert-file-contents file-name)) + (when (file-exists-p file-name) + (insert-file-contents file-name)) (goto-char (point-max)) + ;; Handle :padlines unless first line in file + (unless (or (string= "no" (cdr (assq :padline (nth 4 spec)))) + (= (point) (point-min))) + (insert "\n")) (insert content) (write-region nil nil file-name)))) ;; if files contain she-bangs, then make the executable @@ -253,10 +295,8 @@ used to limit the exported source code blocks by language." (unless tangle-mode (setq tangle-mode #o755))) ;; update counter (setq block-counter (+ 1 block-counter)) - (add-to-list 'path-collector - (cons file-name tangle-mode) - nil - (lambda (a b) (equal (car a) (car b)))))))) + (unless (assoc file-name path-collector) + (push (cons file-name tangle-mode) path-collector)))))) specs))) (if (equal arg '(4)) (org-babel-tangle-single-block 1 t) @@ -284,7 +324,7 @@ used to limit the exported source code blocks by language." Call this function inside of a source-code file generated by `org-babel-tangle' to remove all comments inserted automatically by `org-babel-tangle'. Warning, this comment removes any lines -containing constructs which resemble org-mode file links or noweb +containing constructs which resemble Org file links or noweb references." (interactive) (goto-char (point-min)) @@ -303,153 +343,134 @@ code file. This function uses `comment-region' which assumes that the appropriate major-mode is set. SPEC has the form: (start-line file link source-name params body comment)" - (let* ((start-line (nth 0 spec)) - (file (nth 1 spec)) - (link (nth 2 spec)) - (source-name (nth 3 spec)) - (body (nth 5 spec)) - (comment (nth 6 spec)) - (comments (cdr (assoc :comments (nth 4 spec)))) - (padline (not (string= "no" (cdr (assoc :padline (nth 4 spec)))))) - (link-p (or (string= comments "both") (string= comments "link") - (string= comments "yes") (string= comments "noweb"))) - (link-data (mapcar (lambda (el) - (cons (symbol-name el) - (let ((le (eval el))) - (if (stringp le) le (format "%S" le))))) - '(start-line file link source-name))) - (insert-comment (lambda (text) - (when (and comments (not (string= comments "no")) - (> (length text) 0)) - (when padline (insert "\n")) - (comment-region (point) (progn (insert text) (point))) - (end-of-line nil) (insert "\n"))))) + (pcase-let* + ((`(,start ,file ,link ,source ,info ,body ,comment) spec) + (comments (cdr (assq :comments info))) + (link? (or (string= comments "both") (string= comments "link") + (string= comments "yes") (string= comments "noweb"))) + (link-data `(("start-line" . ,(number-to-string start)) + ("file" . ,file) + ("link" . ,link) + ("source-name" . ,source))) + (insert-comment (lambda (text) + (when (and comments + (not (string= comments "no")) + (org-string-nw-p text)) + (if org-babel-tangle-uncomment-comments + ;; Plain comments: no processing. + (insert text) + ;; Ensure comments are made to be + ;; comments, and add a trailing newline. + ;; Also ignore invisible characters when + ;; commenting. + (comment-region + (point) + (progn (insert (org-no-properties text)) + (point))) + (end-of-line) + (insert "\n")))))) (when comment (funcall insert-comment comment)) - (when link-p - (funcall - insert-comment - (org-fill-template org-babel-tangle-comment-format-beg link-data))) - (when padline (insert "\n")) - (insert - (format - "%s\n" - (org-unescape-code-in-string - (org-babel-trim body (if org-src-preserve-indentation "[\f\n\r\v]"))))) - (when link-p - (funcall - insert-comment - (org-fill-template org-babel-tangle-comment-format-end link-data))))) - -(defvar org-comment-string) ;; Defined in org.el + (when link? + (funcall insert-comment + (org-fill-template + org-babel-tangle-comment-format-beg link-data))) + (insert body "\n") + (when link? + (funcall insert-comment + (org-fill-template + org-babel-tangle-comment-format-end link-data))))) + (defun org-babel-tangle-collect-blocks (&optional language tangle-file) - "Collect source blocks in the current Org-mode file. + "Collect source blocks in the current Org file. Return an association list of source-code block specifications of the form used by `org-babel-spec-to-string' grouped by language. Optional argument LANGUAGE can be used to limit the collected source code blocks by language. Optional argument TANGLE-FILE can be used to limit the collected code blocks by target file." - (let ((block-counter 1) (current-heading "") blocks by-lang) + (let ((counter 0) last-heading-pos blocks) (org-babel-map-src-blocks (buffer-file-name) - (lambda (new-heading) - (if (not (string= new-heading current-heading)) - (progn - (setq block-counter 1) - (setq current-heading new-heading)) - (setq block-counter (+ 1 block-counter)))) - (replace-regexp-in-string "[ \t]" "-" - (condition-case nil - (or (nth 4 (org-heading-components)) - "(dummy for heading without text)") - (error (buffer-file-name)))) - (let* ((info (org-babel-get-src-block-info 'light)) - (src-lang (nth 0 info)) - (src-tfile (cdr (assoc :tangle (nth 2 info))))) - (unless (or (string-match (concat "^" org-comment-string) current-heading) - (string= (cdr (assoc :tangle (nth 2 info))) "no") - (and tangle-file (not (equal tangle-file src-tfile)))) - (unless (and language (not (string= language src-lang))) - ;; Add the spec for this block to blocks under it's language - (setq by-lang (cdr (assoc src-lang blocks))) - (setq blocks (delq (assoc src-lang blocks) blocks)) - (setq blocks (cons - (cons src-lang - (cons - (org-babel-tangle-single-block - block-counter) - by-lang)) blocks)))))) - ;; Ensure blocks are in the correct order - (setq blocks - (mapcar - (lambda (by-lang) (cons (car by-lang) (reverse (cdr by-lang)))) - blocks)) - blocks)) - -(defun org-babel-tangle-single-block - (block-counter &optional only-this-block) + (let ((current-heading-pos + (org-with-wide-buffer + (org-with-limited-levels (outline-previous-heading))))) + (if (eq last-heading-pos current-heading-pos) (cl-incf counter) + (setq counter 1) + (setq last-heading-pos current-heading-pos))) + (unless (org-in-commented-heading-p) + (let* ((info (org-babel-get-src-block-info 'light)) + (src-lang (nth 0 info)) + (src-tfile (cdr (assq :tangle (nth 2 info))))) + (unless (or (string= src-tfile "no") + (and tangle-file (not (equal tangle-file src-tfile))) + (and language (not (string= language src-lang)))) + ;; Add the spec for this block to blocks under its + ;; language. + (let ((by-lang (assoc src-lang blocks)) + (block (org-babel-tangle-single-block counter))) + (if by-lang (setcdr by-lang (cons block (cdr by-lang))) + (push (cons src-lang (list block)) blocks))))))) + ;; Ensure blocks are in the correct order. + (mapcar (lambda (b) (cons (car b) (nreverse (cdr b)))) blocks))) + +(defun org-babel-tangle-single-block (block-counter &optional only-this-block) "Collect the tangled source for current block. Return the list of block attributes needed by -`org-babel-tangle-collect-blocks'. -When ONLY-THIS-BLOCK is non-nil, return the full association -list to be used by `org-babel-tangle' directly." +`org-babel-tangle-collect-blocks'. When ONLY-THIS-BLOCK is +non-nil, return the full association list to be used by +`org-babel-tangle' directly." (let* ((info (org-babel-get-src-block-info)) (start-line (save-restriction (widen) (+ 1 (line-number-at-pos (point))))) - (file (buffer-file-name)) + (file (buffer-file-name (buffer-base-buffer))) (src-lang (nth 0 info)) (params (nth 2 info)) (extra (nth 3 info)) (cref-fmt (or (and (string-match "-l \"\\(.+\\)\"" extra) (match-string 1 extra)) org-coderef-label-format)) - (link (let ((link (org-no-properties - (org-store-link nil)))) - (and (string-match org-bracket-link-regexp link) - (match-string 1 link)))) + (link (let ((l (org-no-properties (org-store-link nil)))) + (and (string-match org-bracket-link-regexp l) + (match-string 1 l)))) (source-name - (intern (or (nth 4 info) - (format "%s:%d" - (or (ignore-errors (nth 4 (org-heading-components))) - "No heading") - block-counter)))) - (expand-cmd - (intern (concat "org-babel-expand-body:" src-lang))) + (or (nth 4 info) + (format "%s:%d" + (or (ignore-errors (nth 4 (org-heading-components))) + "No heading") + block-counter))) + (expand-cmd (intern (concat "org-babel-expand-body:" src-lang))) (assignments-cmd (intern (concat "org-babel-variable-assignments:" src-lang))) (body ;; Run the tangle-body-hook. - (let* ((body ;; Expand the body in language specific manner. - (if (org-babel-noweb-p params :tangle) - (org-babel-expand-noweb-references info) - (nth 1 info))) - (body - (if (assoc :no-expand params) - body - (if (fboundp expand-cmd) - (funcall expand-cmd body params) - (org-babel-expand-body:generic - body params - (and (fboundp assignments-cmd) - (funcall assignments-cmd params))))))) - (with-temp-buffer - (insert body) - (when (string-match "-r" extra) - (goto-char (point-min)) - (while (re-search-forward - (replace-regexp-in-string "%s" ".+" cref-fmt) nil t) - (replace-match ""))) - (run-hooks 'org-babel-tangle-body-hook) - (buffer-string)))) + (let ((body (if (org-babel-noweb-p params :tangle) + (org-babel-expand-noweb-references info) + (nth 1 info)))) + (with-temp-buffer + (insert + ;; Expand body in language specific manner. + (cond ((assq :no-expand params) body) + ((fboundp expand-cmd) (funcall expand-cmd body params)) + (t + (org-babel-expand-body:generic + body params (and (fboundp assignments-cmd) + (funcall assignments-cmd params)))))) + (when (string-match "-r" extra) + (goto-char (point-min)) + (while (re-search-forward + (replace-regexp-in-string "%s" ".+" cref-fmt) nil t) + (replace-match ""))) + (run-hooks 'org-babel-tangle-body-hook) + (buffer-string)))) (comment - (when (or (string= "both" (cdr (assoc :comments params))) - (string= "org" (cdr (assoc :comments params)))) + (when (or (string= "both" (cdr (assq :comments params))) + (string= "org" (cdr (assq :comments params)))) ;; From the previous heading or code-block end (funcall org-babel-process-comment-text (buffer-substring (max (condition-case nil (save-excursion - (org-back-to-heading t) ; Sets match data + (org-back-to-heading t) ; Sets match data (match-end 0)) (error (point-min))) (save-excursion @@ -459,31 +480,48 @@ list to be used by `org-babel-tangle' directly." (point-min)))) (point))))) (result - (list start-line file link source-name params body comment))) + (list start-line + (if org-babel-tangle-use-relative-file-links + (file-relative-name file) + file) + (if (and org-babel-tangle-use-relative-file-links + (string-match org-link-types-re link) + (string= (match-string 0 link) "file")) + (concat "file:" + (file-relative-name (match-string 1 link) + (file-name-directory + (cdr (assq :tangle params))))) + link) + source-name + params + (org-unescape-code-in-string + (if org-src-preserve-indentation + (org-trim body t) + (org-trim (org-remove-indentation body)))) + comment))) (if only-this-block (list (cons src-lang (list result))) result))) -(defun org-babel-tangle-comment-links ( &optional info) +(defun org-babel-tangle-comment-links (&optional info) "Return a list of begin and end link comments for the code block at point." - (let* ((start-line (org-babel-where-is-src-block-head)) - (file (buffer-file-name)) - (link (org-link-escape (progn (call-interactively 'org-store-link) - (org-no-properties - (car (pop org-stored-links)))))) - (source-name (nth 4 (or info (org-babel-get-src-block-info 'light)))) - (link-data (mapcar (lambda (el) - (cons (symbol-name el) - (let ((le (eval el))) - (if (stringp le) le (format "%S" le))))) - '(start-line file link source-name)))) + (let ((link-data + `(("start-line" . ,(number-to-string + (org-babel-where-is-src-block-head))) + ("file" . ,(buffer-file-name)) + ("link" . ,(org-link-escape + (progn + (call-interactively #'org-store-link) + (org-no-properties (car (pop org-stored-links)))))) + ("source-name" . + ,(nth 4 (or info (org-babel-get-src-block-info 'light))))))) (list (org-fill-template org-babel-tangle-comment-format-beg link-data) (org-fill-template org-babel-tangle-comment-format-end link-data)))) ;; de-tangling functions (defvar org-bracket-link-analytic-regexp) (defun org-babel-detangle (&optional source-code-file) - "Propagate changes in source file back original to Org-mode file. + "Propagate changes in source file back original to Org file. This requires that code blocks were tangled with link comments which enable the original code blocks to be found." (interactive) @@ -504,18 +542,17 @@ which enable the original code blocks to be found." (prog1 counter (message "Detangled %d code blocks" counter))))) (defun org-babel-tangle-jump-to-org () - "Jump from a tangled code file to the related Org-mode file." + "Jump from a tangled code file to the related Org mode file." (interactive) (let ((mid (point)) - start body-start end done + start body-start end target-buffer target-char link path block-name body) (save-window-excursion (save-excursion (while (and (re-search-backward org-bracket-link-analytic-regexp nil t) (not ; ever wider searches until matching block comments - (and (setq start (point-at-eol)) - (setq body-start (save-excursion - (forward-line 2) (point-at-bol))) + (and (setq start (line-beginning-position)) + (setq body-start (line-beginning-position 2)) (setq link (match-string 0)) (setq path (match-string 3)) (setq block-name (match-string 5)) @@ -524,32 +561,37 @@ which enable the original code blocks to be found." (re-search-forward (concat " " (regexp-quote block-name) " ends here") nil t) - (setq end (point-at-bol)))))))) + (setq end (line-beginning-position)))))))) (unless (and start (< start mid) (< mid end)) (error "Not in tangled code")) - (setq body (org-babel-trim (buffer-substring start end)))) + (setq body (buffer-substring body-start end))) (when (string-match "::" path) (setq path (substring path 0 (match-beginning 0)))) - (find-file path) (setq target-buffer (current-buffer)) - (goto-char start) (org-open-link-from-string link) + (find-file (or (car (org-id-find path)) path)) + (setq target-buffer (current-buffer)) + ;; Go to the beginning of the relative block in Org file. + (org-open-link-from-string link) (if (string-match "[^ \t\n\r]:\\([[:digit:]]+\\)" block-name) - (org-babel-next-src-block - (string-to-number (match-string 1 block-name))) + (let ((n (string-to-number (match-string 1 block-name)))) + (if (org-before-first-heading-p) (goto-char (point-min)) + (org-back-to-heading t)) + ;; Do not skip the first block if it begins at point min. + (cond ((or (org-at-heading-p) + (not (eq (org-element-type (org-element-at-point)) + 'src-block))) + (org-babel-next-src-block n)) + ((= n 1)) + (t (org-babel-next-src-block (1- n))))) (org-babel-goto-named-src-block block-name)) - ;; position at the beginning of the code block body (goto-char (org-babel-where-is-src-block-head)) + ;; Preserve location of point within the source code in tangled + ;; code file. (forward-line 1) - ;; Use org-edit-special to isolate the code. - (org-edit-special) - ;; Then move forward the correct number of characters in the - ;; code buffer. (forward-char (- mid body-start)) - ;; And return to the Org-mode buffer with the point in the right - ;; place. - (org-edit-src-exit) (setq target-char (point))) (org-src-switch-to-buffer target-buffer t) - (prog1 body (goto-char target-char)))) + (goto-char target-char) + body)) (provide 'ob-tangle) diff --git a/lisp/org/ob.el b/lisp/org/ob.el index b0c3d521c54..736f58879b5 100644 --- a/lisp/org/ob.el +++ b/lisp/org/ob.el @@ -1,4 +1,4 @@ -;;; ob.el --- working with code blocks in org-mode +;;; ob.el --- Working with Code Blocks in Org -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. diff --git a/lisp/org/org-agenda.el b/lisp/org/org-agenda.el index c870ddd4e43..f90dd53bb05 100644 --- a/lisp/org/org-agenda.el +++ b/lisp/org/org-agenda.el @@ -24,7 +24,7 @@ ;; ;;; Commentary: -;; This file contains the code for creating and using the Agenda for Org-mode. +;; This file contains the code for creating and using the Agenda for Org. ;; ;; The functions `org-batch-agenda', `org-batch-agenda-csv', and ;; `org-batch-store-agenda-views' are implemented as macros to provide @@ -45,10 +45,9 @@ ;;; Code: +(require 'cl-lib) (require 'org) (require 'org-macs) -(eval-when-compile - (require 'cl)) (declare-function diary-add-to-list "diary-lib" (date string specifier &optional marker globcolor literal)) @@ -69,6 +68,7 @@ (declare-function calendar-persian-date-string "cal-persia" (&optional date)) (declare-function calendar-check-holidays "holidays" (date)) +(declare-function org-columns-remove-overlays "org-colview" ()) (declare-function org-datetree-find-date-create "org-datetree" (date &optional keep-restriction)) (declare-function org-columns-quit "org-colview" ()) @@ -79,16 +79,15 @@ (declare-function org-is-habit-p "org-habit" (&optional pom)) (declare-function org-habit-parse-todo "org-habit" (&optional pom)) (declare-function org-habit-get-priority "org-habit" (habit &optional moment)) -(declare-function org-pop-to-buffer-same-window "org-compat" - (&optional buffer-or-name norecord label)) (declare-function org-agenda-columns "org-colview" ()) (declare-function org-add-archive-files "org-archive" (files)) (declare-function org-capture "org-capture" (&optional goto keys)) -(defvar calendar-mode-map) ; defined in calendar.el -(defvar org-clock-current-task nil) ; defined in org-clock.el -(defvar org-mobile-force-id-on-agenda-items) ; defined in org-mobile.el -(defvar org-habit-show-habits) ; defined in org-habit.el +(defvar calendar-mode-map) +(defvar org-clock-current-task) +(defvar org-current-tag-alist) +(defvar org-mobile-force-id-on-agenda-items) +(defvar org-habit-show-habits) (defvar org-habit-show-habits-only-for-today) (defvar org-habit-show-all-today) @@ -96,8 +95,8 @@ (defvar org-agenda-buffer-name "*Org Agenda*") (defvar org-agenda-overriding-header nil) (defvar org-agenda-title-append nil) -(org-no-warnings (defvar entry)) ;; unprefixed, from calendar.el -(org-no-warnings (defvar date)) ;; unprefixed, from calendar.el +(with-no-warnings (defvar entry)) ;; unprefixed, from calendar.el +(with-no-warnings (defvar date)) ;; unprefixed, from calendar.el (defvar original-date) ; dynamically scoped, calendar.el does scope this (defvar org-agenda-undo-list nil @@ -135,7 +134,7 @@ addresses the separator between the current and the previous block." (string))) (defgroup org-agenda-export nil - "Options concerning exporting agenda views in Org-mode." + "Options concerning exporting agenda views in Org mode." :tag "Org Agenda Export" :group 'org-agenda) @@ -152,7 +151,7 @@ before assigned to the variables. So make sure to quote values you do *not* want evaluated, for example (setq org-agenda-exporter-settings - '((ps-print-color-p 'black-white)))" + \\='((ps-print-color-p \\='black-white)))" :group 'org-agenda-export :type '(repeat (list @@ -237,7 +236,7 @@ you can \"misuse\" it to also add other text to the header." :type 'boolean) (defgroup org-agenda-custom-commands nil - "Options concerning agenda views in Org-mode." + "Options concerning agenda views in Org mode." :tag "Org Agenda Custom Commands" :group 'org-agenda) @@ -261,8 +260,8 @@ you can \"misuse\" it to also add other text to the header." ;; Keep custom values for `org-agenda-filter-preset' compatible with ;; the new variable `org-agenda-tag-filter-preset'. -(org-defvaralias 'org-agenda-filter-preset 'org-agenda-tag-filter-preset) -(org-defvaralias 'org-agenda-filter 'org-agenda-tag-filter) +(defvaralias 'org-agenda-filter-preset 'org-agenda-tag-filter-preset) +(defvaralias 'org-agenda-filter 'org-agenda-tag-filter) (defvar org-agenda-entry-types '(:deadline :scheduled :timestamp :sexp) "List of types searched for when creating the daily/weekly agenda. @@ -360,6 +359,12 @@ the daily/weekly agenda, see `org-agenda-skip-function'.") (const :format "" quote) (repeat (string :tag "+tag or -tag")))) + (list :tag "Effort filter preset" + (const org-agenda-effort-filter-preset) + (list + (const :format "" quote) + (repeat + (string :tag "+=10 or -=10 or +<10 or ->10")))) (list :tag "Regexp filter preset" (const org-agenda-regexp-filter-preset) (list @@ -435,8 +440,9 @@ This will be spliced into the custom type of (defcustom org-agenda-custom-commands '(("n" "Agenda and all TODOs" ((agenda "") (alltodo "")))) "Custom commands for the agenda. +\\ These commands will be offered on the splash screen displayed by the -agenda dispatcher \\[org-agenda]. Each entry is a list like this: +agenda dispatcher `\\[org-agenda]'. Each entry is a list like this: (key desc type match settings files) @@ -463,8 +469,8 @@ match What to search for: settings A list of option settings, similar to that in a let form, so like this: ((opt1 val1) (opt2 val2) ...). The values will be evaluated at the moment of execution, so quote them when needed. -files A list of files file to write the produced agenda buffer to - with the command `org-store-agenda-views'. +files A list of files to write the produced agenda buffer to with + the command `org-store-agenda-views'. If a file name ends in \".html\", an HTML version of the buffer is written out. If it ends in \".ps\", a postscript version is produced. Otherwise, only the plain text is written to the file. @@ -601,23 +607,17 @@ subtree to see if any of the subtasks have project status. See also the variable `org-tags-match-list-sublevels' which applies to projects matched by this search as well. -After defining this variable, you may use \\[org-agenda-list-stuck-projects] -or `C-c a #' to produce the list." +After defining this variable, you may use `\\[org-agenda-list-stuck-projects]' +\(bound to `C-c a #') to produce the list." :group 'org-agenda-custom-commands :type '(list (string :tag "Tags/TODO match to identify a project") - (repeat :tag "Projects are *not* stuck if they have an entry with TODO keyword any of" (string)) - (repeat :tag "Projects are *not* stuck if they have an entry with TAG being any of" (string)) - (regexp :tag "Projects are *not* stuck if this regexp matches inside the subtree"))) - -(defcustom org-agenda-filter-effort-default-operator "<" - "The default operator for effort estimate filtering. -If you select an effort estimate limit without first pressing an operator, -this one will be used." - :group 'org-agenda-custom-commands - :type '(choice (const :tag "less or equal" "<") - (const :tag "greater or equal"">") - (const :tag "equal" "="))) + (repeat :tag "Projects are *not* stuck if they have an entry with \ +TODO keyword any of" (string)) + (repeat :tag "Projects are *not* stuck if they have an entry with \ +TAG being any of" (string)) + (regexp :tag "Projects are *not* stuck if this regexp matches inside \ +the subtree"))) (defgroup org-agenda-skip nil "Options concerning skipping parts of agenda files." @@ -769,10 +769,12 @@ to make his option also apply to the tags-todo list." (defcustom org-agenda-todo-ignore-deadlines nil "Non-nil means ignore some deadline TODO items when making TODO list. + There are different motivations for using different values, please think carefully when configuring this variable. -This applies when creating the global todo list. +This applies when creating the global TODO list. + Valid values are: near Don't show near deadline entries. A deadline is near when it is @@ -780,8 +782,8 @@ near Don't show near deadline entries. A deadline is near when it is is that such items will appear in the agenda anyway. far Don't show TODO entries where a deadline has been defined, but - the deadline is not near. This is useful if you don't want to - use the todo list to figure out what to do now. + is not going to happen anytime soon. This is useful if you want to use + the TODO list to figure out what to do now. past Don't show entries with a deadline timestamp for today or in the past. @@ -842,10 +844,9 @@ restricted to unfinished TODO entries only." (defcustom org-agenda-skip-scheduled-if-done nil "Non-nil means don't show scheduled items in agenda when they are done. -This is relevant for the daily/weekly agenda, not for the TODO list. And -it applies only to the actual date of the scheduling. Warnings about -an item with a past scheduling dates are always turned off when the item -is DONE." +This is relevant for the daily/weekly agenda, not for the TODO list. It +applies only to the actual date of the scheduling. Warnings about an item +with a past scheduling dates are always turned off when the item is DONE." :group 'org-agenda-skip :group 'org-agenda-daily/weekly :type 'boolean) @@ -894,8 +895,8 @@ several times." (defcustom org-agenda-skip-deadline-if-done nil "Non-nil means don't show deadlines when the corresponding item is done. When nil, the deadline is still shown and should give you a happy feeling. -This is relevant for the daily/weekly agenda. And it applied only to the -actually date of the deadline. Warnings about approaching and past-due +This is relevant for the daily/weekly agenda. It applies only to the +actual date of the deadline. Warnings about approaching and past-due deadlines are always turned off when the item is DONE." :group 'org-agenda-skip :group 'org-agenda-daily/weekly @@ -1001,8 +1002,6 @@ you want to use two-columns display (see `org-agenda-menu-two-columns')." :version "24.1" :type 'boolean) -(define-obsolete-variable-alias 'org-agenda-menu-two-column 'org-agenda-menu-two-columns "24.3") - (defcustom org-agenda-menu-two-columns nil "Non-nil means, use two columns to show custom commands in the dispatcher. If you use this, you probably want to set `org-agenda-menu-show-matcher' @@ -1011,7 +1010,6 @@ to nil." :version "24.1" :type 'boolean) -(define-obsolete-variable-alias 'org-finalize-agenda-hook 'org-agenda-finalize-hook "24.3") (defcustom org-agenda-finalize-hook nil "Hook run just before displaying an agenda buffer. The buffer is still writable when the hook is called. @@ -1024,8 +1022,8 @@ headlines as the agenda display heavily relies on them." (defcustom org-agenda-mouse-1-follows-link nil "Non-nil means mouse-1 on a link will follow the link in the agenda. -A longer mouse click will still set point. Does not work on XEmacs. -Needs to be set before org.el is loaded." +A longer mouse click will still set point. Needs to be set +before org.el is loaded." :group 'org-agenda-startup :type 'boolean) @@ -1054,9 +1052,9 @@ current item's tree, in an indirect buffer." (defcustom org-agenda-entry-text-maxlines 5 "Number of text lines to be added when `E' is pressed in the agenda. -Note that this variable only used during agenda display. Add add entry text +Note that this variable only used during agenda display. To add entry text when exporting the agenda, configure the variable -`org-agenda-add-entry-ext-maxlines'." +`org-agenda-add-entry-text-maxlines'." :group 'org-agenda :type 'integer) @@ -1097,6 +1095,7 @@ Possible values for this option are: current-window Show agenda in the current window, keeping all other windows. other-window Use `switch-to-buffer-other-window' to display agenda. +only-window Show agenda, deleting all other windows. reorganize-frame Show only two windows on the current frame, the current window and the agenda. other-frame Use `switch-to-buffer-other-frame' to display agenda. @@ -1107,6 +1106,7 @@ See also the variable `org-agenda-restore-windows-after-quit'." (const current-window) (const other-frame) (const other-window) + (const only-window) (const reorganize-frame))) (defcustom org-agenda-window-frame-fractions '(0.5 . 0.75) @@ -1126,16 +1126,6 @@ option will be ignored." :group 'org-agenda-windows :type 'boolean) -(defcustom org-agenda-ndays nil - "Number of days to include in overview display. -Should be 1 or 7. -Obsolete, see `org-agenda-span'." - :group 'org-agenda-daily/weekly - :type '(choice (const nil) - (integer))) - -(make-obsolete-variable 'org-agenda-ndays 'org-agenda-span "24.1") - (defcustom org-agenda-span 'week "Number of days to include in overview display. Can be day, week, month, year, or any number of days. @@ -1211,7 +1201,7 @@ For example, 9:30am would become 09:30 rather than 9:30." :type 'boolean) (defun org-agenda-time-of-day-to-ampm (time) - "Convert TIME of a string like `13:45' to an AM/PM style time string." + "Convert TIME of a string like \"13:45\" to an AM/PM style time string." (let* ((hour-number (string-to-number (substring time 0 -3))) (minute (substring time -2)) (ampm "am")) @@ -1284,20 +1274,22 @@ shown, either today or the nearest into the future." (defcustom org-scheduled-past-days 10000 "Number of days to continue listing scheduled items not marked DONE. -When an item is scheduled on a date, it shows up in the agenda on this -day and will be listed until it is marked done for the number of days -given here." +When an item is scheduled on a date, it shows up in the agenda on +this day and will be listed until it is marked done or for the +number of days given here." :group 'org-agenda-daily/weekly :type 'integer) (defcustom org-agenda-log-mode-items '(closed clock) "List of items that should be shown in agenda log mode. +\\\ This list may contain the following symbols: closed Show entries that have been closed on that day. clock Show entries that have received clocked time on that day. state Show all logged state changes. -Note that instead of changing this variable, you can also press `C-u l' in +Note that instead of changing this variable, you can also press \ +`\\[universal-argument] \\[org-agenda-log-mode]' in the agenda to display all available LOG items temporarily." :group 'org-agenda-daily/weekly :type '(set :greedy t (const closed) (const clock) (const state))) @@ -1413,7 +1405,7 @@ boolean search." :version "24.1" :type 'boolean) -(org-defvaralias 'org-agenda-search-view-search-words-only +(defvaralias 'org-agenda-search-view-search-words-only 'org-agenda-search-view-always-boolean) (defcustom org-agenda-search-view-force-full-words nil @@ -1434,7 +1426,7 @@ value, don't limit agenda view by outline level." :type 'integer) (defgroup org-agenda-time-grid nil - "Options concerning the time grid in the Org-mode Agenda." + "Options concerning the time grid in the Org Agenda." :tag "Org Agenda Time Grid" :group 'org-agenda) @@ -1506,7 +1498,7 @@ a grid line." :type 'string) (defgroup org-agenda-sorting nil - "Options concerning sorting in the Org-mode Agenda." + "Options concerning sorting in the Org Agenda." :tag "Org Agenda Sorting" :group 'org-agenda) @@ -1612,7 +1604,7 @@ When nil, such items are sorted as 0 minutes effort." :type 'boolean) (defgroup org-agenda-line-format nil - "Options concerning the entry prefix in the Org-mode agenda display." + "Options concerning the entry prefix in the Org agenda display." :tag "Org Agenda Line Format" :group 'org-agenda) @@ -1792,17 +1784,18 @@ When non-nil, this must be the number of minutes, e.g. 60 for one hour." (defcustom org-agenda-show-inherited-tags t "Non-nil means show inherited tags in each agenda line. -When this option is set to 'always, it take precedences over +When this option is set to `always', it takes precedence over `org-agenda-use-tag-inheritance' and inherited tags are shown in every agenda. When this option is set to t (the default), inherited tags are shown when they are available, i.e. when the value of -`org-agenda-use-tag-inheritance' has been taken into account. +`org-agenda-use-tag-inheritance' enables tag inheritance for the +given agenda type. This can be set to a list of agenda types in which the agenda -must display the inherited tags. Available types are 'todo, -'agenda, 'search and 'timeline. +must display the inherited tags. Available types are `todo', +`agenda', `search' and `timeline'. When set to nil, never show inherited tags in agenda lines." :group 'org-agenda-line-format @@ -1823,10 +1816,10 @@ controlled by `org-use-tag-inheritance'. In other agenda types, agenda entries. Still, you may want the agenda to be aware of the inherited tags anyway, e.g. for later tag filtering. -Allowed value are 'todo, 'search, 'timeline and 'agenda. +Allowed value are `todo', `search', `timeline' and `agenda'. This variable has no effect if `org-agenda-show-inherited-tags' -is set to 'always. In that case, the agenda is aware of those +is set to `always'. In that case, the agenda is aware of those tags. The default value sets tags in every agenda type. Setting this @@ -1858,10 +1851,10 @@ When this is the symbol `prefix', only remove tags when (const :tag "Never" nil) (const :tag "When prefix format contains %T" prefix))) -(org-defvaralias 'org-agenda-remove-tags-when-in-prefix +(defvaralias 'org-agenda-remove-tags-when-in-prefix 'org-agenda-remove-tags) -(defcustom org-agenda-tags-column (if (featurep 'xemacs) -79 -80) +(defcustom org-agenda-tags-column -80 "Shift tags in agenda items to this column. If this number is positive, it specifies the column. If it is negative, it means that the tags should be flushright to that column. For example, @@ -1869,7 +1862,7 @@ it means that the tags should be flushright to that column. For example, :group 'org-agenda-line-format :type 'integer) -(org-defvaralias 'org-agenda-align-tags-to-column 'org-agenda-tags-column) +(defvaralias 'org-agenda-align-tags-to-column 'org-agenda-tags-column) (defcustom org-agenda-fontify-priorities 'cookies "Non-nil means highlight low and high priorities in agenda. @@ -1948,6 +1941,14 @@ category, you can use: :tag "Org Agenda Column View" :group 'org-agenda) +(defcustom org-agenda-view-columns-initially nil + "When non-nil, switch to columns view right after creating the agenda." + :group 'org-agenda-column-view + :type 'boolean + :version "26.1" + :package-version '(Org . "9.0") + :safe #'booleanp) + (defcustom org-agenda-columns-show-summaries t "Non-nil means show summaries for columns displayed in the agenda view." :group 'org-agenda-column-view @@ -1975,7 +1976,8 @@ estimate." :type 'boolean) (defcustom org-agenda-auto-exclude-function nil - "A function called with a tag to decide if it is filtered on `/ RET'. + "A function called with a tag to decide if it is filtered on \ +\\`\\[org-agenda-filter-by-tag] RET'. The sole argument to the function, which is called once for each possible tag, is a string giving the name of the tag. The function should return either nil if the tag should be included @@ -1990,13 +1992,13 @@ the lower-case version of all tags." "Alist of characters and custom functions for bulk actions. For example, this value makes those two functions available: - ((?R set-category) - (?C bulk-cut)) + \\='((?R set-category) + (?C bulk-cut)) With selected entries in an agenda buffer, `B R' will call the custom function `set-category' on the selected entries. Note that functions in this alist don't need to be quoted." - :type 'alist + :type '(alist :key-type character :value-type (group function)) :version "24.1" :group 'org-agenda) @@ -2006,7 +2008,7 @@ If STRING is non-nil, the text property will be fetched from position 0 in that string. If STRING is nil, it will be fetched from the beginning of the current line." (org-with-gensyms (marker) - `(let ((,marker (get-text-property (if string 0 (point-at-bol)) + `(let ((,marker (get-text-property (if ,string 0 (point-at-bol)) 'org-hd-marker ,string))) (with-current-buffer (marker-buffer ,marker) (save-excursion @@ -2027,7 +2029,7 @@ works you probably want to add it to `org-agenda-custom-commands' for good." (defvar org-agenda-mode-map (make-sparse-keymap) "Keymap for `org-agenda-mode'.") -(org-defvaralias 'org-agenda-keymap 'org-agenda-mode-map) +(defvaralias 'org-agenda-keymap 'org-agenda-mode-map) (defvar org-agenda-menu) ; defined later in this file. (defvar org-agenda-restrict nil) ; defined later in this file. @@ -2044,6 +2046,8 @@ The buffer is still writable when this hook is called.") (defvar org-agenda-force-single-file nil) (defvar org-agenda-bulk-marked-entries nil "List of markers that refer to marked entries in the agenda.") +(defvar org-agenda-current-date nil + "Active date when building the agenda.") ;;; Multiple agenda buffers support @@ -2064,13 +2068,13 @@ When nil, `q' will kill the single agenda buffer." (> (prefix-numeric-value arg) 0) (not org-agenda-sticky)))) (if (equal new-value org-agenda-sticky) - (and (org-called-interactively-p 'interactive) + (and (called-interactively-p 'interactive) (message "Sticky agenda was already %s" (if org-agenda-sticky "enabled" "disabled"))) (setq org-agenda-sticky new-value) (org-agenda-kill-all-agenda-buffers) - (and (org-called-interactively-p 'interactive) - (message "Sticky agenda was %s" + (and (called-interactively-p 'interactive) + (message "Sticky agenda %s" (if org-agenda-sticky "enabled" "disabled")))))) (defvar org-agenda-buffer nil @@ -2080,6 +2084,8 @@ When nil, `q' will kill the single agenda buffer." (defvar org-agenda-this-buffer-name nil) (defvar org-agenda-doing-sticky-redo nil) (defvar org-agenda-this-buffer-is-sticky nil) +(defvar org-agenda-last-indirect-buffer nil + "Last buffer loaded by `org-agenda-tree-to-indirect-buffer'.") (defconst org-agenda-local-vars '(org-agenda-this-buffer-name @@ -2101,8 +2107,10 @@ When nil, `q' will kill the single agenda buffer." org-agenda-category-filter org-agenda-top-headline-filter org-agenda-regexp-filter + org-agenda-effort-filter org-agenda-markers org-agenda-last-search-view-search-was-boolean + org-agenda-last-indirect-buffer org-agenda-filtered-by-category org-agenda-filter-form org-agenda-cycle-counter @@ -2110,7 +2118,7 @@ When nil, `q' will kill the single agenda buffer." "Variables that must be local in agenda buffers to allow multiple buffers.") (defun org-agenda-mode () - "Mode for time-sorted view on action items in Org-mode files. + "Mode for time-sorted view on action items in Org files. The following commands are available: @@ -2123,42 +2131,41 @@ The following commands are available: ;; while letting `kill-all-local-variables' kill the rest (let ((save (buffer-local-variables))) (kill-all-local-variables) - (mapc 'make-local-variable org-agenda-local-vars) + (mapc #'make-local-variable org-agenda-local-vars) (dolist (elem save) - (let ((var (car elem)) - (val (cdr elem))) - (when (and val - (member var org-agenda-local-vars)) - (set var val))))) - (set (make-local-variable 'org-agenda-this-buffer-is-sticky) t)) + (pcase elem + (`(,var . ,val) ;ignore unbound variables + (when (and val (memq var org-agenda-local-vars)) + (set var val)))))) + (setq-local org-agenda-this-buffer-is-sticky t)) (org-agenda-sticky ;; Creating a sticky Agenda buffer for the first time (kill-all-local-variables) (mapc 'make-local-variable org-agenda-local-vars) - (set (make-local-variable 'org-agenda-this-buffer-is-sticky) t)) + (setq-local org-agenda-this-buffer-is-sticky t)) (t ;; Creating a non-sticky agenda buffer (kill-all-local-variables) - (set (make-local-variable 'org-agenda-this-buffer-is-sticky) nil))) + (setq-local org-agenda-this-buffer-is-sticky nil))) (setq org-agenda-undo-list nil org-agenda-pending-undo-list nil org-agenda-bulk-marked-entries nil) (setq major-mode 'org-agenda-mode) ;; Keep global-font-lock-mode from turning on font-lock-mode - (org-set-local 'font-lock-global-modes (list 'not major-mode)) + (setq-local font-lock-global-modes (list 'not major-mode)) (setq mode-name "Org-Agenda") (setq indent-tabs-mode nil) (use-local-map org-agenda-mode-map) (easy-menu-add org-agenda-menu) (if org-startup-truncated (setq truncate-lines t)) - (org-set-local 'line-move-visual nil) - (org-add-hook 'post-command-hook 'org-agenda-update-agenda-type nil 'local) - (org-add-hook 'pre-command-hook 'org-unhighlight nil 'local) + (setq-local line-move-visual nil) + (add-hook 'post-command-hook 'org-agenda-update-agenda-type nil 'local) + (add-hook 'pre-command-hook 'org-unhighlight nil 'local) ;; Make sure properties are removed when copying text - (org-add-hook 'filter-buffer-substring-functions - (lambda (fun start end delete) - (substring-no-properties (funcall fun start end delete))) - nil t) + (add-hook 'filter-buffer-substring-functions + (lambda (fun start end delete) + (substring-no-properties (funcall fun start end delete))) + nil t) (unless org-agenda-keep-modes (setq org-agenda-follow-mode org-agenda-start-with-follow-mode org-agenda-entry-text-mode org-agenda-start-with-entry-text-mode)) @@ -2309,9 +2316,9 @@ The following commands are available: (org-defkey org-agenda-mode-map "{" 'org-agenda-manipulate-query-add-re) (org-defkey org-agenda-mode-map "}" 'org-agenda-manipulate-query-subtract-re) (org-defkey org-agenda-mode-map "/" 'org-agenda-filter-by-tag) +(org-defkey org-agenda-mode-map "_" 'org-agenda-filter-by-effort) (org-defkey org-agenda-mode-map "=" 'org-agenda-filter-by-regexp) (org-defkey org-agenda-mode-map "|" 'org-agenda-filter-remove-all) -(org-defkey org-agenda-mode-map "\\" 'org-agenda-filter-by-tag-refine) (org-defkey org-agenda-mode-map "~" 'org-agenda-limit-interactively) (org-defkey org-agenda-mode-map "<" 'org-agenda-filter-by-category) (org-defkey org-agenda-mode-map "^" 'org-agenda-filter-by-top-headline) @@ -2322,6 +2329,10 @@ The following commands are available: (org-defkey org-agenda-mode-map [mouse-2] 'org-agenda-goto-mouse) (org-defkey org-agenda-mode-map [mouse-3] 'org-agenda-show-mouse) + +(define-key org-agenda-mode-map [remap forward-paragraph] 'org-agenda-forward-block) +(define-key org-agenda-mode-map [remap backward-paragraph] 'org-agenda-backward-block) + (when org-agenda-mouse-1-follows-link (org-defkey org-agenda-mode-map [follow-link] 'mouse-face)) (easy-menu-define org-agenda-menu org-agenda-mode-map "Agenda menu" @@ -2346,7 +2357,7 @@ The following commands are available: ["Fortnight View" org-agenda-fortnight-view :active (org-agenda-check-type nil 'agenda) :style radio :selected (eq org-agenda-current-span 'fortnight) - :keys "v f"] + :keys "v t"] ["Month View" org-agenda-month-view :active (org-agenda-check-type nil 'agenda) :style radio :selected (eq org-agenda-current-span 'month) @@ -2387,7 +2398,7 @@ The following commands are available: ["Remove Restriction" org-agenda-remove-restriction-lock org-agenda-restrict]) ["Write view to file" org-agenda-write t] ["Rebuild buffer" org-agenda-redo t] - ["Save all Org-mode Buffers" org-save-all-org-buffers t] + ["Save all Org buffers" org-save-all-org-buffers t] "--" ["Show original entry" org-agenda-show t] ["Go To (other window)" org-agenda-goto t] @@ -2538,7 +2549,7 @@ For example, if you have a custom agenda command \"p\" and you want this command to be accessible only from plain text files, use this: - \\='((\"p\" ((in-file . \"\\.txt\")))) + \\='((\"p\" ((in-file . \"\\\\.txt\\\\'\")))) Here are the available contexts definitions: @@ -2556,7 +2567,7 @@ accessible if there is at least one valid check. You can also bind a key to another agenda custom command depending on contextual rules. - \\='((\"p\" \"q\" ((in-file . \"\\.txt\")))) + \\='((\"p\" \"q\" ((in-file . \"\\\\.txt\\\\'\")))) Here it means: in .txt files, use \"p\" as the key for the agenda command otherwise associated with \"q\". (The command @@ -2656,6 +2667,7 @@ to limit entries to in this type." (const timeline)) (integer :tag "Max number of minutes"))))) +(defvar org-agenda-keep-restricted-file-list nil) (defvar org-keys nil) (defvar org-match nil) ;;;###autoload @@ -2688,9 +2700,9 @@ More commands can be added by configuring the variable `org-agenda-custom-commands'. In particular, specific tags and TODO keyword searches can be pre-defined in this way. -If the current buffer is in Org-mode and visiting a file, you can also +If the current buffer is in Org mode and visiting a file, you can also first press `<' once to indicate that the agenda should be temporarily -\(until the next use of \\[org-agenda]) restricted to the current file. +\(until the next use of `\\[org-agenda]') restricted to the current file. Pressing `<' twice means to restrict to the current subtree or region \(if active)." (interactive "P") @@ -2722,7 +2734,7 @@ Pressing `<' twice means to restrict to the current subtree or region entry key type org-match lprops ans) ;; Turn off restriction unless there is an overriding one, (unless org-agenda-overriding-restriction - (unless (org-bound-and-true-p org-agenda-keep-restricted-file-list) + (unless org-agenda-keep-restricted-file-list ;; There is a request to keep the file list in place (put 'org-agenda-files 'org-restrict nil)) (setq org-agenda-restrict nil) @@ -2819,7 +2831,7 @@ Pressing `<' twice means to restrict to the current subtree or region ((equal org-keys "M") (org-call-with-arg 'org-tags-view (or arg '(4)))) ((equal org-keys "e") (call-interactively 'org-store-agenda-views)) ((equal org-keys "?") (org-tags-view nil "+FLAGGED") - (org-add-hook + (add-hook 'post-command-hook (lambda () (unless (current-message) @@ -2836,7 +2848,7 @@ Pressing `<' twice means to restrict to the current subtree or region t t)) ((equal org-keys "L") (unless (derived-mode-p 'org-mode) - (user-error "This is not an Org-mode file")) + (user-error "This is not an Org file")) (unless restriction (put 'org-agenda-files 'org-restrict (list bfn)) (org-call-with-arg 'org-timeline arg))) @@ -2928,7 +2940,7 @@ L Timeline for current buffer # List stuck projects (!=configure) type (nth 2 entry) match (nth 3 entry)) (if (> (length key) 1) - (pushnew (string-to-char key) prefixes :test #'equal) + (cl-pushnew (string-to-char key) prefixes :test #'equal) (setq line (format "%-4s%-14s" @@ -3034,7 +3046,7 @@ L Timeline for current buffer # List stuck projects (!=configure) (call-interactively 'org-toggle-sticky-agenda) (sit-for 2)) ((and (not restrict-ok) (memq c '(?1 ?0 ?<))) - (message "Restriction is only possible in Org-mode buffers") + (message "Restriction is only possible in Org buffers") (ding) (sit-for 1)) ((eq c ?1) (org-agenda-remove-restriction-lock 'noupdate) @@ -3067,10 +3079,13 @@ L Timeline for current buffer # List stuck projects (!=configure) "Fit the window to the buffer size." (and (memq org-agenda-window-setup '(reorganize-frame)) (fboundp 'fit-window-to-buffer) - (org-fit-window-to-buffer - nil - (floor (* (frame-height) (cdr org-agenda-window-frame-fractions))) - (floor (* (frame-height) (car org-agenda-window-frame-fractions)))))) + (if (and (= (cdr org-agenda-window-frame-fractions) 1.0) + (= (car org-agenda-window-frame-fractions) 1.0)) + (delete-other-windows) + (org-fit-window-to-buffer + nil + (floor (* (frame-height) (cdr org-agenda-window-frame-fractions))) + (floor (* (frame-height) (car org-agenda-window-frame-fractions))))))) (defvar org-cmd nil) (defvar org-agenda-overriding-cmd nil) @@ -3089,9 +3104,9 @@ L Timeline for current buffer # List stuck projects (!=configure) match ;; The byte compiler incorrectly complains about this. Keep it! org-cmd type lprops) (while (setq org-cmd (pop cmds)) - (setq type (car org-cmd) - match (eval (nth 1 org-cmd)) - lprops (nth 2 org-cmd)) + (setq type (car org-cmd)) + (setq match (eval (nth 1 org-cmd))) + (setq lprops (nth 2 org-cmd)) (let ((org-agenda-overriding-arguments (if (eq org-agenda-overriding-cmd org-cmd) (or org-agenda-overriding-arguments @@ -3144,7 +3159,7 @@ Parameters are alternating variable names and values that will be bound before running the agenda command." (org-eval-in-environment (org-make-parameter-alist parameters) (let (org-agenda-sticky) - (if (> (length cmd-key) 2) + (if (> (length cmd-key) 1) (org-tags-view nil cmd-key) (org-agenda nil cmd-key)))) (set-buffer org-agenda-buffer-name) @@ -3232,7 +3247,7 @@ This ensures the export commands can easily use it." (setq tmp (replace-match "" t t tmp))) (when (and (setq re (plist-get props 'org-todo-regexp)) (setq re (concat "\\`\\.*" re " ?")) - (string-match re tmp)) + (let ((case-fold-search nil)) (string-match re tmp))) (plist-put props 'todo (match-string 1 tmp)) (setq tmp (replace-match "" t t tmp))) (plist-put props 'txt tmp))) @@ -3245,9 +3260,7 @@ This ensures the export commands can easily use it." ((not res) "") ((stringp res) res) (t (prin1-to-string res)))) - (while (string-match "," res) - (setq res (replace-match ";" t t res))) - (org-trim res))) + (org-trim (replace-regexp-in-string "," ";" res nil t)))) ;;;###autoload (defun org-store-agenda-views (&rest parameters) @@ -3306,39 +3319,42 @@ This ensures the export commands can easily use it." (defvar org-agenda-write-buffer-name "Agenda View") (defun org-agenda-write (file &optional open nosettings agenda-bufname) "Write the current buffer (an agenda view) as a file. + Depending on the extension of the file name, plain text (.txt), HTML (.html or .htm), PDF (.pdf) or Postscript (.ps) is produced. -If the extension is .ics, run icalendar export over all files used -to construct the agenda and limit the export to entries listed in the -agenda now. -If the extension is .org, collect all subtrees corresponding to the -agenda entries and add them in an .org file. -With prefix argument OPEN, open the new file immediately. -If NOSETTINGS is given, do not scope the settings of -`org-agenda-exporter-settings' into the export commands. This is used when -the settings have already been scoped and we do not wish to overrule other, -higher priority settings. -If AGENDA-BUFFER-NAME, use this as the buffer name for the agenda to write." +If the extension is .ics, translate visible agenda into iCalendar +format. If the extension is .org, collect all subtrees +corresponding to the agenda entries and add them in an .org file. + +With prefix argument OPEN, open the new file immediately. If +NOSETTINGS is given, do not scope the settings of +`org-agenda-exporter-settings' into the export commands. This is +used when the settings have already been scoped and we do not +wish to overrule other, higher priority settings. If +AGENDA-BUFFER-NAME is provided, use this as the buffer name for +the agenda to write." (interactive "FWrite agenda to file: \nP") (if (or (not (file-writable-p file)) (and (file-exists-p file) - (if (org-called-interactively-p 'any) + (if (called-interactively-p 'any) (not (y-or-n-p (format "Overwrite existing file %s? " file)))))) (user-error "Cannot write agenda to file %s" file)) (org-let (if nosettings nil org-agenda-exporter-settings) '(save-excursion (save-window-excursion - (let ((bs (copy-sequence (buffer-string))) beg content) + (let ((bs (copy-sequence (buffer-string))) + (extension (file-name-extension file)) + beg content) (with-temp-buffer (rename-buffer org-agenda-write-buffer-name t) (set-buffer-modified-p nil) (insert bs) - (org-agenda-remove-marked-text 'org-filtered) + (org-agenda-remove-marked-text 'invisible 'org-filtered) (run-hooks 'org-agenda-before-write-hook) (cond - ((org-bound-and-true-p org-mobile-creating-agendas) + ((bound-and-true-p org-mobile-creating-agendas) (org-mobile-write-agenda-for-mobile file)) - ((string-match "\\.org\\'" file) + ((string= "org" extension) (let (content p m message-log-max) (goto-char (point-min)) (while (setq p (next-single-property-change (point) 'org-hd-marker nil)) @@ -3357,7 +3373,7 @@ If AGENDA-BUFFER-NAME, use this as the buffer name for the agenda to write." (write-file file) (kill-buffer (current-buffer)) (message "Org file written to %s" file))) - ((string-match "\\.html?\\'" file) + ((member extension '("html" "htm")) (require 'htmlize) (set-buffer (htmlize-buffer (current-buffer))) (when org-agenda-export-html-style @@ -3369,11 +3385,11 @@ If AGENDA-BUFFER-NAME, use this as the buffer name for the agenda to write." (write-file file) (kill-buffer (current-buffer)) (message "HTML written to %s" file)) - ((string-match "\\.ps\\'" file) + ((string= "ps" extension) (require 'ps-print) (ps-print-buffer-with-faces file) (message "Postscript written to %s" file)) - ((string-match "\\.pdf\\'" file) + ((string= "pdf" extension) (require 'ps-print) (ps-print-buffer-with-faces (concat (file-name-sans-extension file) ".ps")) @@ -3383,7 +3399,7 @@ If AGENDA-BUFFER-NAME, use this as the buffer name for the agenda to write." (expand-file-name file)) (delete-file (concat (file-name-sans-extension file) ".ps")) (message "PDF written to %s" file)) - ((string-match "\\.ics\\'" file) + ((string= "ics" extension) (require 'ox-icalendar) (org-icalendar-export-current-agenda (expand-file-name file))) (t @@ -3395,7 +3411,7 @@ If AGENDA-BUFFER-NAME, use this as the buffer name for the agenda to write." (kill-buffer (current-buffer)) (message "Plain text written to %s" file)))))))) (set-buffer (or agenda-bufname - (and (org-called-interactively-p 'any) (buffer-name)) + (and (called-interactively-p 'any) (buffer-name)) org-agenda-buffer-name))) (when open (org-open-file file))) @@ -3416,7 +3432,7 @@ This will add a maximum of `org-agenda-add-entry-text-maxlines' lines of the entry text following headings shown in the agenda. Drawers will be excluded, also the line with scheduling/deadline info." (when (and (> org-agenda-add-entry-text-maxlines 0) - (not (org-bound-and-true-p org-mobile-creating-agendas))) + (not (bound-and-true-p org-mobile-creating-agendas))) (let (m txt) (goto-char (point-min)) (while (not (eobp)) @@ -3441,85 +3457,83 @@ removed from the entry content. Currently only `planning' is allowed here." (with-current-buffer (marker-buffer marker) (if (not (derived-mode-p 'org-mode)) (setq txt "") - (save-excursion - (save-restriction - (widen) - (goto-char marker) - (end-of-line 1) - (setq txt (buffer-substring - (min (1+ (point)) (point-max)) - (progn (outline-next-heading) (point))) - drawer-re org-drawer-regexp - kwd-time-re (concat "^[ \t]*" org-keyword-time-regexp - ".*\n?")) - (with-temp-buffer - (insert txt) - (when org-agenda-add-entry-text-descriptive-links - (goto-char (point-min)) - (while (org-activate-bracket-links (point-max)) - (add-text-properties (match-beginning 0) (match-end 0) - '(face org-link)))) - (goto-char (point-min)) - (while (re-search-forward org-bracket-link-regexp (point-max) t) - (set-text-properties (match-beginning 0) (match-end 0) - nil)) - (goto-char (point-min)) - (while (re-search-forward drawer-re nil t) - (delete-region - (match-beginning 0) - (progn (re-search-forward - "^[ \t]*:END:.*\n?" nil 'move) - (point)))) - (unless (member 'planning keep) - (goto-char (point-min)) - (while (re-search-forward kwd-time-re nil t) - (replace-match ""))) - (goto-char (point-min)) - (when org-agenda-entry-text-exclude-regexps - (let ((re-list org-agenda-entry-text-exclude-regexps) re) - (while (setq re (pop re-list)) - (goto-char (point-min)) - (while (re-search-forward re nil t) - (replace-match ""))))) - (goto-char (point-max)) - (skip-chars-backward " \t\n") - (if (looking-at "[ \t\n]+\\'") (replace-match "")) - - ;; find and remove min common indentation - (goto-char (point-min)) - (untabify (point-min) (point-max)) - (setq ind (org-get-indentation)) - (while (not (eobp)) - (unless (looking-at "[ \t]*$") - (setq ind (min ind (org-get-indentation)))) - (beginning-of-line 2)) - (goto-char (point-min)) - (while (not (eobp)) - (unless (looking-at "[ \t]*$") - (move-to-column ind) - (delete-region (point-at-bol) (point))) - (beginning-of-line 2)) - - (run-hooks 'org-agenda-entry-text-cleanup-hook) - - (goto-char (point-min)) - (when indent - (while (and (not (eobp)) (re-search-forward "^" nil t)) - (replace-match indent t t))) - (goto-char (point-min)) - (while (looking-at "[ \t]*\n") (replace-match "")) - (goto-char (point-max)) - (when (> (org-current-line) - n-lines) - (org-goto-line (1+ n-lines)) - (backward-char 1)) - (setq txt (buffer-substring (point-min) (point))))))))) + (org-with-wide-buffer + (goto-char marker) + (end-of-line 1) + (setq txt (buffer-substring + (min (1+ (point)) (point-max)) + (progn (outline-next-heading) (point))) + drawer-re org-drawer-regexp + kwd-time-re (concat "^[ \t]*" org-keyword-time-regexp + ".*\n?")) + (with-temp-buffer + (insert txt) + (when org-agenda-add-entry-text-descriptive-links + (goto-char (point-min)) + (while (org-activate-links (point-max)) + (add-text-properties (match-beginning 0) (match-end 0) + '(face org-link)))) + (goto-char (point-min)) + (while (re-search-forward org-bracket-link-regexp (point-max) t) + (set-text-properties (match-beginning 0) (match-end 0) + nil)) + (goto-char (point-min)) + (while (re-search-forward drawer-re nil t) + (delete-region + (match-beginning 0) + (progn (re-search-forward + "^[ \t]*:END:.*\n?" nil 'move) + (point)))) + (unless (member 'planning keep) + (goto-char (point-min)) + (while (re-search-forward kwd-time-re nil t) + (replace-match ""))) + (goto-char (point-min)) + (when org-agenda-entry-text-exclude-regexps + (let ((re-list org-agenda-entry-text-exclude-regexps) re) + (while (setq re (pop re-list)) + (goto-char (point-min)) + (while (re-search-forward re nil t) + (replace-match ""))))) + (goto-char (point-max)) + (skip-chars-backward " \t\n") + (if (looking-at "[ \t\n]+\\'") (replace-match "")) + + ;; find and remove min common indentation + (goto-char (point-min)) + (untabify (point-min) (point-max)) + (setq ind (org-get-indentation)) + (while (not (eobp)) + (unless (looking-at "[ \t]*$") + (setq ind (min ind (org-get-indentation)))) + (beginning-of-line 2)) + (goto-char (point-min)) + (while (not (eobp)) + (unless (looking-at "[ \t]*$") + (move-to-column ind) + (delete-region (point-at-bol) (point))) + (beginning-of-line 2)) + + (run-hooks 'org-agenda-entry-text-cleanup-hook) + + (goto-char (point-min)) + (when indent + (while (and (not (eobp)) (re-search-forward "^" nil t)) + (replace-match indent t t))) + (goto-char (point-min)) + (while (looking-at "[ \t]*\n") (replace-match "")) + (goto-char (point-max)) + (when (> (org-current-line) + n-lines) + (org-goto-line (1+ n-lines)) + (backward-char 1)) + (setq txt (buffer-substring (point-min) (point)))))))) txt)) (defun org-check-for-org-mode () "Make sure current buffer is in org-mode. Error if not." (or (derived-mode-p 'org-mode) - (error "Cannot execute org-mode agenda command on buffer in %s" + (error "Cannot execute Org agenda command on buffer in %s" major-mode))) ;;; Agenda prepare and finalize @@ -3531,6 +3545,7 @@ removed from the entry content. Currently only `planning' is allowed here." (defvar org-agenda-tag-filter nil) (defvar org-agenda-category-filter nil) (defvar org-agenda-regexp-filter nil) +(defvar org-agenda-effort-filter nil) (defvar org-agenda-top-headline-filter nil) (defvar org-agenda-tag-filter-preset nil "A preset of the tags filter used for secondary agenda filtering. @@ -3562,6 +3577,16 @@ the entire agenda view. In a block agenda, it will not work reliably to define a filter for one of the individual blocks. You need to set it in the global options and expect it to be applied to the entire view.") +(defvar org-agenda-effort-filter-preset nil + "A preset of the effort condition used for secondary agenda filtering. +This must be a list of strings, each string must be a single regexp +preceded by \"+\" or \"-\". +This variable should not be set directly, but agenda custom commands can +bind it in the options section. The preset filter is a global property of +the entire agenda view. In a block agenda, it will not work reliably to +define a filter for one of the individual blocks. You need to set it in +the global options and expect it to be applied to the entire view.") + (defun org-agenda-use-sticky-p () "Return non-nil if an agenda buffer named `org-agenda-buffer-name' exists and should be shown instead of @@ -3593,30 +3618,37 @@ FILTER-ALIST is an alist of filters we need to apply when ((equal (current-buffer) abuf) nil) (awin (select-window awin)) ((not (setq wconf (current-window-configuration)))) - ((equal org-agenda-window-setup 'current-window) - (org-pop-to-buffer-same-window abuf)) - ((equal org-agenda-window-setup 'other-window) + ((eq org-agenda-window-setup 'current-window) + (pop-to-buffer-same-window abuf)) + ((eq org-agenda-window-setup 'other-window) (org-switch-to-buffer-other-window abuf)) - ((equal org-agenda-window-setup 'other-frame) + ((eq org-agenda-window-setup 'other-frame) (switch-to-buffer-other-frame abuf)) - ((equal org-agenda-window-setup 'reorganize-frame) + ((eq org-agenda-window-setup 'only-window) + (delete-other-windows) + (pop-to-buffer-same-window abuf)) + ((eq org-agenda-window-setup 'reorganize-frame) (delete-other-windows) (org-switch-to-buffer-other-window abuf))) - (setq org-agenda-tag-filter (cdr (assoc 'tag filter-alist))) - (setq org-agenda-category-filter (cdr (assoc 'cat filter-alist))) - (setq org-agenda-regexp-filter (cdr (assoc 're filter-alist))) + (setq org-agenda-tag-filter (cdr (assq 'tag filter-alist))) + (setq org-agenda-category-filter (cdr (assq 'cat filter-alist))) + (setq org-agenda-effort-filter (cdr (assq 'effort filter-alist))) + (setq org-agenda-regexp-filter (cdr (assq 're filter-alist))) ;; Additional test in case agenda is invoked from within agenda ;; buffer via elisp link. (unless (equal (current-buffer) abuf) - (org-pop-to-buffer-same-window abuf)) + (pop-to-buffer-same-window abuf)) (setq org-agenda-pre-window-conf - (or org-agenda-pre-window-conf wconf)))) + (or wconf org-agenda-pre-window-conf)))) (defun org-agenda-prepare (&optional name) (let ((filter-alist (if org-agenda-persistent-filter - (list `(tag . ,org-agenda-tag-filter) - `(re . ,org-agenda-regexp-filter) - `(car . ,org-agenda-category-filter))))) + (with-current-buffer + (get-buffer-create org-agenda-buffer-name) + (list `(tag . ,org-agenda-tag-filter) + `(re . ,org-agenda-regexp-filter) + `(effort . ,org-agenda-effort-filter) + `(cat . ,org-agenda-category-filter)))))) (if (org-agenda-use-sticky-p) (progn (put 'org-agenda-tag-filter :preset-filter nil) @@ -3629,13 +3661,14 @@ FILTER-ALIST is an alist of filters we need to apply when (or org-agenda-multi (org-agenda-fit-window-to-buffer)) (throw 'exit "Sticky Agenda buffer, use `r' to refresh")) (setq org-todo-keywords-for-agenda nil) - (setq org-drawers-for-agenda nil) (put 'org-agenda-tag-filter :preset-filter org-agenda-tag-filter-preset) (put 'org-agenda-category-filter :preset-filter org-agenda-category-filter-preset) (put 'org-agenda-regexp-filter :preset-filter org-agenda-regexp-filter-preset) + (put 'org-agenda-effort-filter :preset-filter + org-agenda-effort-filter-preset) (if org-agenda-multi (progn (setq buffer-read-only nil) @@ -3649,7 +3682,6 @@ FILTER-ALIST is an alist of filters we need to apply when "\n")) (narrow-to-region (point) (point-max))) (setq org-done-keywords-for-agenda nil) - ;; Setting any org variables that are in org-agenda-local-vars ;; list need to be done after the prepare call (org-agenda-prepare-window @@ -3666,11 +3698,10 @@ FILTER-ALIST is an alist of filters we need to apply when (org-uniquify org-todo-keywords-for-agenda)) (setq org-done-keywords-for-agenda (org-uniquify org-done-keywords-for-agenda)) - (setq org-drawers-for-agenda (org-uniquify org-drawers-for-agenda)) (setq org-agenda-last-prefix-arg current-prefix-arg) (setq org-agenda-this-buffer-name org-agenda-buffer-name) (and name (not org-agenda-name) - (org-set-local 'org-agenda-name name))) + (setq-local org-agenda-name name))) (setq buffer-read-only nil)))) (defvar org-agenda-overriding-columns-format) ; From org-colview.el @@ -3681,11 +3712,7 @@ FILTER-ALIST is an alist of filters we need to apply when (let ((inhibit-read-only t)) (goto-char (point-min)) (save-excursion - (while (org-activate-bracket-links (point-max)) - (add-text-properties (match-beginning 0) (match-end 0) - '(face org-link)))) - (save-excursion - (while (org-activate-plain-links (point-max)) + (while (org-activate-links (point-max)) (add-text-properties (match-beginning 0) (match-end 0) '(face org-link)))) (unless (eq org-agenda-remove-tags t) @@ -3694,8 +3721,8 @@ FILTER-ALIST is an alist of filters we need to apply when (remove-text-properties (point-min) (point-max) '(face nil))) (if (and (boundp 'org-agenda-overriding-columns-format) org-agenda-overriding-columns-format) - (org-set-local 'org-agenda-overriding-columns-format - org-agenda-overriding-columns-format)) + (setq-local org-agenda-overriding-columns-format + org-agenda-overriding-columns-format)) (if (and (boundp 'org-agenda-view-columns-initially) org-agenda-view-columns-initially) (org-agenda-columns)) @@ -3733,10 +3760,10 @@ FILTER-ALIST is an alist of filters we need to apply when (org-agenda-filter-top-headline-apply org-agenda-top-headline-filter)) (when org-agenda-tag-filter - (org-agenda-filter-apply org-agenda-tag-filter 'tag)) + (org-agenda-filter-apply org-agenda-tag-filter 'tag t)) (when (get 'org-agenda-tag-filter :preset-filter) (org-agenda-filter-apply - (get 'org-agenda-tag-filter :preset-filter) 'tag)) + (get 'org-agenda-tag-filter :preset-filter) 'tag t)) (when org-agenda-category-filter (org-agenda-filter-apply org-agenda-category-filter 'category)) (when (get 'org-agenda-category-filter :preset-filter) @@ -3747,13 +3774,18 @@ FILTER-ALIST is an alist of filters we need to apply when (when (get 'org-agenda-regexp-filter :preset-filter) (org-agenda-filter-apply (get 'org-agenda-regexp-filter :preset-filter) 'regexp)) - (org-add-hook 'kill-buffer-hook 'org-agenda-reset-markers 'append 'local))))) + (when org-agenda-effort-filter + (org-agenda-filter-apply org-agenda-effort-filter 'effort)) + (when (get 'org-agenda-effort-filter :preset-filter) + (org-agenda-filter-apply + (get 'org-agenda-effort-filter :preset-filter) 'effort)) + (add-hook 'kill-buffer-hook 'org-agenda-reset-markers 'append 'local))))) (defun org-agenda-mark-clocking-task () "Mark the current clock entry in the agenda if it is present." ;; We need to widen when `org-agenda-finalize' is called from ;; `org-agenda-change-all-lines' (e.g. in `org-agenda-clock-in') - (when org-clock-current-task + (when (bound-and-true-p org-clock-current-task) (save-restriction (widen) (org-agenda-unmark-clocking-task) @@ -3782,7 +3814,7 @@ FILTER-ALIST is an alist of filters we need to apply when "Make highest priority lines bold, and lowest italic." (interactive) (mapc (lambda (o) (if (eq (overlay-get o 'org-type) 'org-priority) - (delete-overlay o))) + (delete-overlay o))) (overlays-in (point-min) (point-max))) (save-excursion (let (b e p ov h l) @@ -3800,16 +3832,17 @@ FILTER-ALIST is an alist of filters we need to apply when ov (make-overlay b e)) (overlay-put ov 'face - (cons (cond ((org-face-from-face-or-color - 'priority nil - (cdr (assoc p org-priority-faces)))) - ((and (listp org-agenda-fontify-priorities) - (org-face-from-face-or-color - 'priority nil - (cdr (assoc p org-agenda-fontify-priorities))))) - ((equal p l) 'italic) - ((equal p h) 'bold)) - 'org-priority)) + (let ((special-face + (cond ((org-face-from-face-or-color + 'priority 'org-priority + (cdr (assoc p org-priority-faces)))) + ((and (listp org-agenda-fontify-priorities) + (org-face-from-face-or-color + 'priority 'org-priority + (cdr (assoc p org-agenda-fontify-priorities))))) + ((equal p l) 'italic) + ((equal p h) 'bold)))) + (if special-face (list special-face 'org-priority) 'org-priority))) (overlay-put ov 'org-type 'org-priority))))) (defvar org-depend-tag-blocked) @@ -3819,39 +3852,39 @@ FILTER-ALIST is an alist of filters we need to apply when When INVISIBLE is non-nil, hide currently blocked TODO instead of dimming them." (interactive "P") - (when (org-called-interactively-p 'interactive) + (when (called-interactively-p 'interactive) (message "Dim or hide blocked tasks...")) - (mapc (lambda (o) (if (eq (overlay-get o 'org-type) 'org-blocked-todo) - (delete-overlay o))) - (overlays-in (point-min) (point-max))) + (dolist (o (overlays-in (point-min) (point-max))) + (when (eq (overlay-get o 'org-type) 'org-blocked-todo) + (delete-overlay o))) (save-excursion (let ((inhibit-read-only t) (org-depend-tag-blocked nil) - (invis (or (not (null invisible)) - (eq org-agenda-dim-blocked-tasks 'invisible))) - org-blocked-by-checkboxes - invis1 b e p ov h l) + org-blocked-by-checkboxes) (goto-char (point-min)) - (while (let ((pos (next-single-property-change (point) 'todo-state))) - (and pos (goto-char (1+ pos)))) - (setq org-blocked-by-checkboxes nil invis1 invis) + (while (let ((pos (text-property-not-all + (point) (point-max) 'todo-state nil))) + (when pos (goto-char pos))) + (setq org-blocked-by-checkboxes nil) (let ((marker (org-get-at-bol 'org-hd-marker))) - (when (and marker + (when (and (markerp marker) (with-current-buffer (marker-buffer marker) (save-excursion (goto-char marker) (org-entry-blocked-p)))) - (if org-blocked-by-checkboxes (setq invis1 nil)) - (setq b (if invis1 - (max (point-min) (1- (point-at-bol))) - (point-at-bol)) - e (point-at-eol) - ov (make-overlay b e)) - (if invis1 - (progn (overlay-put ov 'invisible t) - (overlay-put ov 'intangible t)) - (overlay-put ov 'face 'org-agenda-dimmed-todo-face)) - (overlay-put ov 'org-type 'org-blocked-todo)))))) - (when (org-called-interactively-p 'interactive) + ;; Entries blocked by checkboxes cannot be made invisible. + ;; See `org-agenda-dim-blocked-tasks' for details. + (let* ((really-invisible + (and (not org-blocked-by-checkboxes) + (or invisible (eq org-agenda-dim-blocked-tasks + 'invisible)))) + (ov (make-overlay (if really-invisible (line-end-position 0) + (line-beginning-position)) + (line-end-position)))) + (if really-invisible (overlay-put ov 'invisible t) + (overlay-put ov 'face 'org-agenda-dimmed-todo-face)) + (overlay-put ov 'org-type 'org-blocked-todo)))) + (forward-line)))) + (when (called-interactively-p 'interactive) (message "Dim or hide blocked tasks...done"))) (defvar org-agenda-skip-function nil @@ -3908,9 +3941,9 @@ functions do." (defun org-agenda-new-marker (&optional pos) "Return a new agenda marker. -Org-mode keeps a list of these markers and resets them when they are -no longer in use." - (let ((m (copy-marker (or pos (point))))) +Maker is at point, or at POS if non-nil. Org mode keeps a list of +these markers and resets them when they are no longer in use." + (let ((m (copy-marker (or pos (point)) t))) (setq org-agenda-last-marker-time (float-time)) (if org-agenda-buffer (with-current-buffer org-agenda-buffer @@ -3972,13 +4005,12 @@ This check for agenda markers in all agenda buffers currently active." (defun org-agenda-get-day-face (date) "Return the face DATE should be displayed with." - (or (and (functionp org-agenda-day-face-function) - (funcall org-agenda-day-face-function date)) - (cond ((org-agenda-todayp date) - 'org-agenda-date-today) - ((member (calendar-day-of-week date) org-agenda-weekend-days) - 'org-agenda-date-weekend) - (t 'org-agenda-date)))) + (cond ((and (functionp org-agenda-day-face-function) + (funcall org-agenda-day-face-function date))) + ((org-agenda-today-p date) 'org-agenda-date-today) + ((memq (calendar-day-of-week date) org-agenda-weekend-days) + 'org-agenda-date-weekend) + (t 'org-agenda-date))) ;;; Agenda timeline @@ -3986,12 +4018,16 @@ This check for agenda markers in all agenda buffers currently active." (defvar org-agenda-show-log-scoped) ;; dynamically scope in `org-timeline' or `org-agenda-list' (defun org-timeline (&optional dotodo) - "Show a time-sorted view of the entries in the current org file. -Only entries with a time stamp of today or later will be listed. With -\\[universal-argument] prefix, all unfinished TODO items will also be shown, + "Show a time-sorted view of the entries in the current Org file. + +Only entries with a time stamp of today or later will be listed. + +With `\\[universal-argument]' prefix, all unfinished TODO items will also be \ +shown, under the current date. -If the buffer contains an active region, only check the region for -dates." + +If the buffer contains an active region, only check the region +for dates." (interactive "P") (let* ((dopast t) (org-agenda-show-log-scoped org-agenda-show-log) @@ -4160,13 +4196,14 @@ items if they have an hour specification like [h]h:mm." (catch 'exit (setq org-agenda-buffer-name (or org-agenda-buffer-tmp-name + (and org-agenda-doing-sticky-redo org-agenda-buffer-name) (if org-agenda-sticky (cond ((and org-keys (stringp org-match)) (format "*Org Agenda(%s:%s)*" org-keys org-match)) (org-keys (format "*Org Agenda(%s)*" org-keys)) (t "*Org Agenda(a)*"))) - org-agenda-buffer-name)) + "*Org Agenda*")) (org-agenda-prepare "Day/Week") (setq start-day (or start-day org-agenda-start-day)) (if (stringp start-day) @@ -4174,8 +4211,7 @@ items if they have an hour specification like [h]h:mm." (setq start-day (time-to-days (org-read-date nil t start-day)))) (org-compile-prefix-format 'agenda) (org-set-sorting-strategy 'agenda) - (let* ((span (org-agenda-ndays-to-span - (or span org-agenda-ndays org-agenda-span))) + (let* ((span (org-agenda-ndays-to-span (or span org-agenda-span))) (today (org-today)) (sd (or start-day today)) (ndays (org-agenda-span-to-ndays span sd)) @@ -4205,9 +4241,9 @@ items if they have an hour specification like [h]h:mm." (setq day-numbers (nreverse day-numbers)) (setq clocktable-start (car day-numbers) clocktable-end (1+ (or (org-last day-numbers) 0))) - (org-set-local 'org-starting-day (car day-numbers)) - (org-set-local 'org-arg-loc arg) - (org-set-local 'org-agenda-current-span (org-agenda-ndays-to-span span)) + (setq-local org-starting-day (car day-numbers)) + (setq-local org-arg-loc arg) + (setq-local org-agenda-current-span (org-agenda-ndays-to-span span)) (unless org-agenda-compact-blocks (let* ((d1 (car day-numbers)) (d2 (org-last day-numbers)) @@ -4353,10 +4389,10 @@ START-DAY is an absolute time value." ((eq span 'fortnight) 14) ((eq span 'month) (let ((date (calendar-gregorian-from-absolute start-day))) - (calendar-last-day-of-month (car date) (caddr date)))) + (calendar-last-day-of-month (car date) (cl-caddr date)))) ((eq span 'year) (let ((date (calendar-gregorian-from-absolute start-day))) - (if (calendar-leap-year-p (caddr date)) 366 365))))) + (if (calendar-leap-year-p (cl-caddr date)) 366 365))))) (defun org-agenda-span-name (span) "Return a SPAN name." @@ -4371,7 +4407,7 @@ START-DAY is an absolute time value." (defvar org-agenda-search-history nil) (defvar org-search-syntax-table nil - "Special syntax table for org-mode search. + "Special syntax table for Org search. In this table, we have single quotes not as word constituents, to that when \"+Ameli\" is searched as a work, it will also match \"Ameli's\"") @@ -4444,7 +4480,7 @@ in `org-agenda-text-search-extra-files'." (full-words org-agenda-search-view-force-full-words) (org-agenda-text-search-extra-files org-agenda-text-search-extra-files) regexp rtn rtnall files file pos inherited-tags - marker category category-pos level tags c neg re boolean + marker category level tags c neg re boolean ee txt beg end words regexps+ regexps- hdl-only buffer beg1 str) (unless (and (not edit-at) (stringp string) @@ -4576,7 +4612,7 @@ in `org-agenda-text-search-extra-files'." (> (org-reduced-level (org-outline-level)) org-agenda-search-view-max-outline-level) (forward-line -1) - (outline-back-to-heading t))) + (org-back-to-heading t))) (skip-chars-forward "* ") (setq beg (point-at-bol) beg1 (point) @@ -4611,7 +4647,6 @@ in `org-agenda-text-search-extra-files'." (setq marker (org-agenda-new-marker (point)) category (org-get-category) level (make-string (org-reduced-level (org-outline-level)) ? ) - category-pos (get-text-property (point) 'org-category-position) inherited-tags (or (eq org-agenda-show-inherited-tags 'always) (and (listp org-agenda-show-inherited-tags) @@ -4630,8 +4665,7 @@ in `org-agenda-text-search-extra-files'." 'org-todo-regexp org-todo-regexp 'level level 'org-complex-heading-regexp org-complex-heading-regexp - 'priority 1000 'org-category category - 'org-category-position category-pos + 'priority 1000 'type "search") (push txt ee) (goto-char (1- end)))))))))) @@ -4648,8 +4682,12 @@ in `org-agenda-text-search-extra-files'." (add-text-properties pos (1- (point)) (list 'face 'org-warning)) (setq pos (point)) (unless org-agenda-multi - (insert (substitute-command-keys - "Press `[', `]' to add/sub word, `{', `}' to add/sub regexp, `C-u r' to edit\n")) + (insert (substitute-command-keys "\ +Press `\\[org-agenda-manipulate-query-add]', \ +`\\[org-agenda-manipulate-query-subtract]' to add/sub word, \ +`\\[org-agenda-manipulate-query-add-re]', \ +`\\[org-agenda-manipulate-query-subtract-re]' to add/sub regexp, \ +`\\[universal-argument] \\[org-agenda-redo]' to edit\n")) (add-text-properties pos (1- (point)) (list 'face 'org-agenda-structure)))) (org-agenda-mark-header-line (point-min)) @@ -4686,7 +4724,7 @@ in `org-agenda-text-search-extra-files'." (defun org-todo-list (&optional arg) "Show all (not done) TODO entries from all agenda file in a single list. The prefix arg can be used to select a specific TODO keyword and limit -the list to these. When using \\[universal-argument], you will be prompted +the list to these. When using `\\[universal-argument]', you will be prompted for a keyword. A numeric prefix directly selects the Nth keyword in `org-todo-keywords-1'." (interactive "P") @@ -4704,8 +4742,8 @@ for a keyword. A numeric prefix directly selects the Nth keyword in rtn rtnall files file pos) (when (equal arg '(4)) (setq org-select-this-todo-keyword - (org-icompleting-read "Keyword (or KWD1|K2D2|...): " - (mapcar 'list kwds) nil nil))) + (completing-read "Keyword (or KWD1|K2D2|...): " + (mapcar #'list kwds) nil nil))) (and (equal 0 arg) (setq org-select-this-todo-keyword nil)) (catch 'exit (if org-agenda-sticky @@ -4743,7 +4781,8 @@ for a keyword. A numeric prefix directly selects the Nth keyword in org-select-this-todo-keyword)) (setq pos (point)) (unless org-agenda-multi - (insert (substitute-command-keys "Available with `N r': (0)[ALL]")) + (insert (substitute-command-keys "Available with \ +`N \\[org-agenda-redo]': (0)[ALL]")) (let ((n 0) s) (mapc (lambda (x) (setq s (format "(%d)%s" (setq n (1+ n)) x)) @@ -4779,6 +4818,7 @@ The prefix arg TODO-ONLY limits the search to TODO entries." (let* ((org-tags-match-list-sublevels org-tags-match-list-sublevels) (completion-ignore-case t) + (org--matcher-tags-todo-only todo-only) rtn rtnall files file pos matcher buffer) (when (and (stringp match) (not (string-match "\\S-" match))) @@ -4794,13 +4834,15 @@ The prefix arg TODO-ONLY limits the search to TODO entries." ;; expanding tags within `org-make-tags-matcher' (org-agenda-prepare (concat "TAGS " match)) (setq matcher (org-make-tags-matcher match) - match (car matcher) matcher (cdr matcher)) + match (car matcher) + matcher (cdr matcher)) (org-compile-prefix-format 'tags) (org-set-sorting-strategy 'tags) (setq org-agenda-query-string match) (setq org-agenda-redo-command - (list 'org-tags-view `(quote ,todo-only) - (list 'if 'current-prefix-arg nil `(quote ,org-agenda-query-string)))) + (list 'org-tags-view + `(quote ,org--matcher-tags-todo-only) + `(if current-prefix-arg nil ,org-agenda-query-string))) (setq files (org-agenda-files nil 'ifmode) rtnall nil) (while (setq file (pop files)) @@ -4823,7 +4865,9 @@ The prefix arg TODO-ONLY limits the search to TODO entries." (narrow-to-region org-agenda-restrict-begin org-agenda-restrict-end) (widen)) - (setq rtn (org-scan-tags 'agenda matcher todo-only)) + (setq rtn (org-scan-tags 'agenda + matcher + org--matcher-tags-todo-only)) (setq rtnall (append rtnall rtn)))))))) (if org-agenda-overriding-header (insert (org-add-props (copy-sequence org-agenda-overriding-header) @@ -4839,18 +4883,21 @@ The prefix arg TODO-ONLY limits the search to TODO entries." (setq pos (point)) (unless org-agenda-multi (insert (substitute-command-keys - "Press `C-u r' to search again with new search string\n"))) - (add-text-properties pos (1- (point)) (list 'face 'org-agenda-structure))) + "Press `\\[universal-argument] \\[org-agenda-redo]' \ +to search again with new search string\n"))) + (add-text-properties pos (1- (point)) + (list 'face 'org-agenda-structure))) (org-agenda-mark-header-line (point-min)) (when rtnall (insert (org-agenda-finalize-entries rtnall 'tags) "\n")) (goto-char (point-min)) (or org-agenda-multi (org-agenda-fit-window-to-buffer)) - (add-text-properties (point-min) (point-max) - `(org-agenda-type tags - org-last-args (,todo-only ,match) - org-redo-cmd ,org-agenda-redo-command - org-series-cmd ,org-cmd)) + (add-text-properties + (point-min) (point-max) + `(org-agenda-type tags + org-last-args (,org--matcher-tags-todo-only ,match) + org-redo-cmd ,org-agenda-redo-command + org-series-cmd ,org-cmd)) (org-agenda-finalize) (setq buffer-read-only t)))) @@ -5038,50 +5085,53 @@ Stuck projects are project that have no next actions. For the definitions of what a project is and how to check if it stuck, customize the variable `org-stuck-projects'." (interactive) - (let* ((org-agenda-skip-function - 'org-agenda-skip-entry-when-regexp-matches-in-subtree) - ;; We could have used org-agenda-skip-if here. - (org-agenda-overriding-header + (let* ((org-agenda-overriding-header (or org-agenda-overriding-header "List of stuck projects: ")) (matcher (nth 0 org-stuck-projects)) (todo (nth 1 org-stuck-projects)) - (todo-wds (if (member "*" todo) - (progn - (org-agenda-prepare-buffers (org-agenda-files - nil 'ifmode)) - (org-delete-all - org-done-keywords-for-agenda - (copy-sequence org-todo-keywords-for-agenda))) - todo)) - (todo-re (concat "^\\*+[ \t]+\\(" - (mapconcat 'identity todo-wds "\\|") - "\\)\\>")) (tags (nth 2 org-stuck-projects)) - (tags-re (if (member "*" tags) - (concat org-outline-regexp-bol - (org-re ".*:[[:alnum:]_@#%]+:[ \t]*$")) - (if tags - (concat org-outline-regexp-bol - ".*:\\(" - (mapconcat 'identity tags "\\|") - (org-re "\\):[[:alnum:]_@#%:]*[ \t]*$"))))) - (gen-re (nth 3 org-stuck-projects)) - (re-list - (delq nil - (list - (if todo todo-re) - (if tags tags-re) - (and gen-re (stringp gen-re) (string-match "\\S-" gen-re) - gen-re))))) - (setq org-agenda-skip-regexp - (if re-list - (mapconcat 'identity re-list "\\|") - (error "No information how to identify unstuck projects"))) + (gen-re (org-string-nw-p (nth 3 org-stuck-projects))) + (todo-wds + (if (not (member "*" todo)) todo + (org-agenda-prepare-buffers (org-agenda-files nil 'ifmode)) + (org-delete-all org-done-keywords-for-agenda + (copy-sequence org-todo-keywords-for-agenda)))) + (todo-re (and todo + (format "^\\*+[ \t]+\\(%s\\)\\>" + (mapconcat #'identity todo-wds "\\|")))) + (tags-re (cond ((null tags) nil) + ((member "*" tags) + (eval-when-compile + (concat org-outline-regexp-bol + ".*:[[:alnum:]_@#%]+:[ \t]*$"))) + (tags (concat org-outline-regexp-bol + ".*:\\(" + (mapconcat #'identity tags "\\|") + "\\):[[:alnum:]_@#%:]*[ \t]*$")) + (t nil))) + (re-list (delq nil (list todo-re tags-re gen-re))) + (skip-re + (if (null re-list) + (error "Missing information to identify unstuck projects") + (mapconcat #'identity re-list "\\|"))) + (org-agenda-skip-function + ;; Skip entry if `org-agenda-skip-regexp' matches anywhere + ;; in the subtree. + `(lambda () + (and (save-excursion + (let ((case-fold-search nil)) + (re-search-forward + ,skip-re (save-excursion (org-end-of-subtree t)) t))) + (progn (outline-next-heading) (point)))))) (org-tags-view nil matcher) (setq org-agenda-buffer-name (buffer-name)) (with-current-buffer org-agenda-buffer-name (setq org-agenda-redo-command - `(org-agenda-list-stuck-projects ,current-prefix-arg))))) + `(org-agenda-list-stuck-projects ,current-prefix-arg)) + (let ((inhibit-read-only t)) + (add-text-properties + (point-min) (point-max) + `(org-redo-cmd ,org-agenda-redo-command)))))) ;;; Diary integration @@ -5159,7 +5209,7 @@ date. It also removes lines that contain only whitespace." (while (re-search-forward "^ +\n" nil t) (replace-match "")) (goto-char (point-min)) - (if (re-search-forward "^Org-mode dummy\n?" nil t) + (if (re-search-forward "^Org mode dummy\n?" nil t) (replace-match "")) (run-hooks 'org-agenda-cleanup-fancy-diary-hook)) @@ -5177,7 +5227,7 @@ date. It also removes lines that contain only whitespace." (setq string (org-modify-diary-entry-string string)))))) (defun org-modify-diary-entry-string (string) - "Add text properties to string, allowing org-mode to act on it." + "Add text properties to string, allowing Org to act on it." (org-add-props string nil 'mouse-face 'highlight 'help-echo (if buffer-file-name @@ -5193,9 +5243,9 @@ Needed to avoid empty dates which mess up holiday display." ;; Catch the error if dealing with the new add-to-diary-alist (when org-disable-agenda-to-diary (condition-case nil - (org-add-to-diary-list original-date "Org-mode dummy" "") + (org-add-to-diary-list original-date "Org mode dummy" "") (error - (org-add-to-diary-list original-date "Org-mode dummy" "" nil))))) + (org-add-to-diary-list original-date "Org mode dummy" "" nil))))) (defun org-add-to-diary-list (&rest args) (if (fboundp 'diary-add-to-list) @@ -5265,67 +5315,77 @@ function from a program - use `org-agenda-get-day-entries' instead." ;;; Agenda entry finders +(defun org-agenda--timestamp-to-absolute (&rest args) + "Call `org-time-string-to-absolute' with ARGS. +However, throw `:skip' whenever an error is raised." + (condition-case e + (apply #'org-time-string-to-absolute args) + (org-diary-sexp-no-match (throw :skip nil)) + (error + (message "%s; Skipping entry" (error-message-string e)) + (throw :skip nil)))) + (defun org-agenda-get-day-entries (file date &rest args) "Does the work for `org-diary' and `org-agenda'. FILE is the path to a file to be checked for entries. DATE is date like the one returned by `calendar-current-date'. ARGS are symbols indicating which kind of entries should be extracted. For details about these, see the documentation of `org-diary'." - (setq args (or args org-agenda-entry-types)) (let* ((org-startup-folded nil) (org-startup-align-all-tables nil) - (buffer (if (file-exists-p file) - (org-get-agenda-file-buffer file) - (error "No such file %s" file))) - arg results rtn deadline-results) + (buffer (if (file-exists-p file) (org-get-agenda-file-buffer file) + (error "No such file %s" file)))) (if (not buffer) - ;; If file does not exist, make sure an error message ends up in diary + ;; If file does not exist, signal it in diary nonetheless. (list (format "ORG-AGENDA-ERROR: No such org-file %s" file)) (with-current-buffer buffer (unless (derived-mode-p 'org-mode) (error "Agenda file %s is not in `org-mode'" file)) (setq org-agenda-buffer (or org-agenda-buffer buffer)) - (let ((case-fold-search nil)) - (save-excursion - (save-restriction - (if (eq buffer org-agenda-restrict) - (narrow-to-region org-agenda-restrict-begin - org-agenda-restrict-end) - (widen)) - ;; The way we repeatedly append to `results' makes it O(n^2) :-( - (while (setq arg (pop args)) - (cond - ((and (eq arg :todo) - (equal date (calendar-gregorian-from-absolute - (org-today)))) - (setq rtn (org-agenda-get-todos)) - (setq results (append results rtn))) - ((eq arg :timestamp) - (setq rtn (org-agenda-get-blocks)) - (setq results (append results rtn)) - (setq rtn (org-agenda-get-timestamps deadline-results)) - (setq results (append results rtn))) - ((eq arg :sexp) - (setq rtn (org-agenda-get-sexps)) - (setq results (append results rtn))) - ((eq arg :scheduled) - (setq rtn (org-agenda-get-scheduled deadline-results)) - (setq results (append results rtn))) - ((eq arg :scheduled*) - (setq rtn (org-agenda-get-scheduled deadline-results t)) - (setq results (append results rtn))) - ((eq arg :closed) - (setq rtn (org-agenda-get-progress)) - (setq results (append results rtn))) - ((eq arg :deadline) - (setq rtn (org-agenda-get-deadlines)) - (setq deadline-results (copy-sequence rtn)) - (setq results (append results rtn))) - ((eq arg :deadline*) - (setq rtn (org-agenda-get-deadlines t)) - (setq deadline-results (copy-sequence rtn)) - (setq results (append results rtn)))))))) - results)))) + (setf org-agenda-current-date date) + (save-excursion + (save-restriction + (if (eq buffer org-agenda-restrict) + (narrow-to-region org-agenda-restrict-begin + org-agenda-restrict-end) + (widen)) + ;; Rationalize ARGS. Also make sure `:deadline' comes + ;; first in order to populate DEADLINES before passing it. + ;; + ;; We use `delq' since `org-uniquify' duplicates ARGS, + ;; guarding us from modifying `org-agenda-entry-types'. + (setf args (org-uniquify (or args org-agenda-entry-types))) + (when (and (memq :scheduled args) (memq :scheduled* args)) + (setf args (delq :scheduled* args))) + (cond + ((memq :deadline args) + (setf args (cons :deadline + (delq :deadline (delq :deadline* args))))) + ((memq :deadline* args) + (setf args (cons :deadline* (delq :deadline* args))))) + ;; Collect list of headlines. Return them flattened. + (let ((case-fold-search nil) results deadlines) + (dolist (arg args (apply #'nconc (nreverse results))) + (pcase arg + ((and :todo (guard (org-agenda-today-p date))) + (push (org-agenda-get-todos) results)) + (:timestamp + (push (org-agenda-get-blocks) results) + (push (org-agenda-get-timestamps deadlines) results)) + (:sexp + (push (org-agenda-get-sexps) results)) + (:scheduled + (push (org-agenda-get-scheduled deadlines) results)) + (:scheduled* + (push (org-agenda-get-scheduled deadlines t) results)) + (:closed + (push (org-agenda-get-progress) results)) + (:deadline + (setf deadlines (org-agenda-get-deadlines)) + (push deadlines results)) + (:deadline* + (setf deadlines (org-agenda-get-deadlines t)) + (push deadlines results))))))))))) (defsubst org-em (x y list) "Is X or Y a member of LIST?" @@ -5334,6 +5394,40 @@ the documentation of `org-diary'." (defvar org-heading-keyword-regexp-format) ; defined in org.el (defvar org-agenda-sorting-strategy-selected nil) +(defun org-agenda-entry-get-agenda-timestamp (pom) + "Retrieve timestamp information for sorting agenda views. +Given a point or marker POM, returns a cons cell of the timestamp +and the timestamp type relevant for the sorting strategy in +`org-agenda-sorting-strategy-selected'." + (let (ts ts-date-type) + (save-match-data + (cond ((org-em 'scheduled-up 'scheduled-down + org-agenda-sorting-strategy-selected) + (setq ts (org-entry-get pom "SCHEDULED") + ts-date-type " scheduled")) + ((org-em 'deadline-up 'deadline-down + org-agenda-sorting-strategy-selected) + (setq ts (org-entry-get pom "DEADLINE") + ts-date-type " deadline")) + ((org-em 'ts-up 'ts-down + org-agenda-sorting-strategy-selected) + (setq ts (org-entry-get pom "TIMESTAMP") + ts-date-type " timestamp")) + ((org-em 'tsia-up 'tsia-down + org-agenda-sorting-strategy-selected) + (setq ts (org-entry-get pom "TIMESTAMP_IA") + ts-date-type " timestamp_ia")) + ((org-em 'timestamp-up 'timestamp-down + org-agenda-sorting-strategy-selected) + (setq ts (or (org-entry-get pom "SCHEDULED") + (org-entry-get pom "DEADLINE") + (org-entry-get pom "TIMESTAMP") + (org-entry-get pom "TIMESTAMP_IA")) + ts-date-type "")) + (t (setq ts-date-type ""))) + (cons (when ts (ignore-errors (org-time-string-to-absolute ts))) + ts-date-type)))) + (defun org-agenda-get-todos () "Return the TODO information for agenda display." (let* ((props (list 'face nil @@ -5345,6 +5439,7 @@ the documentation of `org-diary'." 'help-echo (format "mouse-2 or RET jump to org file %s" (abbreviate-file-name buffer-file-name)))) + (case-fold-search nil) (regexp (format org-heading-keyword-regexp-format (cond ((and org-select-this-todo-keyword @@ -5358,7 +5453,8 @@ the documentation of `org-diary'." "|") "\\|") "\\)")) (t org-not-done-regexp)))) - marker priority category category-pos level tags todo-state ts-date ts-date-type + marker priority category level tags todo-state + ts-date ts-date-type ts-date-pair ee txt beg end inherited-tags todo-state-end-pos) (goto-char (point-min)) (while (re-search-forward regexp nil t) @@ -5378,36 +5474,10 @@ the documentation of `org-diary'." (goto-char (match-beginning 2)) (setq marker (org-agenda-new-marker (match-beginning 0)) category (org-get-category) - ts-date (let (ts) - (save-match-data - (cond ((org-em 'scheduled-up 'scheduled-down - org-agenda-sorting-strategy-selected) - (setq ts (org-entry-get (point) "SCHEDULED") - ts-date-type " scheduled")) - ((org-em 'deadline-up 'deadline-down - org-agenda-sorting-strategy-selected) - (setq ts (org-entry-get (point) "DEADLINE") - ts-date-type " deadline")) - ((org-em 'ts-up 'ts-down - org-agenda-sorting-strategy-selected) - (setq ts (org-entry-get (point) "TIMESTAMP") - ts-date-type " timestamp")) - ((org-em 'tsia-up 'tsia-down - org-agenda-sorting-strategy-selected) - (setq ts (org-entry-get (point) "TIMESTAMP_IA") - ts-date-type " timestamp_ia")) - ((org-em 'timestamp-up 'timestamp-down - org-agenda-sorting-strategy-selected) - (setq ts (or (org-entry-get (point) "SCHEDULED") - (org-entry-get (point) "DEADLINE") - (org-entry-get (point) "TIMESTAMP") - (org-entry-get (point) "TIMESTAMP_IA")) - ts-date-type "")) - (t (setq ts-date-type ""))) - (when ts (ignore-errors (org-time-string-to-absolute ts))))) - category-pos (get-text-property (point) 'org-category-position) - txt (org-trim - (buffer-substring (match-beginning 2) (match-end 0))) + ts-date-pair (org-agenda-entry-get-agenda-timestamp (point)) + ts-date (car ts-date-pair) + ts-date-type (cdr ts-date-pair) + txt (org-trim (buffer-substring (match-beginning 2) (match-end 0))) inherited-tags (or (eq org-agenda-show-inherited-tags 'always) (and (listp org-agenda-show-inherited-tags) @@ -5421,10 +5491,9 @@ the documentation of `org-diary'." priority (1+ (org-get-priority txt))) (org-add-props txt props 'org-marker marker 'org-hd-marker marker - 'priority priority 'org-category category + 'priority priority 'level level 'ts-date ts-date - 'org-category-position category-pos 'type (concat "todo" ts-date-type) 'todo-state todo-state) (push txt ee) (if org-agenda-todo-list-sublevels @@ -5473,7 +5542,7 @@ This function is invoked if `org-agenda-todo-ignore-deadlines', (cond ((memq org-agenda-todo-ignore-deadlines '(t all)) t) ((eq org-agenda-todo-ignore-deadlines 'far) - (not (org-deadline-close (match-string 1)))) + (not (org-deadline-close-p (match-string 1)))) ((eq org-agenda-todo-ignore-deadlines 'future) (> (org-time-stamp-to-now (match-string 1) org-agenda-todo-ignore-time-comparison-use-seconds) 0)) @@ -5483,7 +5552,7 @@ This function is invoked if `org-agenda-todo-ignore-deadlines', ((numberp org-agenda-todo-ignore-deadlines) (org-agenda-todo-custom-ignore-p (match-string 1) org-agenda-todo-ignore-deadlines)) - (t (org-deadline-close (match-string 1))))) + (t (org-deadline-close-p (match-string 1))))) (and org-agenda-todo-ignore-timestamp (let ((buffer (current-buffer)) (regexp @@ -5512,24 +5581,27 @@ This function is invoked if `org-agenda-todo-ignore-deadlines', (match-string 1) org-agenda-todo-ignore-timestamp)) (t)))))))))) -(defun org-agenda-get-timestamps (&optional deadline-results) - "Return the date stamp information for agenda display." +(defun org-agenda-get-timestamps (&optional deadlines) + "Return the date stamp information for agenda display. +Optional argument DEADLINES is a list of deadline items to be +displayed in agenda view." (let* ((props (list 'face 'org-agenda-calendar-event 'org-not-done-regexp org-not-done-regexp 'org-todo-regexp org-todo-regexp 'org-complex-heading-regexp org-complex-heading-regexp 'mouse-face 'highlight 'help-echo - (format "mouse-2 or RET jump to org file %s" + (format "mouse-2 or RET jump to Org file %s" (abbreviate-file-name buffer-file-name)))) - (d1 (calendar-absolute-from-gregorian date)) - mm + (current (calendar-absolute-from-gregorian date)) + (today (org-today)) (deadline-position-alist - (mapcar (lambda (a) (and (setq mm (get-text-property - 0 'org-hd-marker a)) - (cons (marker-position mm) a))) - deadline-results)) - (remove-re org-ts-regexp) + (mapcar (lambda (d) + (let ((m (get-text-property 0 'org-hd-marker d))) + (and m (marker-position m)))) + deadlines)) + ;; Match time-stamps set to current date, time-stamps with + ;; a repeater, and S-exp time-stamps. (regexp (concat (if org-agenda-include-inactive-timestamps "[[<]" "<") @@ -5537,97 +5609,106 @@ This function is invoked if `org-agenda-todo-ignore-deadlines', (substring (format-time-string (car org-time-stamp-formats) - (apply 'encode-time ; DATE bound by calendar + (apply #'encode-time ; DATE bound by calendar (list 0 0 0 (nth 1 date) (car date) (nth 2 date)))) 1 11)) "\\|\\(<[0-9]+-[0-9]+-[0-9]+[^>\n]+?\\+[0-9]+[hdwmy]>\\)" "\\|\\(<%%\\(([^>\n]+)\\)>\\)")) - marker hdmarker deadlinep scheduledp clockp closedp inactivep - donep tmp priority category category-pos level ee txt timestr tags - b0 b3 e3 head todo-state end-of-match show-all warntime habitp - inherited-tags ts-date) + timestamp-items) (goto-char (point-min)) - (while (setq end-of-match (re-search-forward regexp nil t)) - (setq b0 (match-beginning 0) - b3 (match-beginning 3) e3 (match-end 3) - todo-state (save-match-data (ignore-errors (org-get-todo-state))) - habitp (and (functionp 'org-is-habit-p) (save-match-data (org-is-habit-p))) - show-all (or (eq org-agenda-repeating-timestamp-show-all t) - (member todo-state - org-agenda-repeating-timestamp-show-all))) + (while (re-search-forward regexp nil t) + ;; Skip date ranges, scheduled and deadlines, which are handled + ;; specially. Also skip time-stamps before first headline as + ;; there would be no entry to add to the agenda. Eventually, + ;; ignore clock entries. (catch :skip - (and (org-at-date-range-p) (throw :skip nil)) - (org-agenda-skip) - (if (and (match-end 1) - (not (= d1 (org-time-string-to-absolute - (match-string 1) d1 nil show-all - (current-buffer) b0)))) - (throw :skip nil)) - (if (and e3 - (not (org-diary-sexp-entry (buffer-substring b3 e3) "" date))) + (save-match-data + (when (or (org-at-date-range-p) + (org-at-planning-p) + (org-before-first-heading-p) + (and org-agenda-include-inactive-timestamps + (org-at-clock-log-p))) (throw :skip nil)) - (setq tmp (buffer-substring (max (point-min) - (- b0 org-ds-keyword-length)) - b0) - timestr (if b3 "" (buffer-substring b0 (point-at-eol))) - inactivep (= (char-after b0) ?\[) - deadlinep (string-match org-deadline-regexp tmp) - scheduledp (string-match org-scheduled-regexp tmp) - closedp (and org-agenda-include-inactive-timestamps - (string-match org-closed-string tmp)) - clockp (and org-agenda-include-inactive-timestamps - (or (string-match org-clock-string tmp) - (string-match "]-+\\'" tmp))) - warntime (get-text-property (point) 'org-appt-warntime) - donep (member todo-state org-done-keywords)) - (if (or scheduledp deadlinep closedp clockp - (and donep org-agenda-skip-timestamp-if-done)) + (org-agenda-skip)) + (let* ((pos (match-beginning 0)) + (repeat (match-string 1)) + (sexp-entry (match-string 3)) + (time-stamp (if (or repeat sexp-entry) (match-string 0) + (save-excursion + (goto-char pos) + (looking-at org-ts-regexp-both) + (match-string 0)))) + (todo-state (org-get-todo-state)) + (show-all (or (eq org-agenda-repeating-timestamp-show-all t) + (member todo-state + org-agenda-repeating-timestamp-show-all))) + (warntime (get-text-property (point) 'org-appt-warntime)) + (done? (member todo-state org-done-keywords))) + ;; Possibly skip done tasks. + (when (and done? org-agenda-skip-timestamp-if-done) (throw :skip t)) - (if (string-match ">" timestr) - ;; substring should only run to end of time stamp - (setq timestr (substring timestr 0 (match-end 0)))) - (setq marker (org-agenda-new-marker b0) - category (org-get-category b0) - category-pos (get-text-property b0 'org-category-position)) - (save-excursion - (if (not (re-search-backward org-outline-regexp-bol nil t)) - (throw :skip nil) - (goto-char (match-beginning 0)) - (if (and (eq t org-agenda-skip-timestamp-if-deadline-is-shown) - (assoc (point) deadline-position-alist)) - (throw :skip nil)) - (setq hdmarker (org-agenda-new-marker) - inherited-tags - (or (eq org-agenda-show-inherited-tags 'always) - (and (listp org-agenda-show-inherited-tags) - (memq 'agenda org-agenda-show-inherited-tags)) - (and (eq org-agenda-show-inherited-tags t) - (or (eq org-agenda-use-tag-inheritance t) - (memq 'agenda org-agenda-use-tag-inheritance)))) - tags (org-get-tags-at nil (not inherited-tags)) - level (make-string (org-reduced-level (org-outline-level)) ? )) - (looking-at "\\*+[ \t]+\\([^\r\n]+\\)") - (setq head (or (match-string 1) "")) - (setq txt (org-agenda-format-item - (if inactivep org-agenda-inactive-leader nil) - head level category tags timestr - remove-re habitp))) - (setq priority (org-get-priority txt)) - (org-add-props txt props 'priority priority - 'org-marker marker 'org-hd-marker hdmarker - 'org-category category 'date date - 'level level - 'ts-date - (ignore-errors (org-time-string-to-absolute timestr)) - 'org-category-position category-pos - 'todo-state todo-state - 'warntime warntime - 'type "timestamp") - (push txt ee)) - (if org-agenda-skip-additional-timestamps-same-entry - (outline-next-heading) - (goto-char end-of-match)))) - (nreverse ee))) + ;; S-exp entry doesn't match current day: skip it. + (when (and sexp-entry (not (org-diary-sexp-entry sexp-entry "" date))) + (throw :skip nil)) + ;; When time-stamp doesn't match CURRENT but has a repeater, + ;; make sure it repeats on CURRENT. Furthermore, if + ;; SHOW-ALL is nil, ensure that repeats are only the first + ;; before and the first after today. + (when (and repeat + (if show-all + (/= current + (org-agenda--timestamp-to-absolute + repeat current 'future (current-buffer) pos)) + (and (/= current + (org-agenda--timestamp-to-absolute + repeat today 'past (current-buffer) pos)) + (/= current + (org-agenda--timestamp-to-absolute + repeat today 'future (current-buffer) pos))))) + (throw :skip nil)) + (save-excursion + (re-search-backward org-outline-regexp-bol nil t) + ;; Possibly skip time-stamp when a deadline is set. + (when (and org-agenda-skip-timestamp-if-deadline-is-shown + (assq (point) deadline-position-alist)) + (throw :skip nil)) + (let* ((category (org-get-category pos)) + (inherited-tags + (or (eq org-agenda-show-inherited-tags 'always) + (and (consp org-agenda-show-inherited-tags) + (memq 'agenda org-agenda-show-inherited-tags)) + (and (eq org-agenda-show-inherited-tags t) + (or (eq org-agenda-use-tag-inheritance t) + (memq 'agenda + org-agenda-use-tag-inheritance))))) + (tags (org-get-tags-at nil (not inherited-tags))) + (level (make-string (org-reduced-level (org-outline-level)) + ?\s)) + (head (and (looking-at "\\*+[ \t]+\\(.*\\)") + (match-string 1))) + (inactive? (= (char-after pos) ?\[)) + (habit? (and (fboundp 'org-is-habit-p) (org-is-habit-p))) + (item + (org-agenda-format-item + (and inactive? org-agenda-inactive-leader) + head level category tags time-stamp org-ts-regexp habit?))) + (org-add-props item props + 'priority (if habit? + (org-habit-get-priority (org-habit-parse-todo)) + (org-get-priority item)) + 'org-marker (org-agenda-new-marker pos) + 'org-hd-marker (org-agenda-new-marker) + 'date date + 'level level + 'ts-date (if repeat (org-agenda--timestamp-to-absolute repeat) + current) + 'todo-state todo-state + 'warntime warntime + 'type "timestamp") + (push item timestamp-items)))) + (when org-agenda-skip-additional-timestamps-same-entry + (outline-next-heading)))) + (nreverse timestamp-items))) (defun org-agenda-get-sexps () "Return the sexp information for agenda display." @@ -5638,7 +5719,7 @@ This function is invoked if `org-agenda-todo-ignore-deadlines', (format "mouse-2 or RET jump to org file %s" (abbreviate-file-name buffer-file-name)))) (regexp "^&?%%(") - marker category extra category-pos level ee txt tags entry + marker category extra level ee txt tags entry result beg b sexp sexp-entry todo-state warntime inherited-tags) (goto-char (point-min)) (while (re-search-forward regexp nil t) @@ -5657,7 +5738,6 @@ This function is invoked if `org-agenda-todo-ignore-deadlines', (setq marker (org-agenda-new-marker beg) level (make-string (org-reduced-level (org-outline-level)) ? ) category (org-get-category beg) - category-pos (get-text-property beg 'org-category-position) inherited-tags (or (eq org-agenda-show-inherited-tags 'always) (and (listp org-agenda-show-inherited-tags) @@ -5682,38 +5762,33 @@ This function is invoked if `org-agenda-todo-ignore-deadlines', (setq txt "SEXP entry returned empty string")) (setq txt (org-agenda-format-item extra txt level category tags 'time)) (org-add-props txt props 'org-marker marker - 'org-category category 'date date 'todo-state todo-state - 'org-category-position category-pos - 'level level - 'type "sexp" 'warntime warntime) + 'date date 'todo-state todo-state + 'level level 'type "sexp" 'warntime warntime) (push txt ee))))) (nreverse ee))) ;; Calendar sanity: define some functions that are independent of ;; `calendar-date-style'. -;; Normally I would like to use ISO format when calling the diary functions, -;; but to make sure we still have Emacs 22 compatibility we bind -;; also `european-calendar-style' and use european format (defun org-anniversary (year month day &optional mark) "Like `diary-anniversary', but with fixed (ISO) order of arguments." - (org-no-warnings - (let ((calendar-date-style 'european) (european-calendar-style t)) - (diary-anniversary day month year mark)))) + (with-no-warnings + (let ((calendar-date-style 'iso)) + (diary-anniversary year month day mark)))) (defun org-cyclic (N year month day &optional mark) "Like `diary-cyclic', but with fixed (ISO) order of arguments." - (org-no-warnings - (let ((calendar-date-style 'european) (european-calendar-style t)) - (diary-cyclic N day month year mark)))) + (with-no-warnings + (let ((calendar-date-style 'iso)) + (diary-cyclic N year month day mark)))) (defun org-block (Y1 M1 D1 Y2 M2 D2 &optional mark) "Like `diary-block', but with fixed (ISO) order of arguments." - (org-no-warnings - (let ((calendar-date-style 'european) (european-calendar-style t)) - (diary-block D1 M1 Y1 D2 M2 Y2 mark)))) + (with-no-warnings + (let ((calendar-date-style 'iso)) + (diary-block Y1 M1 D1 Y2 M2 D2 mark)))) (defun org-date (year month day &optional mark) "Like `diary-date', but with fixed (ISO) order of arguments." - (org-no-warnings - (let ((calendar-date-style 'european) (european-calendar-style t)) - (diary-date day month year mark)))) + (with-no-warnings + (let ((calendar-date-style 'iso)) + (diary-date year month day mark)))) ;; Define the `org-class' function (defun org-class (y1 m1 d1 y2 m2 d2 dayname &rest skip-weeks) @@ -5740,26 +5815,6 @@ then those holidays will be skipped." (delq nil (mapcar (lambda(g) (member g skip-weeks)) h)))) entry))) -(defun org-diary-class (m1 d1 y1 m2 d2 y2 dayname &rest skip-weeks) - "Like `org-class', but honor `calendar-date-style'. -The order of the first 2 times 3 arguments depends on the variable -`calendar-date-style' or, if that is not defined, on `european-calendar-style'. -So for American calendars, give this as MONTH DAY YEAR, for European as -DAY MONTH YEAR, and for ISO as YEAR MONTH DAY. -DAYNAME is a number between 0 (Sunday) and 6 (Saturday). SKIP-WEEKS -is any number of ISO weeks in the block period for which the item should -be skipped. - -This function is here only for backward compatibility and it is deprecated, -please use `org-class' instead." - (let* ((date1 (org-order-calendar-date-args m1 d1 y1)) - (date2 (org-order-calendar-date-args m2 d2 y2))) - (org-class - (nth 2 date1) (car date1) (nth 1 date1) - (nth 2 date2) (car date2) (nth 1 date2) - dayname skip-weeks))) -(make-obsolete 'org-diary-class 'org-class "") - (defalias 'org-get-closed 'org-agenda-get-progress) (defun org-agenda-get-progress () "Return the logged TODO entries for agenda display." @@ -5794,7 +5849,7 @@ please use `org-class' instead." (list 0 0 0 (nth 1 date) (car date) (nth 2 date)))) 1 11)))) (org-agenda-search-headline-for-time nil) - marker hdmarker priority category category-pos level tags closedp + marker hdmarker priority category level tags closedp statep clockp state ee txt extra timestr rest clocked inherited-tags) (goto-char (point-min)) (while (re-search-forward regexp nil t) @@ -5806,7 +5861,6 @@ please use `org-class' instead." clockp (not (or closedp statep)) state (and statep (match-string 2)) category (org-get-category (match-beginning 0)) - category-pos (get-text-property (match-beginning 0) 'org-category-position) timestr (buffer-substring (match-beginning 0) (point-at-eol))) (when (string-match "\\]" timestr) ;; substring should only run to end of time stamp @@ -5858,9 +5912,7 @@ please use `org-class' instead." (setq priority 100000) (org-add-props txt props 'org-marker marker 'org-hd-marker hdmarker 'face 'org-agenda-done - 'priority priority 'org-category category - 'org-category-position category-pos - 'level level + 'priority priority 'level level 'type "closed" 'date date 'undone-face 'org-warning 'done-face 'org-agenda-done) (push txt ee)) @@ -5876,7 +5928,7 @@ See also the user option `org-agenda-clock-consistency-checks'." (re (concat "^[ \t]*" org-clock-string "[ \t]+" - "\\(\\[.*?\\]\\)" ; group 1 is first stamp + "\\(\\[.*?\\]\\)" ; group 1 is first stamp "\\(-\\{1,3\\}\\(\\[.*?\\]\\)\\)?")) ; group 3 is second (tlstart 0.) (tlend 0.) @@ -5913,9 +5965,9 @@ See also the user option `org-agenda-clock-consistency-checks'." (setq ts (match-string 1) te (match-string 3) ts (float-time - (apply 'encode-time (org-parse-time-string ts))) + (apply #'encode-time (org-parse-time-string ts))) te (float-time - (apply 'encode-time (org-parse-time-string te))) + (apply #'encode-time (org-parse-time-string te))) dt (- te ts)))) (cond ((> dt (* 60 maxtime)) @@ -6001,312 +6053,348 @@ specification like [h]h:mm." (regexp (if with-hour org-deadline-time-hour-regexp org-deadline-time-regexp)) - (todayp (org-agenda-todayp date)) ; DATE bound by calendar - (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar - (dl0 (car org-agenda-deadline-leaders)) - (dl1 (nth 1 org-agenda-deadline-leaders)) - (dl2 (or (nth 2 org-agenda-deadline-leaders) dl1)) - d2 diff dfrac wdays pos pos1 category category-pos level - tags suppress-prewarning ee txt head face s todo-state - show-all upcomingp donep timestr warntime inherited-tags ts-date) + (today (org-today)) + (today? (org-agenda-today-p date)) ; DATE bound by calendar. + (current (calendar-absolute-from-gregorian date)) + deadline-items) (goto-char (point-min)) (while (re-search-forward regexp nil t) (catch :skip + (unless (save-match-data (org-at-planning-p)) (throw :skip nil)) (org-agenda-skip) - (setq s (match-string 1) - txt nil - pos (1- (match-beginning 1)) - todo-state (save-match-data (org-get-todo-state)) - show-all (or (eq org-agenda-repeating-timestamp-show-all t) - (member todo-state - org-agenda-repeating-timestamp-show-all)) - d2 (org-time-string-to-absolute - s d1 'past show-all (current-buffer) pos) - diff (- d2 d1)) - (setq suppress-prewarning - (let ((ds (and org-agenda-skip-deadline-prewarning-if-scheduled - (let ((item (buffer-substring (point-at-bol) - (point-at-eol)))) - (save-match-data - (and (string-match - org-scheduled-time-regexp item) - (match-string 1 item))))))) - (cond - ((not ds) nil) - ;; The current item has a scheduled date (in ds), so - ;; evaluate its prewarning lead time. - ((integerp org-agenda-skip-deadline-prewarning-if-scheduled) - ;; Use global prewarning-restart lead time. - org-agenda-skip-deadline-prewarning-if-scheduled) - ((eq org-agenda-skip-deadline-prewarning-if-scheduled - 'pre-scheduled) - ;; Set prewarning to no earlier than scheduled. - (min (- d2 (org-time-string-to-absolute - ds d1 'past show-all (current-buffer) pos)) - org-deadline-warning-days)) - ;; Set prewarning to deadline. - (t 0)))) - (setq wdays (if suppress-prewarning - (let ((org-deadline-warning-days suppress-prewarning)) - (org-get-wdays s)) - (org-get-wdays s)) - dfrac (- 1 (/ (* 1.0 diff) (max wdays 1))) - upcomingp (and todayp (> diff 0))) - ;; When to show a deadline in the calendar: - ;; If the expiration is within wdays warning time. - ;; Past-due deadlines are only shown on the current date - (if (and (or (and (<= diff wdays) - (and todayp (not org-agenda-only-exact-dates))) - (= diff 0))) - (save-excursion - ;; (setq todo-state (org-get-todo-state)) - (setq donep (member todo-state org-done-keywords)) - (if (and donep - (or org-agenda-skip-deadline-if-done - (not (= diff 0)))) - (setq txt nil) - (setq category (org-get-category) - warntime (get-text-property (point) 'org-appt-warntime) - category-pos (get-text-property (point) 'org-category-position)) - (if (not (re-search-backward "^\\*+[ \t]+" nil t)) - (throw :skip nil) - (goto-char (match-end 0)) - (setq pos1 (match-beginning 0)) - (setq level (make-string (org-reduced-level (org-outline-level)) ? )) - (setq inherited-tags - (or (eq org-agenda-show-inherited-tags 'always) - (and (listp org-agenda-show-inherited-tags) - (memq 'agenda org-agenda-show-inherited-tags)) - (and (eq org-agenda-show-inherited-tags t) - (or (eq org-agenda-use-tag-inheritance t) - (memq 'agenda org-agenda-use-tag-inheritance)))) - tags (org-get-tags-at pos1 (not inherited-tags))) - (setq head (buffer-substring - (point) - (progn (skip-chars-forward "^\r\n") - (point)))) - (if (string-match " \\([012]?[0-9]:[0-9][0-9]\\)" s) - (setq timestr - (concat (substring s (match-beginning 1)) " ")) - (setq timestr 'time)) - (setq txt (org-agenda-format-item - (cond ((= diff 0) dl0) - ((> diff 0) - (if (functionp dl1) - (funcall dl1 diff date) - (format dl1 diff))) - (t - (if (functionp dl2) - (funcall dl2 diff date) - (format dl2 (if (string= dl2 dl1) - diff (abs diff)))))) - head level category tags - (if (not (= diff 0)) nil timestr))))) - (when txt - (setq face (org-agenda-deadline-face dfrac)) - (org-add-props txt props - 'org-marker (org-agenda-new-marker pos) - 'warntime warntime - 'level level - 'ts-date d2 - 'org-hd-marker (org-agenda-new-marker pos1) - 'priority (+ (- diff) - (org-get-priority txt)) - 'org-category category - 'org-category-position category-pos - 'todo-state todo-state - 'type (if upcomingp "upcoming-deadline" "deadline") - 'date (if upcomingp date d2) - 'face (if donep 'org-agenda-done face) - 'undone-face face 'done-face 'org-agenda-done) - (push txt ee)))))) - (nreverse ee))) + (let* ((s (match-string 1)) + (pos (1- (match-beginning 1))) + (todo-state (save-match-data (org-get-todo-state))) + (done? (member todo-state org-done-keywords)) + (show-all (or (eq org-agenda-repeating-timestamp-show-all t) + (member todo-state + org-agenda-repeating-timestamp-show-all))) + (sexp? (string-prefix-p "%%" s)) + ;; DEADLINE is the bare deadline date, i.e., without + ;; any repeater, or the last repeat if SHOW-ALL is + ;; non-nil. REPEAT is closest repeat after CURRENT, if + ;; all repeated time stamps are to be shown, or after + ;; TODAY otherwise. REPEAT only applies to future + ;; dates. + (deadline (cond + (sexp? (org-agenda--timestamp-to-absolute s current)) + (show-all (org-agenda--timestamp-to-absolute s)) + (t (org-agenda--timestamp-to-absolute + s today 'past (current-buffer) pos)))) + (repeat (cond (sexp? deadline) + ((< current today) deadline) + (t + (org-agenda--timestamp-to-absolute + s (if show-all current today) 'future + (current-buffer) pos)))) + (diff (- deadline current)) + (suppress-prewarning + (let ((scheduled + (and org-agenda-skip-deadline-prewarning-if-scheduled + (org-entry-get nil "SCHEDULED")))) + (cond + ((not scheduled) nil) + ;; The current item has a scheduled date, so + ;; evaluate its prewarning lead time. + ((integerp org-agenda-skip-deadline-prewarning-if-scheduled) + ;; Use global prewarning-restart lead time. + org-agenda-skip-deadline-prewarning-if-scheduled) + ((eq org-agenda-skip-deadline-prewarning-if-scheduled + 'pre-scheduled) + ;; Set pre-warning to no earlier than SCHEDULED. + (min (- deadline + (org-agenda--timestamp-to-absolute scheduled)) + org-deadline-warning-days)) + ;; Set pre-warning to deadline. + (t 0)))) + (wdays (if suppress-prewarning + (let ((org-deadline-warning-days suppress-prewarning)) + (org-get-wdays s)) + (org-get-wdays s)))) + ;; When to show a deadline in the calendar: if the + ;; expiration is within WDAYS warning time. Past-due + ;; deadlines are only shown on today agenda. + (when (cond ((= current deadline) nil) + ((< deadline today) + (and (not today?) + (or (< current today) (/= repeat current)))) + ((> deadline current) + (or (not today?) (> diff wdays))) + (t (/= repeat current))) + (throw :skip nil)) + ;; Possibly skip done tasks. + (when (and done? + (or org-agenda-skip-deadline-if-done + (/= deadline current))) + (throw :skip nil)) + (save-excursion + (re-search-backward "^\\*+[ \t]+" nil t) + (goto-char (match-end 0)) + (let* ((category (org-get-category)) + (level + (make-string (org-reduced-level (org-outline-level)) ?\s)) + (head (buffer-substring (point) (line-end-position))) + (inherited-tags + (or (eq org-agenda-show-inherited-tags 'always) + (and (listp org-agenda-show-inherited-tags) + (memq 'agenda org-agenda-show-inherited-tags)) + (and (eq org-agenda-show-inherited-tags t) + (or (eq org-agenda-use-tag-inheritance t) + (memq 'agenda + org-agenda-use-tag-inheritance))))) + (tags (org-get-tags-at nil (not inherited-tags))) + (time + (cond + ;; No time of day designation if it is only + ;; a reminder. + ((and (/= current deadline) (/= current repeat)) nil) + ((string-match " \\([012]?[0-9]:[0-9][0-9]\\)" s) + (concat (substring s (match-beginning 1)) " ")) + (t 'time))) + (item + (org-agenda-format-item + ;; Insert appropriate suffixes before deadlines. + (pcase-let ((`(,now ,future ,past) + org-agenda-deadline-leaders)) + (cond + ;; Future (i.e., repeated) deadlines are + ;; displayed as new headlines. + ((> current today) now) + ;; When SHOW-ALL is nil, prefer repeated + ;; deadlines over reminders of past deadlines. + ((and (not show-all) (= repeat today)) now) + ((= deadline current) now) + ((< deadline current) (format past (- diff))) + (t (format future diff)))) + head level category tags + (and (or (= repeat current) (= deadline current)) + time))) + (face (org-agenda-deadline-face + (- 1 (/ (float (- deadline current)) (max wdays 1))))) + (upcoming? (and today? (> deadline today))) + (warntime (get-text-property (point) 'org-appt-warntime))) + (org-add-props item props + 'org-marker (org-agenda-new-marker pos) + 'org-hd-marker (org-agenda-new-marker (line-beginning-position)) + 'warntime warntime + 'level level + 'ts-date deadline + 'priority + ;; Adjust priority to today reminders about deadlines. + ;; Overdue deadlines get the highest priority + ;; increase, then imminent deadlines and eventually + ;; more distant deadlines. + (let ((adjust (cond ((not today?) 0) + ((and (not show-all) (= repeat current)) 0) + (t (- diff))))) + (+ adjust (org-get-priority item))) + 'todo-state todo-state + 'type (if upcoming? "upcoming-deadline" "deadline") + 'date (if upcoming? date deadline) + 'face (if done? 'org-agenda-done face) + 'undone-face face + 'done-face 'org-agenda-done) + (push item deadline-items)))))) + (nreverse deadline-items))) (defun org-agenda-deadline-face (fraction) "Return the face to displaying a deadline item. FRACTION is what fraction of the head-warning time has passed." - (let ((faces org-agenda-deadline-faces) f) - (catch 'exit - (while (setq f (pop faces)) - (if (>= fraction (car f)) (throw 'exit (cdr f))))))) + (assoc-default fraction org-agenda-deadline-faces #'<=)) -(defun org-agenda-get-scheduled (&optional deadline-results with-hour) +(defun org-agenda-get-scheduled (&optional deadlines with-hour) "Return the scheduled information for agenda display. -When WITH-HOUR is non-nil, only return scheduled items with -an hour specification like [h]h:mm." +Optional argument DEADLINES is a list of deadline items to be +displayed in agenda view. When WITH-HOUR is non-nil, only return +scheduled items with an hour specification like [h]h:mm." (let* ((props (list 'org-not-done-regexp org-not-done-regexp 'org-todo-regexp org-todo-regexp 'org-complex-heading-regexp org-complex-heading-regexp 'done-face 'org-agenda-done 'mouse-face 'highlight 'help-echo - (format "mouse-2 or RET jump to org file %s" + (format "mouse-2 or RET jump to Org file %s" (abbreviate-file-name buffer-file-name)))) (regexp (if with-hour org-scheduled-time-hour-regexp org-scheduled-time-regexp)) - (todayp (org-agenda-todayp date)) ; DATE bound by calendar - (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar - mm - (deadline-position-alist - (mapcar (lambda (a) (and (setq mm (get-text-property - 0 'org-hd-marker a)) - (cons (marker-position mm) a))) - deadline-results)) - d2 diff pos pos1 category category-pos level tags donep - ee txt head pastschedp todo-state face timestr s habitp show-all - did-habit-check-p warntime inherited-tags ts-date suppress-delay - ddays) + (today (org-today)) + (todayp (org-agenda-today-p date)) ; DATE bound by calendar. + (current (calendar-absolute-from-gregorian date)) + (deadline-pos + (mapcar (lambda (d) + (let ((m (get-text-property 0 'org-hd-marker d))) + (and m (marker-position m)))) + deadlines)) + scheduled-items) (goto-char (point-min)) (while (re-search-forward regexp nil t) (catch :skip + (unless (save-match-data (org-at-planning-p)) (throw :skip nil)) (org-agenda-skip) - (setq s (match-string 1) - txt nil - pos (1- (match-beginning 1)) - todo-state (save-match-data (org-get-todo-state)) - show-all (or (eq org-agenda-repeating-timestamp-show-all t) - (member todo-state - org-agenda-repeating-timestamp-show-all)) - d2 (org-time-string-to-absolute - s d1 'past show-all (current-buffer) pos) - diff (- d2 d1) - warntime (get-text-property (point) 'org-appt-warntime)) - (setq pastschedp (and todayp (< diff 0))) - (setq did-habit-check-p nil) - (setq suppress-delay - (let ((ds (and org-agenda-skip-scheduled-delay-if-deadline - (let ((item (buffer-substring (point-at-bol) (point-at-eol)))) - (save-match-data - (and (string-match - org-deadline-time-regexp item) - (match-string 1 item))))))) + (let* ((s (match-string 1)) + (pos (1- (match-beginning 1))) + (todo-state (save-match-data (org-get-todo-state))) + (donep (member todo-state org-done-keywords)) + (show-all (or (eq org-agenda-repeating-timestamp-show-all t) + (member todo-state + org-agenda-repeating-timestamp-show-all))) + (sexp? (string-prefix-p "%%" s)) + ;; SCHEDULE is the bare scheduled date, i.e., without + ;; any repeater if non-nil, or last repeat if SHOW-ALL + ;; is nil. REPEAT is the closest repeat after CURRENT, + ;; if all repeated time stamps are to be shown, or + ;; after TODAY otherwise. REPEAT only applies to + ;; future dates. + (schedule (cond + (sexp? (org-agenda--timestamp-to-absolute s current)) + (show-all (org-agenda--timestamp-to-absolute s)) + (t (org-agenda--timestamp-to-absolute + s today 'past (current-buffer) pos)))) + (repeat (cond + (sexp? schedule) + ((< current today) schedule) + (t + (org-agenda--timestamp-to-absolute + s (if show-all current today) 'future + (current-buffer) pos)))) + (diff (- current schedule)) + (warntime (get-text-property (point) 'org-appt-warntime)) + (pastschedp (< schedule today)) + (habitp (and (fboundp 'org-is-habit-p) (org-is-habit-p))) + (suppress-delay + (let ((deadline (and org-agenda-skip-scheduled-delay-if-deadline + (org-entry-get nil "DEADLINE")))) + (cond + ((not deadline) nil) + ;; The current item has a deadline date, so + ;; evaluate its delay time. + ((integerp org-agenda-skip-scheduled-delay-if-deadline) + ;; Use global delay time. + (- org-agenda-skip-scheduled-delay-if-deadline)) + ((eq org-agenda-skip-scheduled-delay-if-deadline + 'post-deadline) + ;; Set delay to no later than DEADLINE. + (min (- schedule + (org-agenda--timestamp-to-absolute deadline)) + org-scheduled-delay-days)) + (t 0)))) + (ddays (cond - ((not ds) nil) - ;; The current item has a deadline date (in ds), so - ;; evaluate its delay time. - ((integerp org-agenda-skip-scheduled-delay-if-deadline) - ;; Use global delay time. - (- org-agenda-skip-scheduled-delay-if-deadline)) - ((eq org-agenda-skip-scheduled-delay-if-deadline - 'post-deadline) - ;; Set delay to no later than deadline. - (min (- d2 (org-time-string-to-absolute - ds d1 'past show-all (current-buffer) pos)) - org-scheduled-delay-days)) - (t 0)))) - (setq ddays (if suppress-delay - (let ((org-scheduled-delay-days suppress-delay)) - (org-get-wdays s t t)) - (org-get-wdays s t))) - ;; Use a delay of 0 when there is a repeater and the delay is - ;; of the form --3d - (when (and (save-match-data (string-match "--[0-9]+[hdwmy]" s)) - (< (org-time-string-to-absolute s) - (org-time-string-to-absolute - s d2 'past nil (current-buffer) pos))) - (setq ddays 0)) - ;; When to show a scheduled item in the calendar: - ;; If it is on or past the date. - (when (or (and (> ddays 0) (= diff (- ddays))) - (and (zerop ddays) (= diff 0)) - (and (< (+ diff ddays) 0) - (< (abs diff) org-scheduled-past-days) - (and todayp (not org-agenda-only-exact-dates))) - ;; org-is-habit-p uses org-entry-get, which is expansive - ;; so we go extra mile to only call it once - (and todayp - (boundp 'org-habit-show-all-today) - org-habit-show-all-today - (setq did-habit-check-p t) - (setq habitp (and (functionp 'org-is-habit-p) - (org-is-habit-p))))) - (save-excursion - (setq donep (member todo-state org-done-keywords)) - (if (and donep + ;; Nullify delay when a repeater triggered already + ;; and the delay is of the form --Xd. + ((and (string-match-p "--[0-9]+[hdwmy]" s) + (> current schedule)) + 0) + (suppress-delay + (let ((org-scheduled-delay-days suppress-delay)) + (org-get-wdays s t t))) + (t (org-get-wdays s t))))) + ;; Display scheduled items at base date (SCHEDULE), today if + ;; scheduled before the current date, and at any repeat past + ;; today. However, skip delayed items and items that have + ;; been displayed for more than `org-scheduled-past-days'. + (unless (and todayp + habitp + (bound-and-true-p org-habit-show-all-today)) + (when (or (and (> ddays 0) (< diff ddays)) + (> diff org-scheduled-past-days) + (> schedule current) + (and (< schedule current) + (not todayp) + (/= repeat current))) + (throw :skip nil))) + ;; Possibly skip done tasks. + (when (and donep (or org-agenda-skip-scheduled-if-done - (not (= diff 0)) - (and (functionp 'org-is-habit-p) - (org-is-habit-p)))) - (setq txt nil) - (setq habitp (if did-habit-check-p habitp - (and (functionp 'org-is-habit-p) - (org-is-habit-p)))) - (setq category (org-get-category) - category-pos (get-text-property (point) 'org-category-position)) - (if (and (eq org-agenda-skip-scheduled-if-deadline-is-shown - 'repeated-after-deadline) - (org-get-deadline-time (point)) - (<= 0 (- d2 (time-to-days (org-get-deadline-time (point)))))) - (throw :skip nil)) - (if (not (re-search-backward "^\\*+[ \t]+" nil t)) - (throw :skip nil) - (goto-char (match-end 0)) - (setq pos1 (match-beginning 0)) - (if habitp - (if (or (not org-habit-show-habits) - (and (not todayp) - (boundp 'org-habit-show-habits-only-for-today) - org-habit-show-habits-only-for-today)) - (throw :skip nil)) - (if (and - (or (eq t org-agenda-skip-scheduled-if-deadline-is-shown) - (and (eq org-agenda-skip-scheduled-if-deadline-is-shown 'not-today) - pastschedp)) - (setq mm (assoc pos1 deadline-position-alist))) - (throw :skip nil))) - (setq inherited-tags - (or (eq org-agenda-show-inherited-tags 'always) - (and (listp org-agenda-show-inherited-tags) - (memq 'agenda org-agenda-show-inherited-tags)) - (and (eq org-agenda-show-inherited-tags t) - (or (eq org-agenda-use-tag-inheritance t) - (memq 'agenda org-agenda-use-tag-inheritance)))) - - tags (org-get-tags-at nil (not inherited-tags))) - (setq level (make-string (org-reduced-level (org-outline-level)) ? )) - (setq head (buffer-substring - (point) - (progn (skip-chars-forward "^\r\n") (point)))) - (if (string-match " \\([012]?[0-9]:[0-9][0-9]\\)" s) - (setq timestr - (concat (substring s (match-beginning 1)) " ")) - (setq timestr 'time)) - (setq txt (org-agenda-format-item - (if (= diff 0) - (car org-agenda-scheduled-leaders) - (format (nth 1 org-agenda-scheduled-leaders) - (- 1 diff))) - head level category tags - (if (not (= diff 0)) nil timestr) - nil habitp)))) - (when txt - (setq face + (/= schedule current))) + (throw :skip nil)) + ;; Skip entry if it already appears as a deadline, per + ;; `org-agenda-skip-scheduled-if-deadline-is-shown'. This + ;; doesn't apply to habits. + (when (pcase org-agenda-skip-scheduled-if-deadline-is-shown + ((guard + (or (not (memq (line-beginning-position 0) deadline-pos)) + habitp)) + nil) + (`repeated-after-deadline + (>= repeat (time-to-days (org-get-deadline-time (point))))) + (`not-today pastschedp) + (`t t) + (_ nil)) + (throw :skip nil)) + ;; Skip habits if `org-habit-show-habits' is nil, or if we + ;; only show them for today. Also skip done habits. + (when (and habitp + (or donep + (not (bound-and-true-p org-habit-show-habits)) + (and (not todayp) + (bound-and-true-p + org-habit-show-habits-only-for-today)))) + (throw :skip nil)) + (save-excursion + (re-search-backward "^\\*+[ \t]+" nil t) + (goto-char (match-end 0)) + (let* ((category (org-get-category)) + (inherited-tags + (or (eq org-agenda-show-inherited-tags 'always) + (and (listp org-agenda-show-inherited-tags) + (memq 'agenda org-agenda-show-inherited-tags)) + (and (eq org-agenda-show-inherited-tags t) + (or (eq org-agenda-use-tag-inheritance t) + (memq 'agenda + org-agenda-use-tag-inheritance))))) + (tags (org-get-tags-at nil (not inherited-tags))) + (level + (make-string (org-reduced-level (org-outline-level)) ?\s)) + (head (buffer-substring (point) (line-end-position))) + (time (cond - ((and (not habitp) pastschedp) - 'org-scheduled-previously) - (todayp 'org-scheduled-today) - (t 'org-scheduled)) - habitp (and habitp (org-habit-parse-todo))) - (org-add-props txt props + ;; No time of day designation if it is only + ;; a reminder. + ((and (/= current schedule) (/= current repeat)) nil) + ((string-match " \\([012]?[0-9]:[0-9][0-9]\\)" s) + (concat (substring s (match-beginning 1)) " ")) + (t 'time))) + (item + (org-agenda-format-item + (pcase-let ((`(,first ,next) org-agenda-scheduled-leaders)) + (cond + ;; If CURRENT is in the future, don't use past + ;; scheduled prefix. + ((> current today) first) + ;; SHOW-ALL focuses on future repeats. If one + ;; such repeat happens today, ignore late + ;; schedule reminder. However, still report + ;; such reminders when repeat happens later. + ((and (not show-all) (= repeat today)) first) + ;; Initial report. + ((= schedule current) first) + ;; Subsequent reminders. Count from base + ;; schedule. + (t (format next diff)))) + head level category tags time nil habitp)) + (face (cond ((and (not habitp) pastschedp) + 'org-scheduled-previously) + (todayp 'org-scheduled-today) + (t 'org-scheduled))) + (habitp (and habitp (org-habit-parse-todo)))) + (org-add-props item props 'undone-face face 'face (if donep 'org-agenda-done face) 'org-marker (org-agenda-new-marker pos) - 'org-hd-marker (org-agenda-new-marker pos1) + 'org-hd-marker (org-agenda-new-marker (line-beginning-position)) 'type (if pastschedp "past-scheduled" "scheduled") - 'date (if pastschedp d2 date) - 'ts-date d2 + 'date (if pastschedp schedule date) + 'ts-date schedule 'warntime warntime 'level level - 'priority (if habitp - (org-habit-get-priority habitp) - (+ 94 (- 5 diff) (org-get-priority txt))) - 'org-category category - 'category-position category-pos + 'priority (if habitp (org-habit-get-priority habitp) + (+ 99 diff (org-get-priority item))) 'org-habit-p habitp 'todo-state todo-state) - (push txt ee)))))) - (nreverse ee))) + (push item scheduled-items)))))) + (nreverse scheduled-items))) (defun org-agenda-get-blocks () "Return the date-range information for agenda display." @@ -6320,7 +6408,7 @@ an hour specification like [h]h:mm." (abbreviate-file-name buffer-file-name)))) (regexp org-tr-regexp) (d0 (calendar-absolute-from-gregorian date)) - marker hdmarker ee txt d1 d2 s1 s2 category category-pos + marker hdmarker ee txt d1 d2 s1 s2 category level todo-state tags pos head donep inherited-tags) (goto-char (point-min)) (while (re-search-forward regexp nil t) @@ -6341,9 +6429,8 @@ an hour specification like [h]h:mm." (setq donep (member todo-state org-done-keywords)) (if (and donep org-agenda-skip-timestamp-if-done) (throw :skip t)) - (setq marker (org-agenda-new-marker (point))) - (setq category (org-get-category) - category-pos (get-text-property (point) 'org-category-position)) + (setq marker (org-agenda-new-marker (point)) + category (org-get-category)) (if (not (re-search-backward org-outline-regexp-bol nil t)) (throw :skip nil) (goto-char (match-beginning 0)) @@ -6358,7 +6445,7 @@ an hour specification like [h]h:mm." tags (org-get-tags-at nil (not inherited-tags))) (setq level (make-string (org-reduced-level (org-outline-level)) ? )) - (looking-at "\\*+[ \t]+\\([^\r\n]+\\)") + (looking-at "\\*+[ \t]+\\(.*\\)") (setq head (match-string 1)) (let ((remove-re (if org-agenda-remove-timeranges-from-blocks @@ -6385,8 +6472,7 @@ an hour specification like [h]h:mm." 'type "block" 'date date 'level level 'todo-state todo-state - 'priority (org-get-priority txt) 'org-category category - 'org-category-position category-pos) + 'priority (org-get-priority txt)) (push txt ee)))) (goto-char pos))) ;; Sort the entries by expiration date. @@ -6413,11 +6499,11 @@ The flag is set if the currently compiled format contains a `%b'.") (defun org-agenda-get-category-icon (category) "Return an image for CATEGORY according to `org-agenda-category-icon-alist'." - (dolist (entry org-agenda-category-icon-alist) - (when (org-string-match-p (car entry) category) + (cl-dolist (entry org-agenda-category-icon-alist) + (when (string-match-p (car entry) category) (if (listp (cadr entry)) - (return (cadr entry)) - (return (apply 'create-image (cdr entry))))))) + (cl-return (cadr entry)) + (cl-return (apply #'create-image (cdr entry))))))) (defun org-agenda-format-item (extra txt &optional level category tags dotime remove-re habitp) @@ -6444,8 +6530,8 @@ Any match of REMOVE-RE will be removed from TXT." ;; buffer (let* ((bindings (car org-prefix-format-compiled)) (formatter (cadr org-prefix-format-compiled))) - (loop for (var value) in bindings - do (set var value)) + (cl-loop for (var value) in bindings + do (set var value)) (save-match-data ;; Diary entries sometimes have extra whitespace at the beginning (setq txt (org-trim txt)) @@ -6457,9 +6543,6 @@ Any match of REMOVE-RE will be removed from TXT." org-agenda-hide-tags-regexp)) (let* ((category (or category - (if (stringp org-category) - org-category - (and org-category (symbol-name org-category))) (if buffer-file-name (file-name-sans-extension (file-name-nondirectory buffer-file-name)) @@ -6468,15 +6551,17 @@ Any match of REMOVE-RE will be removed from TXT." (category-icon (if category-icon (propertize " " 'display category-icon) "")) + (effort (and (not (string= txt "")) + (get-text-property 1 'effort txt))) ;; time, tag, effort are needed for the eval of the prefix format (tag (if tags (nth (1- (length tags)) tags) "")) - time effort neffort + time (ts (if dotime (concat (if (stringp dotime) dotime "") (and org-agenda-search-headline-for-time txt)))) (time-of-day (and dotime (org-get-time-of-day ts))) stamp plain s0 s1 s2 rtn srp l - duration thecategory breadcrumbs) + duration breadcrumbs) (and (derived-mode-p 'org-mode) buffer-file-name (add-to-list 'org-agenda-contributing-files buffer-file-name)) (when (and dotime time-of-day) @@ -6516,8 +6601,7 @@ Any match of REMOVE-RE will be removed from TXT." (setq duration (- (org-hh:mm-string-to-minutes s2) (org-hh:mm-string-to-minutes s1))))) - (when (string-match (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$") - txt) + (when (string-match "\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$" txt) ;; Tags are in the string (if (or (eq org-agenda-remove-tags t) (and org-agenda-remove-tags @@ -6527,16 +6611,6 @@ Any match of REMOVE-RE will be removed from TXT." (concat (make-string (max (- 50 (length txt)) 1) ?\ ) (match-string 2 txt)) t t txt)))) - (when (derived-mode-p 'org-mode) - (setq effort (ignore-errors (get-text-property 0 'org-effort txt)))) - - ;; org-agenda-add-time-grid-maybe calls us with *Agenda* as - ;; current buffer, so move this check outside of above - (if effort - (setq neffort (org-duration-string-to-minutes effort) - effort (setq effort (concat "[" effort "]"))) - ;; prevent erroring out with %e format when there is no effort - (setq effort "")) (when remove-re (while (string-match remove-re txt) @@ -6563,7 +6637,6 @@ Any match of REMOVE-RE will be removed from TXT." (t "")) extra (or (and (not habitp) extra) "") category (if (symbolp category) (symbol-name category) category) - thecategory (copy-sequence category) level (or level "")) (if (string-match org-bracket-link-regexp category) (progn @@ -6584,14 +6657,12 @@ Any match of REMOVE-RE will be removed from TXT." ;; And finally add the text properties (remove-text-properties 0 (length rtn) '(line-prefix t wrap-prefix t) rtn) (org-add-props rtn nil - 'org-category (if thecategory (downcase thecategory) category) + 'org-category category 'tags (mapcar 'org-downcase-keep-props tags) 'org-highest-priority org-highest-priority 'org-lowest-priority org-lowest-priority 'time-of-day time-of-day 'duration duration - 'effort effort - 'effort-minutes neffort 'breadcrumbs breadcrumbs 'txt txt 'level level @@ -6605,7 +6676,7 @@ Any match of REMOVE-RE will be removed from TXT." The modified list may contain inherited tags, and tags matched by `org-agenda-hide-tags-regexp' will be removed." (when (or add-inherited hide-re) - (if (string-match (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$") txt) + (if (string-match "\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$" txt) (setq txt (substring txt 0 (match-beginning 0)))) (setq tags (delq nil @@ -6710,12 +6781,12 @@ and stored in the variable `org-prefix-format-compiled'." c (or (match-string 3 s) "") opt (match-beginning 1) start (1+ (match-beginning 0))) - (if (equal var 'time) (setq org-prefix-has-time t)) - (if (equal var 'tag) (setq org-prefix-has-tag t)) - (if (equal var 'effort) (setq org-prefix-has-effort t)) - (if (equal var 'breadcrumbs) (setq org-prefix-has-breadcrumbs t)) + (if (eq var 'time) (setq org-prefix-has-time t)) + (if (eq var 'tag) (setq org-prefix-has-tag t)) + (if (eq var 'effort) (setq org-prefix-has-effort t)) + (if (eq var 'breadcrumbs) (setq org-prefix-has-breadcrumbs t)) (setq f (concat "%" (match-string 2 s) "s")) - (when (equal var 'category) + (when (eq var 'category) (setq org-prefix-category-length (floor (abs (string-to-number (match-string 2 s))))) (setq org-prefix-category-max-length @@ -6727,10 +6798,13 @@ and stored in the variable `org-prefix-format-compiled'." (setq varform `(format ,f (org-eval ,(read (match-string 4 s))))) (if opt (setq varform - `(if (equal "" ,var) + `(if (or (equal "" ,var) (equal nil ,var)) "" - (format ,f (if (equal "" ,var) "" (concat ,var ,c))))) - (setq varform `(format ,f (if (equal ,var "") "" (concat ,var ,c (get-text-property 0 'extra-space ,var))))))) + (format ,f (concat ,var ,c)))) + (setq varform + `(format ,f (if (or (equal ,var "") + (equal ,var nil)) "" + (concat ,var ,c (get-text-property 0 'extra-space ,var))))))) (setq s (replace-match "%s" t nil s)) (push varform vars)) (setq vars (nreverse vars)) @@ -6817,7 +6891,7 @@ The optional argument TYPE tells the agenda type." (t org-agenda-max-tags))) (max-entries (cond ((listp org-agenda-max-entries) (cdr (assoc type org-agenda-max-entries))) - (t org-agenda-max-entries))) l) + (t org-agenda-max-entries)))) (when org-agenda-before-sorting-filter-function (setq list (delq nil @@ -6827,7 +6901,9 @@ The optional argument TYPE tells the agenda type." list (mapcar 'identity (sort list 'org-entries-lessp))) (when max-effort (setq list (org-agenda-limit-entries - list 'effort-minutes max-effort 'identity))) + list 'effort-minutes max-effort + (lambda (e) (or e (if org-sort-agenda-noeffort-is-high + 32767 -1)))))) (when max-todo (setq list (org-agenda-limit-entries list 'todo-state max-todo))) (when max-tags @@ -6845,26 +6921,39 @@ The optional argument TYPE tells the agenda type." (delq nil (mapcar (lambda (e) - (let ((pval (funcall fun (get-text-property 1 prop e)))) + (let ((pval (funcall + fun (get-text-property (1- (length e)) + prop e)))) (if pval (setq lim (+ lim pval))) (cond ((and pval (<= lim (abs limit))) e) ((and include (not pval)) e)))) list))) list))) -(defun org-agenda-limit-interactively () +(defun org-agenda-limit-interactively (remove) "In agenda, interactively limit entries to various maximums." - (interactive) - (let* ((max (read-char "Number of [e]ntries [t]odos [T]ags [E]ffort? ")) - (num (string-to-number (read-from-minibuffer "How many? ")))) - (cond ((equal max ?e) - (let ((org-agenda-max-entries num)) (org-agenda-redo))) - ((equal max ?t) - (let ((org-agenda-max-todos num)) (org-agenda-redo))) - ((equal max ?T) - (let ((org-agenda-max-tags num)) (org-agenda-redo))) - ((equal max ?E) - (let ((org-agenda-max-effort num)) (org-agenda-redo))))) + (interactive "P") + (if remove + (progn (setq org-agenda-max-entries nil + org-agenda-max-todos nil + org-agenda-max-tags nil + org-agenda-max-effort nil) + (org-agenda-redo)) + (let* ((max (read-char "Number of [e]ntries [t]odos [T]ags [E]ffort? ")) + (msg (cond ((= max ?E) "How many minutes? ") + ((= max ?e) "How many entries? ") + ((= max ?t) "How many TODO entries? ") + ((= max ?T) "How many tagged entries? ") + (t (user-error "Wrong input")))) + (num (string-to-number (read-from-minibuffer msg)))) + (cond ((equal max ?e) + (let ((org-agenda-max-entries num)) (org-agenda-redo))) + ((equal max ?t) + (let ((org-agenda-max-todos num)) (org-agenda-redo))) + ((equal max ?T) + (let ((org-agenda-max-tags num)) (org-agenda-redo))) + ((equal max ?E) + (let ((org-agenda-max-effort num)) (org-agenda-redo)))))) (org-agenda-fit-window-to-buffer)) (defun org-agenda-highlight-todo (x) @@ -6910,25 +6999,31 @@ The optional argument TYPE tells the agenda type." (substring x (match-end 3))))))) x))) -(defsubst org-cmp-priority (a b) - "Compare the priorities of string A and B." - (let ((pa (or (get-text-property 1 'priority a) 0)) - (pb (or (get-text-property 1 'priority b) 0))) +(defsubst org-cmp-values (a b property) + "Compare the numeric value of text PROPERTY for string A and B." + (let ((pa (or (get-text-property (1- (length a)) property a) 0)) + (pb (or (get-text-property (1- (length b)) property b) 0))) (cond ((> pa pb) +1) ((< pa pb) -1)))) (defsubst org-cmp-effort (a b) "Compare the effort values of string A and B." (let* ((def (if org-sort-agenda-noeffort-is-high 32767 -1)) - (ea (or (get-text-property 1 'effort-minutes a) def)) - (eb (or (get-text-property 1 'effort-minutes b) def))) + ;; `effort-minutes' property is not directly accessible from + ;; the strings, but is stored as a property in `txt'. + (ea (or (get-text-property + 0 'effort-minutes (get-text-property 0 'txt a)) + def)) + (eb (or (get-text-property + 0 'effort-minutes (get-text-property 0 'txt b)) + def))) (cond ((> ea eb) +1) ((< ea eb) -1)))) (defsubst org-cmp-category (a b) "Compare the string values of categories of strings A and B." - (let ((ca (or (get-text-property 1 'org-category a) "")) - (cb (or (get-text-property 1 'org-category b) ""))) + (let ((ca (or (get-text-property (1- (length a)) 'org-category a) "")) + (cb (or (get-text-property (1- (length b)) 'org-category b) ""))) (cond ((string-lessp ca cb) -1) ((string-lessp cb ca) +1)))) @@ -6959,7 +7054,8 @@ The optional argument TYPE tells the agenda type." (let* ((pla (text-property-any 0 (length a) 'org-heading t a)) (plb (text-property-any 0 (length b) 'org-heading t b)) (ta (and pla (substring a pla))) - (tb (and plb (substring b plb)))) + (tb (and plb (substring b plb))) + (case-fold-search nil)) (when pla (if (string-match (concat "\\`[ \t]*" (or (get-text-property 0 'org-todo-regexp a) "") "\\([ \t]*\\[[a-zA-Z0-9]\\]\\)? *") ta) @@ -7038,8 +7134,11 @@ their type." (time-up (and (org-em 'time-up 'time-down ss) (org-cmp-time a b))) (time-down (if time-up (- time-up) nil)) + (stats-up (and (org-em 'stats-up 'stats-down ss) + (org-cmp-values a b 'org-stats))) + (stats-down (if stats-up (- stats-up) nil)) (priority-up (and (org-em 'priority-up 'priority-down ss) - (org-cmp-priority a b))) + (org-cmp-values a b 'priority))) (priority-down (if priority-up (- priority-up) nil)) (effort-up (and (org-em 'effort-up 'effort-down ss) (org-cmp-effort a b))) @@ -7080,15 +7179,16 @@ their type." 'face 'org-agenda-restriction-lock) (overlay-put org-agenda-restriction-lock-overlay 'help-echo "Agendas are currently limited to this subtree.") -(org-detach-overlay org-agenda-restriction-lock-overlay) +(delete-overlay org-agenda-restriction-lock-overlay) ;;;###autoload (defun org-agenda-set-restriction-lock (&optional type) "Set restriction lock for agenda, to current subtree or file. -Restriction will be the file if TYPE is `file', or if TYPE is the -universal prefix `(4)', or if the cursor is before the first headline +Restriction will be the file if TYPE is `file', or if type is the +universal prefix \\='(4), or if the cursor is before the first headline in the file. Otherwise, restriction will be to the current subtree." (interactive "P") + (org-agenda-remove-restriction-lock 'noupdate) (and (equal type '(4)) (setq type 'file)) (setq type (cond (type type) @@ -7125,8 +7225,8 @@ in the file. Otherwise, restriction will be to the current subtree." (defun org-agenda-remove-restriction-lock (&optional noupdate) "Remove the agenda restriction lock." (interactive "P") - (org-detach-overlay org-agenda-restriction-lock-overlay) - (org-detach-overlay org-speedbar-restriction-lock-overlay) + (delete-overlay org-agenda-restriction-lock-overlay) + (delete-overlay org-speedbar-restriction-lock-overlay) (setq org-agenda-overriding-restriction nil) (setq org-agenda-restrict nil) (put 'org-agenda-files 'org-restrict nil) @@ -7138,7 +7238,9 @@ in the file. Otherwise, restriction will be to the current subtree." (defun org-agenda-maybe-redo () "If there is any window showing the agenda view, update it." - (let ((w (get-buffer-window org-agenda-buffer-name t)) + (let ((w (get-buffer-window (or org-agenda-this-buffer-name + org-agenda-buffer-name) + t)) (w0 (selected-window))) (when w (select-window w) @@ -7154,7 +7256,7 @@ in the file. Otherwise, restriction will be to the current subtree." (defun org-agenda-check-type (error &rest types) "Check if agenda buffer is of allowed type. If ERROR is non-nil, throw an error, otherwise just return nil. -Allowed types are 'agenda 'timeline 'todo 'tags 'search." +Allowed types are `agenda' `timeline' `todo' `tags' `search'." (if (not org-agenda-type) (error "No Org agenda currently displayed") (if (memq org-agenda-type types) @@ -7164,77 +7266,76 @@ Allowed types are 'agenda 'timeline 'todo 'tags 'search." nil)))) (defun org-agenda-Quit () - "Exit the agenda and kill buffers loaded by `org-agenda'. -Also restore the window configuration." + "Exit the agenda, killing the agenda buffer. +Like `org-agenda-quit', but kill the buffer even when +`org-agenda-sticky' is non-nil." (interactive) - (if org-agenda-columns-active - (org-columns-quit) - (let ((buf (current-buffer))) - (if (eq org-agenda-window-setup 'other-frame) - (progn - (org-agenda-reset-markers) - (kill-buffer buf) - (org-columns-remove-overlays) - (setq org-agenda-archives-mode nil) - (delete-frame)) - (and (not (eq org-agenda-window-setup 'current-window)) - (not (one-window-p)) - (delete-window)) - (org-agenda-reset-markers) - (kill-buffer buf) - (org-columns-remove-overlays) - (setq org-agenda-archives-mode nil))) - (setq org-agenda-buffer nil) - ;; Maybe restore the pre-agenda window configuration. - (and org-agenda-restore-windows-after-quit - (not (eq org-agenda-window-setup 'other-frame)) - org-agenda-pre-window-conf - (set-window-configuration org-agenda-pre-window-conf) - (setq org-agenda-pre-window-conf nil)))) + (org-agenda--quit)) (defun org-agenda-quit () - "Exit the agenda and restore the window configuration. -When `org-agenda-sticky' is non-nil, only bury the agenda." + "Exit the agenda. + +When `org-agenda-sticky' is non-nil, bury the agenda buffer +instead of killing it. + +When `org-agenda-restore-windows-after-quit' is non-nil, restore +the pre-agenda window configuration. + +When column view is active, exit column view instead of the +agenda." (interactive) - (if (and (eq org-indirect-buffer-display 'other-window) - org-last-indirect-buffer) - (let ((org-last-indirect-window - (get-buffer-window org-last-indirect-buffer))) - (if org-last-indirect-window - (delete-window org-last-indirect-window)))) + (org-agenda--quit org-agenda-sticky)) + +(defun org-agenda--quit (&optional bury) (if org-agenda-columns-active (org-columns-quit) - (if org-agenda-sticky - (let ((buf (current-buffer))) - (if (eq org-agenda-window-setup 'other-frame) - (progn - (delete-frame)) - (and (not (eq org-agenda-window-setup 'current-window)) - (not (one-window-p)) - (delete-window))) + (let ((wconf org-agenda-pre-window-conf) + (buf (current-buffer)) + (org-agenda-last-indirect-window + (and (eq org-indirect-buffer-display 'other-window) + org-agenda-last-indirect-buffer + (get-buffer-window org-agenda-last-indirect-buffer)))) + (cond + ((eq org-agenda-window-setup 'other-frame) + (delete-frame)) + ((and org-agenda-restore-windows-after-quit + wconf) + ;; Maybe restore the pre-agenda window configuration. Reset + ;; `org-agenda-pre-window-conf' before running + ;; `set-window-configuration', which loses the current buffer. + (setq org-agenda-pre-window-conf nil) + (set-window-configuration wconf)) + (t + (when org-agenda-last-indirect-window + (delete-window org-agenda-last-indirect-window)) + (and (not (eq org-agenda-window-setup 'current-window)) + (not (one-window-p)) + (delete-window)))) + (if bury + ;; Set the agenda buffer as the current buffer instead of + ;; passing it as an argument to `bury-buffer' so that + ;; `bury-buffer' removes it from the window. (with-current-buffer buf - (bury-buffer) - ;; Maybe restore the pre-agenda window configuration. - (and org-agenda-restore-windows-after-quit - (not (eq org-agenda-window-setup 'other-frame)) - org-agenda-pre-window-conf - (set-window-configuration org-agenda-pre-window-conf) - (setq org-agenda-pre-window-conf nil)))) - (org-agenda-Quit)))) + (bury-buffer)) + (kill-buffer buf) + (setq org-agenda-archives-mode nil + org-agenda-buffer nil))))) (defun org-agenda-exit () - "Exit the agenda and restore the window configuration. -Also kill Org-mode buffers loaded by `org-agenda'. Org-mode -buffers visited directly by the user will not be touched." + "Exit the agenda, killing Org buffers loaded by the agenda. +Like `org-agenda-Quit', but kill any buffers that were created by +the agenda. Org buffers visited directly by the user will not be +touched. Also, exit the agenda even if it is in column view." (interactive) + (when org-agenda-columns-active + (org-columns-quit)) (org-release-buffers org-agenda-new-buffers) (setq org-agenda-new-buffers nil) (org-agenda-Quit)) (defun org-agenda-kill-all-agenda-buffers () "Kill all buffers in `org-agenda-mode'. -This is used when toggling sticky agendas. -You can also explicitly invoke it with `C-c a C-k'." +This is used when toggling sticky agendas." (interactive) (let (blist) (dolist (buf (buffer-list)) @@ -7267,6 +7368,9 @@ in the agenda." (cat-preset (get 'org-agenda-category-filter :preset-filter)) (re-filter org-agenda-regexp-filter) (re-preset (get 'org-agenda-regexp-filter :preset-filter)) + (effort-filter org-agenda-effort-filter) + (effort-preset (get 'org-agenda-effort-filter :preset-filter)) + (org-agenda-tag-filter-while-redo (or tag-filter tag-preset)) (cols org-agenda-columns-active) (line (org-current-line)) (window-line (- line (org-current-line (window-start)))) @@ -7284,6 +7388,7 @@ in the agenda." (put 'org-agenda-tag-filter :preset-filter nil) (put 'org-agenda-category-filter :preset-filter nil) (put 'org-agenda-regexp-filter :preset-filter nil) + (put 'org-agenda-effort-filter :preset-filter nil) (and cols (org-columns-quit)) (message "Rebuilding agenda buffer...") (if series-redo-cmd @@ -7294,19 +7399,23 @@ in the agenda." org-agenda-tag-filter tag-filter org-agenda-category-filter cat-filter org-agenda-regexp-filter re-filter + org-agenda-effort-filter effort-filter org-agenda-top-headline-filter top-hl-filter) (message "Rebuilding agenda buffer...done") (put 'org-agenda-tag-filter :preset-filter tag-preset) (put 'org-agenda-category-filter :preset-filter cat-preset) (put 'org-agenda-regexp-filter :preset-filter re-preset) + (put 'org-agenda-effort-filter :preset-filter effort-preset) (let ((tag (or tag-filter tag-preset)) (cat (or cat-filter cat-preset)) - (re (or re-filter re-preset))) - (when tag (org-agenda-filter-apply tag 'tag)) + (effort (or effort-filter effort-preset)) + (re (or re-filter re-preset))) + (when tag (org-agenda-filter-apply tag 'tag t)) (when cat (org-agenda-filter-apply cat 'category)) + (when effort (org-agenda-filter-apply effort 'effort)) (when re (org-agenda-filter-apply re 'regexp))) (and top-hl-filter (org-agenda-filter-top-headline-apply top-hl-filter)) - (and cols (org-called-interactively-p 'any) (org-agenda-columns)) + (and cols (called-interactively-p 'any) (org-agenda-columns)) (org-goto-line line) (recenter window-line))) @@ -7315,32 +7424,36 @@ in the agenda." (defvar org-agenda-filtered-by-category nil) (defun org-agenda-filter-by-category (strip) - "Keep only those lines in the agenda buffer that have a specific category. -The category is that of the current line." + "Filter lines in the agenda buffer that have a specific category. +The category is that of the current line. +Without prefix argument, keep only the lines of that category. +With a prefix argument, exclude the lines of that category. +" (interactive "P") (if (and org-agenda-filtered-by-category org-agenda-category-filter) (org-agenda-filter-show-all-cat) - (let ((cat (org-no-properties (get-text-property (point) 'org-category)))) + (let ((cat (org-no-properties (org-get-at-eol 'org-category 1)))) (cond ((and cat strip) (org-agenda-filter-apply (push (concat "-" cat) org-agenda-category-filter) 'category)) - ((and cat) + (cat (org-agenda-filter-apply (setq org-agenda-category-filter (list (concat "+" cat))) 'category)) (t (error "No category at point")))))) (defun org-find-top-headline (&optional pos) - "Find the topmost parent headline and return it." + "Find the topmost parent headline and return it. +POS when non-nil is the marker or buffer position to start the +search from." (save-excursion - (with-current-buffer (if pos (marker-buffer pos) (current-buffer)) - (if pos (goto-char pos)) - ;; Skip up to the topmost parent - (while (ignore-errors (outline-up-heading 1) t)) - (ignore-errors - (nth 4 (org-heading-components)))))) + (with-current-buffer (if (markerp pos) (marker-buffer pos) (current-buffer)) + (when pos (goto-char pos)) + ;; Skip up to the topmost parent. + (while (org-up-heading-safe)) + (ignore-errors (nth 4 (org-heading-components)))))) (defvar org-agenda-filtered-by-top-headline nil) (defun org-agenda-filter-by-top-headline (strip) @@ -7375,6 +7488,49 @@ With two prefix arguments, remove the regexp filters." (org-agenda-filter-show-all-re) (message "Regexp filter removed"))) +(defvar org-agenda-effort-filter nil) +(defun org-agenda-filter-by-effort (strip) + "Filter agenda entries by effort. +With no prefix argument, keep entries matching the effort condition. +With one prefix argument, filter out entries matching the condition. +With two prefix arguments, remove the effort filters." + (interactive "P") + (cond + ((member strip '(nil 4)) + (let* ((efforts (split-string + (or (cdr (assoc (concat org-effort-property "_ALL") + org-global-properties)) + "0 0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00"))) + ;; XXX: the following handles only up to 10 different + ;; effort values. + (allowed-keys (if (null efforts) nil + (mapcar (lambda (n) (mod n 10)) ;turn 10 into 0 + (number-sequence 1 (length efforts))))) + (op nil)) + (while (not (memq op '(?< ?> ?=))) + (setq op (read-char-exclusive "Effort operator? (> = or <)"))) + ;; Select appropriate duration. Ignore non-digit characters. + (let ((prompt + (apply #'format + (concat "Effort %c " + (mapconcat (lambda (s) (concat "[%d]" s)) + efforts + " ")) + op allowed-keys)) + (eff -1)) + (while (not (memq eff allowed-keys)) + (message prompt) + (setq eff (- (read-char-exclusive) 48))) + (setq org-agenda-effort-filter + (list (concat (if strip "-" "+") + (char-to-string op) + ;; Numbering is 1 2 3 ... 9 0, but we want + ;; 0 1 2 ... 8 9. + (nth (mod (1- eff) 10) efforts))))) + (org-agenda-filter-apply org-agenda-effort-filter 'effort))) + (t (org-agenda-filter-show-all-effort) + (message "Effort filter removed")))) + (defun org-agenda-filter-remove-all () "Remove all filters from the current agenda buffer." (interactive) @@ -7386,15 +7542,24 @@ With two prefix arguments, remove the regexp filters." (org-agenda-filter-show-all-re)) (when org-agenda-top-headline-filter (org-agenda-filter-show-all-top-filter)) + (when org-agenda-effort-filter + (org-agenda-filter-show-all-effort)) (org-agenda-finalize)) -(defun org-agenda-filter-by-tag (strip &optional char narrow) +(defun org-agenda-filter-by-tag (arg &optional char exclude) "Keep only those lines in the agenda buffer that have a specific tag. + The tag is selected with its fast selection letter, as configured. -With prefix argument STRIP, remove all lines that do have the tag. -A lisp caller can specify CHAR. NARROW means that the new tag should be -used to narrow the search - the interactive user can also press `-' or `+' -to switch to narrowing." + +With a `\\[universal-argument]' prefix, exclude the agenda search. + +With a `\\[universal-argument] \\[universal-argument]' prefix, filter the literal tag, \ +i.e. don't +filter on all its group members. + +A lisp caller can specify CHAR. EXCLUDE means that the new tag +should be used to exclude the search - the interactive user can +also press `-' or `+' to switch between filtering and excluding." (interactive "P") (let* ((alist org-tag-alist-for-agenda) (tag-chars (mapconcat @@ -7402,54 +7567,34 @@ to switch to narrowing." (cdr x)) (char-to-string (cdr x)) "")) - alist "")) - (efforts (org-split-string - (or (cdr (assoc (concat org-effort-property "_ALL") - org-global-properties)) - "0 0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00 8:00" - ""))) - (effort-op org-agenda-filter-effort-default-operator) - (effort-prompt "") + org-tag-alist-for-agenda "")) + (valid-char-list (append '(?\t ?\r ?/ ?. ?\s ?q) + (string-to-list tag-chars))) + (exclude (or exclude (equal arg '(4)))) + (expand (not (equal arg '(16)))) (inhibit-read-only t) (current org-agenda-tag-filter) - maybe-refresh a n tag) + a n tag) (unless char - (message - "%s by tag [%s ], [TAB], %s[/]:off, [+-]:narrow, [>==<]:effort: " tag-chars) - (setq char (read-char-exclusive))) - (when (member char '(?< ?> ?= ??)) - ;; An effort operator - (setq effort-op (char-to-string char)) - (setq alist nil) ; to make sure it will be interpreted as effort. - (unless (equal char ??) - (loop for i from 0 to 9 do - (setq effort-prompt - (concat - effort-prompt " [" - (if (= i 9) "0" (int-to-string (1+ i))) - "]" (nth i efforts)))) - (message "Effort%s: %s " effort-op effort-prompt) + (while (not (memq char valid-char-list)) + (message + "%s by tag [%s ], [TAB], %s[/]:off, [+/-]:filter/exclude%s, [q]:quit" + (if exclude "Exclude" "Filter") tag-chars + (if org-agenda-auto-exclude-function "[RET], " "") + (if expand "" ", no grouptag expand")) (setq char (read-char-exclusive)) - (when (or (< char ?0) (> char ?9)) - (error "Need 1-9,0 to select effort")))) - (when (equal char ?\t) + ;; Excluding or filtering down + (cond ((eq char ?-) (setq exclude t)) + ((eq char ?+) (setq exclude nil))))) + (when (eq char ?\t) (unless (local-variable-p 'org-global-tags-completion-table (current-buffer)) - (org-set-local 'org-global-tags-completion-table - (org-global-tags-completion-table))) + (setq-local org-global-tags-completion-table + (org-global-tags-completion-table))) (let ((completion-ignore-case t)) - (setq tag (org-icompleting-read + (setq tag (completing-read "Tag: " org-global-tags-completion-table)))) (cond - ((equal char ?\r) + ((eq char ?\r) (org-agenda-filter-show-all-tag) (when org-agenda-auto-exclude-function (setq org-agenda-tag-filter nil) @@ -7458,39 +7603,27 @@ to switch to narrowing." (if modifier (push modifier org-agenda-tag-filter)))) (if (not (null org-agenda-tag-filter)) - (org-agenda-filter-apply org-agenda-tag-filter 'tag))) - (setq maybe-refresh t)) - ((equal char ?/) + (org-agenda-filter-apply org-agenda-tag-filter 'tag expand)))) + ((eq char ?/) (org-agenda-filter-show-all-tag) (when (get 'org-agenda-tag-filter :preset-filter) - (org-agenda-filter-apply org-agenda-tag-filter 'tag)) - (setq maybe-refresh t)) - ((equal char ?. ) + (org-agenda-filter-apply org-agenda-tag-filter 'tag expand))) + ((eq char ?.) (setq org-agenda-tag-filter (mapcar (lambda(tag) (concat "+" tag)) (org-get-at-bol 'tags))) - (org-agenda-filter-apply org-agenda-tag-filter 'tag) - (setq maybe-refresh t)) - ((or (equal char ?\ ) + (org-agenda-filter-apply org-agenda-tag-filter 'tag expand)) + ((eq char ?q)) ;If q, abort (even if there is a q-key for a tag...) + ((or (eq char ?\s) (setq a (rassoc char alist)) - (and (>= char ?0) (<= char ?9) - (setq n (if (= char ?0) 9 (- char ?0 1)) - tag (concat effort-op (nth n efforts)) - a (cons tag nil))) - (and (= char ??) - (setq tag "?eff") - a (cons tag nil)) (and tag (setq a (cons tag nil)))) (org-agenda-filter-show-all-tag) (setq tag (car a)) (setq org-agenda-tag-filter - (cons (concat (if strip "-" "+") tag) - (if narrow current nil))) - (org-agenda-filter-apply org-agenda-tag-filter 'tag) - (setq maybe-refresh t)) - (t (error "Invalid tag selection character %c" char))) - (when maybe-refresh - (org-agenda-redo)))) + (cons (concat (if exclude "-" "+") tag) + current)) + (org-agenda-filter-apply org-agenda-tag-filter 'tag expand)) + (t (error "Invalid tag selection character %c" char))))) (defun org-agenda-get-represented-tags () "Get a list of all tags currently represented in the agenda." @@ -7503,13 +7636,11 @@ to switch to narrowing." (get-text-property (point) 'tags)))) tags)) -(defun org-agenda-filter-by-tag-refine (strip &optional char) - "Refine the current filter. See `org-agenda-filter-by-tag'." - (interactive "P") - (org-agenda-filter-by-tag strip char 'refine)) -(defun org-agenda-filter-make-matcher (filter type) - "Create the form that tests a line for agenda filter." +(defun org-agenda-filter-make-matcher (filter type &optional expand) + "Create the form that tests a line for agenda filter. Optional +argument EXPAND can be used for the TYPE tag and will expand the +tags in the FILTER if any of the tags in FILTER are grouptags." (let (f f1) (cond ;; Tag filter @@ -7519,28 +7650,11 @@ to switch to narrowing." (append (get 'org-agenda-tag-filter :preset-filter) filter))) (dolist (x filter) - (let ((nfilter (org-agenda-filter-expand-tags filter)) nf nf1 - (ffunc - (lambda (nf0 nf01 fltr notgroup op) - (dolist (x fltr) - (if (member x '("-" "+")) - (setq nf01 (if (equal x "-") 'tags '(not tags))) - (if (string-match "[<=>?]" x) - (setq nf01 (org-agenda-filter-effort-form x)) - (setq nf01 (list 'member (downcase (substring x 1)) - 'tags))) - (when (equal (string-to-char x) ?-) - (setq nf01 (list 'not nf01)) - (when (not notgroup) (setq op 'and)))) - (push nf01 nf0)) - (if notgroup - (push (cons 'and nf0) f) - (push (cons (or op 'or) nf0) f))))) - (cond ((equal filter '("+")) - (setq f (list (list 'not 'tags)))) - ((equal nfilter filter) - (funcall ffunc f1 f filter t nil)) - (t (funcall ffunc nf1 nf nfilter nil nil)))))) + (let ((op (string-to-char x))) + (if expand (setq x (org-agenda-filter-expand-tags (list x) t)) + (setq x (list x))) + (setq f1 (org-agenda-filter-make-matcher-tag-exp x op)) + (push f1 f)))) ;; Category filter ((eq type 'category) (setq filter @@ -7562,9 +7676,35 @@ to switch to narrowing." (if (equal "-" (substring x 0 1)) (setq f1 (list 'not (list 'string-match (substring x 1) 'txt))) (setq f1 (list 'string-match (substring x 1) 'txt))) - (push f1 f)))) + (push f1 f))) + ;; Effort filter + ((eq type 'effort) + (setq filter + (delete-dups + (append (get 'org-agenda-effort-filter :preset-filter) + filter))) + (dolist (x filter) + (push (org-agenda-filter-effort-form x) f)))) (cons 'and (nreverse f)))) +(defun org-agenda-filter-make-matcher-tag-exp (tags op) + "Return a form associated to tag-expression TAGS. +Build a form testing a line for agenda filter for +tag-expressions. OP is an operator of type CHAR that allows the +function to set the right switches in the returned form." + (let (form) + ;; Any of the expressions can match if OP is +, all must match if + ;; the operator is -. + (dolist (x tags (cons (if (eq op ?-) 'and 'or) form)) + (let* ((tag (substring x 1)) + (f (cond + ((string= "" tag) '(not tags)) + ((and (string-match-p "\\`{" tag) (string-match-p "}\\'" tag)) + ;; TAG is a regexp. + (list 'org-match-any-p (substring tag 1 -1) 'tags)) + (t (list 'member (downcase tag) 'tags))))) + (push (if (eq op ?-) (list 'not f) f) form))))) + (defun org-agenda-filter-effort-form (e) "Return the form to compare the effort of the current line with what E says. E looks like \"+<2:25\"." @@ -7581,11 +7721,12 @@ E looks like \"+<2:25\"." (defun org-agenda-compare-effort (op value) "Compare the effort of the current line with VALUE, using OP. If the line does not have an effort defined, return nil." - (let ((eff (org-get-at-bol 'effort-minutes))) - (if (equal op ??) - (not eff) - (funcall op (or eff (if org-sort-agenda-noeffort-is-high 32767 0)) - value)))) + ;; `effort-minutes' property cannot be extracted directly from + ;; current line but is stored as a property in `txt'. + (let ((effort (get-text-property 0 'effort-minutes (org-get-at-bol 'txt)))) + (funcall op + (or effort (if org-sort-agenda-noeffort-is-high 32767 -1)) + value))) (defun org-agenda-filter-expand-tags (filter &optional no-operator) "Expand group tags in FILTER for the agenda. @@ -7605,12 +7746,14 @@ When NO-OPERATOR is non-nil, do not add the + operator to returned tags." (reverse rtn)) filter)) -(defun org-agenda-filter-apply (filter type) - "Set FILTER as the new agenda filter and apply it." +(defun org-agenda-filter-apply (filter type &optional expand) + "Set FILTER as the new agenda filter and apply it. Optional +argument EXPAND can be used for the TYPE tag and will expand the +tags in the FILTER if any of the tags in FILTER are grouptags." ;; Deactivate `org-agenda-entry-text-mode' when filtering (if org-agenda-entry-text-mode (org-agenda-entry-text-mode)) (let (tags cat txt) - (setq org-agenda-filter-form (org-agenda-filter-make-matcher filter type)) + (setq org-agenda-filter-form (org-agenda-filter-make-matcher filter type expand)) ;; Only set `org-agenda-filtered-by-category' to t when a unique ;; category is used as the filter: (setq org-agenda-filtered-by-category @@ -7622,13 +7765,9 @@ When NO-OPERATOR is non-nil, do not add the + operator to returned tags." (while (not (eobp)) (if (org-get-at-bol 'org-marker) (progn - (setq tags ; used in eval - (apply 'append - (mapcar (lambda (f) - (org-agenda-filter-expand-tags (list f) t)) - (org-get-at-bol 'tags))) - cat (get-text-property (point) 'org-category) - txt (get-text-property (point) 'txt)) + (setq tags (org-get-at-bol 'tags) + cat (org-get-at-eol 'org-category 1) + txt (org-get-at-bol 'txt)) (if (not (eval org-agenda-filter-form)) (org-agenda-filter-hide-line type)) (beginning-of-line 2)) @@ -7681,6 +7820,8 @@ When NO-OPERATOR is non-nil, do not add the + operator to returned tags." (org-agenda-remove-filter 'tag)) (defun org-agenda-filter-show-all-re nil (org-agenda-remove-filter 'regexp)) +(defun org-agenda-filter-show-all-effort nil + (org-agenda-remove-filter 'effort)) (defun org-agenda-filter-show-all-cat nil (org-agenda-remove-filter 'category)) (defun org-agenda-filter-show-all-top-filter nil @@ -7779,7 +7920,7 @@ Negative selection means regexp must not match for selection of an entry." (tdpos (goto-char tdpos)) ((eq org-agenda-type 'agenda) (let* ((sd (org-agenda-compute-starting-span - (org-today) (or curspan org-agenda-ndays org-agenda-span))) + (org-today) (or curspan org-agenda-span))) (org-agenda-overriding-arguments args)) (setf (nth 1 org-agenda-overriding-arguments) sd) (org-agenda-redo) @@ -7792,27 +7933,40 @@ Negative selection means regexp must not match for selection of an entry." (text-property-any (point-min) (point-max) 'org-today t) (text-property-any (point-min) (point-max) 'org-agenda-type 'agenda) (and (get-text-property (min (1- (point-max)) (point)) 'org-series) - (org-agenda-goto-block-beginning)) + (org-agenda-backward-block)) (point-min)))) -(defun org-agenda-goto-block-beginning () - "Go the agenda block beginning." +(defun org-agenda-backward-block () + "Move backward by one agenda block." (interactive) - (if (not (derived-mode-p 'org-agenda-mode)) - (error "Cannot execute this command outside of org-agenda-mode buffers") - (let (dest) - (save-excursion - (unless (looking-at "\\'") - (forward-char)) - (let* ((prop 'org-agenda-structural-header) - (p (previous-single-property-change (point) prop)) - (n (next-single-property-change (or (and (looking-at "\\`") 1) - (1- (point))) prop))) - (setq dest (cond ((eq n (point-at-eol)) (1- n)) (p (1- p)))))) - (if (not dest) - (error "Cannot find the beginning of the blog") - (goto-char dest) - (move-beginning-of-line 1))))) + (org-agenda-forward-block 'backward)) + +(defun org-agenda-forward-block (&optional backward) + "Move forward by one agenda block. +When optional argument BACKWARD is set, go backward" + (interactive) + (cond ((not (derived-mode-p 'org-agenda-mode)) + (user-error + "Cannot execute this command outside of org-agenda-mode buffers")) + ((looking-at (if backward "\\`" "\\'")) + (message "Already at the %s block" (if backward "first" "last"))) + (t (let ((pos (prog1 (point) + (ignore-errors (if backward (backward-char 1) + (move-end-of-line 1))))) + (f (if backward + 'previous-single-property-change + 'next-single-property-change)) + moved dest) + (while (and (setq dest (funcall + f (point) 'org-agenda-structural-header)) + (not (get-text-property + (point) 'org-agenda-structural-header))) + (setq moved t) + (goto-char dest)) + (if moved (move-beginning-of-line 1) + (goto-char (if backward (point-min) (point-max))) + (move-beginning-of-line 1) + (message "No %s block" (if backward "previous" "further"))))))) (defun org-agenda-later (arg) "Go forward in time by the current span. @@ -7866,71 +8020,77 @@ With prefix ARG, go backward that many times the current span." (message "View: [d]ay [w]eek for[t]night [m]onth [y]ear [SPC]reset [q]uit/abort time[G]rid [[]inactive [f]ollow [l]og [L]og-all [c]lockcheck [a]rch-trees [A]rch-files clock[R]eport include[D]iary [E]ntryText") - (let ((a (read-char-exclusive))) - (case a - (?\ (call-interactively 'org-agenda-reset-view)) - (?d (call-interactively 'org-agenda-day-view)) - (?w (call-interactively 'org-agenda-week-view)) - (?t (call-interactively 'org-agenda-fortnight-view)) - (?m (call-interactively 'org-agenda-month-view)) - (?y (call-interactively 'org-agenda-year-view)) - (?l (call-interactively 'org-agenda-log-mode)) - (?L (org-agenda-log-mode '(4))) - (?c (org-agenda-log-mode 'clockcheck)) - ((?F ?f) (call-interactively 'org-agenda-follow-mode)) - (?a (call-interactively 'org-agenda-archives-mode)) - (?A (org-agenda-archives-mode 'files)) - ((?R ?r) (call-interactively 'org-agenda-clockreport-mode)) - ((?E ?e) (call-interactively 'org-agenda-entry-text-mode)) - (?G (call-interactively 'org-agenda-toggle-time-grid)) - (?D (call-interactively 'org-agenda-toggle-diary)) - (?\! (call-interactively 'org-agenda-toggle-deadlines)) - (?\[ (let ((org-agenda-include-inactive-timestamps t)) - (org-agenda-check-type t 'timeline 'agenda) - (org-agenda-redo)) - (message "Display now includes inactive timestamps as well")) - (?q (message "Abort")) - (otherwise (error "Invalid key" ))))) + (pcase (read-char-exclusive) + (?\ (call-interactively 'org-agenda-reset-view)) + (?d (call-interactively 'org-agenda-day-view)) + (?w (call-interactively 'org-agenda-week-view)) + (?t (call-interactively 'org-agenda-fortnight-view)) + (?m (call-interactively 'org-agenda-month-view)) + (?y (call-interactively 'org-agenda-year-view)) + (?l (call-interactively 'org-agenda-log-mode)) + (?L (org-agenda-log-mode '(4))) + (?c (org-agenda-log-mode 'clockcheck)) + ((or ?F ?f) (call-interactively 'org-agenda-follow-mode)) + (?a (call-interactively 'org-agenda-archives-mode)) + (?A (org-agenda-archives-mode 'files)) + ((or ?R ?r) (call-interactively 'org-agenda-clockreport-mode)) + ((or ?E ?e) (call-interactively 'org-agenda-entry-text-mode)) + (?G (call-interactively 'org-agenda-toggle-time-grid)) + (?D (call-interactively 'org-agenda-toggle-diary)) + (?\! (call-interactively 'org-agenda-toggle-deadlines)) + (?\[ (let ((org-agenda-include-inactive-timestamps t)) + (org-agenda-check-type t 'timeline 'agenda) + (org-agenda-redo)) + (message "Display now includes inactive timestamps as well")) + (?q (message "Abort")) + (key (user-error "Invalid key: %s" key)))) (defun org-agenda-reset-view () "Switch to default view for agenda." (interactive) - (org-agenda-change-time-span (or org-agenda-ndays org-agenda-span))) + (org-agenda-change-time-span org-agenda-span)) + (defun org-agenda-day-view (&optional day-of-month) "Switch to daily view for agenda. With argument DAY-OF-MONTH, switch to that day of the month." (interactive "P") (org-agenda-change-time-span 'day day-of-month)) + (defun org-agenda-week-view (&optional iso-week) - "Switch to daily view for agenda. + "Switch to weekly view for agenda. With argument ISO-WEEK, switch to the corresponding ISO week. -If ISO-WEEK has more then 2 digits, only the last two encode the -week. Any digits before this encode a year. So 200712 means -week 12 of year 2007. Years in the range 1938-2037 can also be -written as 2-digit years." +If ISO-WEEK has more then 2 digits, only the last two encode +the week. Any digits before this encode a year. So 200712 +means week 12 of year 2007. Years ranging from 70 years ago +to 30 years in the future can also be written as 2-digit years." (interactive "P") (org-agenda-change-time-span 'week iso-week)) + (defun org-agenda-fortnight-view (&optional iso-week) - "Switch to daily view for agenda. + "Switch to fortnightly view for agenda. With argument ISO-WEEK, switch to the corresponding ISO week. -If ISO-WEEK has more then 2 digits, only the last two encode the -week. Any digits before this encode a year. So 200712 means -week 12 of year 2007. Years in the range 1938-2037 can also be -written as 2-digit years." +If ISO-WEEK has more then 2 digits, only the last two encode +the week. Any digits before this encode a year. So 200712 +means week 12 of year 2007. Years ranging from 70 years ago +to 30 years in the future can also be written as 2-digit years." (interactive "P") (org-agenda-change-time-span 'fortnight iso-week)) + (defun org-agenda-month-view (&optional month) "Switch to monthly view for agenda. -With argument MONTH, switch to that month." +With argument MONTH, switch to that month. If MONTH has more +then 2 digits, only the last two encode the month. Any digits +before this encode a year. So 200712 means December year 2007. +Years ranging from 70 years ago to 30 years in the future can +also be written as 2-digit years." (interactive "P") (org-agenda-change-time-span 'month month)) + (defun org-agenda-year-view (&optional year) "Switch to yearly view for agenda. -With argument YEAR, switch to that year. -If MONTH has more then 2 digits, only the last two encode the -month. Any digits before this encode a year. So 200712 means -December year 2007. Years in the range 1938-2037 can also be -written as 2-digit years." +With argument YEAR, switch to that year. Years ranging from 70 +years ago to 30 years in the future can also be written as +2-digit years." (interactive "P") (when year (setq year (org-small-year-to-year year))) @@ -7988,7 +8148,7 @@ so that the date SD will be in that range." (setq y1 (org-small-year-to-year (/ n 100)) n (mod n 100))) (setq sd - (calendar-absolute-from-iso + (calendar-iso-to-absolute (list n 1 (or y1 (nth 2 (calendar-iso-from-absolute sd))))))))) ((eq span 'month) @@ -8034,7 +8194,7 @@ so that the date SD will be in that range." (defun org-unhighlight () "Detach overlay INDEX." - (org-detach-overlay org-hl)) + (delete-overlay org-hl)) (defun org-unhighlight-once () "Remove the highlight from its position, and this function from the hook." @@ -8091,9 +8251,12 @@ so that the date SD will be in that range." (defun org-agenda-log-mode (&optional special) "Toggle log mode in an agenda buffer. + With argument SPECIAL, show all possible log items, not only the ones configured in `org-agenda-log-mode-items'. -With a double `C-u' prefix arg, show *only* log items, nothing else." + +With a `\\[universal-argument] \\[universal-argument]' prefix, show *only* \ +log items, nothing else." (interactive "P") (org-agenda-check-type t 'agenda 'timeline) (setq org-agenda-show-log @@ -8107,8 +8270,7 @@ With a double `C-u' prefix arg, show *only* log items, nothing else." (setq org-agenda-start-with-log-mode org-agenda-show-log) (org-agenda-set-mode-name) (org-agenda-redo) - (message "Log mode is %s" - (if org-agenda-show-log "on" "off"))) + (message "Log mode is %s" (if org-agenda-show-log "on" "off"))) (defun org-agenda-archives-mode (&optional with-files) "Toggle inclusion of items in trees marked with :ARCHIVE:. @@ -8180,7 +8342,7 @@ When called with a prefix argument, include all archive files as well." (t "")) (if (or org-agenda-category-filter (get 'org-agenda-category-filter :preset-filter)) - '(:eval (org-propertize + '(:eval (propertize (concat " <" (mapconcat 'identity @@ -8193,7 +8355,7 @@ When called with a prefix argument, include all archive files as well." 'help-echo "Category used in filtering")) "") (if (or org-agenda-tag-filter (get 'org-agenda-tag-filter :preset-filter)) - '(:eval (org-propertize + '(:eval (propertize (concat " {" (mapconcat 'identity @@ -8204,9 +8366,22 @@ When called with a prefix argument, include all archive files as well." "}") 'face 'org-agenda-filter-tags 'help-echo "Tags used in filtering")) "") + (if (or org-agenda-effort-filter + (get 'org-agenda-effort-filter :preset-filter)) + '(:eval (propertize + (concat " {" + (mapconcat + 'identity + (append + (get 'org-agenda-effort-filter :preset-filter) + org-agenda-effort-filter) + "") + "}") + 'face 'org-agenda-filter-effort + 'help-echo "Effort conditions used in filtering")) "") (if (or org-agenda-regexp-filter (get 'org-agenda-regexp-filter :preset-filter)) - '(:eval (org-propertize + '(:eval (propertize (concat " [" (mapconcat 'identity @@ -8225,9 +8400,6 @@ When called with a prefix argument, include all archive files as well." (if org-agenda-clockreport-mode " Clock" ""))) (force-mode-line-update)) -(define-obsolete-function-alias - 'org-agenda-post-command-hook 'org-agenda-update-agenda-type "24.3") - (defun org-agenda-update-agenda-type () "Update the agenda type after each command." (setq org-agenda-type @@ -8290,7 +8462,7 @@ When called with a prefix argument, include all archive files as well." (message "No tags associated with this line")))) (defun org-agenda-goto (&optional highlight) - "Go to the Org-mode file which contains the item at point." + "Go to the entry at point in the corresponding Org file." (interactive) (let* ((marker (or (org-get-at-bol 'org-marker) (org-agenda-error))) @@ -8302,12 +8474,11 @@ When called with a prefix argument, include all archive files as well." (goto-char pos) (when (derived-mode-p 'org-mode) (org-show-context 'agenda) - (save-excursion - (and (outline-next-heading) - (org-flag-heading nil)))) ; show the next heading - (when (outline-invisible-p) - (show-entry)) ; display invisible text - (recenter (/ (window-height) 2)) + (recenter (/ (window-height) 2)) + (org-back-to-heading t) + (let ((case-fold-search nil)) + (when (re-search-forward org-complex-heading-regexp nil t) + (goto-char (match-beginning 4))))) (run-hooks 'org-agenda-after-show-hook) (and highlight (org-highlight (point-at-bol) (point-at-eol))))) @@ -8394,7 +8565,7 @@ Point is in the buffer where the item originated.") (org-remove-subtree-entries-from-agenda)) (org-back-to-heading t) (funcall cmd))) - (error "Archiving works only in Org-mode files")))))) + (error "Archiving works only in Org files")))))) (defun org-remove-subtree-entries-from-agenda (&optional buf beg end) "Remove all lines in the agenda that correspond to a given subtree. @@ -8424,9 +8595,16 @@ If this information is not given, the function uses the tree at point." (defun org-agenda-refile (&optional goto rfloc no-update) "Refile the item at point. -When GOTO is 0 or '(64), clear the refile cache. -When GOTO is '(16), go to the location of the last refiled item. +When called with `\\[universal-argument] \\[universal-argument]', \ +go to the location of the last +refiled item. + +When called with `\\[universal-argument] \\[universal-argument] \ +\\[universal-argument]' prefix or when GOTO is 0, clear +the refile cache. + RFLOC can be a refile location obtained in a different way. + When NO-UPDATE is non-nil, don't redo the agenda buffer." (interactive "P") (cond @@ -8445,13 +8623,11 @@ When NO-UPDATE is non-nil, don't redo the agenda buffer." (if goto "Goto" "Refile to") buffer org-refile-allow-creating-parent-nodes)))) (with-current-buffer buffer - (save-excursion - (save-restriction - (widen) - (goto-char marker) - (let ((org-agenda-buffer-name buffer-orig)) - (org-remove-subtree-entries-from-agenda)) - (org-refile goto buffer rfloc))))) + (org-with-wide-buffer + (goto-char marker) + (let ((org-agenda-buffer-name buffer-orig)) + (org-remove-subtree-entries-from-agenda)) + (org-refile goto buffer rfloc)))) (unless no-update (org-agenda-redo))))) (defun org-agenda-open-link (&optional arg) @@ -8476,13 +8652,11 @@ It also looks at the text of the entry itself." (setq trg (and (string-match org-bracket-link-regexp l) (match-string 1 l))) (if (or (not trg) (string-match org-any-link-re trg)) - (save-excursion - (save-restriction - (widen) - (goto-char marker) - (when (search-forward l nil lkend) - (goto-char (match-beginning 0)) - (org-open-at-point)))) + (org-with-wide-buffer + (goto-char marker) + (when (search-forward l nil lkend) + (goto-char (match-beginning 0)) + (org-open-at-point))) ;; This is an internal link, widen the buffer (switch-to-buffer-other-window buffer) (widen) @@ -8502,11 +8676,14 @@ It also looks at the text of the entry itself." "Get a variable from a referenced buffer and install it here." (let ((m (org-get-at-bol 'org-marker))) (when (and m (buffer-live-p (marker-buffer m))) - (org-set-local var (with-current-buffer (marker-buffer m) - (symbol-value var)))))) + (set (make-local-variable var) + (with-current-buffer (marker-buffer m) + (symbol-value var)))))) (defun org-agenda-switch-to (&optional delete-other-windows) - "Go to the Org-mode file which contains the item at point." + "Go to the Org mode file which contains the item at point. +When optional argument DELETE-OTHER-WINDOWS is non-nil, the +displayed Org file fills the frame." (interactive) (if (and org-return-follows-link (not (org-get-at-bol 'org-marker)) @@ -8516,44 +8693,40 @@ It also looks at the text of the entry itself." (org-agenda-error))) (buffer (marker-buffer marker)) (pos (marker-position marker))) - (org-pop-to-buffer-same-window buffer) - (and delete-other-windows (delete-other-windows)) + (unless buffer (user-error "Trying to switch to non-existent buffer")) + (pop-to-buffer-same-window buffer) + (when delete-other-windows (delete-other-windows)) (widen) (goto-char pos) (when (derived-mode-p 'org-mode) (org-show-context 'agenda) - (save-excursion - (and (outline-next-heading) - (org-flag-heading nil))) ; show the next heading - (when (outline-invisible-p) - (show-entry)) ; display invisible text (run-hooks 'org-agenda-after-show-hook))))) (defun org-agenda-goto-mouse (ev) - "Go to the Org-mode file which contains the item at the mouse click." + "Go to the Org file which contains the item at the mouse click." (interactive "e") (mouse-set-point ev) (org-agenda-goto)) (defun org-agenda-show (&optional full-entry) - "Display the Org-mode file which contains the item at point. + "Display the Org file which contains the item at point. With prefix argument FULL-ENTRY, make the entire entry visible if it was hidden in the outline." (interactive "P") (let ((win (selected-window))) - (if full-entry - (let ((org-show-entry-below t)) - (org-agenda-goto t)) - (org-agenda-goto t)) + (org-agenda-goto t) + (when full-entry (org-show-entry)) (select-window win))) (defvar org-agenda-show-window nil) (defun org-agenda-show-and-scroll-up (&optional arg) - "Display the Org-mode file which contains the item at point. + "Display the Org file which contains the item at point. + When called repeatedly, scroll the window that is displaying the buffer. -With a \\[universal-argument] prefix, use `org-show-entry' instead of -`show-subtree' to display the item, so that drawers and logbooks stay -folded." + +With a `\\[universal-argument]' prefix, use `org-show-entry' instead of \ +`outline-show-subtree' +to display the item, so that drawers and logbooks stay folded." (interactive "P") (let ((win (selected-window))) (if (and (window-live-p org-agenda-show-window) @@ -8562,7 +8735,7 @@ folded." (select-window org-agenda-show-window) (ignore-errors (scroll-up))) (org-agenda-goto t) - (if arg (org-show-entry) (show-subtree)) + (if arg (org-show-entry) (outline-show-subtree)) (setq org-agenda-show-window (selected-window))) (select-window win))) @@ -8576,7 +8749,7 @@ folded." (select-window win)))) (defun org-agenda-show-1 (&optional more) - "Display the Org-mode file which contains the item at point. + "Display the Org file which contains the item at point. The prefix arg selects the amount of information to display: 0 hide the subtree @@ -8594,50 +8767,46 @@ if it was hidden in the outline." (set-window-start (selected-window) (point-at-bol)) (cond ((= more 0) - (hide-subtree) + (outline-hide-subtree) (save-excursion (org-back-to-heading) (run-hook-with-args 'org-cycle-hook 'folded)) (message "Remote: FOLDED")) - ((and (org-called-interactively-p 'any) (= more 1)) + ((and (called-interactively-p 'any) (= more 1)) (message "Remote: show with default settings")) ((= more 2) - (show-entry) - (show-children) + (outline-show-entry) + (org-show-children) (save-excursion (org-back-to-heading) (run-hook-with-args 'org-cycle-hook 'children)) (message "Remote: CHILDREN")) ((= more 3) - (show-subtree) + (outline-show-subtree) (save-excursion (org-back-to-heading) (run-hook-with-args 'org-cycle-hook 'subtree)) (message "Remote: SUBTREE")) ((= more 4) - (let* ((org-drawers (delete "LOGBOOK" (copy-sequence org-drawers))) - (org-drawer-regexp - (concat "^[ \t]*:\\(" - (mapconcat 'regexp-quote org-drawers "\\|") - "\\):[ \t]*$"))) - (show-subtree) - (save-excursion - (org-back-to-heading) - (org-cycle-hide-drawers 'subtree))) + (outline-show-subtree) + (save-excursion + (org-back-to-heading) + (org-cycle-hide-drawers 'subtree '("LOGBOOK"))) (message "Remote: SUBTREE AND LOGBOOK")) ((> more 4) - (show-subtree) + (outline-show-subtree) (message "Remote: SUBTREE AND ALL DRAWERS"))) (select-window win))) (defvar org-agenda-cycle-counter nil) (defun org-agenda-cycle-show (&optional n) "Show the current entry in another window, with default settings. -Default settings are taken from `org-show-hierarchy-above' and siblings. -When use repeatedly in immediate succession, the remote entry will cycle -through visibility -children -> subtree -> folded +Default settings are taken from `org-show-context-detail'. When +use repeatedly in immediate succession, the remote entry will +cycle through visibility + + children -> subtree -> folded When called with a numeric prefix arg, that arg will be passed through to `org-agenda-show-1'. For the interpretation of that argument, see the @@ -8655,7 +8824,7 @@ docstring of `org-agenda-show-1'." (org-agenda-show-1 org-agenda-cycle-counter)) (defun org-agenda-recenter (arg) - "Display the Org-mode file which contains the item at point and recenter." + "Display the Org file which contains the item at point and recenter." (interactive "P") (let ((win (selected-window))) (org-agenda-goto t) @@ -8663,7 +8832,7 @@ docstring of `org-agenda-show-1'." (select-window win))) (defun org-agenda-show-mouse (ev) - "Display the Org-mode file which contains the item at the mouse click." + "Display the Org file which contains the item at the mouse click." (interactive "e") (mouse-set-point ev) (org-agenda-show)) @@ -8674,7 +8843,8 @@ docstring of `org-agenda-show-1'." (org-agenda-error))) (defun org-agenda-error () - (error "Command not allowed in this line")) + "Throw an error when a command is not allowed in the agenda." + (user-error "Command not allowed in this line")) (defun org-agenda-tree-to-indirect-buffer (arg) "Show the subtree corresponding to the current entry in an indirect buffer. @@ -8682,8 +8852,10 @@ This calls the command `org-tree-to-indirect-buffer' from the original buffer. With a numerical prefix ARG, go up to this level and then take that tree. With a negative numeric ARG, go up by this number of levels. -With a \\[universal-argument] prefix, make a separate frame for this tree (i.e. don't -use the dedicated frame)." + +With a `\\[universal-argument]' prefix, make a separate frame for this tree, \ +i.e. don't use +the dedicated frame." (interactive "P") (if current-prefix-arg (org-agenda-do-tree-to-indirect-buffer arg) @@ -8701,7 +8873,8 @@ use the dedicated frame)." (and indirect-window (select-window indirect-window)) (switch-to-buffer org-last-indirect-buffer :norecord) (fit-window-to-buffer indirect-window))) - (select-window (get-buffer-window agenda-buffer))))) + (select-window (get-buffer-window agenda-buffer)) + (setq org-agenda-last-indirect-buffer org-last-indirect-buffer)))) (defun org-agenda-do-tree-to-indirect-buffer (arg) "Same as `org-agenda-tree-to-indirect-buffer' without saving window." @@ -8730,9 +8903,9 @@ by a remote command from the agenda.") (org-agenda-todo 'previousset)) (defun org-agenda-todo (&optional arg) - "Cycle TODO state of line at point, also in Org-mode file. + "Cycle TODO state of line at point, also in Org file. This changes the line at point, all other lines in the agenda referring to -the same tree node, and the headline of the tree node in the Org-mode file." +the same tree node, and the headline of the tree node in the Org file." (interactive "P") (org-agenda-check-no-diary) (let* ((col (current-column)) @@ -8741,7 +8914,7 @@ the same tree node, and the headline of the tree node in the Org-mode file." (buffer (marker-buffer marker)) (pos (marker-position marker)) (hdmarker (org-get-at-bol 'org-hd-marker)) - (todayp (org-agenda-todayp (org-get-at-bol 'day))) + (todayp (org-agenda-today-p (org-get-at-bol 'day))) (inhibit-read-only t) org-agenda-headline-snapshot-before-repeat newhead just-one) (org-with-remote-undo buffer @@ -8749,14 +8922,11 @@ the same tree node, and the headline of the tree node in the Org-mode file." (widen) (goto-char pos) (org-show-context 'agenda) - (save-excursion - (and (outline-next-heading) - (org-flag-heading nil))) ; show the next heading (let ((current-prefix-arg arg)) (call-interactively 'org-todo)) (and (bolp) (forward-char 1)) (setq newhead (org-get-heading)) - (when (and (org-bound-and-true-p + (when (and (bound-and-true-p org-agenda-headline-snapshot-before-repeat) (not (equal org-agenda-headline-snapshot-before-repeat newhead)) @@ -8769,11 +8939,12 @@ the same tree node, and the headline of the tree node in the Org-mode file." (beginning-of-line 1) (save-window-excursion (org-agenda-change-all-lines newhead hdmarker 'fixface just-one)) - (when (org-bound-and-true-p org-clock-out-when-done) + (when (bound-and-true-p org-clock-out-when-done) (string-match (concat "^" (regexp-opt org-done-keywords-for-agenda)) newhead) (org-agenda-unmark-clocking-task)) - (org-move-to-column col)))) + (org-move-to-column col) + (org-agenda-mark-clocking-task)))) (defun org-agenda-add-note (&optional arg) "Add a time-stamped note to the entry at point." @@ -8789,9 +8960,6 @@ the same tree node, and the headline of the tree node in the Org-mode file." (widen) (goto-char pos) (org-show-context 'agenda) - (save-excursion - (and (outline-next-heading) - (org-flag-heading nil))) ; show the next heading (org-add-note)))) (defun org-agenda-change-all-lines (newhead hdmarker @@ -8808,9 +8976,9 @@ If FORCE-TAGS is non nil, the car of it returns the new tags." (line (org-current-line)) (org-agenda-buffer (current-buffer)) (thetags (with-current-buffer (marker-buffer hdmarker) - (save-excursion (save-restriction (widen) - (goto-char hdmarker) - (org-get-tags-at))))) + (org-with-wide-buffer + (goto-char hdmarker) + (org-get-tags-at)))) props m pl undone-face done-face finish new dotime level cat tags) (save-excursion (goto-char (point-max)) @@ -8822,7 +8990,7 @@ If FORCE-TAGS is non nil, the car of it returns the new tags." (equal m hdmarker)) (setq props (text-properties-at (point)) dotime (org-get-at-bol 'dotime) - cat (org-get-at-bol 'org-category) + cat (org-get-at-eol 'org-category 1) level (org-get-at-bol 'level) tags thetags new @@ -8831,20 +8999,25 @@ If FORCE-TAGS is non nil, the car of it returns the new tags." org-prefix-format-compiled)) (extra (org-get-at-bol 'extra))) (with-current-buffer (marker-buffer hdmarker) - (save-excursion - (save-restriction - (widen) - (org-agenda-format-item extra newhead level cat tags dotime))))) + (org-with-wide-buffer + (org-agenda-format-item extra newhead level cat tags dotime)))) pl (text-property-any (point-at-bol) (point-at-eol) 'org-heading t) undone-face (org-get-at-bol 'undone-face) done-face (org-get-at-bol 'done-face)) (beginning-of-line 1) (cond - ((equal new "") - (and (looking-at ".*\n?") (replace-match ""))) + ((equal new "") (delete-region (point) (line-beginning-position 2))) ((looking-at ".*") - (replace-match new t t) - (beginning-of-line 1) + ;; When replacing the whole line, preserve bulk mark + ;; overlay, if any. + (let ((mark (catch :overlay + (dolist (o (overlays-in (point) (+ 2 (point)))) + (when (eq (overlay-get o 'type) + 'org-marked-entry-overlay) + (throw :overlay o)))))) + (replace-match new t t) + (beginning-of-line) + (when mark (move-overlay mark (point) (+ 2 (point))))) (add-text-properties (point-at-bol) (point-at-eol) props) (when fixface (add-text-properties @@ -8865,7 +9038,7 @@ If FORCE-TAGS is non nil, the car of it returns the new tags." (let ((inhibit-read-only t) l c) (save-excursion (goto-char (if line (point-at-bol) (point-min))) - (while (re-search-forward (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$") + (while (re-search-forward "\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$" (if line (point-at-eol) nil) t) (add-text-properties (match-beginning 2) (match-end 2) @@ -8889,19 +9062,19 @@ If FORCE-TAGS is non nil, the car of it returns the new tags." (org-font-lock-add-tag-faces (point-max))))) (defun org-agenda-priority-up () - "Increase the priority of line at point, also in Org-mode file." + "Increase the priority of line at point, also in Org file." (interactive) (org-agenda-priority 'up)) (defun org-agenda-priority-down () - "Decrease the priority of line at point, also in Org-mode file." + "Decrease the priority of line at point, also in Org file." (interactive) (org-agenda-priority 'down)) (defun org-agenda-priority (&optional force-direction) - "Set the priority of line at point, also in Org-mode file. + "Set the priority of line at point, also in Org file. This changes the line at point, all other lines in the agenda referring to -the same tree node, and the headline of the tree node in the Org-mode file. +the same tree node, and the headline of the tree node in the Org file. Called with a universal prefix arg, show the priority instead of setting it." (interactive "P") (if (equal force-direction '(4)) @@ -8922,9 +9095,6 @@ Called with a universal prefix arg, show the priority instead of setting it." (widen) (goto-char pos) (org-show-context 'agenda) - (save-excursion - (and (outline-next-heading) - (org-flag-heading nil))) ; show the next heading (funcall 'org-priority force-direction) (end-of-line 1) (setq newhead (org-get-heading))) @@ -8936,7 +9106,7 @@ Called with a universal prefix arg, show the priority instead of setting it." "Set tags for the current headline." (interactive) (org-agenda-check-no-diary) - (if (and (org-region-active-p) (org-called-interactively-p 'any)) + (if (and (org-region-active-p) (called-interactively-p 'any)) (call-interactively 'org-change-tag-in-region) (let* ((hdmarker (or (org-get-at-bol 'org-hd-marker) (org-agenda-error))) @@ -8948,12 +9118,7 @@ Called with a universal prefix arg, show the priority instead of setting it." (with-current-buffer buffer (widen) (goto-char pos) - (save-excursion - (org-show-context 'agenda)) - (save-excursion - (and (outline-next-heading) - (org-flag-heading nil))) ; show the next heading - (goto-char pos) + (org-show-context 'agenda) (if tag (org-toggle-tag tag onoff) (call-interactively 'org-set-tags)) @@ -8976,12 +9141,7 @@ Called with a universal prefix arg, show the priority instead of setting it." (with-current-buffer buffer (widen) (goto-char pos) - (save-excursion - (org-show-context 'agenda)) - (save-excursion - (and (outline-next-heading) - (org-flag-heading nil))) ; show the next heading - (goto-char pos) + (org-show-context 'agenda) (call-interactively 'org-set-property))))) (defun org-agenda-set-effort () @@ -8998,12 +9158,7 @@ Called with a universal prefix arg, show the priority instead of setting it." (with-current-buffer buffer (widen) (goto-char pos) - (save-excursion - (org-show-context 'agenda)) - (save-excursion - (and (outline-next-heading) - (org-flag-heading nil))) ; show the next heading - (goto-char pos) + (org-show-context 'agenda) (call-interactively 'org-set-effort) (end-of-line 1) (setq newhead (org-get-heading))) @@ -9024,9 +9179,6 @@ Called with a universal prefix arg, show the priority instead of setting it." (widen) (goto-char pos) (org-show-context 'agenda) - (save-excursion - (and (outline-next-heading) - (org-flag-heading nil))) ; show the next heading (call-interactively 'org-toggle-archive-tag) (end-of-line 1) (setq newhead (org-get-heading))) @@ -9140,18 +9292,10 @@ Called with a universal prefix arg, show the priority instead of setting it." (when (equal marker (org-get-at-bol 'org-marker)) (remove-text-properties (point-at-bol) (point-at-eol) '(display)) (org-move-to-column (- (window-width) (length stamp)) t) - (if (featurep 'xemacs) - ;; Use `duplicable' property to trigger undo recording - (let ((ex (make-extent nil nil)) - (gl (make-glyph stamp))) - (set-glyph-face gl 'secondary-selection) - (set-extent-properties - ex (list 'invisible t 'end-glyph gl 'duplicable t)) - (insert-extent ex (1- (point)) (point-at-eol))) - (add-text-properties - (1- (point)) (point-at-eol) - (list 'display (org-add-props stamp nil - 'face '(secondary-selection default))))) + (add-text-properties + (1- (point)) (point-at-eol) + (list 'display (org-add-props stamp nil + 'face '(secondary-selection default)))) (beginning-of-line 1)) (beginning-of-line 0))))) @@ -9187,7 +9331,6 @@ ARG is passed through to `org-schedule'." (type (marker-insertion-type marker)) (buffer (marker-buffer marker)) (pos (marker-position marker)) - (org-insert-labeled-timestamps-at-point nil) ts) (set-marker-insertion-type marker t) (org-with-remote-undo buffer @@ -9208,7 +9351,6 @@ ARG is passed through to `org-deadline'." (org-agenda-error))) (buffer (marker-buffer marker)) (pos (marker-position marker)) - (org-insert-labeled-timestamps-at-point nil) ts) (org-with-remote-undo buffer (with-current-buffer buffer @@ -9235,7 +9377,6 @@ ARG is passed through to `org-deadline'." (widen) (goto-char pos) (org-show-context 'agenda) - (org-show-entry) (org-cycle-hide-drawers 'children) (org-clock-in arg) (setq newhead (org-get-heading))) @@ -9250,14 +9391,12 @@ ARG is passed through to `org-deadline'." (let ((marker (make-marker)) (col (current-column)) newhead) (org-with-remote-undo (marker-buffer org-clock-marker) (with-current-buffer (marker-buffer org-clock-marker) - (save-excursion - (save-restriction - (widen) - (goto-char org-clock-marker) - (org-back-to-heading t) - (move-marker marker (point)) - (org-clock-out) - (setq newhead (org-get-heading)))))) + (org-with-wide-buffer + (goto-char org-clock-marker) + (org-back-to-heading t) + (move-marker marker (point)) + (org-clock-out) + (setq newhead (org-get-heading))))) (org-agenda-change-all-lines newhead marker) (move-marker marker nil) (org-move-to-column col) @@ -9284,7 +9423,7 @@ buffer, display it in another window." (cond (pos (goto-char pos)) ;; If the currently clocked entry is not in the agenda ;; buffer, we visit it in another window: - (org-clock-current-task + ((bound-and-true-p org-clock-current-task) (org-switch-to-buffer-other-window (org-clock-goto))) (t (message "No running clock, use `C-c C-x C-j' to jump to the most recent one"))))) @@ -9334,11 +9473,13 @@ buffer, display it in another window." "Where in `org-agenda-diary-file' should new entries be added? Valid values: -date-tree in the date tree, as child of the date -top-level as top-level entries at the end of the file." +date-tree in the date tree, as first child of the date +date-tree-last in the date tree, as last child of the date +top-level as top-level entries at the end of the file." :group 'org-agenda :type '(choice - (const :tag "in a date tree" date-tree) + (const :tag "first in a date tree" date-tree) + (const :tag "last in a date tree" date-tree-last) (const :tag "as top level at end of file" top-level))) (defcustom org-agenda-insert-diary-extract-time nil @@ -9434,40 +9575,43 @@ Add TEXT as headline, and position the cursor in the second line so that a timestamp can be added there." (widen) (goto-char (point-max)) - (or (bolp) (insert "\n")) - (insert "* " text "\n") - (if org-adapt-indentation (org-indent-to-column 2))) + (unless (bolp) (insert "\n")) + (org-insert-heading nil t t) + (insert text) + (org-end-of-meta-data) + (unless (bolp) (insert "\n")) + (when org-adapt-indentation (indent-to-column 2))) (defun org-agenda-insert-diary-make-new-entry (text) - "Make a new entry with TEXT as the first child of the current subtree. -Position the point in the line right after the new heading so -that a timestamp can be added there." - (let ((org-show-following-heading t) - (org-show-siblings t) - (org-show-hierarchy-above t) - (org-show-entry-below t) - col) + "Make a new entry with TEXT as a child of the current subtree. +Position the point in the heading's first body line so that +a timestamp can be added there." + (cond + ((eq org-agenda-insert-diary-strategy 'date-tree-last) + (end-of-line) + (org-insert-heading '(4) t) + (org-do-demote)) + (t (outline-next-heading) (org-back-over-empty-lines) - (or (looking-at "[ \t]*$") - (progn (insert "\n") (backward-char 1))) + (unless (looking-at "[ \t]*$") (save-excursion (insert "\n"))) (org-insert-heading nil t) - (org-do-demote) - (setq col (current-column)) - (insert text "\n") - (if org-adapt-indentation (org-indent-to-column col)) - (let ((org-show-following-heading t) - (org-show-siblings t) - (org-show-hierarchy-above t) - (org-show-entry-below t)) - (org-show-context)))) + (org-do-demote))) + (let ((col (current-column))) + (insert text) + (org-end-of-meta-data) + ;; Ensure point is left on a blank line, at proper indentation. + (unless (bolp) (insert "\n")) + (unless (looking-at-p "^[ \t]*$") (save-excursion (insert "\n"))) + (when org-adapt-indentation (indent-to-column col))) + (org-show-set-visibility 'lineage)) (defun org-agenda-diary-entry () "Make a diary entry, like the `i' command from the calendar. All the standard commands work: block, weekly etc. When `org-agenda-diary-file' points to a file, `org-agenda-diary-entry-in-org-file' is called instead to create -entries in that Org-mode file." +entries in that Org file." (interactive) (if (not (eq org-agenda-diary-file 'diary-file)) (org-agenda-diary-entry-in-org-file) @@ -9476,13 +9620,13 @@ entries in that Org-mode file." (message "Diary entry: [d]ay [w]eekly [m]onthly [y]early [a]nniversary [b]lock [c]yclic") (read-char-exclusive))) (cmd (cdr (assoc char - '((?d . insert-diary-entry) - (?w . insert-weekly-diary-entry) - (?m . insert-monthly-diary-entry) - (?y . insert-yearly-diary-entry) - (?a . insert-anniversary-diary-entry) - (?b . insert-block-diary-entry) - (?c . insert-cyclic-diary-entry))))) + '((?d . diary-insert-entry) + (?w . diary-insert-weekly-entry) + (?m . diary-insert-monthly-entry) + (?y . diary-insert-yearly-entry) + (?a . diary-insert-anniversary-entry) + (?b . diary-insert-block-entry) + (?c . diary-insert-cyclic-entry))))) (oldf (symbol-function 'calendar-cursor-to-date)) ;; (buf (get-file-buffer (substitute-in-file-name diary-file))) (point (point)) @@ -9533,12 +9677,12 @@ entries in that Org-mode file." (defun org-agenda-phases-of-moon () "Display the phases of the moon for the 3 months around the cursor date." (interactive) - (org-agenda-execute-calendar-command 'calendar-phases-of-moon)) + (org-agenda-execute-calendar-command 'calendar-lunar-phases)) (defun org-agenda-holidays () "Display the holidays for the 3 months around the cursor date." (interactive) - (org-agenda-execute-calendar-command 'list-calendar-holidays)) + (org-agenda-execute-calendar-command 'calendar-list-holidays)) (defvar calendar-longitude) ; defined in calendar.el (defvar calendar-latitude) ; defined in calendar.el @@ -9572,12 +9716,16 @@ argument, latitude and longitude will be prompted for." ;;;###autoload (defun org-calendar-goto-agenda () - "Compute the Org-mode agenda for the calendar date displayed at the cursor. + "Compute the Org agenda for the calendar date displayed at the cursor. This is a command that has to be installed in `calendar-mode-map'." (interactive) - (org-agenda-list nil (calendar-absolute-from-gregorian - (calendar-cursor-to-date)) - nil)) + ;; Temporarily disable sticky agenda since user clearly wants to + ;; refresh view anyway. + (let ((org-agenda-buffer-tmp-name "*Org Agenda(a)*") + (org-agenda-sticky nil)) + (org-agenda-list nil (calendar-absolute-from-gregorian + (calendar-cursor-to-date)) + nil))) (defun org-agenda-convert-date () (interactive) @@ -9610,6 +9758,7 @@ This is a command that has to be installed in `calendar-mode-map'." ;;; Bulk commands (defun org-agenda-bulk-marked-p () + "Non-nil when current entry is marked for bulk action." (eq (get-char-property (point-at-bol) 'type) 'org-marked-entry-overlay)) @@ -9651,9 +9800,12 @@ This is a command that has to be installed in `calendar-mode-map'." (goto-char (next-single-property-change (point) 'org-hd-marker)) (while (and (re-search-forward regexp nil t) (setq txt-at-point (get-text-property (point) 'txt))) - (when (string-match regexp txt-at-point) - (setq entries-marked (1+ entries-marked)) - (call-interactively 'org-agenda-bulk-mark)))) + (if (get-char-property (point) 'invisible) + (beginning-of-line 2) + (when (string-match regexp txt-at-point) + (setq entries-marked (1+ entries-marked)) + (call-interactively 'org-agenda-bulk-mark))))) + (if (not entries-marked) (message "No entry matching this regexp.")))) @@ -9712,7 +9864,6 @@ This will remove the markers and the overlays." (interactive) (if (null org-agenda-bulk-marked-entries) (message "No entry to unmark") - (mapc (lambda (m) (move-marker m nil)) org-agenda-bulk-marked-entries) (setq org-agenda-bulk-marked-entries nil) (org-agenda-bulk-remove-overlays (point-min) (point-max)))) @@ -9786,21 +9937,21 @@ The prefix arg is passed through to the command if possible." redo-at-end t)) ((equal action ?t) - (setq state (org-icompleting-read + (setq state (completing-read "Todo state: " (with-current-buffer (marker-buffer (car entries)) - (mapcar 'list org-todo-keywords-1)))) + (mapcar #'list org-todo-keywords-1)))) (setq cmd `(let ((org-inhibit-blocking t) (org-inhibit-logging 'note)) (org-agenda-todo ,state)))) ((memq action '(?- ?+)) - (setq tag (org-icompleting-read + (setq tag (completing-read (format "Tag to %s: " (if (eq action ?+) "add" "remove")) (with-current-buffer (marker-buffer (car entries)) (delq nil - (mapcar (lambda (x) - (if (stringp (car x)) x)) org-tag-alist))))) + (mapcar (lambda (x) (and (stringp (car x)) x)) + org-current-tag-alist))))) (setq cmd `(org-agenda-set-tags ,tag ,(if (eq action ?+) ''on ''off)))) ((memq action '(?s ?d)) @@ -9810,8 +9961,17 @@ The prefix arg is passed through to the command if possible." nil nil nil (if (eq action ?s) "(Re)Schedule to" "(Re)Set Deadline to") org-overriding-default-time))) - (c1 (if (eq action ?s) 'org-agenda-schedule 'org-agenda-deadline))) - (setq cmd `(eval '(,c1 arg ,time))))) + (c1 (if (eq action ?s) 'org-agenda-schedule + 'org-agenda-deadline))) + ;; Make sure to not prompt for a note when bulk + ;; rescheduling as Org cannot cope with simultaneous + ;; notes. Besides, it could be annoying depending on the + ;; number of items re-scheduled. + (setq cmd `(eval '(let ((org-log-reschedule + (and org-log-reschedule 'time)) + (org-log-redeadline + (and org-log-redeadline 'time))) + (,c1 arg ,time)))))) ((equal action ?S) (if (not (org-agenda-check-type nil 'agenda 'timeline 'todo)) @@ -9828,13 +9988,13 @@ The prefix arg is passed through to the command if possible." (calendar-gregorian-from-absolute (org-today))))) (dotimes (i (1+ dist)) (while (member day-of-week org-agenda-weekend-days) - (incf distance) - (incf day-of-week) - (if (= day-of-week 7) - (setq day-of-week 0))) - (incf day-of-week) - (if (= day-of-week 7) - (setq day-of-week 0))))) + (cl-incf distance) + (cl-incf day-of-week) + (when (= day-of-week 7) + (setq day-of-week 0))) + (cl-incf day-of-week) + (when (= day-of-week 7) + (setq day-of-week 0))))) ;; silently fail when try to replan a sexp entry (condition-case nil (let* ((date (calendar-gregorian-from-absolute @@ -9850,8 +10010,8 @@ The prefix arg is passed through to the command if possible." ((equal action ?f) (setq cmd (list (intern - (org-icompleting-read "Function: " - obarray 'fboundp t nil nil))))) + (completing-read "Function: " + obarray 'fboundp t nil nil))))) (t (user-error "Invalid bulk action"))) @@ -9874,6 +10034,11 @@ The prefix arg is passed through to the command if possible." (goto-char pos) (let (org-loop-over-headlines-in-active-region) (eval cmd)) + ;; `post-command-hook' is not run yet. We make sure any + ;; pending log note is processed. + (when (or (memq 'org-add-log-note (default-value 'post-command-hook)) + (memq 'org-add-log-note post-command-hook)) + (org-add-log-note)) (setq cnt (1+ cnt)))) (when redo-at-end (org-agenda-redo)) (unless org-agenda-persistent-marks @@ -9903,12 +10068,14 @@ current HH:MM time." (defun org-agenda-reapply-filters () "Re-apply all agenda filters." (mapcar - (lambda(f) (when (car f) (org-agenda-filter-apply (car f) (cadr f)))) + (lambda(f) (when (car f) (org-agenda-filter-apply (car f) (cadr f) t))) `((,org-agenda-tag-filter tag) (,org-agenda-category-filter category) (,org-agenda-regexp-filter regexp) + (,org-agenda-effort-filter effort) (,(get 'org-agenda-tag-filter :preset-filter) tag) (,(get 'org-agenda-category-filter :preset-filter) category) + (,(get 'org-agenda-effort-filter :preset-filter) effort) (,(get 'org-agenda-regexp-filter :preset-filter) regexp)))) (defun org-agenda-drag-line-forward (arg &optional backward) @@ -9969,7 +10136,9 @@ tag and (if present) the flagging note." (replace-match "\n" t t)) (goto-char (point-min)) (select-window win) - (message "Flagging note pushed to kill ring. Press [?] again to remove tag and note")))) + (message "%s" (substitute-command-keys "Flagging note pushed to \ +kill ring. Press `\\[org-agenda-show-the-flagging-note]' again to remove \ +tag and note"))))) (defun org-agenda-remove-flag (marker) "Remove the FLAGGED tag and any flagging note in the entry." @@ -9992,7 +10161,8 @@ tag and (if present) the flagging note." ;;;###autoload (defun org-agenda-to-appt (&optional refresh filter &rest args) "Activate appointments found in `org-agenda-files'. -With a \\[universal-argument] prefix, refresh the list of + +With a `\\[universal-argument]' prefix, refresh the list of \ appointments. If FILTER is t, interactively prompt the user for a regular @@ -10008,8 +10178,8 @@ argument: an entry from `org-agenda-get-day-entries'. FILTER can also be an alist with the car of each cell being either `headline' or `category'. For example: - ((headline \"IMPORTANT\") - (category \"Work\")) + \\='((headline \"IMPORTANT\") + (category \"Work\")) will only add headlines containing IMPORTANT or headlines belonging to the \"Work\" category. @@ -10026,75 +10196,78 @@ to override `appt-message-warning-time'." (if refresh (setq appt-time-msg-list nil)) (if (eq filter t) (setq filter (read-from-minibuffer "Regexp filter: "))) - (let* ((cnt 0) ; count added events - (scope (or args '(:deadline* :scheduled* :timestamp))) - (org-agenda-new-buffers nil) - (org-deadline-warning-days 0) - ;; Do not use `org-today' here because appt only takes - ;; time and without date as argument, so it may pass wrong - ;; information otherwise - (today (org-date-to-gregorian - (time-to-days (current-time)))) - (org-agenda-restrict nil) - (files (org-agenda-files 'unrestricted)) entries file - (org-agenda-buffer nil)) + (let* ((cnt 0) ; count added events + (scope (or args '(:deadline* :scheduled* :timestamp))) + (org-agenda-new-buffers nil) + (org-deadline-warning-days 0) + ;; Do not use `org-today' here because appt only takes + ;; time and without date as argument, so it may pass wrong + ;; information otherwise + (today (org-date-to-gregorian + (time-to-days (current-time)))) + (org-agenda-restrict nil) + (files (org-agenda-files 'unrestricted)) entries file + (org-agenda-buffer nil)) ;; Get all entries which may contain an appt (org-agenda-prepare-buffers files) (while (setq file (pop files)) (setq entries - (delq nil - (append entries - (apply 'org-agenda-get-day-entries - file today scope))))) + (delq nil + (append entries + (apply 'org-agenda-get-day-entries + file today scope))))) ;; Map thru entries and find if we should filter them out (mapc - (lambda(x) + (lambda (x) (let* ((evt (org-trim - (replace-regexp-in-string - org-bracket-link-regexp "\\3" - (or (get-text-property 1 'txt x) "")))) - (cat (get-text-property 1 'org-category x)) - (tod (get-text-property 1 'time-of-day x)) - (ok (or (null filter) - (and (stringp filter) (string-match filter evt)) - (and (functionp filter) (funcall filter x)) - (and (listp filter) - (let ((cat-filter (cadr (assoc 'category filter))) - (evt-filter (cadr (assoc 'headline filter)))) - (or (and (stringp cat-filter) - (string-match cat-filter cat)) - (and (stringp evt-filter) - (string-match evt-filter evt))))))) - (wrn (get-text-property 1 'warntime x))) - ;; FIXME: Shall we remove text-properties for the appt text? - ;; (setq evt (set-text-properties 0 (length evt) nil evt)) - (when (and ok tod) - (setq tod (concat "00" (number-to-string tod)) - tod (when (string-match - "\\([0-9]\\{1,2\\}\\)\\([0-9]\\{2\\}\\)\\'" tod) - (concat (match-string 1 tod) ":" - (match-string 2 tod)))) - (if (version< emacs-version "23.3") - (appt-add tod evt) - (appt-add tod evt wrn)) - (setq cnt (1+ cnt))))) entries) + (replace-regexp-in-string + org-bracket-link-regexp "\\3" + (or (get-text-property 1 'txt x) "")))) + (cat (get-text-property (1- (length x)) 'org-category x)) + (tod (get-text-property 1 'time-of-day x)) + (ok (or (null filter) + (and (stringp filter) (string-match filter evt)) + (and (functionp filter) (funcall filter x)) + (and (listp filter) + (let ((cat-filter (cadr (assq 'category filter))) + (evt-filter (cadr (assq 'headline filter)))) + (or (and (stringp cat-filter) + (string-match cat-filter cat)) + (and (stringp evt-filter) + (string-match evt-filter evt))))))) + (wrn (get-text-property 1 'warntime x))) + ;; FIXME: Shall we remove text-properties for the appt text? + ;; (setq evt (set-text-properties 0 (length evt) nil evt)) + (when (and ok tod (not (string-match "\\`DONE\\|CANCELLED" evt))) + (setq tod (concat "00" (number-to-string tod))) + (setq tod (when (string-match + "\\([0-9]\\{1,2\\}\\)\\([0-9]\\{2\\}\\)\\'" tod) + (concat (match-string 1 tod) ":" + (match-string 2 tod)))) + (when (if (version< emacs-version "23.3") + (appt-add tod evt) + (appt-add tod evt wrn)) + (setq cnt (1+ cnt)))))) + entries) (org-release-buffers org-agenda-new-buffers) (if (eq cnt 0) - (message "No event to add") + (message "No event to add") (message "Added %d event%s for today" cnt (if (> cnt 1) "s" ""))))) -(defun org-agenda-todayp (date) - "Does DATE mean today, when considering `org-extend-today-until'?" - (let ((today (org-today)) - (date (if (and date (listp date)) (calendar-absolute-from-gregorian date) - date))) - (eq date today))) +(defun org-agenda-today-p (date) + "Non nil when DATE means today. +DATE is either a list of the form (month day year) or a number of +days as returned by `calendar-absolute-from-gregorian' or +`org-today'. This function considers `org-extend-today-until' +when defining today." + (eq (org-today) + (if (consp date) (calendar-absolute-from-gregorian date) date))) (defun org-agenda-todo-yesterday (&optional arg) "Like `org-agenda-todo' but the time of change will be 23:59 of yesterday." (interactive "P") - (let* ((hour (third (decode-time - (org-current-time)))) + (let* ((org-use-effective-time t) + (hour (nth 2 (decode-time (org-current-time)))) (org-extend-today-until (1+ hour))) (org-agenda-todo arg))) diff --git a/lisp/org/org-archive.el b/lisp/org/org-archive.el index 39a6581046a..ce1f35df365 100644 --- a/lisp/org/org-archive.el +++ b/lisp/org/org-archive.el @@ -1,4 +1,4 @@ -;;; org-archive.el --- Archiving for Org-mode +;;; org-archive.el --- Archiving for Org -*- lexical-binding: t; -*- ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. @@ -29,10 +29,10 @@ ;;; Code: (require 'org) -(eval-when-compile (require 'cl)) -(declare-function org-inlinetask-remove-END-maybe "org-inlinetask" ()) +(declare-function org-element-type "org-element" (element)) (declare-function org-datetree-find-date-create "org-datetree" (date &optional keep-restriction)) +(declare-function org-inlinetask-remove-END-maybe "org-inlinetask" ()) (defcustom org-archive-default-command 'org-archive-subtree "The default archiving command." @@ -57,7 +57,7 @@ See `org-archive-to-archive-sibling' for more information." (defcustom org-archive-mark-done nil "Non-nil means mark entries as DONE when they are moved to the archive file. -This can be a string to set the keyword to use. When t, Org-mode will +This can be a string to set the keyword to use. When non-nil, Org will use the first keyword in its list that means done." :group 'org-archive :type '(choice @@ -120,9 +120,15 @@ information." (const :tag "Outline path" olpath) (const :tag "Local tags" ltags))) +(defvar org-archive-hook nil + "Hook run after successfully archiving a subtree. +Hook functions are called with point on the subtree in the +original file. At this stage, the subtree has been added to the +archive location, but not yet deleted from the original file.") + (defun org-get-local-archive-location () "Get the archive location applicable at point." - (let ((re "^#\\+ARCHIVE:[ \t]+\\(\\S-.*\\S-\\)[ \t]*$") + (let ((re "^[ \t]*#\\+ARCHIVE:[ \t]+\\(\\S-.*\\S-\\)[ \t]*$") prop) (save-excursion (save-restriction @@ -154,21 +160,24 @@ archive file is." (defun org-all-archive-files () "Get a list of all archive files used in the current buffer." - (let (file files) - (save-excursion - (save-restriction - (goto-char (point-min)) - (while (re-search-forward - "^\\(#\\+\\|[ \t]*:\\)ARCHIVE:[ \t]+\\(.*\\)" - nil t) - (setq file (org-extract-archive-file - (org-match-string-no-properties 2))) - (and file (> (length file) 0) (file-exists-p file) - (pushnew file files :test #'equal))))) + (let ((case-fold-search t) + files) + (org-with-wide-buffer + (goto-char (point-min)) + (while (re-search-forward + "^[ \t]*\\(#\\+\\|:\\)ARCHIVE:[ \t]+\\(.*\\)" + nil t) + (when (save-match-data + (if (eq (match-string 1) ":") (org-at-property-p) + (eq (org-element-type (org-element-at-point)) 'keyword))) + (let ((file (org-extract-archive-file + (match-string-no-properties 2)))) + (when (and (org-string-nw-p file) (file-exists-p file)) + (push file files)))))) (setq files (nreverse files)) - (setq file (org-extract-archive-file)) - (and file (> (length file) 0) (file-exists-p file) - (pushnew file files :test #'equal)) + (let ((file (org-extract-archive-file))) + (when (and (org-string-nw-p file) (file-exists-p file)) + (push file files))) files)) (defun org-extract-archive-file (&optional location) @@ -195,15 +204,19 @@ if LOCATION is not given, the value of `org-archive-location' is used." ;;;###autoload (defun org-archive-subtree (&optional find-done) "Move the current subtree to the archive. -The archive can be a certain top-level heading in the current file, or in -a different file. The tree will be moved to that location, the subtree -heading be marked DONE, and the current time will be added. - -When called with prefix argument FIND-DONE, find whole trees without any -open TODO items and archive them (after getting confirmation from the user). -If the cursor is not at a headline when this command is called, try all level -1 trees. If the cursor is on a headline, only try the direct children of -this heading." +The archive can be a certain top-level heading in the current +file, or in a different file. The tree will be moved to that +location, the subtree heading be marked DONE, and the current +time will be added. + +When called with a single prefix argument FIND-DONE, find whole +trees without any open TODO items and archive them (after getting +confirmation from the user). When called with a double prefix +argument, find whole trees with timestamps before today and +archive them (after getting confirmation from the user). If the +cursor is not at a headline when these commands are called, try +all level 1 trees. If the cursor is on a headline, only try the +direct children of this heading." (interactive "P") (if (and (org-region-active-p) org-loop-over-headlines-in-active-region) (let ((cl (if (eq org-loop-over-headlines-in-active-region 'start-level) @@ -213,46 +226,36 @@ this heading." `(progn (setq org-map-continue-from (progn (org-back-to-heading) (point))) (org-archive-subtree ,find-done)) org-loop-over-headlines-in-active-region - cl (if (outline-invisible-p) (org-end-of-subtree nil t)))) - (if find-done - (org-archive-all-done) + cl (if (org-invisible-p) (org-end-of-subtree nil t)))) + (cond + ((equal find-done '(4)) (org-archive-all-done)) + ((equal find-done '(16)) (org-archive-all-old)) + (t ;; Save all relevant TODO keyword-relatex variables - (let ((tr-org-todo-line-regexp org-todo-line-regexp) ; keep despite compiler - (tr-org-todo-keywords-1 org-todo-keywords-1) - (tr-org-todo-kwd-alist org-todo-kwd-alist) - (tr-org-done-keywords org-done-keywords) - (tr-org-todo-regexp org-todo-regexp) - (tr-org-todo-line-regexp org-todo-line-regexp) - (tr-org-odd-levels-only org-odd-levels-only) - (this-buffer (current-buffer)) - ;; start of variables that will be used for saving context - ;; The compiler complains about them - keep them anyway! - (file (abbreviate-file-name - (or (buffer-file-name (buffer-base-buffer)) - (error "No file associated to buffer")))) - (olpath (mapconcat 'identity (org-get-outline-path) "/")) - (time (format-time-string - (substring (cdr org-time-stamp-formats) 1 -1))) - category todo priority ltags itags atags - ;; end of variables that will be used for saving context - location afile heading buffer level newfile-p infile-p visiting - datetree-date datetree-subheading-p) - - ;; Find the local archive location - (setq location (org-get-local-archive-location) - afile (org-extract-archive-file location) - heading (org-extract-archive-heading location) - infile-p (equal file (abbreviate-file-name (or afile "")))) - (unless afile - (error "Invalid `org-archive-location'")) - - (if (> (length afile) 0) - (setq newfile-p (not (file-exists-p afile)) - visiting (find-buffer-visiting afile) - buffer (or visiting (find-file-noselect afile))) - (setq buffer (current-buffer))) - (unless buffer - (error "Cannot access file \"%s\"" afile)) + (let* ((tr-org-todo-keywords-1 org-todo-keywords-1) + (tr-org-todo-kwd-alist org-todo-kwd-alist) + (tr-org-done-keywords org-done-keywords) + (tr-org-todo-regexp org-todo-regexp) + (tr-org-todo-line-regexp org-todo-line-regexp) + (tr-org-odd-levels-only org-odd-levels-only) + (this-buffer (current-buffer)) + (time (format-time-string + (substring (cdr org-time-stamp-formats) 1 -1))) + (file (abbreviate-file-name + (or (buffer-file-name (buffer-base-buffer)) + (error "No file associated to buffer")))) + (location (org-get-local-archive-location)) + (afile (or (org-extract-archive-file location) + (error "Invalid `org-archive-location'"))) + (heading (org-extract-archive-heading location)) + (infile-p (equal file (abbreviate-file-name (or afile "")))) + (newfile-p (and (org-string-nw-p afile) + (not (file-exists-p afile)))) + (buffer (cond ((not (org-string-nw-p afile)) this-buffer) + ((find-buffer-visiting afile)) + ((find-file-noselect afile)) + (t (error "Cannot access file \"%s\"" afile)))) + level datetree-date datetree-subheading-p) (when (string-match "\\`datetree/" heading) ;; Replace with ***, to represent the 3 levels of headings the ;; datetree has. @@ -266,108 +269,120 @@ this heading." (setq heading nil level 0)) (save-excursion (org-back-to-heading t) - ;; Get context information that will be lost by moving the tree - (setq category (org-get-category nil 'force-refresh) - todo (and (looking-at org-todo-line-regexp) - (match-string 2)) - priority (org-get-priority - (if (match-end 3) (match-string 3) "")) - ltags (org-get-tags) - itags (org-delete-all ltags (org-get-tags-at)) - atags (org-get-tags-at)) - (setq ltags (mapconcat 'identity ltags " ") - itags (mapconcat 'identity itags " ")) - ;; We first only copy, in case something goes wrong - ;; we need to protect `this-command', to avoid kill-region sets it, - ;; which would lead to duplication of subtrees - (let (this-command) (org-copy-subtree 1 nil t)) - (set-buffer buffer) - ;; Enforce org-mode for the archive buffer - (if (not (derived-mode-p 'org-mode)) - ;; Force the mode for future visits. - (let ((org-insert-mode-line-in-empty-file t) - (org-inhibit-startup t)) - (call-interactively 'org-mode))) - (when (and newfile-p org-archive-file-header-format) - (goto-char (point-max)) - (insert (format org-archive-file-header-format - (buffer-file-name this-buffer)))) - (when datetree-date - (require 'org-datetree) - (org-datetree-find-date-create datetree-date) - (org-narrow-to-subtree)) - ;; Force the TODO keywords of the original buffer - (let ((org-todo-line-regexp tr-org-todo-line-regexp) - (org-todo-keywords-1 tr-org-todo-keywords-1) - (org-todo-kwd-alist tr-org-todo-kwd-alist) - (org-done-keywords tr-org-done-keywords) - (org-todo-regexp tr-org-todo-regexp) - (org-todo-line-regexp tr-org-todo-line-regexp) - (org-odd-levels-only - (if (local-variable-p 'org-odd-levels-only (current-buffer)) - org-odd-levels-only - tr-org-odd-levels-only))) - (goto-char (point-min)) - (show-all) - (if (and heading (not (and datetree-date (not datetree-subheading-p)))) - (progn - (if (re-search-forward - (concat "^" (regexp-quote heading) - (org-re "[ \t]*\\(:[[:alnum:]_@#%:]+:\\)?[ \t]*\\($\\|\r\\)")) - nil t) - (goto-char (match-end 0)) - ;; Heading not found, just insert it at the end - (goto-char (point-max)) - (or (bolp) (insert "\n")) - ;; datetrees don't need too much spacing - (insert (if datetree-date "" "\n") heading "\n") - (end-of-line 0)) - ;; Make the subtree visible - (show-subtree) - (if org-archive-reversed-order - (progn - (org-back-to-heading t) - (outline-next-heading)) - (org-end-of-subtree t)) - (skip-chars-backward " \t\r\n") - (and (looking-at "[ \t\r\n]*") - ;; datetree archives don't need so much spacing. - (replace-match (if datetree-date "\n" "\n\n")))) - ;; No specific heading, just go to end of file. - (goto-char (point-max)) (unless datetree-date (insert "\n"))) - ;; Paste - (org-paste-subtree (org-get-valid-level level (and heading 1))) - ;; Shall we append inherited tags? - (and itags - (or (and (eq org-archive-subtree-add-inherited-tags 'infile) - infile-p) - (eq org-archive-subtree-add-inherited-tags t)) - (org-set-tags-to atags)) - ;; Mark the entry as done - (when (and org-archive-mark-done - (looking-at org-todo-line-regexp) - (or (not (match-end 2)) - (not (member (match-string 2) org-done-keywords)))) - (let (org-log-done org-todo-log-states) - (org-todo - (car (or (member org-archive-mark-done org-done-keywords) - org-done-keywords))))) - - ;; Add the context info - (when org-archive-save-context-info - (let ((l org-archive-save-context-info) e n v) - (while (setq e (pop l)) - (when (and (setq v (symbol-value e)) - (stringp v) (string-match "\\S-" v)) - (setq n (concat "ARCHIVE_" (upcase (symbol-name e)))) - (org-entry-put (point) n v))))) - - (widen) - ;; Save and kill the buffer, if it is not the same buffer. - (when (not (eq this-buffer buffer)) - (save-buffer)))) - ;; Here we are back in the original buffer. Everything seems to have - ;; worked. So now cut the tree and finish up. + ;; Get context information that will be lost by moving the + ;; tree. See `org-archive-save-context-info'. + (let* ((all-tags (org-get-tags-at)) + (local-tags (org-get-tags)) + (inherited-tags (org-delete-all local-tags all-tags)) + (context + `((category . ,(org-get-category nil 'force-refresh)) + (file . ,file) + (itags . ,(mapconcat #'identity inherited-tags " ")) + (ltags . ,(mapconcat #'identity local-tags " ")) + (olpath . ,(mapconcat #'identity + (org-get-outline-path) + "/")) + (time . ,time) + (todo . ,(org-entry-get (point) "TODO"))))) + ;; We first only copy, in case something goes wrong + ;; we need to protect `this-command', to avoid kill-region sets it, + ;; which would lead to duplication of subtrees + (let (this-command) (org-copy-subtree 1 nil t)) + (set-buffer buffer) + ;; Enforce Org mode for the archive buffer + (if (not (derived-mode-p 'org-mode)) + ;; Force the mode for future visits. + (let ((org-insert-mode-line-in-empty-file t) + (org-inhibit-startup t)) + (call-interactively 'org-mode))) + (when (and newfile-p org-archive-file-header-format) + (goto-char (point-max)) + (insert (format org-archive-file-header-format + (buffer-file-name this-buffer)))) + (when datetree-date + (require 'org-datetree) + (org-datetree-find-date-create datetree-date) + (org-narrow-to-subtree)) + ;; Force the TODO keywords of the original buffer + (let ((org-todo-line-regexp tr-org-todo-line-regexp) + (org-todo-keywords-1 tr-org-todo-keywords-1) + (org-todo-kwd-alist tr-org-todo-kwd-alist) + (org-done-keywords tr-org-done-keywords) + (org-todo-regexp tr-org-todo-regexp) + (org-todo-line-regexp tr-org-todo-line-regexp) + (org-odd-levels-only + (if (local-variable-p 'org-odd-levels-only (current-buffer)) + org-odd-levels-only + tr-org-odd-levels-only))) + (goto-char (point-min)) + (outline-show-all) + (if (and heading (not (and datetree-date (not datetree-subheading-p)))) + (progn + (if (re-search-forward + (concat "^" (regexp-quote heading) + "[ \t]*\\(:[[:alnum:]_@#%:]+:\\)?[ \t]*\\($\\|\r\\)") + nil t) + (goto-char (match-end 0)) + ;; Heading not found, just insert it at the end + (goto-char (point-max)) + (or (bolp) (insert "\n")) + ;; datetrees don't need too much spacing + (insert (if datetree-date "" "\n") heading "\n") + (end-of-line 0)) + ;; Make the subtree visible + (outline-show-subtree) + (if org-archive-reversed-order + (progn + (org-back-to-heading t) + (outline-next-heading)) + (org-end-of-subtree t)) + (skip-chars-backward " \t\r\n") + (and (looking-at "[ \t\r\n]*") + ;; datetree archives don't need so much spacing. + (replace-match (if datetree-date "\n" "\n\n")))) + ;; No specific heading, just go to end of file. + (goto-char (point-max)) + ;; Subtree narrowing can let the buffer end on + ;; a headline. `org-paste-subtree' then deletes it. + ;; To prevent this, make sure visible part of buffer + ;; always terminates on a new line, while limiting + ;; number of blank lines in a date tree. + (unless (and datetree-date (bolp)) (insert "\n"))) + ;; Paste + (org-paste-subtree (org-get-valid-level level (and heading 1))) + ;; Shall we append inherited tags? + (and inherited-tags + (or (and (eq org-archive-subtree-add-inherited-tags 'infile) + infile-p) + (eq org-archive-subtree-add-inherited-tags t)) + (org-set-tags-to all-tags)) + ;; Mark the entry as done + (when (and org-archive-mark-done + (let ((case-fold-search nil)) + (looking-at org-todo-line-regexp)) + (or (not (match-end 2)) + (not (member (match-string 2) org-done-keywords)))) + (let (org-log-done org-todo-log-states) + (org-todo + (car (or (member org-archive-mark-done org-done-keywords) + org-done-keywords))))) + + ;; Add the context info. + (dolist (item org-archive-save-context-info) + (let ((value (cdr (assq item context)))) + (when (org-string-nw-p value) + (org-entry-put + (point) + (concat "ARCHIVE_" (upcase (symbol-name item))) + value)))) + (widen) + ;; Save and kill the buffer, if it is not the same + ;; buffer. + (unless (eq this-buffer buffer) (save-buffer))))) + ;; Here we are back in the original buffer. Everything seems + ;; to have worked. So now run hooks, cut the tree and finish + ;; up. + (run-hooks 'org-archive-hook) (let (this-command) (org-cut-subtree)) (when (featurep 'org-inlinetask) (org-inlinetask-remove-END-maybe)) @@ -375,7 +390,7 @@ this heading." (message "Subtree archived %s" (if (eq this-buffer buffer) (concat "under heading: " heading) - (concat "in file: " (abbreviate-file-name afile)))))) + (concat "in file: " (abbreviate-file-name afile))))))) (org-reveal) (if (looking-at "^[ \t]*$") (outline-next-visible-heading 1)))) @@ -383,9 +398,12 @@ this heading." ;;;###autoload (defun org-archive-to-archive-sibling () "Archive the current heading by moving it under the archive sibling. + The archive sibling is a sibling of the heading with the heading name `org-archive-sibling-heading' and an `org-archive-tag' tag. If this -sibling does not exist, it will be created at the end of the subtree." +sibling does not exist, it will be created at the end of the subtree. + +Archiving time is retained in the ARCHIVE_TIME node property." (interactive) (if (and (org-region-active-p) org-loop-over-headlines-in-active-region) (let ((cl (when (eq org-loop-over-headlines-in-active-region 'start-level) @@ -400,7 +418,7 @@ sibling does not exist, it will be created at the end of the subtree." (when (org-at-heading-p) (org-archive-to-archive-sibling))) org-loop-over-headlines-in-active-region - cl (if (outline-invisible-p) (org-end-of-subtree nil t)))) + cl (if (org-invisible-p) (org-end-of-subtree nil t)))) (save-restriction (widen) (let (b e pos leader level) @@ -443,7 +461,7 @@ sibling does not exist, it will be created at the end of the subtree." (format-time-string (substring (cdr org-time-stamp-formats) 1 -1))) (outline-up-heading 1 t) - (hide-subtree) + (outline-hide-subtree) (org-cycle-show-empty-lines 'folded) (goto-char pos))) (org-reveal) @@ -455,13 +473,51 @@ sibling does not exist, it will be created at the end of the subtree." If the cursor is not on a headline, try all level 1 trees. If it is on a headline, try all direct children. When TAG is non-nil, don't move trees, but mark them with the ARCHIVE tag." - (let ((re org-not-done-heading-regexp) re1 - (rea (concat ".*:" org-archive-tag ":")) + (org-archive-all-matches + (lambda (_beg end) + (let ((case-fold-search nil)) + (unless (re-search-forward org-not-done-heading-regexp end t) + "no open TODO items"))) + tag)) + +(defun org-archive-all-old (&optional tag) + "Archive sublevels of the current tree with timestamps prior to today. +If the cursor is not on a headline, try all level 1 trees. If +it is on a headline, try all direct children. +When TAG is non-nil, don't move trees, but mark them with the ARCHIVE tag." + (org-archive-all-matches + (lambda (_beg end) + (let (ts) + (and (re-search-forward org-ts-regexp end t) + (setq ts (match-string 0)) + (< (org-time-stamp-to-now ts) 0) + (if (not (looking-at + (concat "--\\(" org-ts-regexp "\\)"))) + (concat "old timestamp " ts) + (setq ts (concat "old timestamp " ts (match-string 0))) + (and (< (org-time-stamp-to-now (match-string 1)) 0) + ts))))) + tag)) + +(defun org-archive-all-matches (predicate &optional tag) + "Archive sublevels of the current tree that match PREDICATE. + +PREDICATE is a function of two arguments, BEG and END, which +specify the beginning and end of the headline being considered. +It is called with point positioned at BEG. The headline will be +archived if PREDICATE returns non-nil. If the return value of +PREDICATE is a string, it should describe the reason for +archiving the heading. + +If the cursor is not on a headline, try all level 1 trees. If it +is on a headline, try all direct children. When TAG is non-nil, +don't move trees, but mark them with the ARCHIVE tag." + (let ((rea (concat ".*:" org-archive-tag ":")) re1 (begm (make-marker)) (endm (make-marker)) - (question (if tag "Set ARCHIVE tag (no open TODO items)? " - "Move subtree to archive (no open TODO items)? ")) - beg end (cntarch 0)) + (question (if tag "Set ARCHIVE tag? " + "Move subtree to archive? ")) + reason beg end (cntarch 0)) (if (org-at-heading-p) (progn (setq re1 (concat "^" (regexp-quote @@ -481,11 +537,14 @@ When TAG is non-nil, don't move trees, but mark them with the ARCHIVE tag." (setq beg (match-beginning 0) end (save-excursion (org-end-of-subtree t) (point))) (goto-char beg) - (if (re-search-forward re end t) + (if (not (setq reason (funcall predicate beg end))) (goto-char end) (goto-char beg) (if (and (or (not tag) (not (looking-at rea))) - (y-or-n-p question)) + (y-or-n-p + (if (stringp reason) + (concat question "(" reason ")") + question))) (progn (if tag (org-toggle-tag org-archive-tag 'on) @@ -507,14 +566,14 @@ the children that do not contain any open TODO items." (org-map-entries `(org-toggle-archive-tag ,find-done) org-loop-over-headlines-in-active-region - cl (if (outline-invisible-p) (org-end-of-subtree nil t)))) + cl (if (org-invisible-p) (org-end-of-subtree nil t)))) (if find-done (org-archive-all-done 'tag) (let (set) (save-excursion (org-back-to-heading t) (setq set (org-toggle-tag org-archive-tag)) - (when set (hide-subtree))) + (when set (org-flag-subtree t))) (and set (beginning-of-line 1)) (message "Subtree %s" (if set "archived" "unarchived")))))) @@ -528,7 +587,7 @@ the children that do not contain any open TODO items." (org-map-entries 'org-archive-set-tag org-loop-over-headlines-in-active-region - cl (if (outline-invisible-p) (org-end-of-subtree nil t)))) + cl (if (org-invisible-p) (org-end-of-subtree nil t)))) (org-toggle-tag org-archive-tag 'on))) ;;;###autoload diff --git a/lisp/org/org-attach.el b/lisp/org/org-attach.el index 7d25437d9f5..a026eee4f13 100644 --- a/lisp/org/org-attach.el +++ b/lisp/org/org-attach.el @@ -1,4 +1,4 @@ -;;; org-attach.el --- Manage file attachments to org-mode tasks +;;; org-attach.el --- Manage file attachments to Org tasks -*- lexical-binding: t; -*- ;; Copyright (C) 2008-2017 Free Software Foundation, Inc. @@ -22,7 +22,7 @@ ;;; Commentary: -;; See the Org-mode manual for information on how to use it. +;; See the Org manual for information on how to use it. ;; ;; Attachments are managed in a special directory called "data", which ;; lives in the same directory as the org file itself. If this data @@ -37,14 +37,13 @@ ;;; Code: -(eval-when-compile - (require 'cl)) -(require 'org-id) +(require 'cl-lib) (require 'org) +(require 'org-id) (require 'vc-git) (defgroup org-attach nil - "Options concerning entry attachments in Org-mode." + "Options concerning entry attachments in Org mode." :tag "Org Attach" :group 'org) @@ -55,6 +54,14 @@ where the Org file lives." :group 'org-attach :type 'directory) +(defcustom org-attach-commit t + "If non-nil commit attachments with git. +This is only done if the Org file is in a git repository." + :group 'org-attach + :type 'boolean + :version "26.1" + :package-version '(Org . "9.0")) + (defcustom org-attach-git-annex-cutoff (* 32 1024) "If non-nil, files larger than this will be annexed instead of stored." :group 'org-attach @@ -120,6 +127,28 @@ lns create a symbol link. Note that this is not supported (const :tag "Link to origin location" t) (const :tag "Link to the attach-dir location" attached))) +(defcustom org-attach-archive-delete nil + "Non-nil means attachments are deleted upon archiving a subtree. +When set to `query', ask the user instead." + :group 'org-attach + :version "26.1" + :package-version '(Org . "8.3") + :type '(choice + (const :tag "Never delete attachments" nil) + (const :tag "Always delete attachments" t) + (const :tag "Query the user" query))) + +(defcustom org-attach-annex-auto-get 'ask + "Confirmation preference for automatically getting annex files. +If \\='ask, prompt using `y-or-n-p'. If t, always get. If nil, never get." + :group 'org-attach + :package-version '(Org . "9") + :version "26.1" + :type '(choice + (const :tag "confirm with `y-or-n-p'" ask) + (const :tag "always get from annex if necessary" t) + (const :tag "never get from annex" nil))) + ;;;###autoload (defun org-attach () "The dispatcher for attachment commands. @@ -197,25 +226,23 @@ using the entry ID will be invoked to access the unique directory for the current entry. If the directory does not exist and CREATE-IF-NOT-EXISTS-P is non-nil, the directory and (if necessary) the corresponding ID will be created." - (let (attach-dir uuid inherit) + (let (attach-dir uuid) (setq org-attach-inherited (org-entry-get nil "ATTACH_DIR_INHERIT")) (cond ((setq attach-dir (org-entry-get nil "ATTACH_DIR")) (org-attach-check-absolute-path attach-dir)) ((and org-attach-allow-inheritance - (setq inherit (org-entry-get nil "ATTACH_DIR_INHERIT" t))) + (org-entry-get nil "ATTACH_DIR_INHERIT" t)) (setq attach-dir - (save-excursion - (save-restriction - (widen) - (if (marker-position org-entry-property-inherited-from) - (goto-char org-entry-property-inherited-from) - (org-back-to-heading t)) - (let (org-attach-allow-inheritance) - (org-attach-dir create-if-not-exists-p))))) + (org-with-wide-buffer + (if (marker-position org-entry-property-inherited-from) + (goto-char org-entry-property-inherited-from) + (org-back-to-heading t)) + (let (org-attach-allow-inheritance) + (org-attach-dir create-if-not-exists-p)))) (org-attach-check-absolute-path attach-dir) (setq org-attach-inherited t)) - (t ; use the ID + (t ; use the ID (org-attach-check-absolute-path nil) (setq uuid (org-id-get (point) create-if-not-exists-p)) (when (or uuid create-if-not-exists-p) @@ -261,33 +288,59 @@ the ATTACH_DIR property) their own attachment directory." (org-entry-put nil "ATTACH_DIR_INHERIT" "t") (message "Children will inherit attachment directory")) +(defun org-attach-use-annex () + "Return non-nil if git annex can be used." + (let ((git-dir (vc-git-root (expand-file-name org-attach-directory)))) + (and org-attach-git-annex-cutoff + (or (file-exists-p (expand-file-name "annex" git-dir)) + (file-exists-p (expand-file-name ".git/annex" git-dir)))))) + +(defun org-attach-annex-get-maybe (path) + "Call git annex get PATH (via shell) if using git annex. +Signals an error if the file content is not available and it was not retrieved." + (let ((path-relative (file-relative-name path))) + (when (and (org-attach-use-annex) + (not + (string-equal + "found" + (shell-command-to-string + (format "git annex find --format=found --in=here %s" + (shell-quote-argument path-relative)))))) + (let ((should-get + (if (eq org-attach-annex-auto-get 'ask) + (y-or-n-p (format "Run git annex get %s? " path-relative)) + org-attach-annex-auto-get))) + (if should-get + (progn (message "Running git annex get \"%s\"." path-relative) + (call-process "git" nil nil nil "annex" "get" path-relative)) + (error "File %s stored in git annex but it is not available, and was not retrieved" + path)))))) + (defun org-attach-commit () "Commit changes to git if `org-attach-directory' is properly initialized. This checks for the existence of a \".git\" directory in that directory." (let* ((dir (expand-file-name org-attach-directory)) (git-dir (vc-git-root dir)) + (use-annex (org-attach-use-annex)) (changes 0)) (when (and git-dir (executable-find "git")) (with-temp-buffer (cd dir) - (let ((have-annex - (and org-attach-git-annex-cutoff - (file-exists-p (expand-file-name "annex" git-dir))))) - (dolist (new-or-modified - (split-string - (shell-command-to-string - "git ls-files -zmo --exclude-standard") "\0" t)) - (if (and have-annex - (>= (nth 7 (file-attributes new-or-modified)) - org-attach-git-annex-cutoff)) - (call-process "git" nil nil nil "annex" "add" new-or-modified) - (call-process "git" nil nil nil "add" new-or-modified)) - (incf changes))) + (dolist (new-or-modified + (split-string + (shell-command-to-string + "git ls-files -zmo --exclude-standard") "\0" t)) + (if (and use-annex + (>= (nth 7 (file-attributes new-or-modified)) + org-attach-git-annex-cutoff)) + (call-process "git" nil nil nil "annex" "add" new-or-modified) + (call-process "git" nil nil nil "add" new-or-modified)) + (cl-incf changes)) (dolist (deleted (split-string (shell-command-to-string "git ls-files -z --deleted") "\0" t)) (call-process "git" nil nil nil "rm" deleted) - (incf changes)) + (cl-incf changes)) (when (> changes 0) (shell-command "git commit -m 'Synchronized attachments'")))))) @@ -328,7 +381,8 @@ METHOD may be `cp', `mv', `ln', or `lns' default taken from ((eq method 'cp) (copy-file file fname)) ((eq method 'ln) (add-name-to-file file fname)) ((eq method 'lns) (make-symbolic-link file fname))) - (org-attach-commit) + (when org-attach-commit + (org-attach-commit)) (org-attach-tag) (cond ((eq org-attach-store-link-p 'attached) (org-attach-store-link fname)) @@ -378,7 +432,7 @@ The attachment is created as an Emacs buffer." (let* ((attach-dir (org-attach-dir t)) (files (org-attach-file-list attach-dir)) (file (or file - (org-icompleting-read + (completing-read "Delete attachment: " (mapcar (lambda (f) (list (file-name-nondirectory f))) @@ -387,7 +441,8 @@ The attachment is created as an Emacs buffer." (unless (file-exists-p file) (error "No such attachment: %s" file)) (delete-file file) - (org-attach-commit))) + (when org-attach-commit + (org-attach-commit)))) (defun org-attach-delete-all (&optional force) "Delete all attachments from the current task. @@ -403,14 +458,16 @@ A safer way is to open the directory in dired and delete from there." (y-or-n-p "Are you sure you want to remove all attachments of this entry? "))) (shell-command (format "rm -fr %s" attach-dir)) (message "Attachment directory removed") - (org-attach-commit) + (when org-attach-commit + (org-attach-commit)) (org-attach-untag)))) (defun org-attach-sync () "Synchronize the current tasks with its attachments. This can be used after files have been added externally." (interactive) - (org-attach-commit) + (when org-attach-commit + (org-attach-commit)) (when (and org-attach-file-list-property (not org-attach-inherited)) (org-entry-delete (point) org-attach-file-list-property)) (let ((attach-dir (org-attach-dir))) @@ -419,15 +476,15 @@ This can be used after files have been added externally." (and files (org-attach-tag)) (when org-attach-file-list-property (dolist (file files) - (unless (string-match "^\\." file) + (unless (string-match "^\\.\\.?\\'" file) (org-entry-add-to-multivalued-property (point) org-attach-file-list-property file)))))))) (defun org-attach-file-list (dir) "Return a list of files in the attachment directory. -This ignores files starting with a \".\", and files ending in \"~\"." +This ignores files ending in \"~\"." (delq nil - (mapcar (lambda (x) (if (string-match "^\\." x) nil x)) + (mapcar (lambda (x) (if (string-match "^\\.\\.?\\'" x) nil x)) (directory-files dir nil "[^~]\\'")))) (defun org-attach-reveal (&optional if-exists) @@ -454,9 +511,11 @@ If IN-EMACS is non-nil, force opening in Emacs." (files (org-attach-file-list attach-dir)) (file (if (= (length files) 1) (car files) - (org-icompleting-read "Open attachment: " - (mapcar 'list files) nil t)))) - (org-open-file (expand-file-name file attach-dir) in-emacs))) + (completing-read "Open attachment: " + (mapcar #'list files) nil t))) + (path (expand-file-name file attach-dir))) + (org-attach-annex-get-maybe path) + (org-open-file path in-emacs))) (defun org-attach-open-in-emacs () "Open attachment, force opening in Emacs. @@ -475,6 +534,17 @@ Basically, this adds the path to the attachment directory, and a \"file:\" prefix." (concat "file:" (org-attach-expand file))) +(defun org-attach-archive-delete-maybe () + "Maybe delete subtree attachments when archiving. +This function is called by `org-archive-hook'. The option +`org-attach-archive-delete' controls its behavior." + (when (if (eq org-attach-archive-delete 'query) + (yes-or-no-p "Delete all attachments? ") + org-attach-archive-delete) + (org-attach-delete-all t))) + +(add-hook 'org-archive-hook 'org-attach-archive-delete-maybe) + (provide 'org-attach) ;; Local variables: diff --git a/lisp/org/org-bbdb.el b/lisp/org/org-bbdb.el index e41bda47dbf..bf6a79ab855 100644 --- a/lisp/org/org-bbdb.el +++ b/lisp/org/org-bbdb.el @@ -1,4 +1,4 @@ -;;; org-bbdb.el --- Support for links to BBDB entries from within Org-mode +;;; org-bbdb.el --- Support for links to BBDB entries -*- lexical-binding: t; -*- ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. @@ -25,12 +25,12 @@ ;; ;;; Commentary: -;; This file implements links to BBDB database entries from within Org-mode. -;; Org-mode loads this module by default - if this is not what you want, +;; This file implements links to BBDB database entries from within Org. +;; Org mode loads this module by default - if this is not what you want, ;; configure the variable `org-modules'. ;; It also implements an interface (based on Ivar Rummelhoff's -;; bbdb-anniv.el) for those org-mode users, who do not use the diary +;; bbdb-anniv.el) for those Org users, who do not use the diary ;; but who do want to include the anniversaries stored in the BBDB ;; into the org-agenda. If you already include the `diary' into the ;; agenda, you might want to prefer to include the anniversaries in @@ -94,8 +94,7 @@ ;;; Code: (require 'org) -(eval-when-compile - (require 'cl)) +(require 'cl-lib) ;; Declare external functions and variables @@ -106,6 +105,7 @@ (declare-function bbdb-name "ext:bbdb-com" (string elidep)) (declare-function bbdb-completing-read-record "ext:bbdb-com" (prompt &optional omit-records)) +(declare-function bbdb-record-field "ext:bbdb" (record field)) (declare-function bbdb-record-getprop "ext:bbdb" (record property)) (declare-function bbdb-record-name "ext:bbdb" (record)) (declare-function bbdb-records "ext:bbdb" @@ -124,7 +124,7 @@ (declare-function calendar-leap-year-p "calendar" (year)) (declare-function diary-ordinal-suffix "diary-lib" (n)) -(org-no-warnings (defvar date)) ;; unprefixed, from calendar.el +(with-no-warnings (defvar date)) ;; unprefixed, from calendar.el ;; Customization @@ -194,10 +194,12 @@ date year)." :group 'org-bbdb-anniversaries :require 'bbdb) - ;; Install the link type -(org-add-link-type "bbdb" 'org-bbdb-open 'org-bbdb-export) -(add-hook 'org-store-link-functions 'org-bbdb-store-link) +(org-link-set-parameters "bbdb" + :follow #'org-bbdb-open + :export #'org-bbdb-export + :complete #'org-bbdb-complete-link + :store #'org-bbdb-store-link) ;; Implementation (defun org-bbdb-store-link () @@ -208,7 +210,7 @@ date year)." (name (bbdb-record-name rec)) (company (if (fboundp 'bbdb-record-getprop) (bbdb-record-getprop rec 'company) - (car (bbdb-record-get-field rec 'organization)))) + (car (bbdb-record-field rec 'organization)))) (link (concat "bbdb:" name))) (org-store-link-props :type "bbdb" :name name :company company :link link :description name) @@ -230,10 +232,9 @@ italicized, in all other cases it is left unchanged." (defun org-bbdb-open (name) "Follow a BBDB link to NAME." (require 'bbdb-com) - (let ((inhibit-redisplay (not debug-on-error)) - (bbdb-electric-p nil)) + (let ((inhibit-redisplay (not debug-on-error))) (if (fboundp 'bbdb-name) - (org-bbdb-open-old name) + (org-bbdb-open-old name) (org-bbdb-open-new name)))) (defun org-bbdb-open-old (name) @@ -280,14 +281,11 @@ italicized, in all other cases it is left unchanged." "Convert YYYY-MM-DD to (month date year). Argument TIME-STR is the value retrieved from BBDB. If YYYY- is omitted it will be considered unknown." - (multiple-value-bind (a b c) (values-list (org-split-string time-str "-")) - (if (eq c nil) - (list (string-to-number a) - (string-to-number b) - nil) - (list (string-to-number b) - (string-to-number c) - (string-to-number a))))) + (pcase (org-split-string time-str "-") + (`(,a ,b nil) (list (string-to-number a) (string-to-number b) nil)) + (`(,a ,b ,c) (list (string-to-number b) + (string-to-number c) + (string-to-number a))))) (defun org-bbdb-anniv-split (str) "Split multiple entries in the BBDB anniversary field. @@ -325,9 +323,9 @@ The anniversaries are assumed to be stored `org-bbdb-anniversary-field'." (bbdb-split "\n" annivs))) (while annivs (setq split (org-bbdb-anniv-split (pop annivs))) - (multiple-value-bind (m d y) - (values-list (funcall org-bbdb-extract-date-fun (car split))) - (setq tmp (gethash (list m d) org-bbdb-anniv-hash)) + (pcase-let ((`(,m ,d ,y) (funcall org-bbdb-extract-date-fun + (car split)))) + (setq tmp (gethash (list m d) org-bbdb-anniv-hash)) (puthash (list m d) (cons (list y (bbdb-record-name rec) (cadr split)) @@ -335,7 +333,7 @@ The anniversaries are assumed to be stored `org-bbdb-anniversary-field'." org-bbdb-anniv-hash)))))) (setq org-bbdb-updated-p nil)) -(defun org-bbdb-updated (rec) +(defun org-bbdb-updated (_rec) "Record the fact that BBDB has been updated. This is used by Org to re-create the anniversary hash table." (setq org-bbdb-updated-p t)) @@ -397,6 +395,66 @@ This is used by Org to re-create the anniversary hash table." )) text)) +;;; Return list of anniversaries for today and the next n-1 (default: n=7) days. +;;; This is meant to be used in an org file instead of org-bbdb-anniversaries: +;;; +;;; %%(org-bbdb-anniversaries-future) +;;; +;;; or +;;; +;;; %%(org-bbdb-anniversaries-future 3) +;;; +;;; to override the 7-day default. + +(defun org-bbdb-date-list (d n) + "Return a list of dates in (m d y) format from the given date D to n-1 days hence." + (let ((abs (calendar-absolute-from-gregorian d))) + (mapcar (lambda (i) (calendar-gregorian-from-absolute (+ abs i))) + (number-sequence 0 (1- n))))) + +;;;###autoload +(defun org-bbdb-anniversaries-future (&optional n) + "Return list of anniversaries for today and the next n-1 days (default n=7)." + (let ((n (or n 7))) + (when (<= n 0) + (error "The (optional) argument of `org-bbdb-anniversaries-future' \ +must be positive")) + (let ( + ;; List of relevant dates. + (dates (org-bbdb-date-list date n)) + ;; Function to annotate text of each element of l with the + ;; anniversary date d. + (annotate-descriptions + (lambda (d l) + (mapcar (lambda (x) + ;; The assumption here is that x is a bbdb link + ;; of the form [[bbdb:name][description]]. + ;; This function rather arbitrarily modifies + ;; the description by adding the date to it in + ;; a fixed format. + (string-match "]]" x) + (replace-match (format " -- %d-%02d-%02d\\&" + (nth 2 d) + (nth 0 d) + (nth 1 d)) + nil nil x)) + l)))) + ;; Map a function that generates anniversaries for each date + ;; over the dates and nconc the results into a single list. When + ;; it is no longer necessary to support older versions of Emacs, + ;; this can be done with a cl-mapcan; for now, we use the (apply + ;; #'nconc ...) method for compatibility. + (apply #'nconc + (mapcar + (lambda (d) + (let ((date d)) + ;; Rebind 'date' so that org-bbdb-anniversaries will + ;; be fooled into giving us the list for the given + ;; date and then annotate the descriptions for that + ;; date. + (funcall annotate-descriptions d (org-bbdb-anniversaries)))) + dates))))) + (defun org-bbdb-complete-link () "Read a bbdb link with name completion." (require 'bbdb-com) diff --git a/lisp/org/org-bibtex.el b/lisp/org/org-bibtex.el index f8b376daa18..d52b9475836 100644 --- a/lisp/org/org-bibtex.el +++ b/lisp/org/org-bibtex.el @@ -1,4 +1,4 @@ -;;; org-bibtex.el --- Org links to BibTeX entries +;;; org-bibtex.el --- Org links to BibTeX entries -*- lexical-binding: t; -*- ;; ;; Copyright (C) 2007-2017 Free Software Foundation, Inc. ;; @@ -73,7 +73,7 @@ ;; ===================================================================== ;; ;; Additionally, the following functions are now available for storing -;; bibtex entries within Org-mode documents. +;; bibtex entries within Org documents. ;; ;; - Run `org-bibtex' to export the current file to a .bib. ;; @@ -92,27 +92,28 @@ ;; ;;; History: ;; -;; The link creation part has been part of Org-mode for a long time. +;; The link creation part has been part of Org for a long time. ;; ;; Creating better capture template information was inspired by a request ;; of Austin Frank: http://article.gmane.org/gmane.emacs.orgmode/4112 ;; and then implemented by Bastien Guerry. ;; ;; Eric Schulte eventually added the functions for translating between -;; Org-mode headlines and Bibtex entries, and for fleshing out the Bibtex -;; fields of existing Org-mode headlines. +;; Org headlines and Bibtex entries, and for fleshing out the Bibtex +;; fields of existing Org headlines. ;; -;; Org-mode loads this module by default - if this is not what you want, +;; Org mode loads this module by default - if this is not what you want, ;; configure the variable `org-modules'. ;;; Code: (require 'org) (require 'bibtex) -(eval-when-compile - (require 'cl)) +(require 'cl-lib) (require 'org-compat) +(defvar org-agenda-overriding-header) +(defvar org-agenda-search-view-always-boolean) (defvar org-bibtex-description nil) ; dynamically scoped from org.el (defvar org-id-locations) @@ -120,7 +121,6 @@ (declare-function bibtex-generate-autokey "bibtex" ()) (declare-function bibtex-parse-entry "bibtex" (&optional content)) (declare-function bibtex-url "bibtex" (&optional pos no-browse)) -(declare-function org-babel-trim "ob-core" (string &optional regexp)) ;;; Bibtex data @@ -264,26 +264,39 @@ IDs must be unique." (defcustom org-bibtex-tags-are-keywords nil "Convert the value of the keywords field to tags and vice versa. -If set to t, comma-separated entries in a bibtex entry's keywords -field will be converted to org tags. Note: spaces will be escaped -with underscores, and characters that are not permitted in org + +When non-nil, comma-separated entries in a bibtex entry's keywords +field will be converted to Org tags. Note: spaces will be escaped +with underscores, and characters that are not permitted in Org tags will be removed. -If t, local tags in an org entry will be exported as a -comma-separated string of keywords when exported to bibtex. Tags -defined in `org-bibtex-tags' or `org-bibtex-no-export-tags' will -not be exported." +When non-nil, local tags in an Org entry will be exported as +a comma-separated string of keywords when exported to bibtex. +If `org-bibtex-inherit-tags' is non-nil, inherited tags will also +be exported as keywords. Tags defined in `org-bibtex-tags' or +`org-bibtex-no-export-tags' will not be exported." :group 'org-bibtex :version "24.1" :type 'boolean) (defcustom org-bibtex-no-export-tags nil "List of tag(s) that should not be converted to keywords. -This variable is relevant only if `org-bibtex-tags-are-keywords' is t." +This variable is relevant only if `org-bibtex-tags-are-keywords' +is non-nil." :group 'org-bibtex :version "24.1" :type '(repeat :tag "Tag" (string))) +(defcustom org-bibtex-inherit-tags nil + "Controls whether inherited tags are converted to bibtex keywords. +It is relevant only if `org-bibtex-tags-are-keywords' is non-nil. +Tag inheritance itself is controlled by `org-use-tag-inheritance' +and `org-exclude-tags-from-inheritance'." + :group 'org-bibtex + :version "26.1" + :package-version '(Org . "8.3") + :type 'boolean) + (defcustom org-bibtex-type-property-name "btype" "Property in which to store bibtex entry type (e.g., article)." :group 'org-bibtex @@ -299,7 +312,7 @@ This variable is relevant only if `org-bibtex-tags-are-keywords' is t." (org-entry-get (point) (upcase property)) (org-entry-get (point) (concat org-bibtex-prefix (upcase property))))))) - (when it (org-babel-trim it)))) + (when it (org-trim it)))) (defun org-bibtex-put (property value) (let ((prop (upcase (if (keywordp property) @@ -312,27 +325,27 @@ This variable is relevant only if `org-bibtex-tags-are-keywords' is t." (defun org-bibtex-headline () "Return a bibtex entry of the given headline as a string." - (let* ((val (lambda (key lst) (cdr (assoc key lst)))) - (to (lambda (string) (intern (concat ":" string)))) - (from (lambda (key) (substring (symbol-name key) 1))) - flatten ; silent compiler warning - (flatten (lambda (&rest lsts) - (apply #'append (mapcar - (lambda (e) - (if (listp e) (apply flatten e) (list e))) - lsts)))) - (notes (buffer-string)) - (id (org-bibtex-get org-bibtex-key-property)) - (type (org-bibtex-get org-bibtex-type-property-name)) - (tags (when org-bibtex-tags-are-keywords - (delq nil - (mapcar - (lambda (tag) - (unless (member tag - (append org-bibtex-tags - org-bibtex-no-export-tags)) - tag)) - (org-get-local-tags-at)))))) + (letrec ((val (lambda (key lst) (cdr (assoc key lst)))) + (to (lambda (string) (intern (concat ":" string)))) + (from (lambda (key) (substring (symbol-name key) 1))) + (flatten (lambda (&rest lsts) + (apply #'append (mapcar + (lambda (e) + (if (listp e) (apply flatten e) (list e))) + lsts)))) + (id (org-bibtex-get org-bibtex-key-property)) + (type (org-bibtex-get org-bibtex-type-property-name)) + (tags (when org-bibtex-tags-are-keywords + (delq nil + (mapcar + (lambda (tag) + (unless (member tag + (append org-bibtex-tags + org-bibtex-no-export-tags)) + tag)) + (if org-bibtex-inherit-tags + (org-get-tags-at) + (org-get-local-tags-at))))))) (when type (let ((entry (format "@%s{%s,\n%s\n}\n" type id @@ -358,7 +371,7 @@ This variable is relevant only if `org-bibtex-tags-are-keywords' is t." (mapcar (lambda (field) (let ((value (or (org-bibtex-get (funcall from field)) - (and (equal :title field) + (and (eq :title field) (nth 4 (org-heading-components)))))) (when value (cons (funcall from field) value)))) (funcall flatten @@ -421,13 +434,14 @@ With optional argument OPTIONAL, also prompt for optional fields." (funcall val :required (funcall val type org-bibtex-types))) (when optional (funcall val :optional (funcall val type org-bibtex-types))))) (when (consp field) ; or'd pair of fields e.g., (:editor :author) - (let ((present (first (remove + (let ((present (nth 0 (remove nil (mapcar - (lambda (f) (when (org-bibtex-get (funcall name f)) f)) + (lambda (f) + (when (org-bibtex-get (funcall name f)) f)) field))))) (setf field (or present (funcall keyword - (org-icompleting-read + (completing-read "Field: " (mapcar name field))))))) (let ((name (funcall name field))) (unless (org-bibtex-get name) @@ -439,8 +453,9 @@ With optional argument OPTIONAL, also prompt for optional fields." ;;; Bibtex link functions -(org-add-link-type "bibtex" 'org-bibtex-open) -(add-hook 'org-store-link-functions 'org-bibtex-store-link) +(org-link-set-parameters "bibtex" + :follow #'org-bibtex-open + :store #'org-bibtex-store-link) (defun org-bibtex-open (path) "Visit the bibliography entry on PATH." @@ -533,21 +548,23 @@ With optional argument OPTIONAL, also prompt for optional fields." (add-hook 'org-execute-file-search-functions 'org-execute-file-search-in-bibtex) -;;; Bibtex <-> Org-mode headline translation functions -(defun org-bibtex (&optional filename) +;;; Bibtex <-> Org headline translation functions +(defun org-bibtex (filename) "Export each headline in the current file to a bibtex entry. Headlines are exported using `org-bibtex-headline'." (interactive (list (read-file-name "Bibtex file: " nil nil nil - (file-name-nondirectory - (concat (file-name-sans-extension (buffer-file-name)) ".bib"))))) + (let ((file (buffer-file-name (buffer-base-buffer)))) + (and file + (file-name-nondirectory + (concat (file-name-sans-extension file) ".bib"))))))) (let ((error-point (catch 'bib (let ((bibtex-entries (remove nil (org-map-entries (lambda () - (condition-case foo + (condition-case nil (org-bibtex-headline) (error (throw 'bib (point))))))))) (with-temp-file filename @@ -578,7 +595,7 @@ With prefix argument OPTIONAL also prompt for optional fields." With a prefix arg, query for optional fields as well. If nonew is t, add data to the headline of the entry at point." (interactive "P") - (let* ((type (org-icompleting-read + (let* ((type (completing-read "Type: " (mapcar (lambda (type) (substring (symbol-name (car type)) 1)) org-bibtex-types) @@ -597,7 +614,7 @@ If nonew is t, add data to the headline of the entry at point." (org-bibtex-put org-bibtex-type-property-name (substring (symbol-name type) 1)) (org-bibtex-fleshout type arg) - (mapc (lambda (tag) (org-toggle-tag tag 'on)) org-bibtex-tags))) + (dolist (tag org-bibtex-tags) (org-toggle-tag tag 'on)))) (defun org-bibtex-create-in-current-entry (&optional arg) "Add bibliographical data to the current entry. @@ -611,10 +628,10 @@ This uses `bibtex-parse-entry'." (interactive) (let ((keyword (lambda (str) (intern (concat ":" (downcase str))))) (clean-space (lambda (str) (replace-regexp-in-string - "[[:space:]\n\r]+" " " str))) + "[[:space:]\n\r]+" " " str))) (strip-delim - (lambda (str) ; strip enclosing "..." and {...} - (dolist (pair '((34 . 34) (123 . 125) (123 . 125))) + (lambda (str) ; strip enclosing "..." and {...} + (dolist (pair '((34 . 34) (123 . 125))) (when (and (> (length str) 1) (= (aref str 0) (car pair)) (= (aref str (1- (length str))) (cdr pair))) @@ -622,10 +639,10 @@ This uses `bibtex-parse-entry'." (push (mapcar (lambda (pair) (cons (let ((field (funcall keyword (car pair)))) - (case field + (pcase field (:=type= :type) (:=key= :key) - (otherwise field))) + (_ field))) (funcall clean-space (funcall strip-delim (cdr pair))))) (save-excursion (bibtex-beginning-of-entry) (bibtex-parse-entry))) org-bibtex-entries))) @@ -633,7 +650,7 @@ This uses `bibtex-parse-entry'." (defun org-bibtex-read-buffer (buffer) "Read all bibtex entries in BUFFER and save to `org-bibtex-entries'. Return the number of saved entries." - (interactive "bbuffer: ") + (interactive "bBuffer: ") (let ((start-length (length org-bibtex-entries))) (with-current-buffer buffer (save-excursion @@ -643,12 +660,12 @@ Return the number of saved entries." (org-bibtex-read) (bibtex-beginning-of-entry)))) (let ((added (- (length org-bibtex-entries) start-length))) - (message "parsed %d entries" added) + (message "Parsed %d entries" added) added))) (defun org-bibtex-read-file (file) "Read FILE with `org-bibtex-read-buffer'." - (interactive "ffile: ") + (interactive "fFile: ") (org-bibtex-read-buffer (find-file-noselect file 'nowarn 'rawfile))) (defun org-bibtex-write () @@ -666,25 +683,23 @@ Return the number of saved entries." (org-bibtex-put org-bibtex-type-property-name (downcase (funcall val :type))) (dolist (pair entry) - (case (car pair) + (pcase (car pair) (:title nil) (:type nil) (:key (org-bibtex-put org-bibtex-key-property (cdr pair))) (:keywords (if org-bibtex-tags-are-keywords - (mapc - (lambda (kw) - (funcall - togtag - (replace-regexp-in-string - "[^[:alnum:]_@#%]" "" - (replace-regexp-in-string "[ \t]+" "_" kw)))) - (split-string (cdr pair) ", *")) + (dolist (kw (split-string (cdr pair) ", *")) + (funcall + togtag + (replace-regexp-in-string + "[^[:alnum:]_@#%]" "" + (replace-regexp-in-string "[ \t]+" "_" kw)))) (org-bibtex-put (car pair) (cdr pair)))) - (otherwise (org-bibtex-put (car pair) (cdr pair))))) + (_ (org-bibtex-put (car pair) (cdr pair))))) (mapc togtag org-bibtex-tags))) (defun org-bibtex-yank () - "If kill ring holds a bibtex entry yank it as an Org-mode headline." + "If kill ring holds a bibtex entry yank it as an Org headline." (interactive) (let (entry) (with-temp-buffer (yank 1) (setf entry (org-bibtex-read))) @@ -693,8 +708,8 @@ Return the number of saved entries." (error "Yanked text does not appear to contain a BibTeX entry")))) (defun org-bibtex-import-from-file (file) - "Read bibtex entries from FILE and insert as Org-mode headlines after point." - (interactive "ffile: ") + "Read bibtex entries from FILE and insert as Org headlines after point." + (interactive "fFile: ") (dotimes (_ (org-bibtex-read-file file)) (save-excursion (org-bibtex-write)) (re-search-forward org-property-end-re) diff --git a/lisp/org/org-capture.el b/lisp/org/org-capture.el index b302113f3e8..63e23cc118b 100644 --- a/lisp/org/org-capture.el +++ b/lisp/org/org-capture.el @@ -1,4 +1,4 @@ -;;; org-capture.el --- Fast note taking in Org-mode +;;; org-capture.el --- Fast note taking in Org -*- lexical-binding: t; -*- ;; Copyright (C) 2010-2017 Free Software Foundation, Inc. @@ -47,23 +47,22 @@ ;;; Code: -(eval-when-compile - (require 'cl)) +(require 'cl-lib) (require 'org) +(declare-function org-at-encrypted-entry-p "org-crypt" ()) (declare-function org-datetree-find-date-create "org-datetree" (date &optional keep-restriction)) -(declare-function org-table-get-specials "org-table" ()) -(declare-function org-table-goto-line "org-table" (N)) -(declare-function org-pop-to-buffer-same-window "org-compat" - (&optional buffer-or-name norecord label)) -(declare-function org-at-encrypted-entry-p "org-crypt" ()) -(declare-function org-encrypt-entry "org-crypt" ()) (declare-function org-decrypt-entry "org-crypt" ()) +(declare-function org-encrypt-entry "org-crypt" ()) +(declare-function org-table-analyze "org-table" ()) +(declare-function org-table-goto-line "org-table" (N)) +(defvar org-end-time-was-given) (defvar org-remember-default-headline) (defvar org-remember-templates) (defvar org-table-hlines) +(defvar org-table-current-begin-pos) (defvar dired-buffers) (defvar org-capture-clock-was-started nil @@ -76,6 +75,9 @@ ;; to indicate that the link properties have already been stored (defvar org-capture-link-is-already-stored nil) +(defvar org-capture-is-refiling nil + "Non-nil when capture process is refiling an entry.") + (defgroup org-capture nil "Options concerning capturing new entries." :tag "Org Capture" @@ -103,9 +105,9 @@ description A short string describing the template, will be shown during selection. type The type of entry. Valid types are: - entry an Org-mode node, with a headline. Will be - filed as the child of the target entry or as - a top-level entry. + entry an Org node, with a headline. Will be filed + as the child of the target entry or as a + top-level entry. item a plain list item, will be placed in the first plain list at the target location. @@ -116,21 +118,22 @@ type The type of entry. Valid types are: plain text to be inserted as it is. target Specification of where the captured item should be placed. - In Org-mode files, targets usually define a node. Entries will + In Org files, targets usually define a node. Entries will become children of this node, other types will be added to the table or list in the body of this node. Most target specifications contain a file name. If that file name is the empty string, it defaults to `org-default-notes-file'. A file can also be given as a variable, function, or Emacs Lisp - form. + form. When an absolute path is not specified for a + target, it is taken as relative to `org-directory'. Valid values are: (file \"path/to/file\") Text will be placed at the beginning or end of that file - (id \"id of existing org entry\") + (id \"id of existing Org entry\") File as child of this entry, or in the body of the entry (file+headline \"path/to/file\" \"node headline\") @@ -148,6 +151,12 @@ target Specification of where the captured item should be placed. (file+datetree+prompt \"path/to/file\") Will create a heading in a date tree, prompts for date + (file+weektree \"path/to/file\") + Will create a heading in a week tree for today's date + + (file+weektree+prompt \"path/to/file\") + Will create a heading in a week tree, prompts for date + (file+function \"path/to/file\" function-finding-location) A function to find the right location in the file @@ -155,8 +164,8 @@ target Specification of where the captured item should be placed. File to the entry that is currently being clocked (function function-finding-location) - Most general way, write your own function to find both - file and location + Most general way: write your own function which both visits + the file and moves point to the right location template The template for creating the capture item. If you leave this empty, an appropriate default template will be used. See below @@ -218,15 +227,20 @@ properties are: is finalized. The template defines the text to be inserted. Often this is an -org-mode entry (so the first line should start with a star) that +Org mode entry (so the first line should start with a star) that will be filed as a child of the target headline. It can also be freely formatted text. Furthermore, the following %-escapes will -be replaced with content and expanded in this order: +be replaced with content and expanded: - %[pathname] Insert the contents of the file given by `pathname'. + %[pathname] Insert the contents of the file given by + `pathname'. These placeholders are expanded at the very + beginning of the process so they can be used to extend the + current template. %(sexp) Evaluate elisp `(sexp)' and replace it with the results. - For convenience, %:keyword (see below) placeholders within - the expression will be expanded prior to this. + Only placeholders pre-existing within the template, or + introduced with %[pathname] are expanded this way. Since this + happens after expanding non-interactive %-escapes, those can + be used to fill the expression. %<...> The result of format-time-string on the ... format specification. %t Time stamp, date only. %T Time stamp with date and time. @@ -255,8 +269,8 @@ be replaced with content and expanded in this order: A default value and a completion table ca be specified like this: %^{prompt|default|completion2|completion3|...}. %? After completing the template, position cursor here. - %\\n Insert the text entered at the nth %^{prompt}, where `n' is - a number, starting from 1. + %\\1 ... %\\N Insert the text entered at the nth %^{prompt}, where N + is a number, starting from 1. Apart from these general escapes, you can access information specific to the link type that is created. For example, calling `org-capture' in emails @@ -274,13 +288,21 @@ gnus | %:from %:fromname %:fromaddress | %:date %:date-timestamp (as active timestamp) | %:date-timestamp-inactive (as inactive timestamp) gnus | %:group, for messages also all email fields -w3, w3m | %:type %:url +eww, w3, w3m | %:type %:url info | %:type %:file %:node -calendar | %:type %:date" +calendar | %:type %:date + +When you need to insert a literal percent sign in the template, +you can escape ambiguous cases with a backward slash, e.g., \\%i." :group 'org-capture :version "24.1" :type - '(repeat + (let ((file-variants '(choice :tag "Filename " + (file :tag "Literal") + (function :tag "Function") + (variable :tag "Variable") + (sexp :tag "Form")))) + `(repeat (choice :value ("" "" entry (file "~/org/notes.org") "") (list :tag "Multikey description" (string :tag "Keys ") @@ -297,39 +319,45 @@ calendar | %:type %:date" (choice :tag "Target location" (list :tag "File" (const :format "" file) - (file :tag " File")) + ,file-variants) (list :tag "ID" (const :format "" id) (string :tag " ID")) (list :tag "File & Headline" (const :format "" file+headline) - (file :tag " File ") + ,file-variants (string :tag " Headline")) (list :tag "File & Outline path" (const :format "" file+olp) - (file :tag " File ") + ,file-variants (repeat :tag "Outline path" :inline t (string :tag "Headline"))) (list :tag "File & Regexp" (const :format "" file+regexp) - (file :tag " File ") + ,file-variants (regexp :tag " Regexp")) (list :tag "File & Date tree" (const :format "" file+datetree) - (file :tag " File")) + ,file-variants) (list :tag "File & Date tree, prompt for date" (const :format "" file+datetree+prompt) - (file :tag " File")) + ,file-variants) + (list :tag "File & Week tree" + (const :format "" file+weektree) + ,file-variants) + (list :tag "File & Week tree, prompt for date" + (const :format "" file+weektree+prompt) + ,file-variants) (list :tag "File & function" (const :format "" file+function) - (file :tag " File ") + ,file-variants (sexp :tag " Function")) (list :tag "Current clocking task" (const :format "" clock)) (list :tag "Function" (const :format "" function) (sexp :tag " Function"))) - (choice :tag "Template" + (choice :tag "Template " (string) (list :tag "File" (const :format "" file) @@ -350,7 +378,7 @@ calendar | %:type %:date" ((const :format "%v " :clock-resume) (const t)) ((const :format "%v " :unnarrowed) (const t)) ((const :format "%v " :table-line-pos) (const t)) - ((const :format "%v " :kill-buffer) (const t)))))))) + ((const :format "%v " :kill-buffer) (const t))))))))) (defcustom org-capture-before-finalize-hook nil "Hook that is run right before a capture process is finalized. @@ -421,7 +449,7 @@ to avoid conflicts with other active capture processes." (defvar org-capture-mode-map (make-sparse-keymap) "Keymap for `org-capture-mode', a minor mode. -Use this map to set additional keybindings for when Org-mode is used +Use this map to set additional keybindings for when Org mode is used for a capture buffer.") (defvar org-capture-mode-hook nil @@ -432,10 +460,12 @@ for a capture buffer.") Turning on this mode runs the normal hook `org-capture-mode-hook'." nil " Rem" org-capture-mode-map - (org-set-local - 'header-line-format + (setq-local + header-line-format (substitute-command-keys - "Capture buffer. Finish `C-c C-c', refile `C-c C-w', abort `C-c C-k'."))) + "\\Capture buffer. Finish \ +`\\[org-capture-finalize]', refile `\\[org-capture-refile]', \ +abort `\\[org-capture-kill]'."))) (define-key org-capture-mode-map "\C-c\C-c" 'org-capture-finalize) (define-key org-capture-mode-map "\C-c\C-k" 'org-capture-kill) (define-key org-capture-mode-map "\C-c\C-w" 'org-capture-refile) @@ -460,7 +490,7 @@ For example, if you have a capture template \"c\" and you want this template to be accessible only from `message-mode' buffers, use this: - ((\"c\" ((in-mode . \"message-mode\")))) + \\='((\"c\" ((in-mode . \"message-mode\")))) Here are the available contexts definitions: @@ -478,7 +508,7 @@ accessible if there is at least one valid check. You can also bind a key to another agenda custom command depending on contextual rules. - ((\"c\" \"d\" ((in-mode . \"message-mode\")))) + \\='((\"c\" \"d\" ((in-mode . \"message-mode\")))) Here it means: in `message-mode buffers', use \"c\" as the key for the capture template otherwise associated with \"d\". @@ -504,7 +534,8 @@ to avoid duplicates.)" (defcustom org-capture-use-agenda-date nil "Non-nil means use the date at point when capturing from agendas. -When nil, you can still capture using the date at point with \\[org-agenda-capture]." +When nil, you can still capture using the date at point with +`\\[org-agenda-capture]'." :group 'org-capture :version "24.3" :type 'boolean) @@ -513,17 +544,20 @@ When nil, you can still capture using the date at point with \\[org-agenda-captu (defun org-capture (&optional goto keys) "Capture something. \\ -This will let you select a template from `org-capture-templates', and then -file the newly captured information. The text is immediately inserted -at the target location, and an indirect buffer is shown where you can -edit it. Pressing \\[org-capture-finalize] brings you back to the previous state -of Emacs, so that you can continue your work. - -When called interactively with a \\[universal-argument] prefix argument GOTO, don't capture -anything, just go to the file/headline where the selected template -stores its notes. With a double prefix argument \ -\\[universal-argument] \\[universal-argument], go to the last note -stored. +This will let you select a template from `org-capture-templates', and +then file the newly captured information. The text is immediately +inserted at the target location, and an indirect buffer is shown where +you can edit it. Pressing `\\[org-capture-finalize]' brings you back to the \ +previous +state of Emacs, so that you can continue your work. + +When called interactively with a `\\[universal-argument]' prefix argument \ +GOTO, don't +capture anything, just go to the file/headline where the selected +template stores its notes. + +With a `\\[universal-argument] \\[universal-argument]' prefix argument, go to \ +the last note stored. When called with a `C-0' (zero) prefix, insert a template at point. @@ -564,7 +598,7 @@ of the day at point (if any) or the current HH:MM time." ((equal entry "C") (customize-variable 'org-capture-templates)) ((equal entry "q") - (error "Abort")) + (user-error "Abort")) (t (org-capture-set-plist entry) (org-capture-get-template) @@ -596,10 +630,10 @@ of the day at point (if any) or the current HH:MM time." (org-capture-insert-template-here) (condition-case error (org-capture-place-template - (equal (car (org-capture-get :target)) 'function)) + (eq (car (org-capture-get :target)) 'function)) ((error quit) (if (and (buffer-base-buffer (current-buffer)) - (string-match "\\`CAPTURE-" (buffer-name))) + (string-prefix-p "CAPTURE-" (buffer-name))) (kill-buffer (current-buffer))) (set-window-configuration (org-capture-get :return-to-wconf)) (error "Capture template `%s': %s" @@ -613,7 +647,7 @@ of the day at point (if any) or the current HH:MM time." (org-capture-put :interrupted-clock (copy-marker org-clock-marker))) (org-clock-in) - (org-set-local 'org-capture-clock-was-started t)) + (setq-local org-capture-clock-was-started t)) (error "Could not start the clock in this capture buffer"))) (if (org-capture-get :immediate-finish) @@ -646,7 +680,7 @@ captured item after finalizing." (setq stay-with-capture t)) (unless (and org-capture-mode (buffer-base-buffer (current-buffer))) - (error "This does not seem to be a capture buffer for Org-mode")) + (error "This does not seem to be a capture buffer for Org mode")) (run-hooks 'org-capture-prepare-finalize-hook) @@ -682,23 +716,13 @@ captured item after finalizing." (m2 (org-capture-get :end-marker 'local))) (if (and m1 m2 (= m1 beg) (= m2 end)) (progn - (setq m2 (if (cdr (assoc 'heading org-blank-before-new-entry)) + (setq m2 (if (cdr (assq 'heading org-blank-before-new-entry)) m2 (1+ m2)) m2 (if (< (point-max) m2) (point-max) m2)) (setq abort-note 'clean) (kill-region m1 m2)) (setq abort-note 'dirty))) - ;; Make sure that the empty lines after are correct - (when (and (> (point-max) end) ; indeed, the buffer was still narrowed - (member (org-capture-get :type 'local) - '(entry item checkitem plain))) - (save-excursion - (goto-char end) - (or (bolp) (newline)) - (org-capture-empty-lines-after - (or (org-capture-get :empty-lines-after 'local) - (org-capture-get :empty-lines 'local) 0)))) ;; Postprocessing: Update Statistics cookies, do the sorting (when (derived-mode-p 'org-mode) (save-excursion @@ -715,8 +739,7 @@ captured item after finalizing." ;; Store this place as the last one where we stored something ;; Do the marking in the base buffer, so that it makes sense after ;; the indirect buffer has been killed. - (when org-capture-bookmark - (org-capture-bookmark-last-stored-position)) + (org-capture-store-last-position) ;; Run the hook (run-hooks 'org-capture-before-finalize-hook)) @@ -770,11 +793,12 @@ captured item after finalizing." ;; Special cases (cond (abort-note - (cond - ((equal abort-note 'clean) - (message "Capture process aborted and target buffer cleaned up")) - ((equal abort-note 'dirty) - (error "Capture process aborted, but target buffer could not be cleaned up correctly")))) + (cl-case abort-note + (clean + (message "Capture process aborted and target buffer cleaned up")) + (dirty + (error "Capture process aborted, but target buffer could not be \ +cleaned up correctly")))) (stay-with-capture (org-capture-goto-last-stored))) ;; Return if we did store something @@ -786,19 +810,28 @@ Refiling is done from the base buffer, because the indirect buffer is then already gone. Any prefix argument will be passed to the refile command." (interactive) (unless (eq (org-capture-get :type 'local) 'entry) - (error - "Refiling from a capture buffer makes only sense for `entry'-type templates")) - (let ((pos (point)) - (base (buffer-base-buffer (current-buffer))) - (org-refile-for-capture t)) - (save-window-excursion - (with-current-buffer (or base (current-buffer)) - (save-excursion - (save-restriction - (widen) - (goto-char pos) - (call-interactively 'org-refile))))) - (org-capture-finalize))) + (user-error "Refiling from a capture buffer makes only sense \ +for `entry'-type templates")) + (let* ((base (or (buffer-base-buffer) (current-buffer))) + (pos (make-marker)) + (org-capture-is-refiling t) + (kill-buffer (org-capture-get :kill-buffer 'local))) + ;; Since `org-capture-finalize' may alter buffer contents (e.g., + ;; empty lines) around entry, use a marker to refer to the + ;; headline to be refiled. Place the marker in the base buffer, + ;; as the current indirect one is going to be killed. + (set-marker pos (save-excursion (org-back-to-heading t) (point)) base) + (org-capture-put :kill-buffer nil) + (unwind-protect + (progn + (org-capture-finalize) + (save-window-excursion + (with-current-buffer base + (org-with-wide-buffer + (goto-char pos) + (call-interactively 'org-refile)))) + (when kill-buffer (kill-buffer base))) + (set-marker pos nil)))) (defun org-capture-kill () "Abort the current capture process." @@ -813,7 +846,8 @@ already gone. Any prefix argument will be passed to the refile command." "Go to the location where the last capture note was stored." (interactive) (org-goto-marker-or-bmk org-capture-last-stored-marker - "org-capture-last-stored") + (plist-get org-bookmark-names-plist + :last-capture)) (message "This is the last note stored by a capture process")) ;;; Supporting functions for handling the process @@ -823,7 +857,7 @@ already gone. Any prefix argument will be passed to the refile command." (org-capture-put :initial-target-region ;; Check if the buffer is currently narrowed - (when (/= (buffer-size) (- (point-max) (point-min))) + (when (org-buffer-narrowed-p) (cons (point-min) (point-max)))) ;; store the current point (org-capture-put :initial-target-position (point))) @@ -853,14 +887,14 @@ Store them in the capture property list." ((eq (car target) 'file+headline) (set-buffer (org-capture-target-buffer (nth 1 target))) + (unless (derived-mode-p 'org-mode) + (error + "Target buffer \"%s\" for file+headline should be in Org mode" + (current-buffer))) (org-capture-put-target-region-and-position) (widen) (let ((hd (nth 2 target))) (goto-char (point-min)) - (unless (derived-mode-p 'org-mode) - (error - "Target buffer \"%s\" for file+headline should be in Org mode" - (current-buffer))) (if (re-search-forward (format org-complex-heading-regexp-format (regexp-quote hd)) nil t) @@ -892,21 +926,29 @@ Store them in the capture property list." (setq target-entry-p (and (derived-mode-p 'org-mode) (org-at-heading-p)))) (error "No match for target regexp in file %s" (nth 1 target)))) - ((memq (car target) '(file+datetree file+datetree+prompt)) + ((memq (car target) '(file+datetree file+datetree+prompt file+weektree file+weektree+prompt)) (require 'org-datetree) (set-buffer (org-capture-target-buffer (nth 1 target))) + (unless (derived-mode-p 'org-mode) + (error "Target buffer \"%s\" for %s should be in Org mode" + (current-buffer) + (car target))) (org-capture-put-target-region-and-position) (widen) - ;; Make a date tree entry, with the current date (or yesterday, - ;; if we are extending dates for a couple of hours) - (org-datetree-find-date-create + ;; Make a date/week tree entry, with the current date (or + ;; yesterday, if we are extending dates for a couple of hours) + (funcall + (cond + ((memq (car target) '(file+weektree file+weektree+prompt)) + #'org-datetree-find-iso-week-create) + (t #'org-datetree-find-date-create)) (calendar-gregorian-from-absolute (cond (org-overriding-default-time ;; use the overriding default time (time-to-days org-overriding-default-time)) - ((eq (car target) 'file+datetree+prompt) + ((memq (car target) '(file+datetree+prompt file+weektree+prompt)) ;; prompt for date (let ((prompt-time (org-read-date nil t nil "Date for tree entry:" @@ -917,7 +959,9 @@ Store them in the capture property list." (not org-time-was-given)) (not (= (time-to-days prompt-time) (org-today)))) ;; Use 00:00 when no time is given for another date than today? - (apply 'encode-time (append '(0 0 0) (cdddr (decode-time prompt-time))))) + (apply #'encode-time + (append '(0 0 0) + (cl-cdddr (decode-time prompt-time))))) ((string-match "\\([^ ]+\\)--?[^ ]+[ ]+\\(.*\\)" org-read-date-final-answer) ;; Replace any time range by its start (apply 'encode-time @@ -964,31 +1008,31 @@ Store them in the capture property list." :decrypted decrypted-hl-pos)))) (defun org-capture-expand-file (file) - "Expand functions and symbols for FILE. + "Expand functions, symbols and file names for FILE. When FILE is a function, call it. When it is a form, evaluate -it. When it is a variable, retrieve the value. Return whatever we get." +it. When it is a variable, retrieve the value. When it is +a string, treat it as a file name, possibly expanding it +according to `org-directory', and return it. If it is the empty +string, however, return `org-default-notes-file'. In any other +case, raise an error." (cond - ((org-string-nw-p file) file) + ((equal file "") org-default-notes-file) + ((stringp file) (expand-file-name file org-directory)) ((functionp file) (funcall file)) ((and (symbolp file) (boundp file)) (symbol-value file)) - ((and file (consp file)) (eval file)) + ((consp file) (eval file)) (t file))) (defun org-capture-target-buffer (file) - "Get a buffer for FILE." - (setq file (org-capture-expand-file file)) - (setq file (or (org-string-nw-p file) - org-default-notes-file - (error "No notes file specified, and no default available"))) - (or (org-find-base-buffer-visiting file) - (progn (org-capture-put :new-buffer t) - (find-file-noselect (expand-file-name file org-directory))))) - -(defun org-capture-steal-local-variables (buffer) - "Install Org-mode local variables of BUFFER." - (mapc (lambda (v) - (ignore-errors (org-set-local (car v) (cdr v)))) - (buffer-local-variables buffer))) + "Get a buffer for FILE. +FILE is a generalized file location, as handled by +`org-capture-expand-file'." + (let ((file (or (org-string-nw-p (org-capture-expand-file file)) + org-default-notes-file + (error "No notes file specified, and no default available")))) + (or (org-find-base-buffer-visiting file) + (progn (org-capture-put :new-buffer t) + (find-file-noselect file))))) (defun org-capture-place-template (&optional inhibit-wconf-store) "Insert the template at the target location, and display the buffer. @@ -1000,65 +1044,52 @@ may have been stored before." (org-switch-to-buffer-other-window (org-capture-get-indirect-buffer (org-capture-get :buffer) "CAPTURE")) (widen) - (show-all) + (outline-show-all) (goto-char (org-capture-get :pos)) - (org-set-local 'org-capture-target-marker - (point-marker)) - (org-set-local 'outline-level 'org-outline-level) - (let* ((template (org-capture-get :template)) - (type (org-capture-get :type))) - (case type - ((nil entry) (org-capture-place-entry)) - (table-line (org-capture-place-table-line)) - (plain (org-capture-place-plain-text)) - (item (org-capture-place-item)) - (checkitem (org-capture-place-item)))) + (setq-local outline-level 'org-outline-level) + (pcase (org-capture-get :type) + ((or `nil `entry) (org-capture-place-entry)) + (`table-line (org-capture-place-table-line)) + (`plain (org-capture-place-plain-text)) + (`item (org-capture-place-item)) + (`checkitem (org-capture-place-item))) (org-capture-mode 1) - (org-set-local 'org-capture-current-plist org-capture-plist)) + (setq-local org-capture-current-plist org-capture-plist)) (defun org-capture-place-entry () "Place the template as a new Org entry." - (let* ((txt (org-capture-get :template)) - (reversed (org-capture-get :prepend)) - (target-entry-p (org-capture-get :target-entry-p)) - level beg end file) - - (cond - ((org-capture-get :exact-position) + (let ((reversed? (org-capture-get :prepend)) + level) + (when (org-capture-get :exact-position) (goto-char (org-capture-get :exact-position))) - ((not target-entry-p) - ;; Insert as top-level entry, either at beginning or at end of file - (setq level 1) - (if reversed - (progn (goto-char (point-min)) - (or (org-at-heading-p) - (outline-next-heading))) - (goto-char (point-max)) - (or (bolp) (insert "\n")))) - (t - ;; Insert as a child of the current entry - (and (looking-at "\\*+") - (setq level (- (match-end 0) (match-beginning 0)))) - (setq level (org-get-valid-level (or level 1) 1)) - (if reversed - (progn - (outline-next-heading) - (or (bolp) (insert "\n"))) - (org-end-of-subtree t nil) - (or (bolp) (insert "\n"))))) + (cond + ;; Insert as a child of the current entry. + ((org-capture-get :target-entry-p) + (setq level (org-get-valid-level + (if (org-at-heading-p) (org-outline-level) 1) + 1)) + (if reversed? (outline-next-heading) (org-end-of-subtree t))) + ;; Insert as a top-level entry at the beginning of the file. + (reversed? + (goto-char (point-min)) + (unless (org-at-heading-p) (outline-next-heading))) + ;; Otherwise, insert as a top-level entry at the end of the file. + (t (goto-char (point-max)))) + (unless (bolp) (insert "\n")) (org-capture-empty-lines-before) - (setq beg (point)) - (org-capture-verify-tree txt) - (org-paste-subtree level txt 'for-yank) - (org-capture-empty-lines-after 1) - (org-capture-position-for-last-stored beg) - (outline-next-heading) - (setq end (point)) - (org-capture-mark-kill-region beg (1- end)) - (org-capture-narrow beg (1- end)) - (if (or (re-search-backward "%\\?" beg t) - (re-search-forward "%\\?" end t)) - (replace-match "")))) + (let ((beg (point)) + (template (org-capture-get :template))) + (org-capture-verify-tree template) + (org-paste-subtree level template 'for-yank) + (org-capture-empty-lines-after) + (org-capture-position-for-last-stored beg) + (unless (org-at-heading-p) (outline-next-heading)) + (let ((end (point))) + (org-capture-mark-kill-region beg end) + (org-capture-narrow beg end) + (when (or (re-search-backward "%\\?" beg t) + (re-search-forward "%\\?" end t)) + (replace-match "")))))) (defun org-capture-place-item () "Place the template as a new plain list item." @@ -1075,21 +1106,18 @@ may have been stored before." (t (setq beg (1+ (point-at-eol)) end (save-excursion (outline-next-heading) (point))))) + (setq ind nil) (if (org-capture-get :prepend) (progn (goto-char beg) - (if (org-list-search-forward (org-item-beginning-re) end t) - (progn - (goto-char (match-beginning 0)) - (setq ind (org-get-indentation))) - (goto-char end) - (setq ind 0))) + (when (org-list-search-forward (org-item-beginning-re) end t) + (goto-char (match-beginning 0)) + (setq ind (org-get-indentation)))) (goto-char end) - (if (org-list-search-backward (org-item-beginning-re) beg t) - (progn - (setq ind (org-get-indentation)) - (org-end-of-item)) - (setq ind 0)))) + (when (org-list-search-backward (org-item-beginning-re) beg t) + (setq ind (org-get-indentation)) + (org-end-of-item))) + (unless ind (goto-char end))) ;; Remove common indentation (setq txt (org-remove-indentation txt)) ;; Make sure this is indeed an item @@ -1097,18 +1125,23 @@ may have been stored before." (setq txt (concat "- " (mapconcat 'identity (split-string txt "\n") "\n ")))) + ;; Prepare surrounding empty lines. + (org-capture-empty-lines-before) + (setq beg (point)) + (unless (eolp) (save-excursion (insert "\n"))) + (unless ind + (org-indent-line) + (setq ind (org-get-indentation)) + (delete-region beg (point))) ;; Set the correct indentation, depending on context (setq ind (make-string ind ?\ )) (setq txt (concat ind (mapconcat 'identity (split-string txt "\n") (concat "\n" ind)) "\n")) - ;; Insert, with surrounding empty lines - (org-capture-empty-lines-before) - (setq beg (point)) + ;; Insert item. (insert txt) - (or (bolp) (insert "\n")) - (org-capture-empty-lines-after 1) + (org-capture-empty-lines-after) (org-capture-position-for-last-stored beg) (forward-char 1) (setq end (point)) @@ -1124,7 +1157,7 @@ may have been stored before." (let* ((txt (org-capture-get :template)) (target-entry-p (org-capture-get :target-entry-p)) (table-line-pos (org-capture-get :table-line-pos)) - ind beg end) + beg end) (cond ((org-capture-get :exact-position) (goto-char (org-capture-get :exact-position))) @@ -1149,21 +1182,24 @@ may have been stored before." ;; Check if the template is good (if (not (string-match org-table-dataline-regexp txt)) (setq txt "| %?Bad template |\n")) + (if (functionp table-line-pos) + (setq table-line-pos (funcall table-line-pos)) + (setq table-line-pos (eval table-line-pos))) (cond ((and table-line-pos (string-match "\\(I+\\)\\([-+][0-9]\\)" table-line-pos)) - ;; we have a complex line specification (goto-char (point-min)) - (let ((nh (- (match-end 1) (match-beginning 1))) - (delta (string-to-number (match-string 2 table-line-pos))) - ll) + ;; we have a complex line specification + (let ((ll (ignore-errors + (save-match-data (org-table-analyze)) + (aref org-table-hlines + (- (match-end 1) (match-beginning 1))))) + (delta (string-to-number (match-string 2 table-line-pos)))) ;; The user wants a special position in the table - (org-table-get-specials) - (setq ll (ignore-errors (aref org-table-hlines nh))) - (unless ll (error "Invalid table line specification \"%s\"" - table-line-pos)) - (setq ll (+ ll delta (if (< delta 0) 0 -1))) - (org-goto-line ll) + (unless ll + (error "Invalid table line specification \"%s\"" table-line-pos)) + (goto-char org-table-current-begin-pos) + (forward-line (+ ll delta (if (< delta 0) 0 -1))) (org-table-insert-row 'below) (beginning-of-line 1) (delete-region (point) (1+ (point-at-eol))) @@ -1216,7 +1252,7 @@ Of course, if exact position has been required, just put it there." ;; we should place the text into this entry (if (org-capture-get :prepend) ;; Skip meta data and drawers - (org-end-of-meta-data-and-drawers) + (org-end-of-meta-data t) ;; go to ent of the entry text, before the next headline (outline-next-heading))) (t @@ -1226,7 +1262,7 @@ Of course, if exact position has been required, just put it there." (org-capture-empty-lines-before) (setq beg (point)) (insert txt) - (org-capture-empty-lines-after 1) + (org-capture-empty-lines-after) (org-capture-position-for-last-stored beg) (setq end (point)) (org-capture-mark-kill-region beg (1- end)) @@ -1256,8 +1292,8 @@ Of course, if exact position has been required, just put it there." (org-table-current-dline)))) (t (error "This should not happen")))) -(defun org-capture-bookmark-last-stored-position () - "Bookmark the last-captured position." +(defun org-capture-store-last-position () + "Store the last-captured position." (let* ((where (org-capture-get :position-for-last-stored 'local)) (pos (cond ((markerp where) @@ -1270,16 +1306,11 @@ Of course, if exact position has been required, just put it there." (point-at-bol)) (point)))))) (with-current-buffer (buffer-base-buffer (current-buffer)) - (save-excursion - (save-restriction - (widen) - (goto-char pos) - (let ((bookmark-name (plist-get org-bookmark-names-plist - :last-capture))) - (when bookmark-name - (with-demoted-errors - (bookmark-set bookmark-name)))) - (move-marker org-capture-last-stored-marker (point))))))) + (org-with-point-at pos + (when org-capture-bookmark + (let ((bookmark (plist-get org-bookmark-names-plist :last-capture))) + (when bookmark (with-demoted-errors (bookmark-set bookmark))))) + (move-marker org-capture-last-stored-marker (point)))))) (defun org-capture-narrow (beg end) "Narrow, unless configuration says not to narrow." @@ -1315,7 +1346,7 @@ Point will remain at the first line after the inserted text." (let* ((template (org-capture-get :template)) (type (org-capture-get :type)) beg end pp) - (or (bolp) (newline)) + (unless (bolp) (insert "\n")) (setq beg (point)) (cond ((and (eq type 'entry) (derived-mode-p 'org-mode)) @@ -1337,13 +1368,16 @@ Point will remain at the first line after the inserted text." (org-capture-empty-lines-after) (goto-char beg) (org-list-repair) - (org-end-of-item) - (setq end (point))) - (t (insert template))) + (org-end-of-item)) + (t + (insert template) + (org-capture-empty-lines-after) + (skip-chars-forward " \t\n") + (unless (eobp) (beginning-of-line)))) (setq end (point)) (goto-char beg) - (if (re-search-forward "%\\?" end t) - (replace-match "")))) + (when (re-search-forward "%\\?" end t) + (replace-match "")))) (defun org-capture-set-plist (entry) "Initialize the property list from the template definition." @@ -1365,13 +1399,11 @@ Point will remain at the first line after the inserted text." "Go to the target location of a capture template. The user is queried for the template." (interactive) - (let* (org-select-template-temp-major-mode - (entry (org-capture-select-template template-key))) - (unless entry - (error "No capture template selected")) + (let ((entry (org-capture-select-template template-key))) + (unless entry (error "No capture template selected")) (org-capture-set-plist entry) (org-capture-set-target-location) - (org-pop-to-buffer-same-window (org-capture-get :buffer)) + (pop-to-buffer-same-window (org-capture-get :buffer)) (goto-char (org-capture-get :pos)))) (defun org-capture-get-indirect-buffer (&optional buffer prefix) @@ -1381,7 +1413,7 @@ Use PREFIX as a prefix for the name of the indirect buffer." (let ((n 1) (base (buffer-name buffer)) bname) (setq bname (concat prefix "-" base)) (while (buffer-live-p (get-buffer bname)) - (setq bname (concat prefix "-" (number-to-string (incf n)) "-" base))) + (setq bname (concat prefix "-" (number-to-string (cl-incf n)) "-" base))) (condition-case nil (make-indirect-buffer buffer bname 'clone) (error @@ -1396,6 +1428,7 @@ Use PREFIX as a prefix for the name of the indirect buffer." (defun org-mks (table title &optional prompt specials) "Select a member of an alist with multiple keys. + TABLE is the alist which should contain entries where the car is a string. There should be two types of entries. @@ -1403,7 +1436,7 @@ There should be two types of entries. This indicates that `a' is a prefix key for multi-letter selection, and that there are entries following with keys like \"ab\", \"ax\"... -2. Selectable members must have more than two elements, with the first +2. Select-able members must have more than two elements, with the first being the string of keys that lead to selecting it, and the second a short description string of the item. @@ -1414,84 +1447,72 @@ When you press a prefix key, the commands (and maybe further prefixes) under this key will be shown and offered for selection. TITLE will be placed over the selection in the temporary buffer, -PROMPT will be used when prompting for a key. SPECIAL is an alist with -also (\"key\" \"description\") entries. When one of these is selection, -only the bare key is returned." - (setq prompt (or prompt "Select: ")) - (let (tbl orig-table dkey ddesc des-keys allowed-keys - current prefix rtn re pressed buffer (inhibit-quit t)) - (save-window-excursion - (setq buffer (org-switch-to-buffer-other-window "*Org Select*")) - (setq orig-table table) - (catch 'exit - (while t - (erase-buffer) - (insert title "\n\n") - (setq tbl table - des-keys nil - allowed-keys nil - cursor-type nil) - (setq prefix (if current (concat current " ") "")) - (while tbl - (cond - ((and (= 2 (length (car tbl))) (= (length (caar tbl)) 1)) - ;; This is a description on this level - (setq dkey (caar tbl) ddesc (cadar tbl)) - (pop tbl) - (push dkey des-keys) - (push dkey allowed-keys) - (insert prefix "[" dkey "]" "..." " " ddesc "..." "\n") - ;; Skip keys which are below this prefix - (setq re (concat "\\`" (regexp-quote dkey))) - (let (case-fold-search) - (while (and tbl (string-match re (caar tbl))) (pop tbl)))) - ((= 2 (length (car tbl))) - ;; Not yet a usable description, skip it - ) - (t - ;; usable entry on this level - (insert prefix "[" (caar tbl) "]" " " (nth 1 (car tbl)) "\n") - (push (caar tbl) allowed-keys) - (pop tbl)))) - (when specials - (insert "-------------------------------------------------------------------------------\n") - (let ((sp specials)) - (while sp - (insert (format "[%s] %s\n" - (caar sp) (nth 1 (car sp)))) - (push (caar sp) allowed-keys) - (pop sp)))) - (push "\C-g" allowed-keys) - (goto-char (point-min)) - (if (not (pos-visible-in-window-p (point-max))) - (org-fit-window-to-buffer)) - (message prompt) - (setq pressed (char-to-string (read-char-exclusive))) - (while (not (member pressed allowed-keys)) - (message "Invalid key `%s'" pressed) (sit-for 1) - (message prompt) - (setq pressed (char-to-string (read-char-exclusive)))) - (when (equal pressed "\C-g") - (kill-buffer buffer) - (error "Abort")) - (when (and (not (assoc pressed table)) - (not (member pressed des-keys)) - (assoc pressed specials)) - (throw 'exit (setq rtn pressed))) - (unless (member pressed des-keys) - (throw 'exit (setq rtn (rassoc (cdr (assoc pressed table)) - orig-table)))) - (setq current (concat current pressed)) - (setq table (mapcar - (lambda (x) - (if (and (> (length (car x)) 1) - (equal (substring (car x) 0 1) pressed)) - (cons (substring (car x) 1) (cdr x)) - nil)) - table)) - (setq table (remove nil table))))) - (when buffer (kill-buffer buffer)) - rtn)) +PROMPT will be used when prompting for a key. SPECIAL is an +alist with (\"key\" \"description\") entries. When one of these +is selected, only the bare key is returned." + (save-window-excursion + (let ((inhibit-quit t) + (buffer (org-switch-to-buffer-other-window "*Org Select*")) + (prompt (or prompt "Select: ")) + current) + (unwind-protect + (catch 'exit + (while t + (erase-buffer) + (insert title "\n\n") + (let ((des-keys nil) + (allowed-keys '("\C-g")) + (cursor-type nil)) + ;; Populate allowed keys and descriptions keys + ;; available with CURRENT selector. + (let ((re (format "\\`%s\\(.\\)\\'" + (if current (regexp-quote current) ""))) + (prefix (if current (concat current " ") ""))) + (dolist (entry table) + (pcase entry + ;; Description. + (`(,(and key (pred (string-match re))) ,desc) + (let ((k (match-string 1 key))) + (push k des-keys) + (push k allowed-keys) + (insert prefix "[" k "]" "..." " " desc "..." "\n"))) + ;; Usable entry. + (`(,(and key (pred (string-match re))) ,desc . ,_) + (let ((k (match-string 1 key))) + (insert prefix "[" k "]" " " desc "\n") + (push k allowed-keys))) + (_ nil)))) + ;; Insert special entries, if any. + (when specials + (insert "----------------------------------------------------\ +---------------------------\n") + (pcase-dolist (`(,key ,description) specials) + (insert (format "[%s] %s\n" key description)) + (push key allowed-keys))) + ;; Display UI and let user select an entry or + ;; a sub-level prefix. + (goto-char (point-min)) + (unless (pos-visible-in-window-p (point-max)) + (org-fit-window-to-buffer)) + (message prompt) + (let ((pressed (char-to-string (read-char-exclusive)))) + (while (not (member pressed allowed-keys)) + (message "Invalid key `%s'" pressed) (sit-for 1) + (message prompt) + (setq pressed (char-to-string (read-char-exclusive)))) + (setq current (concat current pressed)) + (cond + ((equal pressed "\C-g") (user-error "Abort")) + ;; Selection is a prefix: open a new menu. + ((member pressed des-keys)) + ;; Selection matches an association: return it. + ((let ((entry (assoc current table))) + (and entry (throw 'exit entry)))) + ;; Selection matches a special entry: return the + ;; selection prefix. + ((assoc current specials) (throw 'exit current)) + (t (error "No entry available"))))))) + (when buffer (kill-buffer buffer)))))) ;;; The template code (defun org-capture-select-template (&optional keys) @@ -1511,46 +1532,41 @@ Lisp programs can force the template by setting KEYS to a string." '(("C" "Customize org-capture-templates") ("q" "Abort")))))) +(defvar org-capture--clipboards nil + "List various clipboards values.") + (defun org-capture-fill-template (&optional template initial annotation) "Fill a template and return the filled template as a string. The template may still contain \"%?\" for cursor positioning." - (setq template (or template (org-capture-get :template))) - (when (stringp initial) - (setq initial (org-no-properties initial))) - (let* ((buffer (org-capture-get :buffer)) + (let* ((template (or template (org-capture-get :template))) + (buffer (org-capture-get :buffer)) (file (buffer-file-name (or (buffer-base-buffer buffer) buffer))) - (ct (org-capture-get :default-time)) - (dct (decode-time ct)) - (ct1 - (if (< (nth 2 dct) org-extend-today-until) - (encode-time 0 59 23 (1- (nth 3 dct)) (nth 4 dct) (nth 5 dct)) - ct)) - (plist-p (if org-store-link-plist t nil)) - (v-c (and (> (length kill-ring) 0) (current-kill 0))) + (time (let* ((c (or (org-capture-get :default-time) (current-time))) + (d (decode-time c))) + (if (< (nth 2 d) org-extend-today-until) + (encode-time 0 59 23 (1- (nth 3 d)) (nth 4 d) (nth 5 d)) + c))) + (v-t (format-time-string (org-time-stamp-format nil) time)) + (v-T (format-time-string (org-time-stamp-format t) time)) + (v-u (format-time-string (org-time-stamp-format nil t) time)) + (v-U (format-time-string (org-time-stamp-format t t) time)) + (v-c (and kill-ring (current-kill 0))) (v-x (or (org-get-x-clipboard 'PRIMARY) (org-get-x-clipboard 'CLIPBOARD) (org-get-x-clipboard 'SECONDARY))) - (v-t (format-time-string (car org-time-stamp-formats) ct1)) - (v-T (format-time-string (cdr org-time-stamp-formats) ct1)) - (v-u (concat "[" (substring v-t 1 -1) "]")) - (v-U (concat "[" (substring v-T 1 -1) "]")) - ;; `initial' and `annotation' might habe been passed. - ;; But if the property list has them, we prefer those values + ;; `initial' and `annotation' might have been passed. But if + ;; the property list has them, we prefer those values. (v-i (or (plist-get org-store-link-plist :initial) - initial + (and (stringp initial) (org-no-properties initial)) (org-capture-get :initial) "")) - (v-a (or (plist-get org-store-link-plist :annotation) - annotation - (org-capture-get :annotation) - "")) - ;; Is the link empty? Then we do not want it... - (v-a (if (equal v-a "[[]]") "" v-a)) - (clipboards (remove nil (list v-i - (org-get-x-clipboard 'PRIMARY) - (org-get-x-clipboard 'CLIPBOARD) - (org-get-x-clipboard 'SECONDARY) - v-c))) + (v-a + (let ((a (or (plist-get org-store-link-plist :annotation) + annotation + (org-capture-get :annotation) + ""))) + ;; Is the link empty? Then we do not want it... + (if (equal a "[[]]") "" a))) (l-re "\\[\\[\\(.*?\\)\\]\\(\\[.*?\\]\\)?\\]") (v-A (if (and v-a (string-match l-re v-a)) (replace-match "[[\\1][%^{Link description}]]" nil nil v-a) @@ -1559,202 +1575,260 @@ The template may still contain \"%?\" for cursor positioning." (replace-match "\\1" nil nil v-a) v-a)) (v-n user-full-name) - (v-k (if (marker-buffer org-clock-marker) - (org-no-properties org-clock-heading))) + (v-k (and (marker-buffer org-clock-marker) + (org-no-properties org-clock-heading))) (v-K (if (marker-buffer org-clock-marker) (org-make-link-string (buffer-file-name (marker-buffer org-clock-marker)) org-clock-heading))) (v-f (or (org-capture-get :original-file-nondirectory) "")) (v-F (or (org-capture-get :original-file) "")) - v-I - (org-startup-folded nil) - (org-inhibit-startup t) - org-time-was-given org-end-time-was-given x - prompt completions char time pos default histvar strings) - - (setq org-store-link-plist - (plist-put org-store-link-plist :annotation v-a) - org-store-link-plist - (plist-put org-store-link-plist :initial v-i)) - (setq initial v-i) - - (unless template (setq template "") (message "No template") (ding) - (sit-for 1)) + (org-capture--clipboards + (delq nil + (list v-i + (org-get-x-clipboard 'PRIMARY) + (org-get-x-clipboard 'CLIPBOARD) + (org-get-x-clipboard 'SECONDARY) + v-c)))) + + (setq org-store-link-plist (plist-put org-store-link-plist :annotation v-a)) + (setq org-store-link-plist (plist-put org-store-link-plist :initial v-i)) + + (unless template + (setq template "") + (message "no template") (ding) + (sit-for 1)) (save-window-excursion - (delete-other-windows) - (org-pop-to-buffer-same-window (get-buffer-create "*Capture*")) + (org-switch-to-buffer-other-window (get-buffer-create "*Capture*")) (erase-buffer) + (setq buffer-file-name nil) + (setq mark-active nil) (insert template) (goto-char (point-min)) - (org-capture-steal-local-variables buffer) - (setq buffer-file-name nil mark-active nil) - ;; %[] Insert contents of a file. - (goto-char (point-min)) - (while (re-search-forward "%\\[\\(.+\\)\\]" nil t) - (unless (org-capture-escaped-%) - (let ((start (match-beginning 0)) - (end (match-end 0)) - (filename (expand-file-name (match-string 1)))) - (goto-char start) - (delete-region start end) - (condition-case error - (insert-file-contents filename) - (error (insert (format "%%![Could not insert %s: %s]" - filename error))))))) - ;; %() embedded elisp - (org-capture-expand-embedded-elisp) + ;; %[] insert contents of a file. + (save-excursion + (while (re-search-forward "%\\[\\(.+\\)\\]" nil t) + (let ((filename (expand-file-name (match-string 1))) + (beg (copy-marker (match-beginning 0))) + (end (copy-marker (match-end 0)))) + (unless (org-capture-escaped-%) + (delete-region beg end) + (set-marker beg nil) + (set-marker end nil) + (condition-case error + (insert-file-contents filename) + (error + (insert (format "%%![couldn not insert %s: %s]" + filename + error)))))))) - ;; The current time - (goto-char (point-min)) - (while (re-search-forward "%<\\([^>\n]+\\)>" nil t) - (replace-match (format-time-string (match-string 1)) t t)) + ;; Mark %() embedded elisp for later evaluation. + (org-capture-expand-embedded-elisp 'mark) - ;; Simple %-escapes - (goto-char (point-min)) - (while (re-search-forward "%\\([tTuUaliAcxkKInfF]\\)" nil t) - (unless (org-capture-escaped-%) - (when (and initial (equal (match-string 0) "%i")) - (save-match-data - (let* ((lead (buffer-substring - (point-at-bol) (match-beginning 0)))) - (setq v-i (mapconcat 'identity - (org-split-string initial "\n") - (concat "\n" lead)))))) - (replace-match (or (eval (intern (concat "v-" (match-string 1)))) "") - t t))) - - ;; From the property list - (when plist-p - (goto-char (point-min)) - (while (re-search-forward "%\\(:[-a-zA-Z]+\\)" nil t) - (unless (org-capture-escaped-%) - (and (setq x (or (plist-get org-store-link-plist - (intern (match-string 1))) "")) - (replace-match x t t))))) - - ;; Turn on org-mode in temp buffer, set local variables - ;; This is to support completion in interactive prompts + ;; Expand non-interactive templates. + (let ((regexp "%\\(:[-a-za-z]+\\|<\\([^>\n]+\\)>\\|[aAcfFikKlntTuUx]\\)")) + (save-excursion + (while (re-search-forward regexp nil t) + ;; `org-capture-escaped-%' may modify buffer and cripple + ;; match-data. Use markers instead. Ditto for other + ;; templates. + (let ((pos (copy-marker (match-beginning 0))) + (end (copy-marker (match-end 0))) + (value (match-string 1)) + (time-string (match-string 2))) + (unless (org-capture-escaped-%) + (delete-region pos end) + (set-marker pos nil) + (set-marker end nil) + (let* ((inside-sexp? (org-capture-inside-embedded-elisp-p)) + (replacement + (pcase (string-to-char value) + (?< (format-time-string time-string)) + (?: + (or (plist-get org-store-link-plist (intern value)) + "")) + (?i + (if inside-sexp? v-i + ;; Outside embedded Lisp, repeat leading + ;; characters before initial place holder + ;; every line. + (let ((lead (buffer-substring-no-properties + (line-beginning-position) (point)))) + (replace-regexp-in-string "\n\\(.\\)" + (concat lead "\\1") + v-i nil nil 1)))) + (?a v-a) + (?A v-A) + (?c v-c) + (?f v-f) + (?F v-F) + (?k v-k) + (?K v-K) + (?l v-l) + (?n v-n) + (?t v-t) + (?T v-T) + (?u v-u) + (?U v-U) + (?x v-x)))) + (insert + (if inside-sexp? + ;; Escape sensitive characters. + (replace-regexp-in-string "[\\\"]" "\\\\\\&" replacement) + replacement)))))))) + + ;; Expand %() embedded Elisp. Limit to Sexp originally marked. + (org-capture-expand-embedded-elisp) + + ;; Expand interactive templates. This is the last step so that + ;; template is mostly expanded when prompting happens. Turn on + ;; Org mode and set local variables. This is to support + ;; completion in interactive prompts. (let ((org-inhibit-startup t)) (org-mode)) - ;; Interactive template entries - (goto-char (point-min)) - (while (re-search-forward "%^\\({\\([^}]*\\)}\\)?\\([gGtTuUCLp]\\)?" nil t) - (unless (org-capture-escaped-%) - (setq char (if (match-end 3) (match-string-no-properties 3)) - prompt (if (match-end 2) (match-string-no-properties 2))) - (goto-char (match-beginning 0)) - (replace-match "") - (setq completions nil default nil) - (when prompt - (setq completions (org-split-string prompt "|") - prompt (pop completions) - default (car completions) - histvar (intern (concat - "org-capture-template-prompt-history::" - (or prompt ""))) - completions (mapcar 'list completions))) - (unless (boundp histvar) (set histvar nil)) - (cond - ((member char '("G" "g")) - (let* ((org-last-tags-completion-table - (org-global-tags-completion-table - (if (equal char "G") - (org-agenda-files) - (and file (list file))))) - (org-add-colon-after-tag-completion t) - (ins (org-icompleting-read - (if prompt (concat prompt ": ") "Tags: ") - 'org-tags-completion-function nil nil nil - 'org-tags-history))) - (setq ins (mapconcat 'identity - (org-split-string - ins (org-re "[^[:alnum:]_@#%]+")) - ":")) - (when (string-match "\\S-" ins) - (or (equal (char-before) ?:) (insert ":")) - (insert ins) - (or (equal (char-after) ?:) (insert ":")) - (and (org-at-heading-p) - (let ((org-ignore-region t)) - (org-set-tags nil 'align)))))) - ((equal char "C") - (cond ((= (length clipboards) 1) (insert (car clipboards))) - ((> (length clipboards) 1) - (insert (read-string "Clipboard/kill value: " - (car clipboards) '(clipboards . 1) - (car clipboards)))))) - ((equal char "L") - (cond ((= (length clipboards) 1) - (org-insert-link 0 (car clipboards))) - ((> (length clipboards) 1) - (org-insert-link 0 (read-string "Clipboard/kill value: " - (car clipboards) - '(clipboards . 1) - (car clipboards)))))) - ((equal char "p") - (org-set-property (org-no-properties prompt) nil)) - (char - ;; These are the date/time related ones - (setq org-time-was-given (equal (upcase char) char)) - (setq time (org-read-date (equal (upcase char) char) t nil - prompt)) - (if (equal (upcase char) char) (setq org-time-was-given t)) - (org-insert-time-stamp time org-time-was-given - (member char '("u" "U")) - nil nil (list org-end-time-was-given))) - (t - (let (org-completion-use-ido) - (push (org-completing-read-no-i - (concat (if prompt prompt "Enter string") - (if default (concat " [" default "]")) - ": ") - completions nil nil nil histvar default) - strings) - (insert (car strings))))))) - ;; Replace %n escapes with nth %^{...} string - (setq strings (nreverse strings)) - (goto-char (point-min)) - (while (re-search-forward "%\\\\\\([1-9][0-9]*\\)" nil t) - (unless (org-capture-escaped-%) - (replace-match - (nth (1- (string-to-number (match-string 1))) strings) - nil t))) + (org-clone-local-variables buffer "\\`org-") + (let (strings) ; Stores interactive answers. + (save-excursion + (let ((regexp "%\\^\\(?:{\\([^}]*\\)}\\)?\\([CgGLptTuU]\\)?")) + (while (re-search-forward regexp nil t) + (let* ((items (and (match-end 1) + (save-match-data + (split-string (match-string-no-properties 1) + "|")))) + (key (match-string 2)) + (beg (copy-marker (match-beginning 0))) + (end (copy-marker (match-end 0))) + (prompt (nth 0 items)) + (default (nth 1 items)) + (completions (nthcdr 2 items))) + (unless (org-capture-escaped-%) + (delete-region beg end) + (set-marker beg nil) + (set-marker end nil) + (pcase key + ((or "G" "g") + (let* ((org-last-tags-completion-table + (org-global-tags-completion-table + (cond ((equal key "G") (org-agenda-files)) + (file (list file)) + (t nil)))) + (org-add-colon-after-tag-completion t) + (ins (mapconcat + #'identity + (org-split-string + (completing-read + (if prompt (concat prompt ": ") "Tags: ") + 'org-tags-completion-function nil nil nil + 'org-tags-history) + "[^[:alnum:]_@#%]+") + ":"))) + (when (org-string-nw-p ins) + (unless (eq (char-before) ?:) (insert ":")) + (insert ins) + (unless (eq (char-after) ?:) (insert ":")) + (and (org-at-heading-p) + (let ((org-ignore-region t)) + (org-set-tags nil 'align)))))) + ((or "C" "L") + (let ((insert-fun (if (equal key "C") #'insert + (lambda (s) (org-insert-link 0 s))))) + (pcase org-capture--clipboards + (`nil nil) + (`(,value) (funcall insert-fun value)) + (`(,first-value . ,_) + (funcall insert-fun + (read-string "Clipboard/kill value: " + first-value + 'org-capture--clipboards + first-value))) + (_ (error "Invalid `org-capture--clipboards' value: %S" + org-capture--clipboards))))) + ("p" (org-set-property prompt nil)) + ((guard key) + ;; These are the date/time related ones. + (let* ((upcase? (equal (upcase key) key)) + (org-time-was-given upcase?) + (org-end-time-was-given) + (time (org-read-date upcase? t nil prompt))) + (org-insert-time-stamp + time org-time-was-given + (member key '("u" "U")) + nil nil (list org-end-time-was-given)))) + (_ + (push (org-completing-read + (concat (or prompt "Enter string") + (and default (format " [%s]" default)) + ": ") + completions nil nil nil nil default) + strings) + (insert (car strings))))))))) + + ;; Replace %n escapes with nth %^{...} string. + (setq strings (nreverse strings)) + (save-excursion + (while (re-search-forward "%\\\\\\([1-9][0-9]*\\)" nil t) + (unless (org-capture-escaped-%) + (replace-match + (nth (1- (string-to-number (match-string 1))) strings) + nil t))))) + ;; Make sure there are no empty lines before the text, and that - ;; it ends with a newline character - (goto-char (point-min)) - (while (looking-at "[ \t]*\n") (replace-match "")) - (if (re-search-forward "[ \t\n]*\\'" nil t) (replace-match "\n")) - ;; Return the expanded template and kill the temporary buffer + ;; it ends with a newline character. + (skip-chars-forward " \t\n") + (delete-region (point-min) (line-beginning-position)) + (goto-char (point-max)) + (skip-chars-backward " \t\n") + (delete-region (point) (point-max)) + (insert "\n") + + ;; Return the expanded template and kill the capture buffer. (untabify (point-min) (point-max)) (set-buffer-modified-p nil) - (prog1 (buffer-string) (kill-buffer (current-buffer)))))) + (prog1 (buffer-substring-no-properties (point-min) (point-max)) + (kill-buffer (current-buffer)))))) (defun org-capture-escaped-% () - "Check if % was escaped - if yes, unescape it now." - (if (equal (char-before (match-beginning 0)) ?\\) - (progn - (delete-region (1- (match-beginning 0)) (match-beginning 0)) - t) - nil)) - -(defun org-capture-expand-embedded-elisp () - "Evaluate embedded elisp %(sexp) and replace with the result." - (goto-char (point-min)) - (while (re-search-forward "%(" nil t) - (unless (org-capture-escaped-%) - (goto-char (match-beginning 0)) - (let ((template-start (point))) - (forward-char 1) - (let* ((sexp (read (current-buffer))) - (result (org-eval - (org-capture--expand-keyword-in-embedded-elisp sexp)))) - (delete-region template-start (point)) - (when result - (if (stringp result) - (insert result) - (error "Capture template sexp `%s' must evaluate to string or nil" - sexp)))))))) + "Non-nil if % was escaped. +If yes, unescape it now. Assume match-data contains the +placeholder to check." + (save-excursion + (goto-char (match-beginning 0)) + (let ((n (abs (skip-chars-backward "\\\\")))) + (delete-char (/ (1+ n) 2)) + (= (% n 2) 1)))) + +(defun org-capture-expand-embedded-elisp (&optional mark) + "Evaluate embedded elisp %(sexp) and replace with the result. +When optional MARK argument is non-nil, mark Sexp with a text +property (`org-embedded-elisp') for later evaluation. Only +marked Sexp are evaluated when this argument is nil." + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "%(" nil t) + (cond + ((get-text-property (match-beginning 0) 'org-embedded-elisp) + (goto-char (match-beginning 0)) + (let ((template-start (point))) + (forward-char 1) + (let* ((sexp (read (current-buffer))) + (result (org-eval + (org-capture--expand-keyword-in-embedded-elisp + sexp)))) + (delete-region template-start (point)) + (cond + ((not result) nil) + ((stringp result) (insert result)) + (t (error + "Capture template sexp `%s' must evaluate to string or nil" + sexp)))))) + ((not mark) nil) + ;; Only mark valid and non-escaped sexp. + ((org-capture-escaped-%) nil) + (t + (let ((end (with-syntax-table emacs-lisp-mode-syntax-table + (ignore-errors (scan-sexps (1- (point)) 1))))) + (when end + (put-text-property (- (point) 2) end 'org-embedded-elisp t)))))))) (defun org-capture--expand-keyword-in-embedded-elisp (attr) "Recursively replace capture link keywords in ATTR sexp. @@ -1771,20 +1845,10 @@ Such keywords are prefixed with \"%:\". See (t attr))) (defun org-capture-inside-embedded-elisp-p () - "Return non-nil if point is inside of embedded elisp %(sexp)." - (let (beg end) - (with-syntax-table emacs-lisp-mode-syntax-table - (save-excursion - ;; `looking-at' and `search-backward' below do not match the "%(" if - ;; point is in its middle - (when (equal (char-before) ?%) - (backward-char)) - (save-match-data - (when (or (looking-at "%(") (search-backward "%(" nil t)) - (setq beg (point)) - (setq end (progn (forward-char) (forward-sexp) (1- (point))))))) - (when (and beg end) - (and (<= (point) end) (>= (point) beg)))))) + "Non-nil if point is inside of embedded elisp %(sexp). +Assume sexps have been marked with +`org-capture-expand-embedded-elisp' beforehand." + (get-text-property (point) 'org-embedded-elisp)) ;;;###autoload (defun org-capture-import-remember-templates () @@ -1828,6 +1892,9 @@ Such keywords are prefixed with \"%:\". See (if jump-to-captured '(:jump-to-captured t))))) org-remember-templates)))) +;;; The function was made obsolete by commit 65399674d5 of +;;; 2013-02-22. This make-obsolete call was added 2016-09-01. +(make-obsolete 'org-capture-import-remember-templates "use the `org-capture-templates' variable instead." "Org 9.0") (provide 'org-capture) diff --git a/lisp/org/org-clock.el b/lisp/org/org-clock.el index 0bba92550f8..cb6a6c9ad1d 100644 --- a/lisp/org/org-clock.el +++ b/lisp/org/org-clock.el @@ -1,4 +1,4 @@ -;;; org-clock.el --- The time clocking code for Org-mode +;;; org-clock.el --- The time clocking code for Org mode -*- lexical-binding: t; -*- ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. @@ -24,40 +24,49 @@ ;; ;;; Commentary: -;; This file contains the time clocking code for Org-mode +;; This file contains the time clocking code for Org mode ;;; Code: -(eval-when-compile - (require 'cl)) +(require 'cl-lib) (require 'org) (declare-function calendar-iso-to-absolute "cal-iso" (date)) (declare-function notifications-notify "notifications" (&rest params)) -(declare-function org-pop-to-buffer-same-window "org-compat" (&optional buffer-or-name norecord label)) -(declare-function org-refresh-properties "org" (dprop tprop)) +(declare-function org-element-property "org-element" (property element)) +(declare-function org-element-type "org-element" (element)) +(declare-function org-table-goto-line "org-table" (n)) + +(defvar org-frame-title-format-backup frame-title-format) (defvar org-time-stamp-formats) (defvar org-ts-what) -(defvar org-frame-title-format-backup frame-title-format) + (defgroup org-clock nil - "Options concerning clocking working time in Org-mode." + "Options concerning clocking working time in Org mode." :tag "Org Clock" :group 'org-progress) -(defcustom org-clock-into-drawer org-log-into-drawer - "Should clocking info be wrapped into a drawer? -When t, clocking info will always be inserted into a :LOGBOOK: drawer. -If necessary, the drawer will be created. -When nil, the drawer will not be created, but used when present. -When an integer and the number of clocking entries in an item -reaches or exceeds this number, a drawer will be created. -When a string, it names the drawer to be used. - -The default for this variable is the value of `org-log-into-drawer', -which see." +(defcustom org-clock-into-drawer t + "Non-nil when clocking info should be wrapped into a drawer. + +When non-nil, clocking info will be inserted into the same drawer +as log notes (see variable `org-log-into-drawer'), if it exists, +or \"LOGBOOK\" otherwise. If necessary, the drawer will be +created. + +When an integer, the drawer is created only when the number of +clocking entries in an item reaches or exceeds this value. + +When a string, it becomes the name of the drawer, ignoring the +log notes drawer altogether. + +Do not check directly this variable in a Lisp program. Call +function `org-clock-into-drawer' instead." :group 'org-todo :group 'org-clock + :version "26.1" + :package-version '(Org . "8.3") :type '(choice (const :tag "Always" t) (const :tag "Only when drawer exists" nil) @@ -66,26 +75,29 @@ which see." (string :tag "Into Drawer named..."))) (defun org-clock-into-drawer () - "Return the value of `org-clock-into-drawer', but let properties overrule. + "Value of `org-clock-into-drawer'. but let properties overrule. + If the current entry has or inherits a CLOCK_INTO_DRAWER -property, it will be used instead of the default value; otherwise -if the current entry has or inherits a LOG_INTO_DRAWER property, -it will be used instead of the default value. -The default is the value of the customizable variable `org-clock-into-drawer', -which see." - (let ((p (org-entry-get nil "CLOCK_INTO_DRAWER" 'inherit)) - (q (org-entry-get nil "LOG_INTO_DRAWER" 'inherit))) - (cond - ((or (not (or p q)) (equal p "nil") (equal q "nil")) org-clock-into-drawer) - ((or (equal p "t") (equal q "t")) "LOGBOOK") - ((not p) q) - (t p)))) +property, it will be used instead of the default value. + +Return value is either a string, an integer, or nil." + (let ((p (org-entry-get nil "CLOCK_INTO_DRAWER" 'inherit t))) + (cond ((equal p "nil") nil) + ((equal p "t") (or (org-log-into-drawer) "LOGBOOK")) + ((org-string-nw-p p) + (if (string-match-p "\\`[0-9]+\\'" p) (string-to-number p) p)) + ((org-string-nw-p org-clock-into-drawer)) + ((integerp org-clock-into-drawer) org-clock-into-drawer) + ((not org-clock-into-drawer) nil) + ((org-log-into-drawer)) + (t "LOGBOOK")))) (defcustom org-clock-out-when-done t "When non-nil, clock will be stopped when the clocked entry is marked DONE. +\\\ DONE here means any DONE-like state. A nil value means clock will keep running until stopped explicitly with -`C-c C-x C-o', or until the clock is started in a different item. +`\\[org-clock-out]', or until the clock is started in a different item. Instead of t, this can also be a list of TODO states that should trigger clocking out." :group 'org-clock @@ -223,9 +235,6 @@ file name Play this sound file, fall back to beep" (const :tag "Standard beep" t) (file :tag "Play sound file"))) -(define-obsolete-variable-alias 'org-clock-modeline-total - 'org-clock-mode-line-total "24.3") - (defcustom org-clock-mode-line-total 'auto "Default setting for the time included for the mode line clock. This can be overruled locally using the CLOCK_MODELINE_TOTAL property. @@ -244,7 +253,7 @@ auto Automatically, either `all', or `repeat' for repeating tasks" (const :tag "All task time" all) (const :tag "Automatically, `all' or since `repeat'" auto))) -(org-defvaralias 'org-task-overrun-text 'org-clock-task-overrun-text) +(defvaralias 'org-task-overrun-text 'org-clock-task-overrun-text) (defcustom org-clock-task-overrun-text nil "Extra mode line text to indicate that the clock is overrun. The can be nil to indicate that instead of adding text, the clock time @@ -268,14 +277,14 @@ string as argument." (function :tag "Function"))) (defgroup org-clocktable nil - "Options concerning the clock table in Org-mode." + "Options concerning the clock table in Org mode." :tag "Org Clock Table" :group 'org-clock) (defcustom org-clocktable-defaults (list :maxlevel 2 - :lang (or (org-bound-and-true-p org-export-default-language) "en") + :lang (or (bound-and-true-p org-export-default-language) "en") :scope 'file :block nil :wstart 1 @@ -312,7 +321,9 @@ For more information, see `org-clocktable-write-default'." '(("en" "File" "L" "Timestamp" "Headline" "Time" "ALL" "Total time" "File time" "Clock summary at") ("es" "Archivo" "N" "Fecha y hora" "Tarea" "Tiempo" "TODO" "Tiempo total" "Tiempo archivo" "Clock summary at") ("fr" "Fichier" "N" "Horodatage" "En-tête" "Durée" "TOUT" "Durée totale" "Durée fichier" "Horodatage sommaire à") - ("nl" "Bestand" "N" "Tijdstip" "Hoofding" "Duur" "ALLES" "Totale duur" "Bestandstijd" "Clock summary at")) + ("nl" "Bestand" "N" "Tijdstip" "Hoofding" "Duur" "ALLES" "Totale duur" "Bestandstijd" "Clock summary at") + ("de" "Datei" "E" "Zeitstempel" "Kopfzeile" "Dauer" "GESAMT" + "Gesamtdauer" "Dateizeit" "Erstellt am")) "Terms used in clocktable, translated to different languages." :group 'org-clocktable :version "24.1" @@ -371,7 +382,7 @@ play with them." :type 'string) (defcustom org-clock-clocked-in-display 'mode-line - "When clocked in for a task, org-mode can display the current + "When clocked in for a task, Org can display the current task and accumulated time in the mode line and/or frame title. Allowed values are: @@ -413,6 +424,26 @@ if you are using Debian." :package-version '(Org . "8.0") :type 'string) +(defcustom org-clock-goto-before-context 2 + "Number of lines of context to display before currently clocked-in entry. +This applies when using `org-clock-goto'." + :group 'org-clock + :type 'integer) + +(defcustom org-clock-display-default-range 'thisyear + "Default range when displaying clocks with `org-clock-display'." + :group 'org-clock + :type '(choice (const today) + (const yesterday) + (const thisweek) + (const lastweek) + (const thismonth) + (const lastmonth) + (const thisyear) + (const lastyear) + (const untilnow) + (const :tag "Select range interactively" interactive))) + (defvar org-clock-in-prepare-hook nil "Hook run when preparing the clock. This hook is run before anything happens to the task that @@ -430,6 +461,33 @@ to add an effort property.") (defvar org-clock-has-been-used nil "Has the clock been used during the current Emacs session?") +(defvar org-clock-stored-history nil + "Clock history, populated by `org-clock-load'") +(defvar org-clock-stored-resume-clock nil + "Clock to resume, saved by `org-clock-load'") + +(defconst org-clock--oldest-date + (let* ((dichotomy + (lambda (min max pred) + (if (funcall pred min) min + (cl-incf min) + (while (> (- max min) 1) + (let ((mean (+ (ash min -1) (ash max -1) (logand min max 1)))) + (if (funcall pred mean) (setq max mean) (setq min mean))))) + max)) + (high + (funcall dichotomy + most-negative-fixnum + 0 + (lambda (m) (ignore-errors (decode-time (list m 0)))))) + (low + (funcall dichotomy + most-negative-fixnum + 0 + (lambda (m) (ignore-errors (decode-time (list high m))))))) + (list high low)) + "Internal time for oldest date representable on the system.") + ;;; The clock for measuring work time. (defvar org-mode-line-string "") @@ -500,8 +558,17 @@ of a different task.") (org-check-and-save-marker org-clock-hd-marker beg end) (org-check-and-save-marker org-clock-default-task beg end) (org-check-and-save-marker org-clock-interrupted-task beg end) - (mapc (lambda (m) (org-check-and-save-marker m beg end)) - org-clock-history)) + (dolist (m org-clock-history) + (org-check-and-save-marker m beg end))) + +(defun org-clock-drawer-name () + "Return clock drawer's name for current entry, or nil." + (let ((drawer (org-clock-into-drawer))) + (cond ((integerp drawer) + (let ((log-drawer (org-log-into-drawer))) + (if (stringp log-drawer) log-drawer "LOGBOOK"))) + ((stringp drawer) drawer) + (t nil)))) (defun org-clocking-buffer () "Return the clocking buffer if we are currently clocking a task or nil." @@ -519,8 +586,8 @@ of a different task.") (interactive) (let (och chl sel-list rpl (i 0) s) ;; Remove successive dups from the clock history to consider - (mapc (lambda (c) (if (not (equal c (car och))) (push c och))) - org-clock-history) + (dolist (c org-clock-history) + (unless (equal c (car och)) (push c och))) (setq och (reverse och) chl (length och)) (if (zerop chl) (user-error "No recent clock") @@ -541,17 +608,15 @@ of a different task.") (setq s (org-clock-insert-selection-line ?c org-clock-marker)) (push s sel-list)) (insert (org-add-props "Recent Tasks\n" nil 'face 'bold)) - (mapc - (lambda (m) - (when (marker-buffer m) - (setq i (1+ i) - s (org-clock-insert-selection-line - (if (< i 10) - (+ i ?0) - (+ i (- ?A 10))) m)) - (if (fboundp 'int-to-char) (setf (car s) (int-to-char (car s)))) - (push s sel-list))) - och) + (dolist (m och) + (when (marker-buffer m) + (setq i (1+ i) + s (org-clock-insert-selection-line + (if (< i 10) + (+ i ?0) + (+ i (- ?A 10))) m)) + (if (fboundp 'int-to-char) (setf (car s) (int-to-char (car s)))) + (push s sel-list))) (run-hooks 'org-clock-before-select-task-hook) (goto-char (point-min)) ;; Set min-height relatively to circumvent a possible but in @@ -559,6 +624,7 @@ of a different task.") (fit-window-to-buffer nil nil (if (< chl 10) chl (+ 5 chl))) (message (or prompt "Select task for clocking:")) (setq cursor-type nil rpl (read-char-exclusive)) + (kill-buffer) (cond ((eq rpl ?q) nil) ((eq rpl ?x) nil) @@ -570,25 +636,22 @@ of a different task.") And return a cons cell with the selection character integer and the marker pointing to it." (when (marker-buffer marker) - (let (file cat task heading prefix) + (let (cat task heading prefix) (with-current-buffer (org-base-buffer (marker-buffer marker)) - (save-excursion - (save-restriction - (widen) - (ignore-errors - (goto-char marker) - (setq file (buffer-file-name (marker-buffer marker)) - cat (org-get-category) - heading (org-get-heading 'notags) - prefix (save-excursion - (org-back-to-heading t) - (looking-at org-outline-regexp) - (match-string 0)) - task (substring - (org-fontify-like-in-org-mode - (concat prefix heading) - org-odd-levels-only) - (length prefix))))))) + (org-with-wide-buffer + (ignore-errors + (goto-char marker) + (setq cat (org-get-category) + heading (org-get-heading 'notags) + prefix (save-excursion + (org-back-to-heading t) + (looking-at org-outline-regexp) + (match-string 0)) + task (substring + (org-fontify-like-in-org-mode + (concat prefix heading) + org-odd-levels-only) + (length prefix)))))) (when (and cat task) (insert (format "[%c] %-12s %s\n" i cat task)) (cons i marker))))) @@ -608,19 +671,19 @@ If not, show simply the clocked time like 01:50." (let* ((effort-in-minutes (org-duration-string-to-minutes org-clock-effort)) (work-done-str - (org-propertize + (propertize (org-minutes-to-clocksum-string clocked-time) 'face (if (and org-clock-task-overrun (not org-clock-task-overrun-text)) 'org-mode-line-clock-overrun 'org-mode-line-clock))) (effort-str (org-minutes-to-clocksum-string effort-in-minutes)) - (clockstr (org-propertize + (clockstr (propertize (concat " [%s/" effort-str "] (" (replace-regexp-in-string "%" "%%" org-clock-heading) ")") 'face 'org-mode-line-clock))) (format clockstr work-done-str)) - (org-propertize (concat "[" (org-minutes-to-clocksum-string clocked-time) - (format " (%s)" org-clock-heading) "]") - 'face 'org-mode-line-clock)))) + (propertize (concat " [" (org-minutes-to-clocksum-string clocked-time) + "]" (format " (%s)" org-clock-heading)) + 'face 'org-mode-line-clock)))) (defun org-clock-get-last-clock-out-time () "Get the last clock-out time for the current subtree." @@ -635,20 +698,21 @@ If not, show simply the clocked time like 01:50." (org-clock-notify-once-if-expired) (setq org-clock-task-overrun nil)) (setq org-mode-line-string - (org-propertize + (propertize (let ((clock-string (org-clock-get-clock-string)) - (help-text "Org-mode clock is running.\nmouse-1 shows a menu\nmouse-2 will jump to task")) + (help-text "Org mode clock is running.\nmouse-1 shows a \ +menu\nmouse-2 will jump to task")) (if (and (> org-clock-string-limit 0) (> (length clock-string) org-clock-string-limit)) - (org-propertize + (propertize (substring clock-string 0 org-clock-string-limit) 'help-echo (concat help-text ": " org-clock-heading)) - (org-propertize clock-string 'help-echo help-text))) + (propertize clock-string 'help-echo help-text))) 'local-map org-clock-mode-line-map - 'mouse-face (if (featurep 'xemacs) 'highlight 'mode-line-highlight))) + 'mouse-face 'mode-line-highlight)) (if (and org-clock-task-overrun org-clock-task-overrun-text) (setq org-mode-line-string - (concat (org-propertize + (concat (propertize org-clock-task-overrun-text 'face 'org-mode-line-clock-overrun) org-mode-line-string))) (force-mode-line-update)) @@ -739,7 +803,7 @@ use libnotify if available, or fall back on a message." org-show-notification-handler notification)) ((fboundp 'notifications-notify) (notifications-notify - :title "Org-mode message" + :title "Org mode message" :body notification ;; FIXME how to link to the Org icon? ;; :app-icon "~/.emacs.d/icons/mail.png" @@ -776,11 +840,12 @@ If CLOCK-SOUND is non-nil, it overrides `org-clock-sound'." "Search through the given file and find all open clocks." (let ((buf (or (get-file-buffer file) (find-file-noselect file))) + (org-clock-re (concat org-clock-string " \\(\\[.*?\\]\\)$")) clocks) (with-current-buffer buf (save-excursion (goto-char (point-min)) - (while (re-search-forward "CLOCK: \\(\\[.*?\\]\\)$" nil t) + (while (re-search-forward org-clock-re nil t) (push (cons (copy-marker (match-end 1) t) (org-time-string-to-time (match-string 1))) clocks)))) clocks)) @@ -793,12 +858,10 @@ If CLOCK-SOUND is non-nil, it overrides `org-clock-sound'." (defmacro org-with-clock-position (clock &rest forms) "Evaluate FORMS with CLOCK as the current active clock." `(with-current-buffer (marker-buffer (car ,clock)) - (save-excursion - (save-restriction - (widen) - (goto-char (car ,clock)) - (beginning-of-line) - ,@forms)))) + (org-with-wide-buffer + (goto-char (car ,clock)) + (beginning-of-line) + ,@forms))) (def-edebug-spec org-with-clock-position (form body)) (put 'org-with-clock-position 'lisp-indent-function 1) @@ -812,7 +875,7 @@ This macro also protects the current active clock from being altered." (org-clock-effort) (org-clock-marker (car ,clock)) (org-clock-hd-marker (save-excursion - (outline-back-to-heading t) + (org-back-to-heading t) (point-marker)))) ,@forms))) (def-edebug-spec org-with-clock (form body)) @@ -885,7 +948,7 @@ If necessary, clock-out of the currently active clock." (defun org-clock-jump-to-current-clock (&optional effective-clock) (interactive) - (let ((org-clock-into-drawer (org-clock-into-drawer)) + (let ((drawer (org-clock-into-drawer)) (clock (or effective-clock (cons org-clock-marker org-clock-start-time)))) (unless (marker-buffer (car clock)) @@ -893,26 +956,21 @@ If necessary, clock-out of the currently active clock." (org-with-clock clock (org-clock-goto)) (with-current-buffer (marker-buffer (car clock)) (goto-char (car clock)) - (if org-clock-into-drawer - (let ((logbook - (if (stringp org-clock-into-drawer) - (concat ":" org-clock-into-drawer ":") - ":LOGBOOK:"))) - (ignore-errors - (outline-flag-region - (save-excursion - (outline-back-to-heading t) - (search-forward logbook) - (goto-char (match-beginning 0))) - (save-excursion - (outline-back-to-heading t) - (search-forward logbook) - (search-forward ":END:") - (goto-char (match-end 0))) - nil))))))) + (when drawer + (org-with-wide-buffer + (let ((drawer-re (format "^[ \t]*:%s:[ \t]*$" + (regexp-quote (if (stringp drawer) drawer "LOGBOOK")))) + (beg (save-excursion (org-back-to-heading t) (point)))) + (catch 'exit + (while (re-search-backward drawer-re beg t) + (let ((element (org-element-at-point))) + (when (eq (org-element-type element) 'drawer) + (when (> (org-element-property :end element) (car clock)) + (org-flag-drawer nil element)) + (throw 'exit nil))))))))))) (defun org-clock-resolve (clock &optional prompt-fn last-valid fail-quietly) - "Resolve an open org-mode clock. + "Resolve an open Org clock. An open clock was found, with `dangling' possibly being non-nil. If this function was invoked with a prefix argument, non-dangling open clocks are ignored. The given clock requires some sort of @@ -930,7 +988,7 @@ The format of clock is (CONS MARKER START-TIME), where MARKER identifies the buffer and position the clock is open at (and thus, the heading it's under), and START-TIME is when the clock was started." - (assert clock) + (cl-assert clock) (let* ((ch (save-window-excursion (save-excursion @@ -947,7 +1005,7 @@ k/K Keep X minutes of the idle time (default is all). If this that many minutes after the time that idling began, and then clocked back in at the present time. -g/G Indicate that you “got back” X minutes ago. This is quite +g/G Indicate that you \"got back\" X minutes ago. This is quite different from `k': it clocks you out from the beginning of the idle period and clock you back in X minutes ago. @@ -963,10 +1021,6 @@ For all these options, using uppercase makes your final state to be CLOCKED OUT.")))) (org-fit-window-to-buffer (get-buffer-window "*Org Clock*")) (let (char-pressed) - (when (featurep 'xemacs) - (message (concat (funcall prompt-fn clock) - " [jkKgGsScCiq]? ")) - (setq char-pressed (read-char-exclusive))) (while (or (null char-pressed) (and (not (memq char-pressed '(?k ?K ?g ?G ?s ?S ?C @@ -1028,7 +1082,7 @@ to be CLOCKED OUT.")))) ;;;###autoload (defun org-resolve-clocks (&optional only-dangling-p prompt-fn last-valid) - "Resolve all currently open org-mode clocks. + "Resolve all currently open Org clocks. If `only-dangling-p' is non-nil, only ask to resolve dangling \(i.e., not currently open and valid) clocks." (interactive "P") @@ -1091,7 +1145,7 @@ This routine returns a floating point number." (defvar org-clock-user-idle-seconds) (defun org-resolve-clocks-if-idle () - "Resolve all currently open org-mode clocks. + "Resolve all currently open Org clocks. This is performed after `org-clock-idle-time' minutes, to check if the user really wants to stay clocked in after being idle for so long." @@ -1106,13 +1160,12 @@ so long." (org-clock-resolve (cons org-clock-marker org-clock-start-time) - (function - (lambda (clock) - (format "Clocked in & idle for %.1f mins" - (/ (float-time - (time-subtract (current-time) - org-clock-user-idle-start)) - 60.0)))) + (lambda (_) + (format "Clocked in & idle for %.1f mins" + (/ (float-time + (time-subtract (current-time) + org-clock-user-idle-start)) + 60.0))) org-clock-user-idle-start))))) (defvar org-clock-current-task nil "Task currently clocked in.") @@ -1122,18 +1175,27 @@ so long." ;;;###autoload (defun org-clock-in (&optional select start-time) "Start the clock on the current item. + If necessary, clock-out of the currently active clock. -With a prefix argument SELECT (\\[universal-argument]), offer a list of recently clocked -tasks to clock into. When SELECT is \\[universal-argument] \\[universal-argument], clock into the current task -and mark it as the default task, a special task that will always be offered -in the clocking selection, associated with the letter `d'. -When SELECT is \\[universal-argument] \\[universal-argument] \\[universal-argument], \ -clock in by using the last clock-out -time as the start time \(see `org-clock-continuously' to -make this the default behavior.)" + +With a `\\[universal-argument]' prefix argument SELECT, offer a list of \ +recently clocked +tasks to clock into. + +When SELECT is `\\[universal-argument] \ \\[universal-argument]', \ +clock into the current task and mark it as +the default task, a special task that will always be offered in the +clocking selection, associated with the letter `d'. + +When SELECT is `\\[universal-argument] \\[universal-argument] \ +\\[universal-argument]', clock in by using the last clock-out +time as the start time. See `org-clock-continuously' to make this +the default behavior." (interactive "P") (setq org-clock-notification-was-shown nil) - (org-refresh-properties org-effort-property 'org-effort) + (org-refresh-properties + org-effort-property '((effort . identity) + (effort-minutes . org-duration-string-to-minutes))) (catch 'abort (let ((interrupting (and (not org-clock-resolving-clocks-due-to-idleness) (org-clocking-p))) @@ -1148,7 +1210,7 @@ make this the default behavior.)" (not org-clock-resolving-clocks)) (setq org-clock-leftover-time nil) (let ((org-clock-clocking-in t)) - (org-resolve-clocks))) ; check if any clocks are dangling + (org-resolve-clocks))) ; check if any clocks are dangling (when (equal select '(64)) ;; Set start-time to `org-clock-out-time' @@ -1201,116 +1263,116 @@ make this the default behavior.)" (set-buffer (org-base-buffer (marker-buffer selected-task))) (setq target-pos (marker-position selected-task)) (move-marker selected-task nil)) - (save-excursion - (save-restriction - (widen) - (goto-char target-pos) - (org-back-to-heading t) - (or interrupting (move-marker org-clock-interrupted-task nil)) - (run-hooks 'org-clock-in-prepare-hook) - (org-clock-history-push) - (setq org-clock-current-task (nth 4 (org-heading-components))) - (cond ((functionp org-clock-in-switch-to-state) - (looking-at org-complex-heading-regexp) - (let ((newstate (funcall org-clock-in-switch-to-state - (match-string 2)))) - (if newstate (org-todo newstate)))) - ((and org-clock-in-switch-to-state - (not (looking-at (concat org-outline-regexp "[ \t]*" - org-clock-in-switch-to-state - "\\>")))) - (org-todo org-clock-in-switch-to-state))) - (setq org-clock-heading - (cond ((and org-clock-heading-function - (functionp org-clock-heading-function)) - (funcall org-clock-heading-function)) - ((nth 4 (org-heading-components)) - (replace-regexp-in-string - "\\[\\[.*?\\]\\[\\(.*?\\)\\]\\]" "\\1" - (match-string-no-properties 4))) - (t "???"))) - (org-clock-find-position org-clock-in-resume) - (cond - ((and org-clock-in-resume - (looking-at - (concat "^[ \t]*" org-clock-string - " \\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}" - " *\\sw+.? +[012][0-9]:[0-5][0-9]\\)\\][ \t]*$"))) - (message "Matched %s" (match-string 1)) - (setq ts (concat "[" (match-string 1) "]")) - (goto-char (match-end 1)) - (setq org-clock-start-time - (apply 'encode-time - (org-parse-time-string (match-string 1)))) - (setq org-clock-effort (org-entry-get (point) org-effort-property)) - (setq org-clock-total-time (org-clock-sum-current-item - (org-clock-get-sum-start)))) - ((eq org-clock-in-resume 'auto-restart) - ;; called from org-clock-load during startup, - ;; do not interrupt, but warn! - (message "Cannot restart clock because task does not contain unfinished clock") - (ding) - (sit-for 2) - (throw 'abort nil)) - (t - (insert-before-markers "\n") - (backward-char 1) - (org-indent-line) - (when (and (save-excursion - (end-of-line 0) - (org-in-item-p))) - (beginning-of-line 1) - (org-indent-line-to (- (org-get-indentation) 2))) - (insert org-clock-string " ") - (setq org-clock-effort (org-entry-get (point) org-effort-property)) - (setq org-clock-total-time (org-clock-sum-current-item - (org-clock-get-sum-start))) - (setq org-clock-start-time - (or (and org-clock-continuously org-clock-out-time) - (and leftover - (y-or-n-p - (format - "You stopped another clock %d mins ago; start this one from then? " - (/ (- (float-time - (org-current-time org-clock-rounding-minutes t)) - (float-time leftover)) 60))) - leftover) - start-time - (org-current-time org-clock-rounding-minutes t))) - (setq ts (org-insert-time-stamp org-clock-start-time - 'with-hm 'inactive)))) - (move-marker org-clock-marker (point) (buffer-base-buffer)) - (move-marker org-clock-hd-marker - (save-excursion (org-back-to-heading t) (point)) - (buffer-base-buffer)) - (setq org-clock-has-been-used t) - ;; add to mode line - (when (or (eq org-clock-clocked-in-display 'mode-line) - (eq org-clock-clocked-in-display 'both)) - (or global-mode-string (setq global-mode-string '(""))) - (or (memq 'org-mode-line-string global-mode-string) - (setq global-mode-string - (append global-mode-string '(org-mode-line-string))))) - ;; add to frame title - (when (or (eq org-clock-clocked-in-display 'frame-title) - (eq org-clock-clocked-in-display 'both)) - (setq frame-title-format org-clock-frame-title-format)) - (org-clock-update-mode-line) - (when org-clock-mode-line-timer - (cancel-timer org-clock-mode-line-timer) - (setq org-clock-mode-line-timer nil)) - (when org-clock-clocked-in-display - (setq org-clock-mode-line-timer - (run-with-timer org-clock-update-period - org-clock-update-period - 'org-clock-update-mode-line))) - (when org-clock-idle-timer - (cancel-timer org-clock-idle-timer) - (setq org-clock-idle-timer nil)) - (setq org-clock-idle-timer - (run-with-timer 60 60 'org-resolve-clocks-if-idle)) - (message "Clock starts at %s - %s" ts org--msg-extra) - (run-hooks 'org-clock-in-hook))))))) + (org-with-wide-buffer + (goto-char target-pos) + (org-back-to-heading t) + (or interrupting (move-marker org-clock-interrupted-task nil)) + (run-hooks 'org-clock-in-prepare-hook) + (org-clock-history-push) + (setq org-clock-current-task (nth 4 (org-heading-components))) + (cond ((functionp org-clock-in-switch-to-state) + (let ((case-fold-search nil)) + (looking-at org-complex-heading-regexp)) + (let ((newstate (funcall org-clock-in-switch-to-state + (match-string 2)))) + (when newstate (org-todo newstate)))) + ((and org-clock-in-switch-to-state + (not (looking-at (concat org-outline-regexp "[ \t]*" + org-clock-in-switch-to-state + "\\>")))) + (org-todo org-clock-in-switch-to-state))) + (setq org-clock-heading + (cond ((and org-clock-heading-function + (functionp org-clock-heading-function)) + (funcall org-clock-heading-function)) + ((nth 4 (org-heading-components)) + (replace-regexp-in-string + "\\[\\[.*?\\]\\[\\(.*?\\)\\]\\]" "\\1" + (match-string-no-properties 4))) + (t "???"))) + (org-clock-find-position org-clock-in-resume) + (cond + ((and org-clock-in-resume + (looking-at + (concat "^[ \t]*" org-clock-string + " \\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}" + " *\\sw+.? +[012][0-9]:[0-5][0-9]\\)\\][ \t]*$"))) + (message "Matched %s" (match-string 1)) + (setq ts (concat "[" (match-string 1) "]")) + (goto-char (match-end 1)) + (setq org-clock-start-time + (apply 'encode-time + (org-parse-time-string (match-string 1)))) + (setq org-clock-effort (org-entry-get (point) org-effort-property)) + (setq org-clock-total-time (org-clock-sum-current-item + (org-clock-get-sum-start)))) + ((eq org-clock-in-resume 'auto-restart) + ;; called from org-clock-load during startup, + ;; do not interrupt, but warn! + (message "Cannot restart clock because task does not contain unfinished clock") + (ding) + (sit-for 2) + (throw 'abort nil)) + (t + (insert-before-markers "\n") + (backward-char 1) + (org-indent-line) + (when (and (save-excursion + (end-of-line 0) + (org-in-item-p))) + (beginning-of-line 1) + (indent-line-to (- (org-get-indentation) 2))) + (insert org-clock-string " ") + (setq org-clock-effort (org-entry-get (point) org-effort-property)) + (setq org-clock-total-time (org-clock-sum-current-item + (org-clock-get-sum-start))) + (setq org-clock-start-time + (or (and org-clock-continuously org-clock-out-time) + (and leftover + (y-or-n-p + (format + "You stopped another clock %d mins ago; start this one from then? " + (/ (- (float-time + (org-current-time org-clock-rounding-minutes t)) + (float-time leftover)) + 60))) + leftover) + start-time + (org-current-time org-clock-rounding-minutes t))) + (setq ts (org-insert-time-stamp org-clock-start-time + 'with-hm 'inactive)))) + (move-marker org-clock-marker (point) (buffer-base-buffer)) + (move-marker org-clock-hd-marker + (save-excursion (org-back-to-heading t) (point)) + (buffer-base-buffer)) + (setq org-clock-has-been-used t) + ;; add to mode line + (when (or (eq org-clock-clocked-in-display 'mode-line) + (eq org-clock-clocked-in-display 'both)) + (or global-mode-string (setq global-mode-string '(""))) + (or (memq 'org-mode-line-string global-mode-string) + (setq global-mode-string + (append global-mode-string '(org-mode-line-string))))) + ;; add to frame title + (when (or (eq org-clock-clocked-in-display 'frame-title) + (eq org-clock-clocked-in-display 'both)) + (setq frame-title-format org-clock-frame-title-format)) + (org-clock-update-mode-line) + (when org-clock-mode-line-timer + (cancel-timer org-clock-mode-line-timer) + (setq org-clock-mode-line-timer nil)) + (when org-clock-clocked-in-display + (setq org-clock-mode-line-timer + (run-with-timer org-clock-update-period + org-clock-update-period + 'org-clock-update-mode-line))) + (when org-clock-idle-timer + (cancel-timer org-clock-idle-timer) + (setq org-clock-idle-timer nil)) + (setq org-clock-idle-timer + (run-with-timer 60 60 'org-resolve-clocks-if-idle)) + (message "Clock starts at %s - %s" ts org--msg-extra) + (run-hooks 'org-clock-in-hook)))))) ;;;###autoload (defun org-clock-in-last (&optional arg) @@ -1324,8 +1386,7 @@ With three universal prefix arguments, interactively prompt for a todo state to switch to, overriding the existing value `org-clock-in-switch-to-state'." (interactive "P") - (if (equal arg '(4)) - (org-clock-in (org-clock-select-task)) + (if (equal arg '(4)) (org-clock-in arg) (let ((start-time (if (or org-clock-continuously (equal arg '(16))) (or org-clock-out-time (org-current-time org-clock-rounding-minutes t)) @@ -1371,10 +1432,12 @@ decides which time to use." (current-time)) ((equal cmt "today") (setq org--msg-extra "showing today's task time.") - (let* ((dt (decode-time))) - (setq dt (append (list 0 0 0) (nthcdr 3 dt))) - (if org-extend-today-until - (setf (nth 2 dt) org-extend-today-until)) + (let* ((dt (decode-time)) + (hour (nth 2 dt)) + (day (nth 3 dt))) + (if (< hour org-extend-today-until) (setf (nth 3 dt) (1- day))) + (setf (nth 2 dt) org-extend-today-until) + (setq dt (append (list 0 0) (nthcdr 2 dt))) (apply 'encode-time dt))) ((or (equal cmt "all") (and (or (not cmt) (equal cmt "auto")) @@ -1396,87 +1459,93 @@ When FIND-UNCLOSED is non-nil, first check if there is an unclosed clock line and position cursor in that line." (org-back-to-heading t) (catch 'exit - (let* ((org-clock-into-drawer (org-clock-into-drawer)) - (beg (save-excursion - (beginning-of-line 2) - (or (bolp) (newline)) - (point))) - (end (progn (outline-next-heading) (point))) - (re (concat "^[ \t]*" org-clock-string)) - (cnt 0) - (drawer (if (stringp org-clock-into-drawer) - org-clock-into-drawer "LOGBOOK")) - first last ind-last) - (goto-char beg) - (when (and find-unclosed - (re-search-forward - (concat "^[ \t]*" org-clock-string - " \\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}" - " *\\sw+ +[012][0-9]:[0-5][0-9]\\)\\][ \t]*$") - end t)) - (beginning-of-line 1) - (throw 'exit t)) - (when (eobp) (newline) (setq end (max (point) end))) - (when (re-search-forward (concat "^[ \t]*:" drawer ":") end t) - ;; we seem to have a CLOCK drawer, so go there. - (beginning-of-line 2) - (or org-log-states-order-reversed - (and (re-search-forward org-property-end-re nil t) - (goto-char (match-beginning 0)))) - (throw 'exit t)) - ;; Lets count the CLOCK lines + (let* ((beg (line-beginning-position)) + (end (save-excursion (outline-next-heading) (point))) + (org-clock-into-drawer (org-clock-into-drawer)) + (drawer (org-clock-drawer-name))) + ;; Look for a running clock if FIND-UNCLOSED in non-nil. + (when find-unclosed + (let ((open-clock-re + (concat "^[ \t]*" + org-clock-string + " \\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}" + " *\\sw+ +[012][0-9]:[0-5][0-9]\\)\\][ \t]*$"))) + (while (re-search-forward open-clock-re end t) + (let ((element (org-element-at-point))) + (when (and (eq (org-element-type element) 'clock) + (eq (org-element-property :status element) 'running)) + (beginning-of-line) + (throw 'exit t)))))) + ;; Look for an existing clock drawer. + (when drawer + (goto-char beg) + (let ((drawer-re (concat "^[ \t]*:" (regexp-quote drawer) ":[ \t]*$"))) + (while (re-search-forward drawer-re end t) + (let ((element (org-element-at-point))) + (when (eq (org-element-type element) 'drawer) + (let ((cend (org-element-property :contents-end element))) + (if (and (not org-log-states-order-reversed) cend) + (goto-char cend) + (forward-line)) + (throw 'exit t))))))) (goto-char beg) - (while (re-search-forward re end t) - (setq first (or first (match-beginning 0)) - last (match-beginning 0) - cnt (1+ cnt))) - (when (and (integerp org-clock-into-drawer) - last - (>= (1+ cnt) org-clock-into-drawer)) - ;; Wrap current entries into a new drawer - (goto-char last) - (setq ind-last (org-get-indentation)) - (beginning-of-line 2) - (if (and (>= (org-get-indentation) ind-last) - (org-at-item-p)) - (when (and (>= (org-get-indentation) ind-last) - (org-at-item-p)) - (let ((struct (org-list-struct))) - (goto-char (org-list-get-bottom-point struct))))) - (insert ":END:\n") - (beginning-of-line 0) - (org-indent-line-to ind-last) - (goto-char first) - (insert ":" drawer ":\n") - (beginning-of-line 0) - (org-indent-line) - (org-flag-drawer t) - (beginning-of-line 2) - (or org-log-states-order-reversed - (and (re-search-forward org-property-end-re nil t) - (goto-char (match-beginning 0)))) - (throw 'exit nil)) - - (goto-char beg) - (while (and (looking-at (concat "[ \t]*" org-keyword-time-regexp)) - (not (equal (match-string 1) org-clock-string))) - ;; Planning info, skip to after it - (beginning-of-line 2) - (or (bolp) (newline))) - (when (or (eq org-clock-into-drawer t) - (stringp org-clock-into-drawer) - (and (integerp org-clock-into-drawer) - (< org-clock-into-drawer 2))) - (insert ":" drawer ":\n:END:\n") - (beginning-of-line -1) - (org-indent-line) - (org-flag-drawer t) - (beginning-of-line 2) - (org-indent-line) - (beginning-of-line) - (or org-log-states-order-reversed - (and (re-search-forward org-property-end-re nil t) - (goto-char (match-beginning 0)))))))) + (let ((clock-re (concat "^[ \t]*" org-clock-string)) + (count 0) + positions) + ;; Count the CLOCK lines and store their positions. + (save-excursion + (while (re-search-forward clock-re end t) + (let ((element (org-element-at-point))) + (when (eq (org-element-type element) 'clock) + (setq positions (cons (line-beginning-position) positions) + count (1+ count)))))) + (cond + ((null positions) + ;; Skip planning line and property drawer, if any. + (org-end-of-meta-data) + (unless (bolp) (insert "\n")) + ;; Create a new drawer if necessary. + (when (and org-clock-into-drawer + (or (not (wholenump org-clock-into-drawer)) + (< org-clock-into-drawer 2))) + (let ((beg (point))) + (insert ":" drawer ":\n:END:\n") + (org-indent-region beg (point)) + (goto-char beg) + (org-flag-drawer t) + (forward-line)))) + ;; When a clock drawer needs to be created because of the + ;; number of clock items or simply if it is missing, collect + ;; all clocks in the section and wrap them within the drawer. + ((if (wholenump org-clock-into-drawer) + (>= (1+ count) org-clock-into-drawer) + drawer) + ;; Skip planning line and property drawer, if any. + (org-end-of-meta-data) + (let ((beg (point))) + (insert + (mapconcat + (lambda (p) + (save-excursion + (goto-char p) + (org-trim (delete-and-extract-region + (save-excursion (skip-chars-backward " \r\t\n") + (line-beginning-position 2)) + (line-beginning-position 2))))) + positions "\n") + "\n:END:\n") + (let ((end (point-marker))) + (goto-char beg) + (save-excursion (insert ":" drawer ":\n")) + (org-flag-drawer t) + (org-indent-region (point) end) + (forward-line) + (unless org-log-states-order-reversed + (goto-char end) + (beginning-of-line -1)) + (set-marker end nil)))) + (org-log-states-order-reversed (goto-char (car (last positions)))) + (t (goto-char (car positions)))))))) ;;;###autoload (defun org-clock-out (&optional switch-to-state fail-quietly at-time) @@ -1504,7 +1573,7 @@ to, overriding the existing value of `org-clock-out-switch-to-state'." ts te s h m remove) (setq org-clock-out-time now) (save-excursion ; Do not replace this with `with-current-buffer'. - (org-no-warnings (set-buffer (org-clocking-buffer))) + (with-no-warnings (set-buffer (org-clocking-buffer))) (save-restriction (widen) (goto-char org-clock-marker) @@ -1517,24 +1586,28 @@ to, overriding the existing value of `org-clock-out-switch-to-state'." (delete-region (point) (point-at-eol)) (insert "--") (setq te (org-insert-time-stamp (or at-time now) 'with-hm 'inactive)) - (setq s (- (float-time (apply 'encode-time (org-parse-time-string te))) - (float-time (apply 'encode-time (org-parse-time-string ts)))) + (setq s (- (float-time + (apply #'encode-time (org-parse-time-string te nil t))) + (float-time + (apply #'encode-time (org-parse-time-string ts nil t)))) h (floor (/ s 3600)) s (- s (* 3600 h)) m (floor (/ s 60)) s (- s (* 60 s))) (insert " => " (format "%2d:%02d" h m)) - (when (setq remove (and org-clock-out-remove-zero-time-clocks - (= (+ h m) 0))) - (beginning-of-line 1) - (delete-region (point) (point-at-eol)) - (and (looking-at "\n") (> (point-max) (1+ (point))) - (delete-char 1))) (move-marker org-clock-marker nil) (move-marker org-clock-hd-marker nil) - (when org-log-note-clock-out - (org-add-log-setup 'clock-out nil nil nil nil - (concat "# Task: " (org-get-heading t) "\n\n"))) + ;; Possibly remove zero time clocks. However, do not add + ;; a note associated to the CLOCK line in this case. + (cond ((and org-clock-out-remove-zero-time-clocks + (= (+ h m) 0)) + (setq remove t) + (delete-region (line-beginning-position) + (line-beginning-position 2))) + (org-log-note-clock-out + (org-add-log-setup + 'clock-out nil nil nil + (concat "# Task: " (org-get-heading t) "\n\n")))) (when org-clock-mode-line-timer (cancel-timer org-clock-mode-line-timer) (setq org-clock-mode-line-timer nil)) @@ -1551,10 +1624,11 @@ to, overriding the existing value of `org-clock-out-switch-to-state'." (org-clock-out-when-done nil)) (cond ((functionp org-clock-out-switch-to-state) - (looking-at org-complex-heading-regexp) + (let ((case-fold-search nil)) + (looking-at org-complex-heading-regexp)) (let ((newstate (funcall org-clock-out-switch-to-state (match-string 2)))) - (if newstate (org-todo newstate)))) + (when newstate (org-todo newstate)))) ((and org-clock-out-switch-to-state (not (looking-at (concat org-outline-regexp "[ \t]*" org-clock-out-switch-to-state @@ -1564,34 +1638,25 @@ to, overriding the existing value of `org-clock-out-switch-to-state'." (message (concat "Clock stopped at %s after " (org-minutes-to-clocksum-string (+ (* 60 h) m)) "%s") te (if remove " => LINE REMOVED" "")) - (let ((h org-clock-out-hook)) - ;; If a closing note needs to be stored in the drawer - ;; where clocks are stored, let's temporarily disable - ;; `org-clock-remove-empty-clock-drawer' - (if (and (equal org-clock-into-drawer org-log-into-drawer) - (eq org-log-done 'note) - org-clock-out-when-done) - (setq h (delq 'org-clock-remove-empty-clock-drawer h))) - (mapc (lambda (f) (funcall f)) h)) + (run-hooks 'org-clock-out-hook) (unless (org-clocking-p) (setq org-clock-current-task nil))))))) (add-hook 'org-clock-out-hook 'org-clock-remove-empty-clock-drawer) -(defun org-clock-remove-empty-clock-drawer nil - "Remove empty clock drawer in the current subtree." - (let* ((olid (or (org-entry-get (point) "LOG_INTO_DRAWER") - org-log-into-drawer)) - (clock-drawer (if (eq t olid) "LOGBOOK" olid)) - (end (save-excursion (org-end-of-subtree t t)))) - (when clock-drawer - (save-excursion - (org-back-to-heading t) - (while (and (< (point) end) - (search-forward clock-drawer end t)) - (goto-char (match-beginning 0)) - (org-remove-empty-drawer-at clock-drawer (point)) - (forward-line 1)))))) +(defun org-clock-remove-empty-clock-drawer () + "Remove empty clock drawers in current subtree." + (save-excursion + (org-back-to-heading t) + (org-map-tree + (lambda () + (let ((drawer (org-clock-drawer-name)) + (case-fold-search t)) + (when drawer + (let ((re (format "^[ \t]*:%s:[ \t]*$" (regexp-quote drawer))) + (end (save-excursion (outline-next-heading)))) + (while (re-search-forward re end t) + (org-remove-empty-drawer-at (point)))))))))) (defun org-clock-timestamps-up (&optional n) "Increase CLOCK timestamps at cursor. @@ -1607,7 +1672,7 @@ Optional argument N tells to change by that many units." (defun org-clock-timestamps-change (updown &optional n) "Change CLOCK timestamps synchronously at cursor. -UPDOWN tells whether to change 'up or 'down. +UPDOWN tells whether to change `up' or `down'. Optional argument N tells to change by that many units." (setq org-ts-what nil) (when (org-at-timestamp-p t) @@ -1654,13 +1719,13 @@ Optional argument N tells to change by that many units." (setq frame-title-format org-frame-title-format-backup) (force-mode-line-update) (error "No active clock")) - (save-excursion ; Do not replace this with `with-current-buffer'. - (org-no-warnings (set-buffer (org-clocking-buffer))) + (save-excursion ; Do not replace this with `with-current-buffer'. + (with-no-warnings (set-buffer (org-clocking-buffer))) (goto-char org-clock-marker) - (if (org-looking-back (concat "^[ \t]*" org-clock-string ".*") - (line-beginning-position)) + (if (looking-back (concat "^[ \t]*" org-clock-string ".*") + (line-beginning-position)) (progn (delete-region (1- (point-at-bol)) (point-at-eol)) - (org-remove-empty-drawer-at "LOGBOOK" (point))) + (org-remove-empty-drawer-at (point))) (message "Clock gone, cancel the timer anyway") (sit-for 2))) (move-marker org-clock-marker nil) @@ -1672,12 +1737,6 @@ Optional argument N tells to change by that many units." (message "Clock canceled") (run-hooks 'org-clock-cancel-hook)) -(defcustom org-clock-goto-before-context 2 - "Number of lines of context to display before currently clocked-in entry. -This applies when using `org-clock-goto'." - :group 'org-clock - :type 'integer) - ;;;###autoload (defun org-clock-goto (&optional select) "Go to the currently clocked-in entry, or to the most recently clocked one. @@ -1695,7 +1754,7 @@ With prefix arg SELECT, offer recently clocked tasks for selection." (setq recent t) (car org-clock-history)) (t (error "No active or recent clock task"))))) - (org-pop-to-buffer-same-window (marker-buffer m)) + (pop-to-buffer-same-window (marker-buffer m)) (if (or (< m (point-min)) (> m (point-max))) (widen)) (goto-char m) (org-show-entry) @@ -1707,15 +1766,27 @@ With prefix arg SELECT, offer recently clocked tasks for selection." (message "No running clock, this is the most recently clocked task")) (run-hooks 'org-clock-goto-hook))) -(defvar org-clock-file-total-minutes nil +(defvar-local org-clock-file-total-minutes nil "Holds the file total time in minutes, after a call to `org-clock-sum'.") -(make-variable-buffer-local 'org-clock-file-total-minutes) (defun org-clock-sum-today (&optional headline-filter) "Sum the times for each subtree for today." - (interactive) (let ((range (org-clock-special-range 'today))) - (org-clock-sum (car range) (cadr range) nil :org-clock-minutes-today))) + (org-clock-sum (car range) (cadr range) + headline-filter :org-clock-minutes-today))) + +(defun org-clock-sum-custom (&optional headline-filter range propname) + "Sum the times for each subtree for today." + (let ((r (or (and (symbolp range) (org-clock-special-range range)) + (org-clock-special-range + (intern (completing-read + "Range: " + '("today" "yesterday" "thisweek" "lastweek" + "thismonth" "lastmonth" "thisyear" "lastyear" + "interactive") + nil t)))))) + (org-clock-sum (car r) (cadr r) + headline-filter (or propname :org-clock-minutes-custom)))) ;;;###autoload (defun org-clock-sum (&optional tstart tend headline-filter propname) @@ -1726,7 +1797,6 @@ HEADLINE-FILTER is a zero-arg function that, if specified, is called for each headline in the time range with point at the headline. Headlines for which HEADLINE-FILTER returns nil are excluded from the clock summation. PROPNAME lets you set a custom text property instead of :org-clock-minutes." - (interactive) (org-with-silent-modifications (let* ((re (concat "^\\(\\*+\\)[ \t]\\|^[ \t]*" org-clock-string @@ -1753,9 +1823,9 @@ PROPNAME lets you set a custom text property instead of :org-clock-minutes." (setq ts (match-string 2) te (match-string 3) ts (float-time - (apply 'encode-time (org-parse-time-string ts))) + (apply #'encode-time (org-parse-time-string ts nil t))) te (float-time - (apply 'encode-time (org-parse-time-string te))) + (apply #'encode-time (org-parse-time-string te nil t))) ts (if tstart (max ts tstart) ts) te (if tend (min te tend) te) dt (- te ts) @@ -1774,7 +1844,8 @@ PROPNAME lets you set a custom text property instead of :org-clock-minutes." (>= (float-time org-clock-start-time) tstart) (<= (float-time org-clock-start-time) tend)) (let ((time (floor (- (float-time) - (float-time org-clock-start-time)) 60))) + (float-time org-clock-start-time)) + 60))) (setq t1 (+ t1 time)))) (let* ((headline-forced (get-text-property (point) @@ -1784,27 +1855,27 @@ PROPNAME lets you set a custom text property instead of :org-clock-minutes." (save-excursion (save-match-data (funcall headline-filter)))))) (setq level (- (match-end 1) (match-beginning 1))) + (when (>= level lmax) + (setq ltimes (vconcat ltimes (make-vector lmax 0)) lmax (* 2 lmax))) (when (or (> t1 0) (> (aref ltimes level) 0)) (when (or headline-included headline-forced) (if headline-included - (loop for l from 0 to level do - (aset ltimes l (+ (aref ltimes l) t1)))) + (cl-loop for l from 0 to level do + (aset ltimes l (+ (aref ltimes l) t1)))) (setq time (aref ltimes level)) (goto-char (match-beginning 0)) (put-text-property (point) (point-at-eol) (or propname :org-clock-minutes) time) - (if headline-filter - (save-excursion - (save-match-data - (while - (> (funcall outline-level) 1) - (outline-up-heading 1 t) - (put-text-property - (point) (point-at-eol) - :org-clock-force-headline-inclusion t)))))) + (when headline-filter + (save-excursion + (save-match-data + (while (org-up-heading-safe) + (put-text-property + (point) (line-end-position) + :org-clock-force-headline-inclusion t)))))) (setq t1 0) - (loop for l from level to (1- lmax) do - (aset ltimes l 0))))))) + (cl-loop for l from level to (1- lmax) do + (aset ltimes l 0))))))) (setq org-clock-file-total-minutes (aref ltimes 0)))))) (defun org-clock-sum-current-item (&optional tstart) @@ -1816,74 +1887,99 @@ PROPNAME lets you set a custom text property instead of :org-clock-minutes." org-clock-file-total-minutes))) ;;;###autoload -(defun org-clock-display (&optional total-only) +(defun org-clock-display (&optional arg) "Show subtree times in the entire buffer. -If TOTAL-ONLY is non-nil, only show the total time for the entire file -in the echo area. -Use \\[org-clock-remove-overlays] to remove the subtree times." - (interactive) +By default, show the total time for the range defined in +`org-clock-display-default-range'. With `\\[universal-argument]' \ +prefix, show +the total time for today instead. + +With `\\[universal-argument] \\[universal-argument]' prefix, \ +use a custom range, entered at prompt. + +With `\\[universal-argument] \ \\[universal-argument] \ +\\[universal-argument]' prefix, display the total time in the +echo area. + +Use `\\[org-clock-remove-overlays]' to remove the subtree times." + (interactive "P") (org-clock-remove-overlays) - (let (time h m p) - (org-clock-sum) - (unless total-only + (let* ((todayp (equal arg '(4))) + (customp (member arg '((16) today yesterday + thisweek lastweek thismonth + lastmonth thisyear lastyear + untilnow interactive))) + (prop (cond ((not arg) :org-clock-minutes-default) + (todayp :org-clock-minutes-today) + (customp :org-clock-minutes-custom) + (t :org-clock-minutes))) + time h m p) + (cond ((not arg) (org-clock-sum-custom + nil org-clock-display-default-range prop)) + (todayp (org-clock-sum-today)) + (customp (org-clock-sum-custom nil arg)) + (t (org-clock-sum))) + (unless (eq arg '(64)) (save-excursion (goto-char (point-min)) (while (or (and (equal (setq p (point)) (point-min)) - (get-text-property p :org-clock-minutes)) + (get-text-property p prop)) (setq p (next-single-property-change - (point) :org-clock-minutes))) + (point) prop))) (goto-char p) - (when (setq time (get-text-property p :org-clock-minutes)) - (org-clock-put-overlay time (funcall outline-level)))) + (when (setq time (get-text-property p prop)) + (org-clock-put-overlay time))) (setq h (/ org-clock-file-total-minutes 60) m (- org-clock-file-total-minutes (* 60 h))) ;; Arrange to remove the overlays upon next change. (when org-remove-highlights-with-change - (org-add-hook 'before-change-functions 'org-clock-remove-overlays + (add-hook 'before-change-functions 'org-clock-remove-overlays nil 'local)))) - (message (concat "Total file time: " - (org-minutes-to-clocksum-string org-clock-file-total-minutes) - " (%d hours and %d minutes)") h m))) - -(defvar org-clock-overlays nil) -(make-variable-buffer-local 'org-clock-overlays) - -(defun org-clock-put-overlay (time &optional level) + (message (concat (format "Total file time%s: " + (cond (todayp " for today") + (customp " (custom)") + (t ""))) + (org-minutes-to-clocksum-string + org-clock-file-total-minutes) + " (%d hours and %d minutes)") + h m))) + +(defvar-local org-clock-overlays nil) + +(defun org-clock-put-overlay (time) "Put an overlays on the current line, displaying TIME. -If LEVEL is given, prefix time with a corresponding number of stars. This creates a new overlay and stores it in `org-clock-overlays', so that it will be easy to remove." - (let* ((l (if level (org-get-valid-level level 0) 0)) - ov tx) + (let (ov tx) (beginning-of-line) - (when (looking-at org-complex-heading-regexp) - (goto-char (match-beginning 4))) + (let ((case-fold-search nil)) + (when (looking-at org-complex-heading-regexp) + (goto-char (match-beginning 4)))) (setq ov (make-overlay (point) (point-at-eol)) - tx (concat (buffer-substring-no-properties (point) (match-end 4)) - (make-string - (max 0 (- (- 60 (current-column)) - (- (match-end 4) (match-beginning 4)) - (length (org-get-at-bol 'line-prefix)))) ?.) - (org-add-props (concat (make-string l ?*) " " - (org-minutes-to-clocksum-string time) - (make-string (- 16 l) ?\ )) - (list 'face 'org-clock-overlay)) + tx (concat (buffer-substring-no-properties (point) (match-end 4)) + (org-add-props + (make-string + (max 0 (- (- 60 (current-column)) + (- (match-end 4) (match-beginning 4)) + (length (org-get-at-bol 'line-prefix)))) + ?\·) + '(face shadow)) + (org-add-props + (format " %9s " (org-minutes-to-clocksum-string time)) + '(face org-clock-overlay)) "")) - (if (not (featurep 'xemacs)) - (overlay-put ov 'display tx) - (overlay-put ov 'invisible t) - (overlay-put ov 'end-glyph (make-glyph tx))) + (overlay-put ov 'display tx) (push ov org-clock-overlays))) ;;;###autoload -(defun org-clock-remove-overlays (&optional beg end noremove) +(defun org-clock-remove-overlays (&optional _beg _end noremove) "Remove the occur highlights from the buffer. -BEG and END are ignored. If NOREMOVE is nil, remove this function -from the `before-change-functions' in the current buffer." +If NOREMOVE is nil, remove this function from the +`before-change-functions' in the current buffer." (interactive) (unless org-inhibit-highlight-removal - (mapc 'delete-overlay org-clock-overlays) + (mapc #'delete-overlay org-clock-overlays) (setq org-clock-overlays nil) (unless noremove (remove-hook 'before-change-functions @@ -2020,127 +2116,159 @@ buffer and update it." (defun org-clock-special-range (key &optional time as-strings wstart mstart) "Return two times bordering a special time range. -Key is a symbol specifying the range and can be one of `today', `yesterday', -`thisweek', `lastweek', `thismonth', `lastmonth', `thisyear', `lastyear'. -By default, a week starts Monday 0:00 and ends Sunday 24:00. -The range is determined relative to TIME, which defaults to current time. -The return value is a cons cell with two internal times like the ones -returned by `current time' or `encode-time'. -If AS-STRINGS is non-nil, the returned times will be formatted strings. -If WSTART is non-nil, use this number to specify the starting day of a -week (monday is 1). -If MSTART is non-nil, use this number to specify the starting day of a -month (1 is the first day of the month). -If you can combine both, the month starting day will have priority." - (if (integerp key) (setq key (intern (number-to-string key)))) + +KEY is a symbol specifying the range and can be one of `today', +`yesterday', `thisweek', `lastweek', `thismonth', `lastmonth', +`thisyear', `lastyear' or `untilnow'. If set to `interactive', +user is prompted for range boundaries. It can be a string or an +integer. + +By default, a week starts Monday 0:00 and ends Sunday 24:00. The +range is determined relative to TIME, which defaults to current +time. + +The return value is a list containing two internal times, one for +the beginning of the range and one for its end, like the ones +returned by `current time' or `encode-time' and a string used to +display information. If AS-STRINGS is non-nil, the returned +times will be formatted strings. + +If WSTART is non-nil, use this number to specify the starting day +of a week (monday is 1). If MSTART is non-nil, use this number +to specify the starting day of a month (1 is the first day of the +month). If you can combine both, the month starting day will +have priority." (let* ((tm (decode-time time)) - (s 0) (m (nth 1 tm)) (h (nth 2 tm)) - (d (nth 3 tm)) (month (nth 4 tm)) (y (nth 5 tm)) + (m (nth 1 tm)) + (h (nth 2 tm)) + (d (nth 3 tm)) + (month (nth 4 tm)) + (y (nth 5 tm)) (dow (nth 6 tm)) - (ws (or wstart 1)) - (ms (or mstart 1)) - (skey (symbol-name key)) + (skey (format "%s" key)) (shift 0) - (q (cond ((>= (nth 4 tm) 10) 4) - ((>= (nth 4 tm) 7) 3) - ((>= (nth 4 tm) 4) 2) - ((>= (nth 4 tm) 1) 1))) - s1 m1 h1 d1 month1 y1 diff ts te fm txt w date - interval tmp shiftedy shiftedm shiftedq) + (q (cond ((>= month 10) 4) + ((>= month 7) 3) + ((>= month 4) 2) + (t 1))) + m1 h1 d1 month1 y1 shiftedy shiftedm shiftedq) (cond - ((string-match "^[0-9]+$" skey) - (setq y (string-to-number skey) m 1 d 1 key 'year)) - ((string-match "^\\([0-9]+\\)-\\([0-9]\\{1,2\\}\\)$" skey) + ((string-match "\\`[0-9]+\\'" skey) + (setq y (string-to-number skey) month 1 d 1 key 'year)) + ((string-match "\\`\\([0-9]+\\)-\\([0-9]\\{1,2\\}\\)\\'" skey) (setq y (string-to-number (match-string 1 skey)) month (string-to-number (match-string 2 skey)) - d 1 key 'month)) - ((string-match "^\\([0-9]+\\)-[wW]\\([0-9]\\{1,2\\}\\)$" skey) + d 1 + key 'month)) + ((string-match "\\`\\([0-9]+\\)-[wW]\\([0-9]\\{1,2\\}\\)\\'" skey) (require 'cal-iso) - (setq y (string-to-number (match-string 1 skey)) - w (string-to-number (match-string 2 skey))) - (setq date (calendar-gregorian-from-absolute - (calendar-absolute-from-iso (list w 1 y)))) - (setq d (nth 1 date) month (car date) y (nth 2 date) - dow 1 - key 'week)) - ((string-match "^\\([0-9]+\\)-[qQ]\\([1-4]\\)$" skey) + (let ((date (calendar-gregorian-from-absolute + (calendar-iso-to-absolute + (list (string-to-number (match-string 2 skey)) + 1 + (string-to-number (match-string 1 skey))))))) + (setq d (nth 1 date) + month (car date) + y (nth 2 date) + dow 1 + key 'week))) + ((string-match "\\`\\([0-9]+\\)-[qQ]\\([1-4]\\)\\'" skey) (require 'cal-iso) - (setq y (string-to-number (match-string 1 skey))) (setq q (string-to-number (match-string 2 skey))) - (setq date (calendar-gregorian-from-absolute - (calendar-absolute-from-iso (org-quarter-to-date q y)))) - (setq d (nth 1 date) month (car date) y (nth 2 date) - dow 1 - key 'quarter)) - ((string-match "^\\([0-9]+\\)-\\([0-9]\\{1,2\\}\\)-\\([0-9]\\{1,2\\}\\)$" skey) + (let ((date (calendar-gregorian-from-absolute + (calendar-iso-to-absolute + (org-quarter-to-date + q (string-to-number (match-string 1 skey))))))) + (setq d (nth 1 date) + month (car date) + y (nth 2 date) + dow 1 + key 'quarter))) + ((string-match + "\\`\\([0-9]+\\)-\\([0-9]\\{1,2\\}\\)-\\([0-9]\\{1,2\\}\\)\\'" + skey) (setq y (string-to-number (match-string 1 skey)) month (string-to-number (match-string 2 skey)) d (string-to-number (match-string 3 skey)) key 'day)) - ((string-match "\\([-+][0-9]+\\)$" skey) + ((string-match "\\([-+][0-9]+\\)\\'" skey) (setq shift (string-to-number (match-string 1 skey)) - key (intern (substring skey 0 (match-beginning 1)))) - (if (and (memq key '(quarter thisq)) (> shift 0)) - (error "Looking forward with quarters isn't implemented")))) - + key (intern (substring skey 0 (match-beginning 1)))) + (when (and (memq key '(quarter thisq)) (> shift 0)) + (error "Looking forward with quarters isn't implemented")))) (when (= shift 0) - (cond ((eq key 'yesterday) (setq key 'today shift -1)) - ((eq key 'lastweek) (setq key 'week shift -1)) - ((eq key 'lastmonth) (setq key 'month shift -1)) - ((eq key 'lastyear) (setq key 'year shift -1)) - ((eq key 'lastq) (setq key 'quarter shift -1)))) - (cond - ((memq key '(day today)) - (setq d (+ d shift) h 0 m 0 h1 24 m1 0)) - ((memq key '(week thisweek)) - (setq diff (+ (* -7 shift) (if (= dow 0) (- 7 ws) (- dow ws))) - m 0 h 0 d (- d diff) d1 (+ 7 d))) - ((memq key '(month thismonth)) - (setq d (or ms 1) h 0 m 0 d1 (or ms 1) - month (+ month shift) month1 (1+ month) h1 0 m1 0)) - ((memq key '(quarter thisq)) - ;; Compute if this shift remains in this year. If not, compute - ;; how many years and quarters we have to shift (via floor*) and - ;; compute the shifted years, months and quarters. - (cond - ((< (+ (- q 1) shift) 0) ; shift not in this year - (setq interval (* -1 (+ (- q 1) shift))) - ;; Set tmp to ((years to shift) (quarters to shift)). - (setq tmp (org-floor* interval 4)) - ;; Due to the use of floor, 0 quarters actually means 4. - (if (= 0 (nth 1 tmp)) - (setq shiftedy (- y (nth 0 tmp)) - shiftedm 1 - shiftedq 1) - (setq shiftedy (- y (+ 1 (nth 0 tmp))) - shiftedm (- 13 (* 3 (nth 1 tmp))) - shiftedq (- 5 (nth 1 tmp)))) - (setq d 1 h 0 m 0 d1 1 month shiftedm month1 (+ 3 shiftedm) h1 0 m1 0 y shiftedy)) - ((> (+ q shift) 0) ; shift is within this year - (setq shiftedq (+ q shift)) - (setq shiftedy y) - (setq d 1 h 0 m 0 d1 1 month (+ 1 (* 3 (- (+ q shift) 1))) month1 (+ 4 (* 3 (- (+ q shift) 1))) h1 0 m1 0)))) - ((memq key '(year thisyear)) - (setq m 0 h 0 d 1 month 1 y (+ y shift) y1 (1+ y))) - (t (error "No such time block %s" key))) - (setq ts (encode-time s m h d month y) - te (encode-time (or s1 s) (or m1 m) (or h1 h) - (or d1 d) (or month1 month) (or y1 y))) - (setq fm (cdr org-time-stamp-formats)) - (cond - ((memq key '(day today)) - (setq txt (format-time-string "%A, %B %d, %Y" ts))) - ((memq key '(week thisweek)) - (setq txt (format-time-string "week %G-W%V" ts))) - ((memq key '(month thismonth)) - (setq txt (format-time-string "%B %Y" ts))) - ((memq key '(year thisyear)) - (setq txt (format-time-string "the year %Y" ts))) - ((memq key '(quarter thisq)) - (setq txt (concat (org-count-quarter shiftedq) " quarter of " (number-to-string shiftedy))))) - (if as-strings - (list (format-time-string fm ts) (format-time-string fm te) txt) - (list ts te txt)))) + (pcase key + (`yesterday (setq key 'today shift -1)) + (`lastweek (setq key 'week shift -1)) + (`lastmonth (setq key 'month shift -1)) + (`lastyear (setq key 'year shift -1)) + (`lastq (setq key 'quarter shift -1)))) + ;; Prepare start and end times depending on KEY's type. + (pcase key + ((or `day `today) (setq m 0 h 0 h1 24 d (+ d shift))) + ((or `week `thisweek) + (let* ((ws (or wstart 1)) + (diff (+ (* -7 shift) (if (= dow 0) (- 7 ws) (- dow ws))))) + (setq m 0 h 0 d (- d diff) d1 (+ 7 d)))) + ((or `month `thismonth) + (setq h 0 m 0 d (or mstart 1) month (+ month shift) month1 (1+ month))) + ((or `quarter `thisq) + ;; Compute if this shift remains in this year. If not, compute + ;; how many years and quarters we have to shift (via floor*) and + ;; compute the shifted years, months and quarters. + (cond + ((< (+ (- q 1) shift) 0) ; Shift not in this year. + (let* ((interval (* -1 (+ (- q 1) shift))) + ;; Set tmp to ((years to shift) (quarters to shift)). + (tmp (cl-floor interval 4))) + ;; Due to the use of floor, 0 quarters actually means 4. + (if (= 0 (nth 1 tmp)) + (setq shiftedy (- y (nth 0 tmp)) + shiftedm 1 + shiftedq 1) + (setq shiftedy (- y (+ 1 (nth 0 tmp))) + shiftedm (- 13 (* 3 (nth 1 tmp))) + shiftedq (- 5 (nth 1 tmp))))) + (setq m 0 h 0 d 1 month shiftedm month1 (+ 3 shiftedm) y shiftedy)) + ((> (+ q shift) 0) ; Shift is within this year. + (setq shiftedq (+ q shift)) + (setq shiftedy y) + (let ((qshift (* 3 (1- (+ q shift))))) + (setq m 0 h 0 d 1 month (+ 1 qshift) month1 (+ 4 qshift)))))) + ((or `year `thisyear) + (setq m 0 h 0 d 1 month 1 y (+ y shift) y1 (1+ y))) + ((or `interactive `untilnow)) ; Special cases, ignore them. + (_ (user-error "No such time block %s" key))) + ;; Format start and end times according to AS-STRINGS. + (let* ((start (pcase key + (`interactive (org-read-date nil t nil "Range start? ")) + (`untilnow org-clock--oldest-date) + (_ (encode-time 0 m h d month y)))) + (end (pcase key + (`interactive (org-read-date nil t nil "Range end? ")) + (`untilnow (current-time)) + (_ (encode-time 0 + (or m1 m) + (or h1 h) + (or d1 d) + (or month1 month) + (or y1 y))))) + (text + (pcase key + ((or `day `today) (format-time-string "%A, %B %d, %Y" start)) + ((or `week `thisweek) (format-time-string "week %G-W%V" start)) + ((or `month `thismonth) (format-time-string "%B %Y" start)) + ((or `year `thisyear) (format-time-string "the year %Y" start)) + ((or `quarter `thisq) + (concat (org-count-quarter shiftedq) + " quarter of " (number-to-string shiftedy))) + (`interactive "(Range interactively set)") + (`untilnow "now")))) + (if (not as-strings) (list start end text) + (let ((f (cdr org-time-stamp-formats))) + (list (format-time-string f start) + (format-time-string f end) + text)))))) (defun org-count-quarter (n) (cond @@ -2196,7 +2324,7 @@ the currently selected interval size." ((and wp (string-match "w\\|W" wp) mw (> (length wp) 0)) (require 'cal-iso) (setq date (calendar-gregorian-from-absolute - (calendar-absolute-from-iso (list (+ mw n) 1 y)))) + (calendar-iso-to-absolute (list (+ mw n) 1 y)))) (setq ins (format-time-string "%G-W%V" (encode-time 0 0 0 (nth 1 date) (car date) (nth 2 date))))) @@ -2213,7 +2341,7 @@ the currently selected interval size." y (- y 1)) ()) (setq date (calendar-gregorian-from-absolute - (calendar-absolute-from-iso (org-quarter-to-date (+ mw n) y)))) + (calendar-iso-to-absolute (org-quarter-to-date (+ mw n) y)))) (setq ins (format-time-string (concat (number-to-string y) "-Q" (number-to-string (+ mw n))) (encode-time 0 0 0 (nth 1 date) (car date) (nth 2 date))))) @@ -2238,25 +2366,32 @@ the currently selected interval size." (setq params (org-combine-plists org-clocktable-defaults params)) (catch 'exit (let* ((scope (plist-get params :scope)) + (files (pcase scope + (`agenda + (org-agenda-files t)) + (`agenda-with-archives + (org-add-archive-files (org-agenda-files t))) + (`file-with-archives + (and buffer-file-name + (org-add-archive-files (list buffer-file-name)))) + ((pred consp) scope) + (_ (or (buffer-file-name) (current-buffer))))) (block (plist-get params :block)) (ts (plist-get params :tstart)) (te (plist-get params :tend)) - (link (plist-get params :link)) - (maxlevel (or (plist-get params :maxlevel) 3)) (ws (plist-get params :wstart)) (ms (plist-get params :mstart)) (step (plist-get params :step)) - (timestamp (plist-get params :timestamp)) (formatter (or (plist-get params :formatter) org-clock-clocktable-formatter 'org-clocktable-write-default)) - cc range-text ipos pos one-file-with-archives - scope-is-list tbls level) + cc) ;; Check if we need to do steps (when block ;; Get the range text for the header (setq cc (org-clock-special-range block nil t ws ms) - ts (car cc) te (nth 1 cc) range-text (nth 2 cc))) + ts (car cc) + te (nth 1 cc))) (when step ;; Write many tables, in steps (unless (or block (and ts te)) @@ -2264,63 +2399,49 @@ the currently selected interval size." (org-clocktable-steps params) (throw 'exit nil)) - (setq ipos (point)) ; remember the insertion position - - ;; Get the right scope - (setq pos (point)) - (cond - ((and scope (listp scope) (symbolp (car scope))) - (setq scope (eval scope))) - ((eq scope 'agenda) - (setq scope (org-agenda-files t))) - ((eq scope 'agenda-with-archives) - (setq scope (org-agenda-files t)) - (setq scope (org-add-archive-files scope))) - ((eq scope 'file-with-archives) - (setq scope (org-add-archive-files (list (buffer-file-name))) - one-file-with-archives t))) - (setq scope-is-list (and scope (listp scope))) - (if scope-is-list - ;; we collect from several files - (let* ((files scope) - file) - (org-agenda-prepare-buffers files) - (while (setq file (pop files)) - (with-current-buffer (find-buffer-visiting file) - (save-excursion - (save-restriction - (push (org-clock-get-table-data file params) tbls)))))) - ;; Just from the current file - (save-restriction - ;; get the right range into the restriction - (org-agenda-prepare-buffers (list (buffer-file-name))) - (cond - ((not scope)) ; use the restriction as it is now - ((eq scope 'file) (widen)) - ((eq scope 'subtree) (org-narrow-to-subtree)) - ((eq scope 'tree) - (while (org-up-heading-safe)) - (org-narrow-to-subtree)) - ((and (symbolp scope) (string-match "^tree\\([0-9]+\\)$" - (symbol-name scope))) - (setq level (string-to-number (match-string 1 (symbol-name scope)))) - (catch 'exit - (while (org-up-heading-safe) - (looking-at org-outline-regexp) - (if (<= (org-reduced-level (funcall outline-level)) level) - (throw 'exit nil)))) - (org-narrow-to-subtree))) - ;; do the table, with no file name. - (push (org-clock-get-table-data nil params) tbls))) - - ;; OK, at this point we tbls as a list of tables, one per file - (setq tbls (nreverse tbls)) - - (setq params (plist-put params :multifile scope-is-list)) - (setq params (plist-put params :one-file-with-archives - one-file-with-archives)) - - (funcall formatter ipos tbls params)))) + (org-agenda-prepare-buffers (if (consp files) files (list files))) + + (let ((origin (point)) + (tables + (if (consp files) + (mapcar (lambda (file) + (with-current-buffer (find-buffer-visiting file) + (save-excursion + (save-restriction + (org-clock-get-table-data file params))))) + files) + ;; Get the right restriction for the scope. + (save-restriction + (cond + ((not scope)) ;use the restriction as it is now + ((eq scope 'file) (widen)) + ((eq scope 'subtree) (org-narrow-to-subtree)) + ((eq scope 'tree) + (while (org-up-heading-safe)) + (org-narrow-to-subtree)) + ((and (symbolp scope) + (string-match "\\`tree\\([0-9]+\\)\\'" + (symbol-name scope))) + (let ((level (string-to-number + (match-string 1 (symbol-name scope))))) + (catch 'exit + (while (org-up-heading-safe) + (looking-at org-outline-regexp) + (when (<= (org-reduced-level (funcall outline-level)) + level) + (throw 'exit nil)))) + (org-narrow-to-subtree)))) + (list (org-clock-get-table-data nil params))))) + (multifile + ;; Even though `file-with-archives' can consist of + ;; multiple files, we consider this is one extended file + ;; instead. + (and (consp files) (not (eq scope 'file-with-archives))))) + + (funcall formatter + origin + tables + (org-combine-plists params `(:multifile ,multifile))))))) (defun org-clocktable-write-default (ipos tables params) "Write out a clock table at position IPOS in the current buffer. @@ -2335,43 +2456,46 @@ from the dynamic block definition." ;; well-defined number of columns... (let* ((hlchars '((1 . "*") (2 . "/"))) (lwords (assoc (or (plist-get params :lang) - (org-bound-and-true-p org-export-default-language) + (bound-and-true-p org-export-default-language) "en") org-clock-clocktable-language-setup)) (multifile (plist-get params :multifile)) (block (plist-get params :block)) - (ts (plist-get params :tstart)) - (te (plist-get params :tend)) - (header (plist-get params :header)) - (narrow (plist-get params :narrow)) + (sort (plist-get params :sort)) + (header (plist-get params :header)) (ws (or (plist-get params :wstart) 1)) (ms (or (plist-get params :mstart) 1)) (link (plist-get params :link)) - (maxlevel (or (plist-get params :maxlevel) 3)) - (emph (plist-get params :emphasize)) - (level-p (plist-get params :level)) (org-time-clocksum-use-effort-durations (plist-get params :effort-durations)) + (maxlevel (or (plist-get params :maxlevel) 3)) + (emph (plist-get params :emphasize)) + (compact? (plist-get params :compact)) + (narrow (or (plist-get params :narrow) (and compact? '40!))) + (level? (and (not compact?) (plist-get params :level))) (timestamp (plist-get params :timestamp)) (properties (plist-get params :properties)) - (ntcol (max 1 (or (plist-get params :tcolumns) 100))) - (rm-file-column (plist-get params :one-file-with-archives)) - (indent (plist-get params :indent)) + (time-columns + (if (or compact? (< maxlevel 2)) 1 + ;; Deepest headline level is a hard limit for the number + ;; of time columns. + (let ((levels + (cl-mapcan + (lambda (table) + (pcase table + (`(,_ ,(and (pred wholenump) (pred (/= 0))) ,entries) + (mapcar #'car entries)))) + tables))) + (min maxlevel + (or (plist-get params :tcolumns) 100) + (if (null levels) 1 (apply #'max levels)))))) + (indent (or compact? (plist-get params :indent))) + (formula (plist-get params :formula)) (case-fold-search t) - range-text total-time tbl level hlc formula pcol - file-time entries entry headline - recalc content narrow-cut-p tcol) - - ;; Implement abbreviations - (when (plist-get params :compact) - (setq level nil indent t narrow (or narrow '40!) ntcol 1)) - - ;; Some consistency test for parameters - (unless (integerp ntcol) - (setq params (plist-put params :tcolumns (setq ntcol 100)))) + range-text total-time recalc narrow-cut-p) (when (and narrow (integerp narrow) link) - ;; We cannot have both integer narrow and link + ;; We cannot have both integer narrow and link. (message "Using hard narrowing in clocktable to allow for links") (setq narrow (intern (format "%d!" narrow)))) @@ -2389,19 +2513,19 @@ from the dynamic block definition." narrow)))) (when block - ;; Get the range text for the header + ;; Get the range text for the header. (setq range-text (nth 2 (org-clock-special-range block nil t ws ms)))) - ;; Compute the total time - (setq total-time (apply '+ (mapcar 'cadr tables))) + ;; Compute the total time. + (setq total-time (apply #'+ (mapcar #'cadr tables))) - ;; Now we need to output this tsuff + ;; Now we need to output this tsuff. (goto-char ipos) - ;; Insert the text *before* the actual table + ;; Insert the text *before* the actual table. (insert-before-markers (or header - ;; Format the standard header + ;; Format the standard header. (concat "#+CAPTION: " (nth 9 lwords) " [" @@ -2415,155 +2539,144 @@ from the dynamic block definition." ;; Insert the narrowing line (when (and narrow (integerp narrow) (not narrow-cut-p)) (insert-before-markers - "|" ; table line starter - (if multifile "|" "") ; file column, maybe - (if level-p "|" "") ; level column, maybe - (if timestamp "|" "") ; timestamp column, maybe - (if properties (make-string (length properties) ?|) "") ;properties columns, maybe - (format "<%d>| |\n" narrow))) ; headline and time columns + "|" ;table line starter + (if multifile "|" "") ;file column, maybe + (if level? "|" "") ;level column, maybe + (if timestamp "|" "") ;timestamp column, maybe + (if properties (make-string (length properties) ?|) "") ;properties columns, maybe + (format "<%d>| |\n" narrow))) ; headline and time columns ;; Insert the table header line (insert-before-markers - "|" ; table line starter - (if multifile (concat (nth 1 lwords) "|") "") ; file column, maybe - (if level-p (concat (nth 2 lwords) "|") "") ; level column, maybe - (if timestamp (concat (nth 3 lwords) "|") "") ; timestamp column, maybe - (if properties (concat (mapconcat 'identity properties "|") "|") "") ;properties columns, maybe - (concat (nth 4 lwords) "|" - (nth 5 lwords) "|\n")) ; headline and time columns + "|" ;table line starter + (if multifile (concat (nth 1 lwords) "|") "") ;file column, maybe + (if level? (concat (nth 2 lwords) "|") "") ;level column, maybe + (if timestamp (concat (nth 3 lwords) "|") "") ;timestamp column, maybe + (if properties ;properties columns, maybe + (concat (mapconcat #'identity properties "|") "|") + "") + (concat (nth 4 lwords) "|") ;headline + (concat (nth 5 lwords) "|") ;time column + (make-string (max 0 (1- time-columns)) ?|) ;other time columns + (if (eq formula '%) "%|\n" "\n")) ;; Insert the total time in the table (insert-before-markers - "|-\n" ; a hline - "|" ; table line starter + "|-\n" ;a hline + "|" ;table line starter (if multifile (concat "| " (nth 6 lwords) " ") "") - ; file column, maybe - (if level-p "|" "") ; level column, maybe - (if timestamp "|" "") ; timestamp column, maybe - (if properties (make-string (length properties) ?|) "") ; properties columns, maybe - (concat (format org-clock-total-time-cell-format (nth 7 lwords)) "| ") ; instead of a headline + ;file column, maybe + (if level? "|" "") ;level column, maybe + (if timestamp "|" "") ;timestamp column, maybe + (make-string (length properties) ?|) ;properties columns, maybe + (concat (format org-clock-total-time-cell-format (nth 7 lwords)) + "| ") (format org-clock-total-time-cell-format - (org-minutes-to-clocksum-string (or total-time 0))) ; the time - "|\n") ; close line - - ;; Now iterate over the tables and insert the data - ;; but only if any time has been collected + (org-minutes-to-clocksum-string (or total-time 0))) ;time + "|" + (make-string (max 0 (1- time-columns)) ?|) + (cond ((not (eq formula '%)) "") + ((or (not total-time) (= total-time 0)) "0.0|") + (t "100.0|")) + "\n") + + ;; Now iterate over the tables and insert the data but only if any + ;; time has been collected. (when (and total-time (> total-time 0)) - - (while (setq tbl (pop tables)) - ;; now tbl is the table resulting from one file. - (setq file-time (nth 1 tbl)) + (pcase-dolist (`(,file-name ,file-time ,entries) tables) (when (or (and file-time (> file-time 0)) (not (plist-get params :fileskip0))) - (insert-before-markers "|-\n") ; a hline because a new file starts - ;; First the file time, if we have multiple files + (insert-before-markers "|-\n") ;hline at new file + ;; First the file time, if we have multiple files. (when multifile - ;; Summarize the time collected from this file + ;; Summarize the time collected from this file. (insert-before-markers (format (concat "| %s %s | %s%s" - (format org-clock-file-time-cell-format (nth 8 lwords)) + (format org-clock-file-time-cell-format + (nth 8 lwords)) " | *%s*|\n") - (file-name-nondirectory (car tbl)) - (if level-p "| " "") ; level column, maybe - (if timestamp "| " "") ; timestamp column, maybe - (if properties (make-string (length properties) ?|) "") ;properties columns, maybe - (org-minutes-to-clocksum-string (nth 1 tbl))))) ; the time + (file-name-nondirectory file-name) + (if level? "| " "") ;level column, maybe + (if timestamp "| " "") ;timestamp column, maybe + (if properties ;properties columns, maybe + (make-string (length properties) ?|) + "") + (org-minutes-to-clocksum-string file-time)))) ;time ;; Get the list of node entries and iterate over it - (setq entries (nth 2 tbl)) - (while (setq entry (pop entries)) - (setq level (car entry) - headline (nth 1 entry) - hlc (if emph (or (cdr (assoc level hlchars)) "") "")) - (when narrow-cut-p - (if (and (string-match (concat "\\`" org-bracket-link-regexp - "\\'") - headline) - (match-end 3)) - (setq headline - (format "[[%s][%s]]" - (match-string 1 headline) - (org-shorten-string (match-string 3 headline) - narrow))) - (setq headline (org-shorten-string headline narrow)))) - (insert-before-markers - "|" ; start the table line - (if multifile "|" "") ; free space for file name column? - (if level-p (format "%d|" (car entry)) "") ; level, maybe - (if timestamp (concat (nth 2 entry) "|") "") ; timestamp, maybe - (if properties - (concat - (mapconcat - (lambda (p) (or (cdr (assoc p (nth 4 entry))) "")) - properties "|") "|") "") ;properties columns, maybe - (if indent (org-clocktable-indent-string level) "") ; indentation - hlc headline hlc "|" ; headline - (make-string (min (1- ntcol) (or (- level 1))) ?|) - ; empty fields for higher levels - hlc (org-minutes-to-clocksum-string (nth 3 entry)) hlc ; time - "|\n" ; close line - ))))) - ;; When exporting subtrees or regions the region might be - ;; activated, so let's disable ̀delete-active-region' - (let ((delete-active-region nil)) (backward-delete-char 1)) - (if (setq formula (plist-get params :formula)) - (cond - ((eq formula '%) - ;; compute the column where the % numbers need to go - (setq pcol (+ 2 - (if multifile 1 0) - (if level-p 1 0) - (if timestamp 1 0) - (min maxlevel (or ntcol 100)))) - ;; compute the column where the total time is - (setq tcol (+ 2 - (if multifile 1 0) - (if level-p 1 0) - (if timestamp 1 0))) - (insert - (format - "\n#+TBLFM: $%d='(org-clock-time%% @%d$%d $%d..$%d);%%.1f" - pcol ; the column where the % numbers should go - (if (and narrow (not narrow-cut-p)) 3 2) ; row of the total time - tcol ; column of the total time - tcol (1- pcol) ; range of columns where times can be found - )) - (setq recalc t)) - ((stringp formula) - (insert "\n#+TBLFM: " formula) - (setq recalc t)) - (t (error "Invalid formula in clocktable"))) - ;; Should we rescue an old formula? - (when (stringp (setq content (plist-get params :content))) - (when (string-match "^\\([ \t]*#\\+tblfm:.*\\)" content) + (when (> maxlevel 0) + (pcase-dolist (`(,level ,headline ,ts ,time ,props) entries) + (when narrow-cut-p + (setq headline + (if (and (string-match + (format "\\`%s\\'" org-bracket-link-regexp) + headline) + (match-end 3)) + (format "[[%s][%s]]" + (match-string 1 headline) + (org-shorten-string (match-string 3 headline) + narrow)) + (org-shorten-string headline narrow)))) + (let ((hlc (if emph (or (cdr (assoc level hlchars)) "") ""))) + (insert-before-markers + "|" ;start the table line + (if multifile "|" "") ;free space for file name column? + (if level? (format "%d|" level) "") ;level, maybe + (if timestamp (concat ts "|") "") ;timestamp, maybe + (if properties ;properties columns, maybe + (concat (mapconcat (lambda (p) + (or (cdr (assoc p props)) "")) + properties + "|") + "|") + "") + (if indent ;indentation + (org-clocktable-indent-string level) + "") + hlc headline hlc "|" ;headline + ;; Empty fields for higher levels. + (make-string (max 0 (1- (min time-columns level))) ?|) + hlc (org-minutes-to-clocksum-string time) hlc "|" ; time + (make-string (max 0 (- time-columns level)) ?|) + (if (eq formula '%) + (format "%.1f |" (* 100 (/ time (float total-time)))) + "") + "\n"))))))) + (delete-char -1) + (cond + ;; Possibly rescue old formula? + ((or (not formula) (eq formula '%)) + (let ((contents (org-string-nw-p (plist-get params :content)))) + (when (and contents (string-match "^\\([ \t]*#\\+tblfm:.*\\)" contents)) (setq recalc t) - (insert "\n" (match-string 1 (plist-get params :content))) + (insert "\n" (match-string 1 contents)) (beginning-of-line 0)))) - ;; Back to beginning, align the table, recalculate if necessary + ;; Insert specified formula line. + ((stringp formula) + (insert "\n#+TBLFM: " formula) + (setq recalc t)) + (t + (user-error "Invalid :formula parameter in clocktable"))) + ;; Back to beginning, align the table, recalculate if necessary. (goto-char ipos) (skip-chars-forward "^|") (org-table-align) (when org-hide-emphasis-markers - ;; we need to align a second time + ;; We need to align a second time. (org-table-align)) - (when recalc - (if (eq formula '%) - (save-excursion - (if (and narrow (not narrow-cut-p)) (beginning-of-line 2)) - (org-table-goto-column pcol nil 'force) - (insert "%"))) - (org-table-recalculate 'all)) - (when rm-file-column - ;; The file column is actually not wanted - (forward-char 1) - (org-table-delete-column)) + (when sort + (save-excursion + (org-table-goto-line 3) + (org-table-goto-column (car sort)) + (org-table-sort-lines nil (cdr sort)))) + (when recalc (org-table-recalculate 'all)) total-time)) (defun org-clocktable-indent-string (level) + "Return indentation string according to LEVEL. +LEVEL is an integer. Indent by two spaces per level above 1." (if (= level 1) "" - (let ((str " ")) - (dotimes (k (1- level) str) - (setq str (concat "\\emsp" str)))))) + (concat "\\_" (make-string (* 2 (1- level)) ?\s)))) (defun org-clocktable-steps (params) "Step through the range to make a number of clock tables." @@ -2576,26 +2689,28 @@ from the dynamic block definition." (step (cdr (assoc step0 '((day . 86400) (week . 604800))))) (stepskip0 (plist-get p1 :stepskip0)) (block (plist-get p1 :block)) - cc range-text step-time tsb) + cc step-time tsb) (when block (setq cc (org-clock-special-range block nil t ws ms) - ts (car cc) te (nth 1 cc) range-text (nth 2 cc))) + ts (car cc) + te (nth 1 cc))) (cond ((numberp ts) - ;; If ts is a number, it's an absolute day number from org-agenda. - (destructuring-bind (month day year) (calendar-gregorian-from-absolute ts) + ;; If ts is a number, it's an absolute day number from + ;; org-agenda. + (pcase-let ((`(,month ,day ,year) (calendar-gregorian-from-absolute ts))) (setq ts (float-time (encode-time 0 0 0 day month year))))) (ts (setq ts (float-time - (apply 'encode-time (org-parse-time-string ts)))))) + (apply #'encode-time (org-parse-time-string ts nil t)))))) (cond ((numberp te) ;; Likewise for te. - (destructuring-bind (month day year) (calendar-gregorian-from-absolute te) + (pcase-let ((`(,month ,day ,year) (calendar-gregorian-from-absolute te))) (setq te (float-time (encode-time 0 0 0 day month year))))) (te (setq te (float-time - (apply 'encode-time (org-parse-time-string te)))))) + (apply #'encode-time (org-parse-time-string te nil t)))))) (setq tsb (if (eq step0 'week) (- ts (* 86400 (- (nth 6 (decode-time (seconds-to-time ts))) ws))) @@ -2635,19 +2750,22 @@ file time (in minutes) as 1st and 2nd elements. The third element of this list will be a list of headline entries. Each entry has the following structure: - (LEVEL HEADLINE TIMESTAMP TIME) - -LEVEL: The level of the headline, as an integer. This will be - the reduced leve, so 1,2,3,... even if only odd levels - are being used. -HEADLINE: The text of the headline. Depending on PARAMS, this may - already be formatted like a link. -TIMESTAMP: If PARAMS require it, this will be a time stamp found in the - entry, any of SCHEDULED, DEADLINE, NORMAL, or first inactive, - in this sequence. -TIME: The sum of all time spend in this tree, in minutes. This time - will of cause be restricted to the time block and tags match - specified in PARAMS." + (LEVEL HEADLINE TIMESTAMP TIME PROPERTIES) + +LEVEL: The level of the headline, as an integer. This will be + the reduced level, so 1,2,3,... even if only odd levels + are being used. +HEADLINE: The text of the headline. Depending on PARAMS, this may + already be formatted like a link. +TIMESTAMP: If PARAMS require it, this will be a time stamp found in the + entry, any of SCHEDULED, DEADLINE, NORMAL, or first inactive, + in this sequence. +TIME: The sum of all time spend in this tree, in minutes. This time + will of cause be restricted to the time block and tags match + specified in PARAMS. +PROPERTIES: The list properties specified in the `:properties' parameter + along with their value, as an alist following the pattern + (NAME . VALUE)." (let* ((maxlevel (or (plist-get params :maxlevel) 3)) (timestamp (plist-get params :timestamp)) (ts (plist-get params :tstart)) @@ -2659,14 +2777,14 @@ TIME: The sum of all time spend in this tree, in minutes. This time (tags (plist-get params :tags)) (properties (plist-get params :properties)) (inherit-property-p (plist-get params :inherit-props)) - todo-only - (matcher (if tags (cdr (org-make-tags-matcher tags)))) - cc range-text st p time level hdl props tsp tbl) + (matcher (and tags (cdr (org-make-tags-matcher tags)))) + cc st p tbl) (setq org-clock-file-total-minutes nil) (when block (setq cc (org-clock-special-range block nil t ws ms) - ts (car cc) te (nth 1 cc) range-text (nth 2 cc))) + ts (car cc) + te (nth 1 cc))) (when (integerp ts) (setq ts (calendar-gregorian-from-absolute ts))) (when (integerp te) (setq te (calendar-gregorian-from-absolute te))) (when (and ts (listp ts)) @@ -2678,12 +2796,12 @@ TIME: The sum of all time spend in this tree, in minutes. This time (if te (setq te (org-matcher-time te))) (save-excursion (org-clock-sum ts te - (unless (null matcher) - (lambda () - (let* ((tags-list (org-get-tags-at)) - (org-scanner-tags tags-list) - (org-trust-scanner-tags t)) - (eval matcher))))) + (when matcher + `(lambda () + (let* ((tags-list (org-get-tags-at)) + (org-scanner-tags tags-list) + (org-trust-scanner-tags t)) + (funcall ,matcher nil tags-list nil))))) (goto-char (point-min)) (setq st t) (while (or (and (bobp) (prog1 st (setq st nil)) @@ -2692,66 +2810,46 @@ TIME: The sum of all time spend in this tree, in minutes. This time (setq p (next-single-property-change (point) :org-clock-minutes))) (goto-char p) - (when (setq time (get-text-property p :org-clock-minutes)) - (save-excursion - (beginning-of-line 1) - (when (and (looking-at (org-re "\\(\\*+\\)[ \t]+\\(.*?\\)\\([ \t]+:[[:alnum:]_@#%:]+:\\)?[ \t]*$")) - (setq level (org-reduced-level - (- (match-end 1) (match-beginning 1)))) - (<= level maxlevel)) - (setq hdl (if (not link) - (match-string 2) - (org-make-link-string - (format "file:%s::%s" - (buffer-file-name) - (save-match-data - (match-string 2))) - (org-make-org-heading-search-string - (replace-regexp-in-string - org-bracket-link-regexp - (lambda (m) (or (match-string 3 m) - (match-string 1 m))) - (match-string 2))))) - tsp (when timestamp - (setq props (org-entry-properties (point))) - (or (cdr (assoc "SCHEDULED" props)) - (cdr (assoc "DEADLINE" props)) - (cdr (assoc "TIMESTAMP" props)) - (cdr (assoc "TIMESTAMP_IA" props)))) - props (when properties - (remove nil - (mapcar - (lambda (p) - (when (org-entry-get (point) p inherit-property-p) - (cons p (org-entry-get (point) p inherit-property-p)))) - properties)))) - (when (> time 0) (push (list level hdl tsp time props) tbl)))))) - (setq tbl (nreverse tbl)) - (list file org-clock-file-total-minutes tbl)))) - -(defun org-clock-time% (total &rest strings) - "Compute a time fraction in percent. -TOTAL s a time string like 10:21 specifying the total times. -STRINGS is a list of strings that should be checked for a time. -The first string that does have a time will be used. -This function is made for clock tables." - (let ((re "\\([0-9]+\\):\\([0-9]+\\)") - tot s) - (save-match-data - (catch 'exit - (if (not (string-match re total)) - (throw 'exit 0.) - (setq tot (+ (string-to-number (match-string 2 total)) - (* 60 (string-to-number (match-string 1 total))))) - (if (= tot 0.) (throw 'exit 0.))) - (while (setq s (pop strings)) - (if (string-match "\\([0-9]+\\):\\([0-9]+\\)" s) - (throw 'exit - (/ (* 100.0 (+ (string-to-number (match-string 2 s)) - (* 60 (string-to-number - (match-string 1 s))))) - tot)))) - 0)))) + (let ((time (get-text-property p :org-clock-minutes))) + (when (and time (> time 0) (org-at-heading-p)) + (let ((level (org-reduced-level (org-current-level)))) + (when (<= level maxlevel) + (let* ((headline (replace-regexp-in-string + (format "\\`%s[ \t]+" org-comment-string) "" + (nth 4 (org-heading-components)))) + (hdl + (if (not link) headline + (let ((search + (org-make-org-heading-search-string headline))) + (org-make-link-string + (if (not (buffer-file-name)) search + (format "file:%s::%s" (buffer-file-name) search)) + ;; Prune statistics cookies. Replace + ;; links with their description, or + ;; a plain link if there is none. + (org-trim + (org-link-display-format + (replace-regexp-in-string + "\\[[0-9]+%\\]\\|\\[[0-9]+/[0-9]+\\]" "" + headline))))))) + (tsp + (and timestamp + (let ((p (org-entry-properties (point) 'special))) + (or (cdr (assoc "SCHEDULED" p)) + (cdr (assoc "DEADLINE" p)) + (cdr (assoc "TIMESTAMP" p)) + (cdr (assoc "TIMESTAMP_IA" p)))))) + (props + (and properties + (delq nil + (mapcar + (lambda (p) + (let ((v (org-entry-get + (point) p inherit-property-p))) + (and v (cons p v)))) + properties))))) + (push (list level hdl tsp time props) tbl))))))) + (list file org-clock-file-total-minutes (nreverse tbl))))) ;; Saving and loading the clock @@ -2789,9 +2887,9 @@ Otherwise, return nil." (setq ts (match-string 1) te (match-string 3)) (setq s (- (float-time - (apply 'encode-time (org-parse-time-string te))) + (apply #'encode-time (org-parse-time-string te nil t))) (float-time - (apply 'encode-time (org-parse-time-string ts)))) + (apply #'encode-time (org-parse-time-string ts nil t)))) neg (< s 0) s (abs s) h (floor (/ s 3600)) @@ -2809,86 +2907,67 @@ The details of what will be saved are regulated by the variable (or org-clock-loaded org-clock-has-been-used (not (file-exists-p org-clock-persist-file)))) - (let (b) - (with-current-buffer (find-file (expand-file-name org-clock-persist-file)) - (progn - (delete-region (point-min) (point-max)) - ;;Store clock - (insert (format ";; org-persist.el - %s at %s\n" - (system-name) (format-time-string - (cdr org-time-stamp-formats)))) - (if (and (memq org-clock-persist '(t clock)) - (setq b (org-clocking-buffer)) - (setq b (or (buffer-base-buffer b) b)) - (buffer-live-p b) - (buffer-file-name b) - (or (not org-clock-persist-query-save) - (y-or-n-p (concat "Save current clock (" - org-clock-heading ") ")))) - (insert "(setq resume-clock '(\"" - (buffer-file-name (org-clocking-buffer)) - "\" . " (int-to-string (marker-position org-clock-marker)) - "))\n")) - ;; Store clocked task history. Tasks are stored reversed to make - ;; reading simpler - (when (and (memq org-clock-persist '(t history)) - org-clock-history) - (insert - "(setq stored-clock-history '(" - (mapconcat - (lambda (m) - (when (and (setq b (marker-buffer m)) - (setq b (or (buffer-base-buffer b) b)) - (buffer-live-p b) - (buffer-file-name b)) - (concat "(\"" (buffer-file-name b) - "\" . " (int-to-string (marker-position m)) - ")"))) - (reverse org-clock-history) " ") "))\n")) - (save-buffer) - (kill-buffer (current-buffer))))))) + (with-temp-file org-clock-persist-file + (insert (format ";; %s - %s at %s\n" + (file-name-nondirectory org-clock-persist-file) + (system-name) + (format-time-string (org-time-stamp-format t)))) + ;; Store clock to be resumed. + (when (and (memq org-clock-persist '(t clock)) + (let ((b (org-base-buffer (org-clocking-buffer)))) + (and (buffer-live-p b) + (buffer-file-name b) + (or (not org-clock-persist-query-save) + (y-or-n-p (format "Save current clock (%s) " + org-clock-heading)))))) + (insert + (format "(setq org-clock-stored-resume-clock '(%S . %d))\n" + (buffer-file-name (org-base-buffer (org-clocking-buffer))) + (marker-position org-clock-marker)))) + ;; Store clocked task history. Tasks are stored reversed to + ;; make reading simpler. + (when (and (memq org-clock-persist '(t history)) + org-clock-history) + (insert + (format "(setq org-clock-stored-history '(%s))\n" + (mapconcat + (lambda (m) + (let ((b (org-base-buffer (marker-buffer m)))) + (when (and (buffer-live-p b) + (buffer-file-name b)) + (format "(%S . %d)" + (buffer-file-name b) + (marker-position m))))) + (reverse org-clock-history) + " "))))))) (defun org-clock-load () "Load clock-related data from disk, maybe resuming a stored clock." (when (and org-clock-persist (not org-clock-loaded)) - (let ((filename (expand-file-name org-clock-persist-file)) - (org-clock-in-resume 'auto-restart) - resume-clock stored-clock-history) - (if (not (file-readable-p filename)) - (message "Not restoring clock data; %s not found" - org-clock-persist-file) - (message "%s" "Restoring clock data") - (setq org-clock-loaded t) - (load-file filename) - ;; load history - (when stored-clock-history - (save-window-excursion - (mapc (lambda (task) - (if (file-exists-p (car task)) - (org-clock-history-push (cdr task) - (find-file (car task))))) - stored-clock-history))) - ;; resume clock - (when (and resume-clock org-clock-persist - (file-exists-p (car resume-clock)) - (or (not org-clock-persist-query-resume) - (y-or-n-p - (concat - "Resume clock (" - (with-current-buffer (find-file (car resume-clock)) - (save-excursion - (goto-char (cdr resume-clock)) - (org-back-to-heading t) - (and (looking-at org-complex-heading-regexp) - (match-string 4)))) - ") ")))) - (when (file-exists-p (car resume-clock)) - (with-current-buffer (find-file (car resume-clock)) - (goto-char (cdr resume-clock)) - (let ((org-clock-auto-clock-resolution nil)) - (org-clock-in) - (if (outline-invisible-p) - (org-show-context)))))))))) + (if (not (file-readable-p org-clock-persist-file)) + (message "Not restoring clock data; %S not found" org-clock-persist-file) + (message "Restoring clock data") + ;; Load history. + (load-file org-clock-persist-file) + (setq org-clock-loaded t) + (pcase-dolist (`(,(and file (pred file-exists-p)) . ,position) + org-clock-stored-history) + (org-clock-history-push position (find-file-noselect file))) + ;; Resume clock. + (pcase org-clock-stored-resume-clock + (`(,(and file (pred file-exists-p)) . ,position) + (with-current-buffer (find-file-noselect file) + (when (or (not org-clock-persist-query-resume) + (y-or-n-p (format "Resume clock (%s) " + (save-excursion + (goto-char position) + (org-get-heading t t))))) + (goto-char position) + (let ((org-clock-in-resume 'auto-restart) + (org-clock-auto-clock-resolution nil)) + (org-clock-in) + (when (org-invisible-p) (org-show-context)))))) + (_ nil))))) ;; Suggested bindings (org-defkey org-mode-map "\C-c\C-x\C-e" 'org-clock-modify-effort-estimate) diff --git a/lisp/org/org-colview.el b/lisp/org/org-colview.el index a2046af29ec..ac8f36ad408 100644 --- a/lisp/org/org-colview.el +++ b/lisp/org/org-colview.el @@ -1,4 +1,4 @@ -;;; org-colview.el --- Column View in Org-mode +;;; org-colview.el --- Column View in Org -*- lexical-binding: t; -*- ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. @@ -28,42 +28,117 @@ ;;; Code: -(eval-when-compile (require 'cl)) +(require 'cl-lib) (require 'org) (declare-function org-agenda-redo "org-agenda" (&optional all)) (declare-function org-agenda-do-context-action "org-agenda" ()) (declare-function org-clock-sum-today "org-clock" (&optional headline-filter)) - -(when (featurep 'xemacs) - (error "Do not load this file into XEmacs, use `org-colview-xemacs.el' from the contrib/ directory")) - +(declare-function org-element-extract-element "org-element" (element)) +(declare-function org-element-interpret-data "org-element" (data)) +(declare-function org-element-map "org-element" (data types fun &optional info first-match no-recursion with-affiliated)) +(declare-function org-element-parse-secondary-string "org-element" (string restriction &optional parent)) +(declare-function org-element-property "org-element" (property element)) +(declare-function org-element-restriction "org-element" (element)) +(declare-function org-element-type "org-element" (element)) + +(defvar org-agenda-columns-add-appointments-to-effort-sum) +(defvar org-agenda-columns-compute-summary-properties) +(defvar org-agenda-columns-show-summaries) +(defvar org-agenda-view-columns-initially) +(defvar org-inlinetask-min-level) + + +;;; Configuration + +(defcustom org-columns-modify-value-for-display-function nil + "Function that modifies values for display in column view. +For example, it can be used to cut out a certain part from a time stamp. +The function must take 2 arguments: + +column-title The title of the column (*not* the property name) +value The value that should be modified. + +The function should return the value that should be displayed, +or nil if the normal value should be used." + :group 'org-properties + :type '(choice (const nil) (function))) + +(defcustom org-columns-summary-types nil + "Alist between operators and summarize functions. + +Each association follows the pattern (LABEL . SUMMARIZE) where + + LABEL is a string used in #+COLUMNS definition describing the + summary type. It can contain any character but \"}\". It is + case-sensitive. + + SUMMARIZE is a function called with two arguments. The first + argument is a non-empty list of values, as non-empty strings. + The second one is a format string or nil. It has to return + a string summarizing the list of values. + +Note that the return value can become one value for an higher +order summary, so the function is expected to handle its own +output. + +Types defined in this variable take precedence over those defined +in `org-columns-summary-types-default', which see." + :group 'org-properties + :version "26.1" + :package-version '(Org . "9.0") + :type '(alist :key-type (string :tag " Label") + :value-type (function :tag "Summarize"))) + + + ;;; Column View (defvar org-columns-overlays nil "Holds the list of current column overlays.") -(defvar org-columns-current-fmt nil +(defvar org-columns--time 0.0 + "Number of seconds since the epoch, as a floating point number.") + +(defvar-local org-columns-current-fmt nil "Local variable, holds the currently active column format.") -(make-variable-buffer-local 'org-columns-current-fmt) -(defvar org-columns-current-fmt-compiled nil + +(defvar-local org-columns-current-fmt-compiled nil "Local variable, holds the currently active column format. This is the compiled version of the format.") -(make-variable-buffer-local 'org-columns-current-fmt-compiled) -(defvar org-columns-current-widths nil - "Loval variable, holds the currently widths of fields.") -(make-variable-buffer-local 'org-columns-current-widths) -(defvar org-columns-current-maxwidths nil - "Loval variable, holds the currently active maximum column widths.") -(make-variable-buffer-local 'org-columns-current-maxwidths) + +(defvar-local org-columns-current-maxwidths nil + "Currently active maximum column widths, as a vector.") + (defvar org-columns-begin-marker (make-marker) "Points to the position where last a column creation command was called.") + (defvar org-columns-top-level-marker (make-marker) "Points to the position where current columns region starts.") (defvar org-columns-map (make-sparse-keymap) "The keymap valid in column display.") +(defconst org-columns-summary-types-default + '(("+" . org-columns--summary-sum) + ("$" . org-columns--summary-currencies) + ("X" . org-columns--summary-checkbox) + ("X/" . org-columns--summary-checkbox-count) + ("X%" . org-columns--summary-checkbox-percent) + ("max" . org-columns--summary-max) + ("mean" . org-columns--summary-mean) + ("min" . org-columns--summary-min) + (":" . org-columns--summary-sum-times) + (":max" . org-columns--summary-max-time) + (":mean" . org-columns--summary-mean-time) + (":min" . org-columns--summary-min-time) + ("@max" . org-columns--summary-max-age) + ("@mean" . org-columns--summary-mean-age) + ("@min" . org-columns--summary-min-age) + ("est+" . org-columns--summary-estimate)) + "Map operators to summarize functions. +See `org-columns-summary-types' for details.") + (defun org-columns-content () "Switch to contents view while in columns view." (interactive) @@ -146,121 +221,181 @@ This is the compiled version of the format.") "--" ["Quit" org-columns-quit t])) -(defun org-columns-new-overlay (beg end &optional string face) +(defun org-columns--displayed-value (spec value) + "Return displayed value for specification SPEC in current entry. +SPEC is a column format specification as stored in +`org-columns-current-fmt-compiled'. VALUE is the real value to +display, as a string." + (or (and (functionp org-columns-modify-value-for-display-function) + (funcall org-columns-modify-value-for-display-function + (nth 1 spec) ;column name + value)) + (pcase spec + (`("ITEM" . ,_) + (concat (make-string (1- (org-current-level)) + (if org-hide-leading-stars ?\s ?*)) + "* " + (org-columns-compact-links value))) + (`(,_ ,_ ,_ ,_ nil) value) + ;; If PRINTF is set, assume we are displaying a number and + ;; obey to the format string. + (`(,_ ,_ ,_ ,_ ,printf) (format printf (string-to-number value))) + (_ (error "Invalid column specification format: %S" spec))))) + +(defun org-columns--collect-values (&optional compiled-fmt) + "Collect values for columns on the current line. + +Return a list of triplets (SPEC VALUE DISPLAYED) suitable for +`org-columns--display-here'. + +This function assumes `org-columns-current-fmt-compiled' is +initialized is set in the current buffer. However, it is +possible to override it with optional argument COMPILED-FMT." + (let ((summaries (get-text-property (point) 'org-summaries))) + (mapcar + (lambda (spec) + (pcase spec + (`(,p . ,_) + (let* ((v (or (cdr (assoc spec summaries)) + (org-entry-get (point) p 'selective t) + (and compiled-fmt ;assume `org-agenda-columns' + ;; Effort property is not defined. Try + ;; to use appointment duration. + org-agenda-columns-add-appointments-to-effort-sum + (string= p (upcase org-effort-property)) + (get-text-property (point) 'duration) + (propertize (org-minutes-to-clocksum-string + (get-text-property (point) 'duration)) + 'face 'org-warning)) + ""))) + (list spec v (org-columns--displayed-value spec v)))))) + (or compiled-fmt org-columns-current-fmt-compiled)))) + +(defun org-columns--set-widths (cache) + "Compute the maximum column widths from the format and CACHE. +This function sets `org-columns-current-maxwidths' as a vector of +integers greater than 0." + (setq org-columns-current-maxwidths + (apply #'vector + (mapcar + (lambda (spec) + (pcase spec + (`(,_ ,_ ,(and width (pred wholenump)) . ,_) width) + (`(,_ ,name . ,_) + ;; No width is specified in the columns format. + ;; Compute it by checking all possible values for + ;; PROPERTY. + (let ((width (length name))) + (dolist (entry cache width) + (let ((value (nth 2 (assoc spec (cdr entry))))) + (setq width (max (length value) width)))))))) + org-columns-current-fmt-compiled)))) + +(defun org-columns--new-overlay (beg end &optional string face) "Create a new column overlay and add it to the list." (let ((ov (make-overlay beg end))) (overlay-put ov 'face (or face 'secondary-selection)) - (remove-text-properties 0 (length string) '(face nil) string) (org-overlay-display ov string face) (push ov org-columns-overlays) ov)) -(defun org-columns-display-here (&optional props dateline) - "Overlay the current line with column display." - (interactive) - (let* ((fmt org-columns-current-fmt-compiled) - (beg (point-at-bol)) - (level-face (save-excursion - (beginning-of-line 1) - (and (looking-at "\\(\\**\\)\\(\\* \\)") - (org-get-level-face 2)))) - (ref-face (or level-face - (and (eq major-mode 'org-agenda-mode) - (get-text-property (point-at-bol) 'face)) - 'default)) - (color (list :foreground (face-attribute ref-face :foreground))) - (font (list :height (face-attribute 'default :height) - :family (face-attribute 'default :family))) - (face (list color font 'org-column ref-face)) - (face1 (list color font 'org-agenda-column-dateline ref-face)) - (cphr (get-text-property (point-at-bol) 'org-complex-heading-regexp)) - pom property ass width f fc string fm ov column val modval s2 title calc) - ;; Check if the entry is in another buffer. - (unless props - (if (eq major-mode 'org-agenda-mode) - (setq pom (or (org-get-at-bol 'org-hd-marker) - (org-get-at-bol 'org-marker)) - props (if pom (org-entry-properties pom) nil)) - (setq props (org-entry-properties nil)))) - ;; Walk the format - (while (setq column (pop fmt)) - (setq property (car column) - title (nth 1 column) - ass (if (equal property "ITEM") - (cons "ITEM" - ;; When in a buffer, get the whole line, - ;; we'll clean it later… - (if (derived-mode-p 'org-mode) - (save-match-data - (org-remove-tabs - (buffer-substring-no-properties - (point-at-bol) (point-at-eol)))) - ;; In agenda, just get the `txt' property - (or (org-get-at-bol 'txt) - (buffer-substring-no-properties - (point) (progn (end-of-line) (point)))))) - (assoc property props)) - width (or (cdr (assoc property org-columns-current-maxwidths)) - (nth 2 column) - (length property)) - f (format "%%-%d.%ds | " width width) - fm (nth 4 column) - fc (nth 5 column) - calc (nth 7 column) - val (or (cdr ass) "") - modval (cond ((and org-columns-modify-value-for-display-function - (functionp - org-columns-modify-value-for-display-function)) - (funcall org-columns-modify-value-for-display-function - title val)) - ((equal property "ITEM") - (org-columns-cleanup-item - val org-columns-current-fmt-compiled - (or org-complex-heading-regexp cphr))) - (fc (org-columns-number-to-string - (org-columns-string-to-number val fm) fm fc)) - ((and calc (functionp calc) - (not (string= val "")) - (not (get-text-property 0 'org-computed val))) - (org-columns-number-to-string - (funcall calc (org-columns-string-to-number - val fm)) fm)))) - (setq s2 (org-columns-add-ellipses (or modval val) width)) - (setq string (format f s2)) - ;; Create the overlay +(defun org-columns--summarize (operator) + "Return summary function associated to string OPERATOR." + (if (not operator) nil + (cdr (or (assoc operator org-columns-summary-types) + (assoc operator org-columns-summary-types-default) + (error "Unknown %S operator" operator))))) + +(defun org-columns--overlay-text (value fmt width property original) + "Return text " + (format fmt + (let ((v (org-columns-add-ellipses value width))) + (pcase property + ("PRIORITY" + (propertize v 'face (org-get-priority-face original))) + ("TAGS" + (if (not org-tags-special-faces-re) + (propertize v 'face 'org-tag) + (replace-regexp-in-string + org-tags-special-faces-re + (lambda (m) (propertize m 'face (org-get-tag-face m))) + v nil nil 1))) + ("TODO" (propertize v 'face (org-get-todo-face original))) + (_ v))))) + +(defun org-columns--display-here (columns &optional dateline) + "Overlay the current line with column display. +COLUMNS is an alist (SPEC VALUE DISPLAYED). Optional argument +DATELINE is non-nil when the face used should be +`org-agenda-column-dateline'." + (save-excursion + (beginning-of-line) + (let* ((level-face (and (looking-at "\\(\\**\\)\\(\\* \\)") + (org-get-level-face 2))) + (ref-face (or level-face + (and (eq major-mode 'org-agenda-mode) + (org-get-at-bol 'face)) + 'default)) + (color (list :foreground (face-attribute ref-face :foreground))) + (font (list :height (face-attribute 'default :height) + :family (face-attribute 'default :family))) + (face (list color font 'org-column ref-face)) + (face1 (list color font 'org-agenda-column-dateline ref-face))) + ;; Each column is an overlay on top of a character. So there has + ;; to be at least as many characters available on the line as + ;; columns to display. + (let ((columns (length org-columns-current-fmt-compiled)) + (chars (- (line-end-position) (line-beginning-position)))) + (when (> columns chars) + (save-excursion + (end-of-line) + (let ((inhibit-read-only t)) + (insert (make-string (- columns chars) ?\s)))))) + ;; Display columns. Create and install the overlay for the + ;; current column on the next character. + (let ((i 0) + (last (1- (length columns)))) + (dolist (column columns) + (pcase column + (`(,spec ,original ,value) + (let* ((property (car spec)) + (width (aref org-columns-current-maxwidths i)) + (fmt (format (if (= i last) "%%-%d.%ds |" + "%%-%d.%ds | ") + width width)) + (ov (org-columns--new-overlay + (point) (1+ (point)) + (org-columns--overlay-text + value fmt width property original) + (if dateline face1 face)))) + (overlay-put ov 'keymap org-columns-map) + (overlay-put ov 'org-columns-key property) + (overlay-put ov 'org-columns-value original) + (overlay-put ov 'org-columns-value-modified value) + (overlay-put ov 'org-columns-format fmt) + (overlay-put ov 'line-prefix "") + (overlay-put ov 'wrap-prefix "") + (forward-char)))) + (cl-incf i))) + ;; Make the rest of the line disappear. + (let ((ov (org-columns--new-overlay (point) (line-end-position)))) + (overlay-put ov 'invisible t) + (overlay-put ov 'keymap org-columns-map) + (overlay-put ov 'line-prefix "") + (overlay-put ov 'wrap-prefix "")) + (let ((ov (make-overlay (1- (line-end-position)) + (line-beginning-position 2)))) + (overlay-put ov 'keymap org-columns-map) + (push ov org-columns-overlays)) (org-with-silent-modifications - (setq ov (org-columns-new-overlay - beg (setq beg (1+ beg)) string (if dateline face1 face))) - (overlay-put ov 'keymap org-columns-map) - (overlay-put ov 'org-columns-key property) - (overlay-put ov 'org-columns-value (cdr ass)) - (overlay-put ov 'org-columns-value-modified modval) - (overlay-put ov 'org-columns-pom pom) - (overlay-put ov 'org-columns-format f) - (overlay-put ov 'line-prefix "") - (overlay-put ov 'wrap-prefix "")) - (if (or (not (char-after beg)) - (equal (char-after beg) ?\n)) - (let ((inhibit-read-only t)) - (save-excursion - (goto-char beg) - (org-unmodified (insert " ")))))) ;; FIXME: add props and remove later? - ;; Make the rest of the line disappear. - (org-unmodified - (setq ov (org-columns-new-overlay beg (point-at-eol))) - (overlay-put ov 'invisible t) - (overlay-put ov 'keymap org-columns-map) - (overlay-put ov 'intangible t) - (overlay-put ov 'line-prefix "") - (overlay-put ov 'wrap-prefix "") - (push ov org-columns-overlays) - (setq ov (make-overlay (1- (point-at-eol)) (1+ (point-at-eol)))) - (overlay-put ov 'keymap org-columns-map) - (push ov org-columns-overlays) - (let ((inhibit-read-only t)) - (put-text-property (max (point-min) (1- (point-at-bol))) - (min (point-max) (1+ (point-at-eol))) - 'read-only "Type `e' to edit property"))))) + (let ((inhibit-read-only t)) + (put-text-property + (line-end-position 0) + (line-beginning-position 2) + 'read-only + (substitute-command-keys + "Type \\`\\[org-columns-edit-value]' \ +to edit property"))))))) (defun org-columns-add-ellipses (string width) "Truncate STRING with WIDTH characters, with ellipses." @@ -285,34 +420,27 @@ for the duration of the command.") (defvar header-line-format) (defvar org-columns-previous-hscroll 0) -(defun org-columns-display-here-title () +(defun org-columns--display-here-title () "Overlay the newline before the current line with the table title." (interactive) - (let ((fmt org-columns-current-fmt-compiled) - string (title "") - property width f column str widths) - (while (setq column (pop fmt)) - (setq property (car column) - str (or (nth 1 column) property) - width (or (cdr (assoc property org-columns-current-maxwidths)) - (nth 2 column) - (length str)) - widths (push width widths) - f (format "%%-%d.%ds | " width width) - string (format f str) - title (concat title string))) - (setq title (concat - (org-add-props " " nil 'display '(space :align-to 0)) - ;;(org-add-props title nil 'face '(:weight bold :underline t :inherit default)))) - (org-add-props title nil 'face 'org-column-title))) - (org-set-local 'org-previous-header-line-format header-line-format) - (org-set-local 'org-columns-current-widths (nreverse widths)) - (setq org-columns-full-header-line-format title) + (let ((title "") + (i 0)) + (dolist (column org-columns-current-fmt-compiled) + (pcase column + (`(,property ,name . ,_) + (let* ((width (aref org-columns-current-maxwidths i)) + (fmt (format "%%-%d.%ds | " width width))) + (setq title (concat title (format fmt (or name property))))))) + (cl-incf i)) + (setq-local org-previous-header-line-format header-line-format) + (setq org-columns-full-header-line-format + (concat + (org-add-props " " nil 'display '(space :align-to 0)) + (org-add-props (substring title 0 -1) nil 'face 'org-column-title))) (setq org-columns-previous-hscroll -1) - ; (org-columns-hscoll-title) - (org-add-hook 'post-command-hook 'org-columns-hscoll-title nil 'local))) + (add-hook 'post-command-hook 'org-columns-hscroll-title nil 'local))) -(defun org-columns-hscoll-title () +(defun org-columns-hscroll-title () "Set the `header-line-format' so that it scrolls along with the table." (sit-for .0001) ; need to force a redisplay to update window-hscroll (when (not (= (window-hscroll) org-columns-previous-hscroll)) @@ -335,7 +463,7 @@ for the duration of the command.") (when (local-variable-p 'org-previous-header-line-format) (setq header-line-format org-previous-header-line-format) (kill-local-variable 'org-previous-header-line-format) - (remove-hook 'post-command-hook 'org-columns-hscoll-title 'local)) + (remove-hook 'post-command-hook 'org-columns-hscroll-title 'local)) (move-marker org-columns-begin-marker nil) (move-marker org-columns-top-level-marker nil) (org-with-silent-modifications @@ -348,29 +476,6 @@ for the duration of the command.") (when (local-variable-p 'org-colview-initial-truncate-line-value) (setq truncate-lines org-colview-initial-truncate-line-value))))) -(defun org-columns-cleanup-item (item fmt cphr) - "Remove from ITEM what is a column in the format FMT. -CPHR is the complex heading regexp to use for parsing ITEM." - (let (fixitem) - (if (not cphr) - item - (unless (string-match "^\\*+ " item) - (setq item (concat "* " item) fixitem t)) - (if (string-match cphr item) - (setq item - (concat - (org-add-props (match-string 1 item) nil - 'org-whitespace (* 2 (1- (org-reduced-level (- (match-end 1) (match-beginning 1)))))) - (and (match-end 2) (not (assoc "TODO" fmt)) (concat " " (match-string 2 item))) - (and (match-end 3) (not (assoc "PRIORITY" fmt)) (concat " " (match-string 3 item))) - " " (save-match-data (org-columns-compact-links (or (match-string 4 item) ""))) - (and (match-end 5) (not (assoc "TAGS" fmt)) (concat " " (match-string 5 item))))) - (add-text-properties - 0 (1+ (match-end 1)) - (list 'org-whitespace (* 2 (1- (org-reduced-level (- (match-end 1) (match-beginning 1)))))) - item)) - (if fixitem (replace-regexp-in-string "^\\*+ " "" item) item)))) - (defun org-columns-compact-links (s) "Replace [[link][desc]] with [desc] or [link]." (while (string-match org-bracket-link-regexp s) @@ -394,25 +499,26 @@ CPHR is the complex heading regexp to use for parsing ITEM." (org-columns-remove-overlays) (let ((inhibit-read-only t)) (remove-text-properties (point-min) (point-max) '(read-only t)))) - (when (eq major-mode 'org-agenda-mode) + (if (not (eq major-mode 'org-agenda-mode)) + (setq org-columns-current-fmt nil) (setq org-agenda-columns-active nil) (message "Modification not yet reflected in Agenda buffer, use `r' to refresh"))) (defun org-columns-check-computed () - "Check if this column value is computed. -If yes, throw an error indicating that changing it does not make sense." - (let ((val (get-char-property (point) 'org-columns-value))) - (when (and (stringp val) - (get-char-property 0 'org-computed val)) - (error "This value is computed from the entry's children")))) - -(defun org-columns-todo (&optional arg) + "Throw an error if current column value is computed." + (let ((spec (nth (current-column) org-columns-current-fmt-compiled))) + (and + (nth 3 spec) + (assoc spec (get-text-property (line-beginning-position) 'org-summaries)) + (error "This value is computed from the entry's children")))) + +(defun org-columns-todo (&optional _arg) "Change the TODO state during column view." (interactive "P") (org-columns-edit-value "TODO")) -(defun org-columns-set-tags-or-toggle (&optional arg) +(defun org-columns-set-tags-or-toggle (&optional _arg) "Toggle checkbox at point, or set tags for current headline." (interactive "P") (if (string-match "\\`\\[[ xX-]\\]\\'" @@ -430,107 +536,76 @@ Where possible, use the standard interface for changing this line." (interactive) (org-columns-check-computed) (let* ((col (current-column)) + (bol (line-beginning-position)) + (eol (line-end-position)) + (pom (or (get-text-property bol 'org-hd-marker) (point))) (key (or key (get-char-property (point) 'org-columns-key))) - (value (get-char-property (point) 'org-columns-value)) - (bol (point-at-bol)) (eol (point-at-eol)) - (pom (or (get-text-property bol 'org-hd-marker) - (point))) ; keep despite of compiler waring - (line-overlays - (delq nil (mapcar (lambda (x) - (and (eq (overlay-buffer x) (current-buffer)) - (>= (overlay-start x) bol) - (<= (overlay-start x) eol) - x)) - org-columns-overlays))) - (org-columns-time (time-to-number-of-days (current-time))) - nval eval allowed) + (org-columns--time (float-time (current-time))) + (action + (pcase key + ("CLOCKSUM" + (error "This special column cannot be edited")) + ("ITEM" + (lambda () (org-with-point-at pom (org-edit-headline)))) + ("TODO" + (lambda () + (org-with-point-at pom (call-interactively #'org-todo)))) + ("PRIORITY" + (lambda () + (org-with-point-at pom + (call-interactively #'org-priority)))) + ("TAGS" + (lambda () + (org-with-point-at pom + (let ((org-fast-tag-selection-single-key + (if (eq org-fast-tag-selection-single-key 'expert) + t + org-fast-tag-selection-single-key))) + (call-interactively #'org-set-tags))))) + ("DEADLINE" + (lambda () + (org-with-point-at pom (call-interactively #'org-deadline)))) + ("SCHEDULED" + (lambda () + (org-with-point-at pom (call-interactively #'org-schedule)))) + ("BEAMER_ENV" + (lambda () + (org-with-point-at pom + (call-interactively #'org-beamer-select-environment)))) + (_ + (let* ((allowed (org-property-get-allowed-values pom key 'table)) + (value (get-char-property (point) 'org-columns-value)) + (nval (org-trim + (if (null allowed) (read-string "Edit: " value) + (completing-read + "Value: " allowed nil + (not (get-text-property + 0 'org-unrestricted (caar allowed)))))))) + (and (not (equal nval value)) + (lambda () (org-entry-put pom key nval)))))))) (cond - ((equal key "CLOCKSUM") - (error "This special column cannot be edited")) - ((equal key "ITEM") - (setq eval '(org-with-point-at pom - (org-edit-headline)))) - ((equal key "TODO") - (setq eval '(org-with-point-at - pom - (call-interactively 'org-todo)))) - ((equal key "PRIORITY") - (setq eval '(org-with-point-at pom - (call-interactively 'org-priority)))) - ((equal key "TAGS") - (setq eval '(org-with-point-at pom - (let ((org-fast-tag-selection-single-key - (if (eq org-fast-tag-selection-single-key 'expert) - t org-fast-tag-selection-single-key))) - (call-interactively 'org-set-tags))))) - ((equal key "DEADLINE") - (setq eval '(org-with-point-at pom - (call-interactively 'org-deadline)))) - ((equal key "SCHEDULED") - (setq eval '(org-with-point-at pom - (call-interactively 'org-schedule)))) - ((equal key "BEAMER_env") - (setq eval '(org-with-point-at pom - (call-interactively 'org-beamer-select-environment)))) + ((null action)) + ((eq major-mode 'org-agenda-mode) + (org-columns--call action) + ;; The following let preserves the current format, and makes + ;; sure that in only a single file things need to be updated. + (let* ((org-agenda-overriding-columns-format org-columns-current-fmt) + (buffer (marker-buffer pom)) + (org-agenda-contributing-files + (list (with-current-buffer buffer + (buffer-file-name (buffer-base-buffer)))))) + (org-agenda-columns))) (t - (setq allowed (org-property-get-allowed-values pom key 'table)) - (if allowed - (setq nval (org-icompleting-read - "Value: " allowed nil - (not (get-text-property 0 'org-unrestricted - (caar allowed))))) - (setq nval (read-string "Edit: " value))) - (setq nval (org-trim nval)) - (when (not (equal nval value)) - (setq eval '(org-entry-put pom key nval))))) - (when eval - - (cond - ((equal major-mode 'org-agenda-mode) - (org-columns-eval eval) - ;; The following let preserves the current format, and makes sure - ;; that in only a single file things need to be updated. - (let* ((org-agenda-overriding-columns-format org-columns-current-fmt) - (buffer (marker-buffer pom)) - (org-agenda-contributing-files - (list (with-current-buffer buffer - (buffer-file-name (buffer-base-buffer)))))) - (org-agenda-columns))) - (t - (let ((inhibit-read-only t)) - (org-with-silent-modifications - (remove-text-properties - (max (point-min) (1- bol)) eol '(read-only t))) - (unwind-protect - (progn - (setq org-columns-overlays - (org-delete-all line-overlays org-columns-overlays)) - (mapc 'delete-overlay line-overlays) - (org-columns-eval eval)) - (org-columns-display-here))) - (org-move-to-column col) - (if (and (derived-mode-p 'org-mode) - (nth 3 (assoc key org-columns-current-fmt-compiled))) - (org-columns-update key))))))) - -(defun org-edit-headline () ; FIXME: this is not columns specific. Make interactive????? Use from agenda???? - "Edit the current headline, the part without TODO keyword, TAGS." - (org-back-to-heading) - (when (looking-at org-todo-line-regexp) - (let ((pos (point)) - (pre (buffer-substring (match-beginning 0) (match-beginning 3))) - (txt (match-string 3)) - (post "") - txt2) - (if (string-match (org-re "[ \t]+:[[:alnum:]:_@#%]+:[ \t]*$") txt) - (setq post (match-string 0 txt) - txt (substring txt 0 (match-beginning 0)))) - (setq txt2 (read-string "Edit: " txt)) - (when (not (equal txt txt2)) - (goto-char pos) - (insert pre txt2 post) - (delete-region (point) (point-at-eol)) - (org-set-tags nil t))))) + (let ((inhibit-read-only t)) + (org-with-silent-modifications + (remove-text-properties (max (point-min) (1- bol)) eol '(read-only t))) + (org-columns--call action)) + ;; Some properties can modify headline (e.g., "TODO"), and + ;; possible shuffle overlays. Make sure they are still all at + ;; the right place on the current line. + (let ((org-columns-inhibit-recalculation)) (org-columns-redo)) + (org-columns-update key) + (org-move-to-column col))))) (defun org-columns-edit-allowed () "Edit the list of allowed values for the current property." @@ -553,15 +628,15 @@ Where possible, use the standard interface for changing this line." (t pom)) key1 nval))) -(defun org-columns-eval (form) - (let (hidep) - (save-excursion - (beginning-of-line 1) - ;; `next-line' is needed here, because it skips invisible line. - (condition-case nil (org-no-warnings (next-line 1)) (error nil)) - (setq hidep (org-at-heading-p 1))) - (eval form) - (and hidep (hide-entry)))) +(defun org-columns--call (fun) + "Call function FUN while preserving heading visibility. +FUN is a function called with no argument." + (let ((hide-body (and (/= (line-end-position) (point-max)) + (save-excursion + (move-beginning-of-line 2) + (org-at-heading-p t))))) + (unwind-protect (funcall fun) + (when hide-body (outline-hide-entry))))) (defun org-columns-previous-allowed-value () "Switch to the previous allowed value for this column." @@ -574,72 +649,57 @@ When PREVIOUS is set, go to the previous value. When NTH is an integer, select that value." (interactive) (org-columns-check-computed) - (let* ((col (current-column)) + (let* ((column (current-column)) (key (get-char-property (point) 'org-columns-key)) (value (get-char-property (point) 'org-columns-value)) - (bol (point-at-bol)) (eol (point-at-eol)) - (pom (or (get-text-property bol 'org-hd-marker) - (point))) ; keep despite of compiler waring - (line-overlays - (delq nil (mapcar (lambda (x) - (and (eq (overlay-buffer x) (current-buffer)) - (>= (overlay-start x) bol) - (<= (overlay-start x) eol) - x)) - org-columns-overlays))) - (allowed (or (org-property-get-allowed-values pom key) - (and (memq - (nth 4 (assoc key org-columns-current-fmt-compiled)) - '(checkbox checkbox-n-of-m checkbox-percent)) - '("[ ]" "[X]")) - (org-colview-construct-allowed-dates value))) - nval) - (when (integerp nth) - (setq nth (1- nth)) - (if (= nth -1) (setq nth 9))) - (when (equal key "ITEM") - (error "Cannot edit item headline from here")) + (pom (or (get-text-property (line-beginning-position) 'org-hd-marker) + (point))) + (allowed + (let ((all + (or (org-property-get-allowed-values pom key) + (pcase (nth column org-columns-current-fmt-compiled) + (`(,_ ,_ ,_ ,(or "X" "X/" "X%") ,_) '("[ ]" "[X]"))) + (org-colview-construct-allowed-dates value)))) + (if previous (reverse all) all)))) + (when (equal key "ITEM") (error "Cannot edit item headline from here")) (unless (or allowed (member key '("SCHEDULED" "DEADLINE" "CLOCKSUM"))) (error "Allowed values for this property have not been defined")) - (if (member key '("SCHEDULED" "DEADLINE" "CLOCKSUM")) - (setq nval (if previous 'earlier 'later)) - (if previous (setq allowed (reverse allowed))) + (let* ((l (length allowed)) + (new + (cond + ((member key '("SCHEDULED" "DEADLINE" "CLOCKSUM")) + (if previous 'earlier 'later)) + ((integerp nth) + (when (> (abs nth) l) + (user-error "Only %d allowed values for property `%s'" l key)) + (nth (mod (1- nth) l) allowed)) + ((member value allowed) + (when (= l 1) (error "Only one allowed value for this property")) + (or (nth 1 (member value allowed)) (car allowed))) + (t (car allowed)))) + (action (lambda () (org-entry-put pom key new)))) (cond - (nth - (setq nval (nth nth allowed)) - (if (not nval) - (error "There are only %d allowed values for property `%s'" - (length allowed) key))) - ((member value allowed) - (setq nval (or (car (cdr (member value allowed))) - (car allowed))) - (if (equal nval value) - (error "Only one allowed value for this property"))) - (t (setq nval (car allowed))))) - (cond - ((equal major-mode 'org-agenda-mode) - (org-columns-eval '(org-entry-put pom key nval)) - ;; The following let preserves the current format, and makes sure - ;; that in only a single file things need to be updated. - (let* ((org-agenda-overriding-columns-format org-columns-current-fmt) - (buffer (marker-buffer pom)) - (org-agenda-contributing-files - (list (with-current-buffer buffer - (buffer-file-name (buffer-base-buffer)))))) - (org-agenda-columns))) - (t - (let ((inhibit-read-only t)) - (remove-text-properties (1- bol) eol '(read-only t)) - (unwind-protect - (progn - (setq org-columns-overlays - (org-delete-all line-overlays org-columns-overlays)) - (mapc 'delete-overlay line-overlays) - (org-columns-eval '(org-entry-put pom key nval))) - (org-columns-display-here))) - (org-move-to-column col) - (and (nth 3 (assoc key org-columns-current-fmt-compiled)) - (org-columns-update key)))))) + ((eq major-mode 'org-agenda-mode) + (org-columns--call action) + ;; The following let preserves the current format, and makes + ;; sure that in only a single file things need to be updated. + (let* ((org-agenda-overriding-columns-format org-columns-current-fmt) + (buffer (marker-buffer pom)) + (org-agenda-contributing-files + (list (with-current-buffer buffer + (buffer-file-name (buffer-base-buffer)))))) + (org-agenda-columns))) + (t + (let ((inhibit-read-only t)) + (remove-text-properties (line-end-position 0) (line-end-position) + '(read-only t)) + (org-columns--call action)) + ;; Some properties can modify headline (e.g., "TODO"), and + ;; possible shuffle overlays. Make sure they are still all at + ;; the right place on the current line. + (let ((org-columns-inhibit-recalculation)) (org-columns-redo)) + (org-columns-update key) + (org-move-to-column column)))))) (defun org-colview-construct-allowed-dates (s) "Construct a list of three dates around the date in S. @@ -662,13 +722,6 @@ around it." (mapcar (lambda (x) (format-time-string fmt (apply 'encode-time x))) (list time-before time time-after))))) -(defun org-verify-version (task) - (cond - ((eq task 'columns) - (if (or (featurep 'xemacs) - (< emacs-major-version 22)) - (error "Emacs 22 is required for the columns feature"))))) - (defun org-columns-open-link (&optional arg) (interactive "P") (let ((value (get-char-property (point) 'org-columns-value))) @@ -681,179 +734,165 @@ around it." fmt)) (defun org-columns-get-format (&optional fmt-string) + "Return columns format specifications. +When optional argument FMT-STRING is non-nil, use it as the +current specifications. This function also sets +`org-columns-current-fmt-compiled' and +`org-columns-current-fmt'." (interactive) - (let (fmt-as-property fmt) - (when (condition-case nil (org-back-to-heading) (error nil)) - (setq fmt-as-property (org-entry-get nil "COLUMNS" t))) - (setq fmt (or fmt-string fmt-as-property org-columns-default-format)) - (org-set-local 'org-columns-current-fmt fmt) - (org-columns-compile-format fmt) - fmt)) + (let ((format + (or fmt-string + (org-entry-get nil "COLUMNS" t) + (org-with-wide-buffer + (goto-char (point-min)) + (catch :found + (let ((case-fold-search t)) + (while (re-search-forward "^[ \t]*#\\+COLUMNS: .+$" nil t) + (let ((element (org-element-at-point))) + (when (eq (org-element-type element) 'keyword) + (throw :found (org-element-property :value element))))) + nil))) + org-columns-default-format))) + (setq org-columns-current-fmt format) + (org-columns-compile-format format) + format)) (defun org-columns-goto-top-level () - (when (condition-case nil (org-back-to-heading) (error nil)) - (org-entry-get nil "COLUMNS" t)) - (if (marker-position org-entry-property-inherited-from) - (move-marker org-columns-top-level-marker org-entry-property-inherited-from) - (move-marker org-columns-top-level-marker (point)))) + "Move to the beginning of the column view area. +Also sets `org-columns-top-level-marker' to the new position." + (goto-char + (move-marker + org-columns-top-level-marker + (cond ((org-before-first-heading-p) (point-min)) + ((org-entry-get nil "COLUMNS" t) org-entry-property-inherited-from) + (t (org-back-to-heading) (point)))))) ;;;###autoload -(defun org-columns (&optional columns-fmt-string) - "Turn on column view on an org-mode file. +(defun org-columns (&optional global columns-fmt-string) + "Turn on column view on an Org mode file. + +Column view applies to the whole buffer if point is before the +first headline. Otherwise, it applies to the first ancestor +setting \"COLUMNS\" property. If there is none, it defaults to +the current headline. With a `\\[universal-argument]' prefix \ +argument, turn on column +view for the whole buffer unconditionally. + When COLUMNS-FMT-STRING is non-nil, use it as the column format." - (interactive) - (org-verify-version 'columns) + (interactive "P") (org-columns-remove-overlays) + (when global (goto-char (point-min))) (move-marker org-columns-begin-marker (point)) - (let ((org-columns-time (time-to-number-of-days (current-time))) - beg end fmt cache maxwidths) - (org-columns-goto-top-level) - (setq fmt (org-columns-get-format columns-fmt-string)) + (org-columns-goto-top-level) + ;; Initialize `org-columns-current-fmt' and + ;; `org-columns-current-fmt-compiled'. + (let ((org-columns--time (float-time (current-time)))) + (org-columns-get-format columns-fmt-string) + (unless org-columns-inhibit-recalculation (org-columns-compute-all)) (save-excursion - (goto-char org-columns-top-level-marker) - (setq beg (point)) - (unless org-columns-inhibit-recalculation - (org-columns-compute-all)) - (setq end (or (condition-case nil (org-end-of-subtree t t) (error nil)) - (point-max))) - ;; Get and cache the properties - (goto-char beg) - (when (assoc "CLOCKSUM" org-columns-current-fmt-compiled) - (save-excursion - (save-restriction - (narrow-to-region beg end) - (org-clock-sum)))) - (when (assoc "CLOCKSUM_T" org-columns-current-fmt-compiled) - (save-excursion - (save-restriction - (narrow-to-region beg end) - (org-clock-sum-today)))) - (while (re-search-forward org-outline-regexp-bol end t) - (if (and org-columns-skip-archived-trees - (looking-at (concat ".*:" org-archive-tag ":"))) - (org-end-of-subtree t) - (push (cons (org-current-line) (org-entry-properties)) cache))) - (when cache - (setq maxwidths (org-columns-get-autowidth-alist fmt cache)) - (org-set-local 'org-columns-current-maxwidths maxwidths) - (org-columns-display-here-title) - (when (org-set-local 'org-columns-flyspell-was-active - (org-bound-and-true-p flyspell-mode)) - (flyspell-mode 0)) - (unless (local-variable-p 'org-colview-initial-truncate-line-value) - (org-set-local 'org-colview-initial-truncate-line-value - truncate-lines)) - (setq truncate-lines t) - (mapc (lambda (x) - (org-goto-line (car x)) - (org-columns-display-here (cdr x))) - cache))))) - -(eval-when-compile (defvar org-columns-time)) - -(defvar org-columns-compile-map - '(("none" none +) - (":" add_times +) - ("+" add_numbers +) - ("$" currency +) - ("X" checkbox +) - ("X/" checkbox-n-of-m +) - ("X%" checkbox-percent +) - ("max" max_numbers max) - ("min" min_numbers min) - ("mean" mean_numbers - (lambda (&rest x) (/ (apply '+ x) (float (length x))))) - (":max" max_times max) - (":min" min_times min) - (":mean" mean_times - (lambda (&rest x) (/ (apply '+ x) (float (length x))))) - ("@min" min_age min (lambda (x) (- org-columns-time x))) - ("@max" max_age max (lambda (x) (- org-columns-time x))) - ("@mean" mean_age - (lambda (&rest x) (/ (apply '+ x) (float (length x)))) - (lambda (x) (- org-columns-time x))) - ("est+" estimate org-estimate-combine)) - "Operator <-> format,function,calc map. -Used to compile/uncompile columns format and completing read in -interactive function `org-columns-new'. - -operator string used in #+COLUMNS definition describing the - summary type -format symbol describing summary type selected interactively in - `org-columns-new' and internally in - `org-columns-number-to-string' and - `org-columns-string-to-number' -function called with a list of values as argument to calculate - the summary value -calc function called on every element before summarizing. This is - optional and should only be specified if needed") - -(defun org-columns-new (&optional prop title width op fmt fun &rest rest) - "Insert a new column, to the left of the current column." + (save-restriction + (when (and (not global) (org-at-heading-p)) + (narrow-to-region (point) (org-end-of-subtree t t))) + (when (assoc "CLOCKSUM" org-columns-current-fmt-compiled) + (org-clock-sum)) + (when (assoc "CLOCKSUM_T" org-columns-current-fmt-compiled) + (org-clock-sum-today)) + (let ((cache + ;; Collect contents of columns ahead of time so as to + ;; compute their maximum width. + (org-map-entries + (lambda () (cons (point) (org-columns--collect-values))) + nil nil (and org-columns-skip-archived-trees 'archive)))) + (when cache + (org-columns--set-widths cache) + (org-columns--display-here-title) + (when (setq-local org-columns-flyspell-was-active + (bound-and-true-p flyspell-mode)) + (flyspell-mode 0)) + (unless (local-variable-p 'org-colview-initial-truncate-line-value) + (setq-local org-colview-initial-truncate-line-value + truncate-lines)) + (setq truncate-lines t) + (dolist (entry cache) + (goto-char (car entry)) + (org-columns--display-here (cdr entry))))))))) + +(defun org-columns-new (&optional spec &rest attributes) + "Insert a new column, to the left of the current column. +Interactively fill attributes for new column. When column format +specification SPEC is provided, edit it instead. + +When optional argument attributes can be a list of columns +specifications attributes to create the new column +non-interactively. See `org-columns-compile-format' for +details." (interactive) - (let ((editp (and prop (assoc prop org-columns-current-fmt-compiled))) - cell) - (setq prop (org-icompleting-read - "Property: " (mapcar 'list (org-buffer-property-keys t nil t)) - nil nil prop)) - (setq title (read-string (concat "Column title [" prop "]: ") (or title prop))) - (setq width (read-string "Column width: " (if width (number-to-string width)))) - (if (string-match "\\S-" width) - (setq width (string-to-number width)) - (setq width nil)) - (setq fmt (org-icompleting-read - "Summary [none]: " - (mapcar (lambda (x) (list (symbol-name (cadr x)))) - org-columns-compile-map) - nil t)) - (setq fmt (intern fmt) - fun (cdr (assoc fmt (mapcar 'cdr org-columns-compile-map)))) - (if (eq fmt 'none) (setq fmt nil)) - (if editp - (progn - (setcar editp prop) - (setcdr editp (list title width nil fmt nil fun))) - (setq cell (nthcdr (1- (current-column)) - org-columns-current-fmt-compiled)) - (setcdr cell (cons (list prop title width nil fmt nil - (car fun) (cadr fun)) - (cdr cell)))) + (let ((new (or attributes + (let ((prop + (completing-read + "Property: " + (mapcar #'list (org-buffer-property-keys t nil t)) + nil nil (nth 0 spec)))) + (list prop + (read-string (format "Column title [%s]: " prop) + (nth 1 spec)) + ;; Use `read-string' instead of `read-number' + ;; to allow empty width. + (let ((w (read-string + "Column width: " + (and (nth 2 spec) + (number-to-string (nth 2 spec)))))) + (and (org-string-nw-p w) (string-to-number w))) + (org-string-nw-p + (completing-read + "Summary: " + (delete-dups + (cons '("") ;Allow empty operator. + (mapcar (lambda (x) (list (car x))) + (append + org-columns-summary-types + org-columns-summary-types-default)))) + nil t (nth 3 spec))) + (org-string-nw-p + (read-string "Format: " (nth 4 spec)))))))) + (if spec + (progn (setcar spec (car new)) + (setcdr spec (cdr new))) + (push new (nthcdr (current-column) org-columns-current-fmt-compiled))) (org-columns-store-format) (org-columns-redo))) (defun org-columns-delete () "Delete the column at point from columns view." (interactive) - (let* ((n (current-column)) - (title (nth 1 (nth n org-columns-current-fmt-compiled)))) - (when (y-or-n-p - (format "Are you sure you want to remove column \"%s\"? " title)) + (let ((spec (nth (current-column) org-columns-current-fmt-compiled))) + (when (y-or-n-p (format "Are you sure you want to remove column %S? " + (nth 1 spec))) (setq org-columns-current-fmt-compiled - (delq (nth n org-columns-current-fmt-compiled) - org-columns-current-fmt-compiled)) + (delq spec org-columns-current-fmt-compiled)) (org-columns-store-format) - (org-columns-redo) - (if (>= (current-column) (length org-columns-current-fmt-compiled)) - (backward-char 1))))) + ;; This may leave a now wrong value in a node property. However + ;; updating it may prove counter-intuitive. See comments in + ;; `org-columns-move-right' for details. + (let ((org-columns-inhibit-recalculation t)) (org-columns-redo)) + (when (>= (current-column) (length org-columns-current-fmt-compiled)) + (backward-char))))) (defun org-columns-edit-attributes () "Edit the attributes of the current column." (interactive) - (let* ((n (current-column)) - (info (nth n org-columns-current-fmt-compiled))) - (apply 'org-columns-new info))) + (org-columns-new (nth (current-column) org-columns-current-fmt-compiled))) (defun org-columns-widen (arg) "Make the column wider by ARG characters." (interactive "p") (let* ((n (current-column)) (entry (nth n org-columns-current-fmt-compiled)) - (width (or (nth 2 entry) - (cdr (assoc (car entry) org-columns-current-maxwidths))))) + (width (aref org-columns-current-maxwidths n))) (setq width (max 1 (+ width arg))) (setcar (nthcdr 2 entry) width) (org-columns-store-format) - (org-columns-redo))) + (let ((org-columns-inhibit-recalculation t)) (org-columns-redo)))) (defun org-columns-narrow (arg) "Make the column narrower by ARG characters." @@ -872,7 +911,16 @@ calc function called on every element before summarizing. This is (setcar cell (car (cdr cell))) (setcdr cell (cons e (cdr (cdr cell)))) (org-columns-store-format) - (org-columns-redo) + ;; Do not compute again properties, since we're just moving + ;; columns around. It can put a property value a bit off when + ;; switching between an non-computed and a computed value for the + ;; same property, e.g. from "%A %A{+}" to "%A{+} %A". + ;; + ;; In this case, the value needs to be updated since the first + ;; column related to a property determines how its value is + ;; computed. However, (correctly) updating the value could be + ;; surprising, so we leave it as-is nonetheless. + (let ((org-columns-inhibit-recalculation t)) (org-columns-redo)) (forward-char 1))) (defun org-columns-move-left () @@ -886,358 +934,455 @@ calc function called on every element before summarizing. This is (backward-char 1))) (defun org-columns-store-format () - "Store the text version of the current columns format in appropriate place. -This is either in the COLUMNS property of the node starting the current column -display, or in the #+COLUMNS line of the current buffer." - (let (fmt (cnt 0)) - (setq fmt (org-columns-uncompile-format org-columns-current-fmt-compiled)) - (org-set-local 'org-columns-current-fmt fmt) - (if (marker-position org-columns-top-level-marker) - (save-excursion - (goto-char org-columns-top-level-marker) - (if (and (org-at-heading-p) - (org-entry-get nil "COLUMNS")) - (org-entry-put nil "COLUMNS" fmt) - (goto-char (point-min)) - ;; Overwrite all #+COLUMNS lines.... - (while (re-search-forward "^#\\+COLUMNS:.*" nil t) - (setq cnt (1+ cnt)) - (replace-match (concat "#+COLUMNS: " fmt) t t)) - (unless (> cnt 0) - (goto-char (point-min)) - (or (org-at-heading-p t) (outline-next-heading)) - (let ((inhibit-read-only t)) - (insert-before-markers "#+COLUMNS: " fmt "\n"))) - (org-set-local 'org-columns-default-format fmt)))))) - -(defun org-columns-get-autowidth-alist (s cache) - "Derive the maximum column widths from the format and the cache." - (let ((start 0) rtn) - (while (string-match (org-re "%\\([[:alpha:]][[:alnum:]_-]*\\)") s start) - (push (cons (match-string 1 s) 1) rtn) - (setq start (match-end 0))) - (mapc (lambda (x) - (setcdr x (apply 'max - (mapcar - (lambda (y) - (length (or (cdr (assoc (car x) (cdr y))) " "))) - cache)))) - rtn) - rtn)) - -(defun org-columns-compute-all () - "Compute all columns that have operators defined." - (org-with-silent-modifications - (remove-text-properties (point-min) (point-max) '(org-summaries t))) - (let ((columns org-columns-current-fmt-compiled) - (org-columns-time (time-to-number-of-days (current-time))) - col) - (while (setq col (pop columns)) - (when (nth 3 col) - (save-excursion - (org-columns-compute (car col))))))) + "Store the text version of the current columns format. +The format is stored either in the COLUMNS property of the node +starting the current column display, or in a #+COLUMNS line of +the current buffer." + (let ((fmt (org-columns-uncompile-format org-columns-current-fmt-compiled))) + (setq-local org-columns-current-fmt fmt) + (when (marker-position org-columns-top-level-marker) + (org-with-wide-buffer + (goto-char org-columns-top-level-marker) + (if (and (org-at-heading-p) (org-entry-get nil "COLUMNS")) + (org-entry-put nil "COLUMNS" fmt) + (goto-char (point-min)) + (let ((case-fold-search t)) + ;; Try to replace the first COLUMNS keyword available. + (catch :found + (while (re-search-forward "^[ \t]*#\\+COLUMNS:\\(.*\\)" nil t) + (let ((element (save-match-data (org-element-at-point)))) + (when (and (eq (org-element-type element) 'keyword) + (equal (org-element-property :key element) + "COLUMNS")) + (replace-match (concat " " fmt) t t nil 1) + (throw :found nil)))) + ;; No COLUMNS keyword in the buffer. Insert one at the + ;; beginning, right before the first heading, if any. + (goto-char (point-min)) + (unless (org-at-heading-p t) (outline-next-heading)) + (let ((inhibit-read-only t)) + (insert-before-markers "#+COLUMNS: " fmt "\n")))) + (setq-local org-columns-default-format fmt)))))) (defun org-columns-update (property) "Recompute PROPERTY, and update the columns display for it." (org-columns-compute property) - (let (fmt val pos) - (save-excursion - (mapc (lambda (ov) - (when (equal (overlay-get ov 'org-columns-key) property) - (setq pos (overlay-start ov)) - (goto-char pos) - (when (setq val (cdr (assoc property - (get-text-property - (point-at-bol) 'org-summaries)))) - (setq fmt (overlay-get ov 'org-columns-format)) - (overlay-put ov 'org-columns-value val) - (overlay-put ov 'display (format fmt val))))) - org-columns-overlays)))) - -(defvar org-inlinetask-min-level - (if (featurep 'org-inlinetask) org-inlinetask-min-level 15)) - -;;;###autoload -(defun org-columns-compute (property) - "Sum the values of property PROPERTY hierarchically, for the entire buffer." - (interactive) - (let* ((re org-outline-regexp-bol) - (lmax 30) ; Does anyone use deeper levels??? - (lvals (make-vector lmax nil)) - (lflag (make-vector lmax nil)) - (level 0) - (ass (assoc property org-columns-current-fmt-compiled)) - (format (nth 4 ass)) - (printf (nth 5 ass)) - (fun (nth 6 ass)) - (calc (or (nth 7 ass) 'identity)) - (beg org-columns-top-level-marker) - (inminlevel org-inlinetask-min-level) - (last-level org-inlinetask-min-level) - val valflag flag end sumpos sum-alist sum str str1 useval) - (save-excursion - ;; Find the region to compute - (goto-char beg) - (setq end (condition-case nil (org-end-of-subtree t) (error (point-max)))) - (goto-char end) - ;; Walk the tree from the back and do the computations - (while (re-search-backward re beg t) - (setq sumpos (match-beginning 0) - last-level (if (not (or (zerop level) (eq level inminlevel))) - level last-level) - level (org-outline-level) - val (org-entry-get nil property) - valflag (and val (string-match "\\S-" val))) - (cond - ((< level last-level) - ;; put the sum of lower levels here as a property - (setq sum (+ (if (and (/= last-level inminlevel) - (aref lvals last-level)) - (apply fun (aref lvals last-level)) 0) - (if (aref lvals inminlevel) - (apply fun (aref lvals inminlevel)) 0)) - flag (or (aref lflag last-level) ; any valid entries from children? - (aref lflag inminlevel)) ; or inline tasks? - str (org-columns-number-to-string sum format printf) - str1 (org-add-props (copy-sequence str) nil 'org-computed t 'face 'bold) - useval (if flag str1 (if valflag val "")) - sum-alist (get-text-property sumpos 'org-summaries)) - (if (assoc property sum-alist) - (setcdr (assoc property sum-alist) useval) - (push (cons property useval) sum-alist) - (org-with-silent-modifications - (add-text-properties sumpos (1+ sumpos) - (list 'org-summaries sum-alist)))) - (when (and val (not (equal val (if flag str val)))) - (org-entry-put nil property (if flag str val))) - ;; add current to current level accumulator - (when (or flag valflag) - (push (if flag - sum - (funcall calc (org-columns-string-to-number - (if flag str val) format))) - (aref lvals level)) - (aset lflag level t)) - ;; clear accumulators for deeper levels - (loop for l from (1+ level) to (1- lmax) do - (aset lvals l nil) - (aset lflag l nil))) - ((>= level last-level) - ;; add what we have here to the accumulator for this level - (when valflag - (push (funcall calc (org-columns-string-to-number val format)) - (aref lvals level)) - (aset lflag level t))) - (t (error "This should not happen"))))))) + (org-with-wide-buffer + (let ((p (upcase property))) + (dolist (ov org-columns-overlays) + (let ((key (overlay-get ov 'org-columns-key))) + (when (and key (equal key p) (overlay-start ov)) + (goto-char (overlay-start ov)) + (let* ((spec (nth (current-column) org-columns-current-fmt-compiled)) + (value + (or (cdr (assoc spec + (get-text-property (line-beginning-position) + 'org-summaries))) + (org-entry-get (point) key)))) + (when value + (let ((displayed (org-columns--displayed-value spec value)) + (format (overlay-get ov 'org-columns-format)) + (width + (aref org-columns-current-maxwidths (current-column)))) + (overlay-put ov 'org-columns-value value) + (overlay-put ov 'org-columns-value-modified displayed) + (overlay-put ov + 'display + (org-columns--overlay-text + displayed format width property value))))))))))) (defun org-columns-redo () "Construct the column display again." (interactive) (message "Recomputing columns...") - (let ((line (org-current-line)) - (col (current-column))) - (save-excursion - (if (marker-position org-columns-begin-marker) - (goto-char org-columns-begin-marker)) - (org-columns-remove-overlays) - (if (derived-mode-p 'org-mode) - (call-interactively 'org-columns) - (org-agenda-redo) - (call-interactively 'org-agenda-columns))) - (org-goto-line line) - (move-to-column col)) + (org-with-wide-buffer + (when (marker-position org-columns-begin-marker) + (goto-char org-columns-begin-marker)) + (org-columns-remove-overlays) + (if (derived-mode-p 'org-mode) + ;; Since we already know the columns format, provide it instead + ;; of computing again. + (call-interactively #'org-columns org-columns-current-fmt) + (org-agenda-redo) + (call-interactively #'org-agenda-columns))) (message "Recomputing columns...done")) -(defun org-columns-not-in-agenda () - (if (eq major-mode 'org-agenda-mode) - (error "This command is only allowed in Org-mode buffers"))) - -(defun org-string-to-number (s) - "Convert string to number, and interpret hh:mm:ss." - (if (not (string-match ":" s)) - (string-to-number s) - (let ((l (nreverse (org-split-string s ":"))) (sum 0.0)) - (while l - (setq sum (+ (string-to-number (pop l)) (/ sum 60)))) - sum))) - -;;;###autoload -(defun org-columns-number-to-string (n fmt &optional printf) - "Convert a computed column number to a string value, according to FMT." - (cond - ((memq fmt '(estimate)) (org-estimate-print n printf)) - ((not (numberp n)) "") - ((memq fmt '(add_times max_times min_times mean_times)) - (org-hours-to-clocksum-string n)) - ((eq fmt 'checkbox) - (cond ((= n (floor n)) "[X]") - ((> n 1.) "[-]") - (t "[ ]"))) - ((memq fmt '(checkbox-n-of-m checkbox-percent)) - (let* ((n1 (floor n)) (n2 (floor (+ .5 (* 1000000 (- n n1)))))) - (org-nofm-to-completion n1 (+ n2 n1) (eq fmt 'checkbox-percent)))) - (printf (format printf n)) - ((eq fmt 'currency) - (format "%.2f" n)) - ((memq fmt '(min_age max_age mean_age)) - (org-format-time-period n)) - (t (number-to-string n)))) - -(defun org-nofm-to-completion (n m &optional percent) - (if (not percent) - (format "[%d/%d]" n m) - (format "[%d%%]" (round (* 100.0 n) m)))) - - -(defun org-columns-string-to-number (s fmt) - "Convert a column value to a number that can be used for column computing." - (if s - (cond - ((memq fmt '(min_age max_age mean_age)) - (cond ((string= s "") org-columns-time) - ((string-match - "\\([0-9]+\\)d \\([0-9]+\\)h \\([0-9]+\\)m \\([0-9]+\\)s" - s) - (+ (* 60 (+ (* 60 (+ (* 24 (string-to-number (match-string 1 s))) - (string-to-number (match-string 2 s)))) - (string-to-number (match-string 3 s)))) - (string-to-number (match-string 4 s)))) - (t (time-to-number-of-days (apply 'encode-time - (org-parse-time-string s t)))))) - ((string-match ":" s) - (let ((l (nreverse (org-split-string s ":"))) (sum 0.0)) - (while l - (setq sum (+ (string-to-number (pop l)) (/ sum 60)))) - sum)) - ((string-match (concat "\\([0-9.]+\\) *\\(" - (regexp-opt (mapcar 'car org-effort-durations)) - "\\)") s) - (setq s (concat "0:" (org-duration-string-to-minutes s t))) - (let ((l (nreverse (org-split-string s ":"))) (sum 0.0)) - (while l - (setq sum (+ (string-to-number (pop l)) (/ sum 60)))) - sum)) - ((memq fmt '(checkbox checkbox-n-of-m checkbox-percent)) - (if (equal s "[X]") 1. 0.000001)) - ((memq fmt '(estimate)) (org-string-to-estimate s)) - (t (string-to-number s))))) - -(defun org-columns-uncompile-format (cfmt) - "Turn the compiled columns format back into a string representation." - (let ((rtn "") e s prop title op op-match width fmt printf fun calc) - (while (setq e (pop cfmt)) - (setq prop (car e) - title (nth 1 e) - width (nth 2 e) - op (nth 3 e) - fmt (nth 4 e) - printf (nth 5 e) - fun (nth 6 e) - calc (nth 7 e)) - (when (setq op-match (rassoc (list fmt fun calc) org-columns-compile-map)) - (setq op (car op-match))) - (if (and op printf) (setq op (concat op ";" printf))) - (if (equal title prop) (setq title nil)) - (setq s (concat "%" (if width (number-to-string width)) - prop - (if title (concat "(" title ")")) - (if op (concat "{" op "}")))) - (setq rtn (concat rtn " " s))) - (org-trim rtn))) +(defun org-columns-uncompile-format (compiled) + "Turn the compiled columns format back into a string representation. +COMPILED is an alist, as returned by +`org-columns-compile-format', which see." + (mapconcat + (lambda (spec) + (pcase spec + (`(,prop ,title ,width ,op ,printf) + (concat "%" + (and width (number-to-string width)) + prop + (and title (not (equal prop title)) (format "(%s)" title)) + (cond ((not op) nil) + (printf (format "{%s;%s}" op printf)) + (t (format "{%s}" op))))))) + compiled " ")) (defun org-columns-compile-format (fmt) - "Turn a column format string into an alist of specifications. + "Turn a column format string FMT into an alist of specifications. + The alist has one entry for each column in the format. The elements of that list are: -property the property -title the title field for the columns -width the column width in characters, can be nil for automatic -operator the operator if any -format the output format for computed results, derived from operator -printf a printf format for computed values -fun the lisp function to compute summary values, derived from operator -calc function to get values from base elements" - (let ((start 0) width prop title op op-match f printf fun calc) - (setq org-columns-current-fmt-compiled nil) +property the property name, as an upper-case string +title the title field for the columns, as a string +width the column width in characters, can be nil for automatic width +operator the summary operator, as a string, or nil +printf a printf format for computed values, as a string, or nil + +This function updates `org-columns-current-fmt-compiled'." + (setq org-columns-current-fmt-compiled nil) + (let ((start 0)) (while (string-match - (org-re "%\\([0-9]+\\)?\\([[:alnum:]_-]+\\)\\(?:(\\([^)]+\\))\\)?\\(?:{\\([^}]+\\)}\\)?\\s-*") + "%\\([0-9]+\\)?\\([[:alnum:]_-]+\\)\\(?:(\\([^)]+\\))\\)?\ +\\(?:{\\([^}]+\\)}\\)?\\s-*" fmt start) - (setq start (match-end 0) - width (match-string 1 fmt) - prop (match-string 2 fmt) - title (or (match-string 3 fmt) prop) - op (match-string 4 fmt) - f nil - printf nil - fun '+ - calc nil) - (if width (setq width (string-to-number width))) - (when (and op (string-match ";" op)) - (setq printf (substring op (match-end 0)) - op (substring op 0 (match-beginning 0)))) - (when (setq op-match (assoc op org-columns-compile-map)) - (setq f (cadr op-match) - fun (caddr op-match) - calc (cadddr op-match))) - (push (list prop title width op f printf fun calc) - org-columns-current-fmt-compiled)) + (setq start (match-end 0)) + (let* ((width (and (match-end 1) (string-to-number (match-string 1 fmt)))) + (prop (match-string-no-properties 2 fmt)) + (title (or (match-string-no-properties 3 fmt) prop)) + (operator (match-string-no-properties 4 fmt))) + (push (if (not operator) (list (upcase prop) title width nil nil) + (let (printf) + (when (string-match ";" operator) + (setq printf (substring operator (match-end 0))) + (setq operator (substring operator 0 (match-beginning 0)))) + (list (upcase prop) title width operator printf))) + org-columns-current-fmt-compiled))) (setq org-columns-current-fmt-compiled (nreverse org-columns-current-fmt-compiled)))) + +;;;; Column View Summary + +(defconst org-columns--duration-re + (concat "[0-9.]+ *" (regexp-opt (mapcar #'car org-effort-durations))) + "Regexp matching a duration.") + +(defun org-columns--time-to-seconds (s) + "Turn time string S into a number of seconds. +A time is expressed as HH:MM, HH:MM:SS, or with units defined in +`org-effort-durations'. Plain numbers are considered as hours." + (cond + ((string-match-p org-columns--duration-re s) + (* 60 (org-duration-string-to-minutes s))) + ((string-match "\\`\\([0-9]+\\):\\([0-9]+\\)\\(?::\\([0-9]+\\)\\)?\\'" s) + (+ (* 3600 (string-to-number (match-string 1 s))) + (* 60 (string-to-number (match-string 2 s))) + (if (match-end 3) (string-to-number (match-string 3 s)) 0))) + (t (* 3600 (string-to-number s))))) + +(defun org-columns--age-to-seconds (s) + "Turn age string S into a number of seconds. +An age is either computed from a given time-stamp, or indicated +as days/hours/minutes/seconds." + (cond + ((string-match-p org-ts-regexp s) + (floor + (- org-columns--time + (float-time (apply #'encode-time (org-parse-time-string s nil t)))))) + ;; Match own output for computations in upper levels. + ((string-match "\\([0-9]+\\)d \\([0-9]+\\)h \\([0-9]+\\)m \\([0-9]+\\)s" s) + (+ (* 86400 (string-to-number (match-string 1 s))) + (* 3600 (string-to-number (match-string 2 s))) + (* 60 (string-to-number (match-string 3 s))) + (string-to-number (match-string 4 s)))) + (t (user-error "Invalid age: %S" s)))) + +(defun org-columns--summary-apply-times (fun times) + "Apply FUN to time values TIMES. +If TIMES contains any time value expressed as a duration, return +the result as a duration. If it contains any H:M:S, use that +format instead. Otherwise, use H:M format." + (let* ((hms-flag nil) + (duration-flag nil) + (seconds + (apply fun + (mapcar + (lambda (time) + (cond + (duration-flag) + ((string-match-p org-columns--duration-re time) + (setq duration-flag t)) + (hms-flag) + ((string-match-p "\\`[0-9]+:[0-9]+:[0-9]+\\'" time) + (setq hms-flag t))) + (org-columns--time-to-seconds time)) + times)))) + (cond (duration-flag (org-minutes-to-clocksum-string (/ seconds 60.0))) + (hms-flag (format-seconds "%h:%.2m:%.2s" seconds)) + (t (format-seconds "%h:%.2m" seconds))))) + +(defun org-columns--compute-spec (spec &optional update) + "Update tree according to SPEC. +SPEC is a column format specification. When optional argument +UPDATE is non-nil, summarized values can replace existing ones in +properties drawers." + (let* ((lmax (if (bound-and-true-p org-inlinetask-min-level) + org-inlinetask-min-level + 29)) ;Hard-code deepest level. + (lvals (make-vector (1+ lmax) nil)) + (level 0) + (inminlevel lmax) + (last-level lmax) + (property (car spec)) + (printf (nth 4 spec)) + (summarize (org-columns--summarize (nth 3 spec)))) + (org-with-wide-buffer + ;; Find the region to compute. + (goto-char org-columns-top-level-marker) + (goto-char (condition-case nil (org-end-of-subtree t) (error (point-max)))) + ;; Walk the tree from the back and do the computations. + (while (re-search-backward + org-outline-regexp-bol org-columns-top-level-marker t) + (unless (or (= level 0) (eq level inminlevel)) + (setq last-level level)) + (setq level (org-reduced-level (org-outline-level))) + (let* ((pos (match-beginning 0)) + (value (org-entry-get nil property)) + (value-set (org-string-nw-p value))) + (cond + ((< level last-level) + ;; Collect values from lower levels and inline tasks here + ;; and summarize them using SUMMARIZE. Store them in text + ;; property `org-summaries', in alist whose key is SPEC. + (let* ((summary + (and summarize + (let ((values (append (and (/= last-level inminlevel) + (aref lvals last-level)) + (aref lvals inminlevel)))) + (and values (funcall summarize values printf)))))) + ;; Leaf values are not summaries: do not mark them. + (when summary + (let* ((summaries-alist (get-text-property pos 'org-summaries)) + (old (assoc spec summaries-alist))) + (if old (setcdr old summary) + (push (cons spec summary) summaries-alist) + (org-with-silent-modifications + (add-text-properties + pos (1+ pos) (list 'org-summaries summaries-alist))))) + ;; When PROPERTY exists in current node, even if empty, + ;; but its value doesn't match the one computed, use + ;; the latter instead. + ;; + ;; Ignore leading or trailing white spaces that might + ;; have been introduced in summary, since those are not + ;; significant in properties value. + (let ((new-value (org-trim summary))) + (when (and update value (not (equal value new-value))) + (org-entry-put (point) property new-value)))) + ;; Add current to current level accumulator. + (when (or summary value-set) + (push (or summary value) (aref lvals level))) + ;; Clear accumulators for deeper levels. + (cl-loop for l from (1+ level) to lmax do (aset lvals l nil)))) + (value-set (push value (aref lvals level))) + (t nil))))))) + +;;;###autoload +(defun org-columns-compute (property) + "Summarize the values of PROPERTY hierarchically. +Also update existing values for PROPERTY according to the first +column specification." + (interactive) + (let ((main-flag t) + (upcase-prop (upcase property))) + (dolist (spec org-columns-current-fmt-compiled) + (pcase spec + (`(,(pred (equal upcase-prop)) . ,_) + (org-columns--compute-spec spec main-flag) + ;; Only the first summary can update the property value. + (when main-flag (setq main-flag nil))))))) +(defun org-columns-compute-all () + "Compute all columns that have operators defined." + (org-with-silent-modifications + (remove-text-properties (point-min) (point-max) '(org-summaries t))) + (let ((org-columns--time (float-time (current-time))) + seen) + (dolist (spec org-columns-current-fmt-compiled) + (let ((property (car spec))) + ;; Property value is updated only the first time a given + ;; property is encountered. + (org-columns--compute-spec spec (not (member property seen))) + (push property seen))))) + +(defun org-columns--summary-sum (values printf) + "Compute the sum of VALUES. +When PRINTF is non-nil, use it to format the result." + (format (or printf "%s") (apply #'+ (mapcar #'string-to-number values)))) + +(defun org-columns--summary-currencies (values _) + "Compute the sum of VALUES, with two decimals." + (format "%.2f" (apply #'+ (mapcar #'string-to-number values)))) + +(defun org-columns--summary-checkbox (check-boxes _) + "Summarize CHECK-BOXES with a check-box." + (let ((done (cl-count "[X]" check-boxes :test #'equal)) + (all (length check-boxes))) + (cond ((= done all) "[X]") + ((> done 0) "[-]") + (t "[ ]")))) + +(defun org-columns--summary-checkbox-count (check-boxes _) + "Summarize CHECK-BOXES with a check-box cookie." + (format "[%d/%d]" + (cl-count-if (lambda (b) (or (equal b "[X]") + (string-match-p "\\[\\([1-9]\\)/\\1\\]" b))) + check-boxes) + (length check-boxes))) + +(defun org-columns--summary-checkbox-percent (check-boxes _) + "Summarize CHECK-BOXES with a check-box percent." + (format "[%d%%]" + (round (* 100.0 (cl-count-if (lambda (b) (member b '("[X]" "[100%]"))) + check-boxes)) + (length check-boxes)))) + +(defun org-columns--summary-min (values printf) + "Compute the minimum of VALUES. +When PRINTF is non-nil, use it to format the result." + (format (or printf "%s") + (apply #'min (mapcar #'string-to-number values)))) + +(defun org-columns--summary-max (values printf) + "Compute the maximum of VALUES. +When PRINTF is non-nil, use it to format the result." + (format (or printf "%s") + (apply #'max (mapcar #'string-to-number values)))) + +(defun org-columns--summary-mean (values printf) + "Compute the mean of VALUES. +When PRINTF is non-nil, use it to format the result." + (format (or printf "%s") + (/ (apply #'+ (mapcar #'string-to-number values)) + (float (length values))))) + +(defun org-columns--summary-sum-times (times _) + "Sum TIMES." + (org-columns--summary-apply-times #'+ times)) + +(defun org-columns--summary-min-time (times _) + "Compute the minimum time among TIMES." + (org-columns--summary-apply-times #'min times)) + +(defun org-columns--summary-max-time (times _) + "Compute the maximum time among TIMES." + (org-columns--summary-apply-times #'max times)) + +(defun org-columns--summary-mean-time (times _) + "Compute the mean time among TIMES." + (org-columns--summary-apply-times + (lambda (&rest values) (/ (apply #'+ values) (float (length values)))) + times)) + +(defun org-columns--summary-min-age (ages _) + "Compute the minimum time among AGES." + (format-seconds + "%dd %.2hh %mm %ss" + (apply #'min (mapcar #'org-columns--age-to-seconds ages)))) + +(defun org-columns--summary-max-age (ages _) + "Compute the maximum time among AGES." + (format-seconds + "%dd %.2hh %mm %ss" + (apply #'max (mapcar #'org-columns--age-to-seconds ages)))) + +(defun org-columns--summary-mean-age (ages _) + "Compute the minimum time among AGES." + (format-seconds + "%dd %.2hh %mm %ss" + (/ (apply #'+ (mapcar #'org-columns--age-to-seconds ages)) + (float (length ages))))) + +(defun org-columns--summary-estimate (estimates _) + "Combine a list of estimates, using mean and variance. +The mean and variance of the result will be the sum of the means +and variances (respectively) of the individual estimates." + (let ((mean 0) + (var 0)) + (dolist (e estimates) + (pcase (mapcar #'string-to-number (split-string e "-")) + (`(,low ,high) + (let ((m (/ (+ low high) 2.0))) + (cl-incf mean m) + (cl-incf var (- (/ (+ (* low low) (* high high)) 2.0) (* m m))))) + (`(,value) (cl-incf mean value)))) + (let ((sd (sqrt var))) + (format "%s-%s" + (format "%.0f" (- mean sd)) + (format "%.0f" (+ mean sd)))))) + + + ;;; Dynamic block for Column view -(defvar org-heading-regexp) ; defined in org.el -(defvar org-heading-keyword-regexp-format) ; defined in org.el -(defun org-columns-capture-view (&optional maxlevel skip-empty-rows) - "Get the column view of the current buffer or subtree. -The first optional argument MAXLEVEL sets the level limit. A -second optional argument SKIP-EMPTY-ROWS tells whether to skip +(defun org-columns--capture-view (maxlevel skip-empty format local) + "Get the column view of the current buffer. + +MAXLEVEL sets the level limit. SKIP-EMPTY tells whether to skip empty rows, an empty row being one where all the column view -specifiers except ITEM are empty. This function returns a list -containing the title row and all other rows. Each row is a list -of fields." - (save-excursion - (let* ((title (mapcar 'cadr org-columns-current-fmt-compiled)) - (re-comment (format org-heading-keyword-regexp-format - org-comment-string)) - (re-archive (concat ".*:" org-archive-tag ":")) - (n (length title)) row tbl) - (goto-char (point-min)) - (while (re-search-forward org-heading-regexp nil t) - (catch 'next - (when (and (or (null maxlevel) - (>= maxlevel - (if org-odd-levels-only - (/ (1+ (length (match-string 1))) 2) - (length (match-string 1))))) - (get-char-property (match-beginning 0) 'org-columns-key)) - (when (save-excursion - (goto-char (point-at-bol)) - (or (looking-at re-comment) - (looking-at re-archive))) - (org-end-of-subtree t) - (throw 'next t)) - (setq row nil) - (loop for i from 0 to (1- n) do - (push - (org-quote-vert - (or (get-char-property (+ (match-beginning 0) i) 'org-columns-value-modified) - (get-char-property (+ (match-beginning 0) i) 'org-columns-value) - "")) - row)) - (setq row (nreverse row)) - (unless (and skip-empty-rows - (eq 1 (length (delete "" (delete-dups (copy-sequence row)))))) - (push row tbl))))) - (append (list title 'hline) (nreverse tbl))))) +specifiers but ITEM are empty. FORMAT is a format string for +columns, or nil. When LOCAL is non-nil, only capture headings in +current subtree. + +This function returns a list containing the title row and all +other rows. Each row is a list of fields, as strings, or +`hline'." + (org-columns (not local) format) + (goto-char org-columns-top-level-marker) + (let ((columns (length org-columns-current-fmt-compiled)) + (has-item (assoc "ITEM" org-columns-current-fmt-compiled)) + table) + (org-map-entries + (lambda () + (when (get-char-property (point) 'org-columns-key) + (let (row) + (dotimes (i columns) + (let* ((col (+ (line-beginning-position) i)) + (p (get-char-property col 'org-columns-key))) + (push (org-quote-vert + (get-char-property col + (if (string= p "ITEM") + 'org-columns-value + 'org-columns-value-modified))) + row))) + (unless (and skip-empty + (let ((r (delete-dups (remove "" row)))) + (or (null r) (and has-item (= (length r) 1))))) + (push (cons (org-reduced-level (org-current-level)) (nreverse row)) + table))))) + (and maxlevel (format "LEVEL<=%d" maxlevel)) + (and local 'tree) + 'archive 'comment) + (org-columns-quit) + ;; Add column titles and a horizontal rule in front of the table. + (cons (mapcar #'cadr org-columns-current-fmt-compiled) + (cons 'hline (nreverse table))))) + +(defun org-columns--clean-item (item) + "Remove sensitive contents from string ITEM. +This includes objects that may not be duplicated within +a document, e.g., a target, or those forbidden in tables, e.g., +an inline src-block." + (let ((data (org-element-parse-secondary-string + item (org-element-restriction 'headline)))) + (org-element-map data + '(footnote-reference inline-babel-call inline-src-block target + radio-target statistics-cookie) + #'org-element-extract-element) + (org-no-properties (org-element-interpret-data data)))) ;;;###autoload (defun org-dblock-write:columnview (params) "Write the column view table. PARAMS is a property list of parameters: -:width enforce same column widths with specifiers. :id the :ID: property of the entry where the columns view should be built. When the symbol `local', call locally. When `global' call column view with the cursor at the beginning @@ -1247,339 +1392,269 @@ PARAMS is a property list of parameters: using `org-id-find'. :hlines When t, insert a hline before each item. When a number, insert a hline before each level <= that number. +:indent When non-nil, indent each ITEM field according to its level. :vlines When t, make each column a colgroup to enforce vertical lines. :maxlevel When set to a number, don't capture headlines below this level. :skip-empty-rows When t, skip rows where all specifiers other than ITEM are empty. +:width apply widths specified in columns format using specifiers. :format When non-nil, specify the column view format to use." - (let ((pos (point-marker)) - (hlines (plist-get params :hlines)) - (vlines (plist-get params :vlines)) - (maxlevel (plist-get params :maxlevel)) - (content-lines (org-split-string (plist-get params :content) "\n")) - (skip-empty-rows (plist-get params :skip-empty-rows)) - (columns-fmt (plist-get params :format)) - (case-fold-search t) - tbl id idpos nfields tmp recalc line - id-as-string view-file view-pos) - (when (setq id (plist-get params :id)) - (setq id-as-string (cond ((numberp id) (number-to-string id)) - ((symbolp id) (symbol-name id)) - ((stringp id) id) - (t ""))) - (cond ((not id) nil) - ((eq id 'global) (setq view-pos (point-min))) - ((eq id 'local)) - ((string-match "^file:\\(.*\\)" id-as-string) - (setq view-file (match-string 1 id-as-string) - view-pos 1) - (unless (file-exists-p view-file) - (error "No such file: \"%s\"" id-as-string))) - ((setq idpos (org-find-entry-with-id id)) - (setq view-pos idpos)) - ((setq idpos (org-id-find id)) - (setq view-file (car idpos)) - (setq view-pos (cdr idpos))) - (t (error "Cannot find entry with :ID: %s" id)))) - (with-current-buffer (if view-file - (get-file-buffer view-file) - (current-buffer)) - (save-excursion - (save-restriction - (widen) - (goto-char (or view-pos (point))) - (org-columns columns-fmt) - (setq tbl (org-columns-capture-view maxlevel skip-empty-rows)) - (setq nfields (length (car tbl))) - (org-columns-quit)))) - (goto-char pos) - (move-marker pos nil) - (when tbl - (when (plist-get params :hlines) - (setq tmp nil) - (while tbl - (if (eq (car tbl) 'hline) - (push (pop tbl) tmp) - (if (string-match "\\` *\\(\\*+\\)" (caar tbl)) - (if (and (not (eq (car tmp) 'hline)) - (or (eq hlines t) - (and (numberp hlines) - (<= (- (match-end 1) (match-beginning 1)) - hlines)))) - (push 'hline tmp))) - (push (pop tbl) tmp))) - (setq tbl (nreverse tmp))) - (when vlines - (setq tbl (mapcar (lambda (x) - (if (eq 'hline x) x (cons "" x))) - tbl)) - (setq tbl (append tbl (list (cons "/" (make-list nfields "<>")))))) - (when content-lines - (while (string-match "^#" (car content-lines)) - (insert (pop content-lines) "\n"))) - (setq pos (point)) - (insert (org-listtable-to-string tbl)) + (let ((table + (let ((id (plist-get params :id)) + view-file view-pos) + (pcase id + (`global nil) + ((or `local `nil) (setq view-pos (point))) + ((and (let id-string (format "%s" id)) + (guard (string-match "^file:\\(.*\\)" id-string))) + (setq view-file (match-string-no-properties 1 id-string)) + (unless (file-exists-p view-file) + (user-error "No such file: %S" id-string))) + ((and (let idpos (org-find-entry-with-id id)) (guard idpos)) + (setq view-pos idpos)) + ((let `(,filename . ,position) (org-id-find id)) + (setq view-file filename) + (setq view-pos position)) + (_ (user-error "Cannot find entry with :ID: %s" id))) + (with-current-buffer (if view-file (get-file-buffer view-file) + (current-buffer)) + (org-with-wide-buffer + (when view-pos (goto-char view-pos)) + (org-columns--capture-view (plist-get params :maxlevel) + (plist-get params :skip-empty-rows) + (plist-get params :format) + view-pos)))))) + (when table + ;; Prune level information from the table. Also normalize + ;; headings: remove stars, add indentation entities, if + ;; required, and possibly precede some of them with a horizontal + ;; rule. + (let ((item-index + (let ((p (assoc "ITEM" org-columns-current-fmt-compiled))) + (and p (cl-position p + org-columns-current-fmt-compiled + :test #'equal)))) + (hlines (plist-get params :hlines)) + (indent (plist-get params :indent)) + new-table) + ;; Copy header and first rule. + (push (pop table) new-table) + (push (pop table) new-table) + (dolist (row table (setq table (nreverse new-table))) + (let ((level (car row))) + (when (and (not (eq (car new-table) 'hline)) + (or (eq hlines t) + (and (numberp hlines) (<= level hlines)))) + (push 'hline new-table)) + (when item-index + (let ((item (org-columns--clean-item (nth item-index (cdr row))))) + (setf (nth item-index (cdr row)) + (if (and indent (> level 1)) + (concat "\\_" (make-string (* 2 (1- level)) ?\s) item) + item)))) + (push (cdr row) new-table)))) (when (plist-get params :width) - (insert "\n|" (mapconcat (lambda (x) (format "<%d>" (max 3 x))) - org-columns-current-widths "|"))) - (while (setq line (pop content-lines)) - (when (string-match "^#" line) - (insert "\n" line) - (when (string-match "^[ \t]*#\\+tblfm" line) - (setq recalc t)))) - (if recalc - (progn (goto-char pos) (org-table-recalculate 'all)) - (goto-char pos) + (setq table + (append table + (list + (mapcar (lambda (spec) + (let ((w (nth 2 spec))) + (if w (format "<%d>" (max 3 w)) ""))) + org-columns-current-fmt-compiled))))) + (when (plist-get params :vlines) + (setq table + (let ((size (length org-columns-current-fmt-compiled))) + (append (mapcar (lambda (x) (if (eq 'hline x) x (cons "" x))) + table) + (list (cons "/" (make-list size "<>"))))))) + (let ((content-lines (org-split-string (plist-get params :content) "\n")) + recalc) + ;; Insert affiliated keywords before the table. + (when content-lines + (while (string-match-p "\\`[ \t]*#\\+" (car content-lines)) + (insert (pop content-lines) "\n"))) + (save-excursion + ;; Insert table at point. + (insert + (mapconcat (lambda (row) + (if (eq row 'hline) "|-|" + (format "|%s|" (mapconcat #'identity row "|")))) + table + "\n")) + ;; Insert TBLFM lines following table. + (let ((case-fold-search t)) + (dolist (line content-lines) + (when (string-match-p "\\`[ \t]*#\\+TBLFM:" line) + (insert "\n" line) + (unless recalc (setq recalc t)))))) + (when recalc (org-table-recalculate 'all t)) (org-table-align))))) -(defun org-listtable-to-string (tbl) - "Convert a listtable TBL to a string that contains the Org-mode table. -The table still need to be aligned. The resulting string has no leading -and tailing newline characters." - (mapconcat - (lambda (x) - (cond - ((listp x) - (concat "|" (mapconcat 'identity x "|") "|")) - ((eq x 'hline) "|-|") - (t (error "Garbage in listtable: %s" x)))) - tbl "\n")) - ;;;###autoload -(defun org-insert-columns-dblock () +(defun org-columns-insert-dblock () "Create a dynamic block capturing a column view table." (interactive) - (let ((defaults '(:name "columnview" :hlines 1)) - (id (org-icompleting-read + (let ((id (completing-read "Capture columns (local, global, entry with :ID: property) [local]: " (append '(("global") ("local")) - (mapcar 'list (org-property-values "ID")))))) - (if (equal id "") (setq id 'local)) - (if (equal id "global") (setq id 'global)) - (setq defaults (append defaults (list :id id))) - (org-create-dblock defaults) - (org-update-dblock))) + (mapcar #'list (org-property-values "ID")))))) + (org-create-dblock + (list :name "columnview" + :hlines 1 + :id (cond ((string= id "global") 'global) + ((member id '("" "local")) 'local) + (id))))) + (org-update-dblock)) -;;; Column view in the agenda - -(defvar org-agenda-view-columns-initially nil - "When set, switch to columns view immediately after creating the agenda.") -(defvar org-agenda-columns-show-summaries) ; defined in org-agenda.el -(defvar org-agenda-columns-compute-summary-properties); defined in org-agenda.el -(defvar org-agenda-columns-add-appointments-to-effort-sum); as well + +;;; Column view in the agenda ;;;###autoload (defun org-agenda-columns () "Turn on or update column view in the agenda." (interactive) - (org-verify-version 'columns) (org-columns-remove-overlays) (move-marker org-columns-begin-marker (point)) - (let ((org-columns-time (time-to-number-of-days (current-time))) - cache maxwidths m p a d fmt) - (cond - ((and (boundp 'org-agenda-overriding-columns-format) - org-agenda-overriding-columns-format) - (setq fmt org-agenda-overriding-columns-format)) - ((setq m (org-get-at-bol 'org-hd-marker)) - (setq fmt (or (org-entry-get m "COLUMNS" t) - (with-current-buffer (marker-buffer m) - org-columns-default-format)))) - ((and (boundp 'org-columns-current-fmt) - (local-variable-p 'org-columns-current-fmt) - org-columns-current-fmt) - (setq fmt org-columns-current-fmt)) - ((setq m (next-single-property-change (point-min) 'org-hd-marker)) - (setq m (get-text-property m 'org-hd-marker)) - (setq fmt (or (org-entry-get m "COLUMNS" t) - (with-current-buffer (marker-buffer m) - org-columns-default-format))))) - (setq fmt (or fmt org-columns-default-format)) - (org-set-local 'org-columns-current-fmt fmt) - (org-columns-compile-format fmt) + (let* ((org-columns--time (float-time (current-time))) + (fmt + (cond + ((bound-and-true-p org-agenda-overriding-columns-format)) + ((let ((m (org-get-at-bol 'org-hd-marker))) + (and m + (or (org-entry-get m "COLUMNS" t) + (with-current-buffer (marker-buffer m) + org-columns-default-format))))) + ((and (local-variable-p 'org-columns-current-fmt) + org-columns-current-fmt)) + ((let ((m (next-single-property-change (point-min) 'org-hd-marker))) + (and m + (let ((m (get-text-property m 'org-hd-marker))) + (or (org-entry-get m "COLUMNS" t) + (with-current-buffer (marker-buffer m) + org-columns-default-format)))))) + (t org-columns-default-format))) + (compiled-fmt (org-columns-compile-format fmt))) + (setq org-columns-current-fmt fmt) (when org-agenda-columns-compute-summary-properties (org-agenda-colview-compute org-columns-current-fmt-compiled)) (save-excursion - ;; Get and cache the properties + ;; Collect properties for each headline in current view. (goto-char (point-min)) - (while (not (eobp)) - (when (setq m (or (org-get-at-bol 'org-hd-marker) - (org-get-at-bol 'org-marker))) - (setq p (org-entry-properties m)) - - (when (or (not (setq a (assoc org-effort-property p))) - (not (string-match "\\S-" (or (cdr a) "")))) - ;; OK, the property is not defined. Use appointment duration? - (when (and org-agenda-columns-add-appointments-to-effort-sum - (setq d (get-text-property (point) 'duration))) - (setq d (org-minutes-to-clocksum-string d)) - (put-text-property 0 (length d) 'face 'org-warning d) - (push (cons org-effort-property d) p))) - (push (cons (org-current-line) p) cache)) - (beginning-of-line 2)) - (when cache - (setq maxwidths (org-columns-get-autowidth-alist fmt cache)) - (org-set-local 'org-columns-current-maxwidths maxwidths) - (org-columns-display-here-title) - (when (org-set-local 'org-columns-flyspell-was-active - (org-bound-and-true-p flyspell-mode)) - (flyspell-mode 0)) - (mapc (lambda (x) - (org-goto-line (car x)) - (org-columns-display-here (cdr x))) - cache) - (when org-agenda-columns-show-summaries - (org-agenda-colview-summarize cache)))))) + (let (cache) + (while (not (eobp)) + (let ((m (org-get-at-bol 'org-hd-marker))) + (when m + (push (cons (line-beginning-position) + ;; `org-columns-current-fmt-compiled' is + ;; initialized but only set locally to the + ;; agenda buffer. Since current buffer is + ;; changing, we need to force the original + ;; compiled-fmt there. + (org-with-point-at m + (org-columns--collect-values compiled-fmt))) + cache))) + (forward-line)) + (when cache + (org-columns--set-widths cache) + (org-columns--display-here-title) + (when (setq-local org-columns-flyspell-was-active + (bound-and-true-p flyspell-mode)) + (flyspell-mode 0)) + (dolist (entry cache) + (goto-char (car entry)) + (org-columns--display-here (cdr entry))) + (when org-agenda-columns-show-summaries + (org-agenda-colview-summarize cache))))))) (defun org-agenda-colview-summarize (cache) "Summarize the summarizable columns in column view in the agenda. This will add overlays to the date lines, to show the summary for each day." - (let* ((fmt (mapcar (lambda (x) - (if (string-match "CLOCKSUM.*" (car x)) - (list (match-string 0 (car x)) - (nth 1 x) (nth 2 x) ":" 'add_times - nil '+ nil) - x)) - org-columns-current-fmt-compiled)) - line c c1 stype calc sumfunc props lsum entries prop v title) - (catch 'exit - (when (delq nil (mapcar 'cadr fmt)) - ;; OK, at least one summation column, it makes sense to try this - (goto-char (point-max)) + (let ((fmt (mapcar + (lambda (spec) + (pcase spec + (`(,property ,title ,width . ,_) + (if (member property '("CLOCKSUM" "CLOCKSUM_T")) + (list property title width ":" nil) + spec)))) + org-columns-current-fmt-compiled))) + ;; Ensure there's at least one summation column. + (when (cl-some (lambda (spec) (nth 3 spec)) fmt) + (goto-char (point-max)) + (catch :complete (while t (when (or (get-text-property (point) 'org-date-line) (eq (get-text-property (point) 'face) 'org-agenda-structure)) - ;; OK, this is a date line that should be used - (setq line (org-current-line)) - (setq entries nil c cache cache nil) - (while (setq c1 (pop c)) - (if (> (car c1) line) - (push c1 entries) - (push c1 cache))) - ;; now ENTRIES are the ones we want to use, CACHE is the rest - ;; Compute the summaries for the properties we want, - ;; set nil properties for the rest. - (when (setq entries (mapcar 'cdr entries)) - (setq props - (mapcar - (lambda (f) - (setq prop (car f) - title (nth 1 f) - stype (nth 4 f) - sumfunc (nth 6 f) - calc (or (nth 7 f) 'identity)) - (cond - ((equal prop "ITEM") - (cons prop (buffer-substring (point-at-bol) - (point-at-eol)))) - ((not stype) (cons prop "")) - (t ;; do the summary - (setq lsum nil) - (dolist (x entries) - (setq v (cdr (assoc prop x))) - (if v - (push - (funcall - (if (not (get-text-property 0 'org-computed v)) - calc - 'identity) - (org-columns-string-to-number - v stype)) - lsum))) - (setq lsum (remove nil lsum)) - (setq lsum - (cond ((> (length lsum) 1) - (org-columns-number-to-string - (apply sumfunc lsum) stype)) - ((eq (length lsum) 1) - (org-columns-number-to-string - (car lsum) stype)) - (t ""))) - (put-text-property 0 (length lsum) 'face 'bold lsum) - (unless (eq calc 'identity) - (put-text-property 0 (length lsum) 'org-computed t lsum)) - (cons prop lsum)))) - fmt)) - (org-columns-display-here props 'dateline) - (org-set-local 'org-agenda-columns-active t))) - (if (bobp) (throw 'exit t)) - (beginning-of-line 0)))))) + ;; OK, this is a date line that should be used. + (let (entries) + (let (rest) + (dolist (c cache) + (if (> (car c) (point)) + (push c entries) + (push c rest))) + (setq cache rest)) + ;; ENTRIES contains entries below the current one. + ;; CACHE is the rest. Compute the summaries for the + ;; properties we want, set nil properties for the rest. + (when (setq entries (mapcar #'cdr entries)) + (org-columns--display-here + (mapcar + (lambda (spec) + (pcase spec + (`("ITEM" . ,_) + ;; Replace ITEM with current date. Preserve + ;; properties for fontification. + (let ((date (buffer-substring + (line-beginning-position) + (line-end-position)))) + (list spec date date))) + (`(,_ ,_ ,_ nil ,_) (list spec "" "")) + (`(,_ ,_ ,_ ,operator ,printf) + (let* ((summarize (org-columns--summarize operator)) + (values + ;; Use real values for summary, not + ;; those prepared for display. + (delq nil + (mapcar + (lambda (e) (org-string-nw-p + (nth 1 (assoc spec e)))) + entries))) + (final (if values + (funcall summarize values printf) + ""))) + (unless (equal final "") + (put-text-property 0 (length final) + 'face 'bold final)) + (list spec final final))))) + fmt) + 'dateline) + (setq-local org-agenda-columns-active t)))) + (if (bobp) (throw :complete t) (forward-line -1))))))) (defun org-agenda-colview-compute (fmt) "Compute the relevant columns in the contributing source buffers." (let ((files org-agenda-contributing-files) (org-columns-begin-marker (make-marker)) - (org-columns-top-level-marker (make-marker)) - f fm a b) - (while (setq f (pop files)) - (setq b (find-buffer-visiting f)) - (with-current-buffer (or (buffer-base-buffer b) b) - (save-excursion - (save-restriction - (widen) - (org-with-silent-modifications - (remove-text-properties (point-min) (point-max) '(org-summaries t))) - (goto-char (point-min)) - (org-columns-get-format-and-top-level) - (while (setq fm (pop fmt)) - (cond ((equal (car fm) "CLOCKSUM") - (org-clock-sum)) - ((equal (car fm) "CLOCKSUM_T") - (org-clock-sum-today)) - ((and (nth 4 fm) - (setq a (assoc (car fm) - org-columns-current-fmt-compiled)) - (equal (nth 4 a) (nth 4 fm))) - (org-columns-compute (car fm))))))))))) - -(defun org-format-time-period (interval) - "Convert time in fractional days to days/hours/minutes/seconds." - (if (numberp interval) - (let* ((days (floor interval)) - (frac-hours (* 24 (- interval days))) - (hours (floor frac-hours)) - (minutes (floor (* 60 (- frac-hours hours)))) - (seconds (floor (* 60 (- (* 60 (- frac-hours hours)) minutes))))) - (format "%dd %02dh %02dm %02ds" days hours minutes seconds)) - "")) - -(defun org-estimate-mean-and-var (v) - "Return the mean and variance of an estimate." - (let* ((low (float (car v))) - (high (float (cadr v))) - (mean (/ (+ low high) 2.0)) - (var (/ (+ (expt (- mean low) 2.0) (expt (- high mean) 2.0)) 2.0))) - (list mean var))) - -(defun org-estimate-combine (&rest el) - "Combine a list of estimates, using mean and variance. -The mean and variance of the result will be the sum of the means -and variances (respectively) of the individual estimates." - (let ((mean 0) - (var 0)) - (mapc (lambda (e) - (let ((stats (org-estimate-mean-and-var e))) - (setq mean (+ mean (car stats))) - (setq var (+ var (cadr stats))))) - el) - (let ((stdev (sqrt var))) - (list (- mean stdev) (+ mean stdev))))) - -(defun org-estimate-print (e &optional fmt) - "Prepare a string representation of an estimate. -This formats these numbers as two numbers with a \"-\" between them." - (if (null fmt) (set 'fmt "%.0f")) - (format "%s" (mapconcat (lambda (n) (format fmt n)) e "-"))) - -(defun org-string-to-estimate (s) - "Convert a string to an estimate. -The string should be two numbers joined with a \"-\"." - (if (string-match "\\(.*\\)-\\(.*\\)" s) - (list (string-to-number (match-string 1 s)) - (string-to-number(match-string 2 s))) - (list (string-to-number s) (string-to-number s)))) + (org-columns-top-level-marker (make-marker))) + (dolist (f files) + (let ((b (find-buffer-visiting f))) + (with-current-buffer (or (buffer-base-buffer b) b) + (org-with-wide-buffer + (org-with-silent-modifications + (remove-text-properties (point-min) (point-max) '(org-summaries t))) + (goto-char (point-min)) + (org-columns-get-format-and-top-level) + (dolist (spec fmt) + (let ((prop (car spec))) + (cond + ((equal prop "CLOCKSUM") (org-clock-sum)) + ((equal prop "CLOCKSUM_T") (org-clock-sum-today)) + ((and (nth 3 spec) + (let ((a (assoc prop org-columns-current-fmt-compiled))) + (equal (nth 3 a) (nth 3 spec)))) + (org-columns-compute prop))))))))))) + (provide 'org-colview) diff --git a/lisp/org/org-compat.el b/lisp/org/org-compat.el index 42e2271c076..e1d40369f19 100644 --- a/lisp/org/org-compat.el +++ b/lisp/org/org-compat.el @@ -1,4 +1,4 @@ -;;; org-compat.el --- Compatibility code for Org-mode +;;; org-compat.el --- Compatibility Code for Older Emacsen -*- lexical-binding: t; -*- ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. @@ -24,65 +24,287 @@ ;; ;;; Commentary: -;; This file contains code needed for compatibility with XEmacs and older +;; This file contains code needed for compatibility with older ;; versions of GNU Emacs. ;;; Code: -(eval-when-compile - (require 'cl)) - +(require 'cl-lib) (require 'org-macs) -;; The following constant is for backward compatibility. We do not use -;; it in org-mode, because the Byte compiler evaluates (featurep 'xemacs) -;; at compilation time and can therefore optimize code better. -(defconst org-xemacs-p (featurep 'xemacs)) -(defconst org-format-transports-properties-p - (let ((x "a")) - (add-text-properties 0 1 '(test t) x) - (get-text-property 0 'test (format "%s" x))) - "Does format transport text properties?") +(declare-function org-at-table.el-p "org" (&optional table-type)) +(declare-function org-element-at-point "org-element" ()) +(declare-function org-element-type "org-element" (element)) +(declare-function org-link-set-parameters "org" (type &rest rest)) +(declare-function org-table-end (&optional table-type)) +(declare-function table--at-cell-p "table" (position &optional object at-column)) + +(defvar org-table-any-border-regexp) +(defvar org-table-dataline-regexp) +(defvar org-table-tab-recognizes-table.el) +(defvar org-table1-hline-regexp) + +;; As of Emacs 25.1, `outline-mode' functions are under the 'outline-' +;; prefix, `find-tag' is replaced with `xref-find-definition' and +;; `x-get-selection' with `gui-get-selection'. +(when (< emacs-major-version 25) + (defalias 'outline-hide-entry 'hide-entry) + (defalias 'outline-hide-sublevels 'hide-sublevels) + (defalias 'outline-hide-subtree 'hide-subtree) + (defalias 'outline-show-all 'show-all) + (defalias 'outline-show-branches 'show-branches) + (defalias 'outline-show-children 'show-children) + (defalias 'outline-show-entry 'show-entry) + (defalias 'outline-show-subtree 'show-subtree) + (defalias 'xref-find-definitions 'find-tag) + (defalias 'format-message 'format) + (defalias 'gui-get-selection 'x-get-selection)) + + +;;; Obsolete aliases (remove them after the next major release). + +;;;; XEmacs compatibility, now removed. +(define-obsolete-function-alias 'org-activate-mark 'activate-mark) +(define-obsolete-function-alias 'org-add-hook 'add-hook "Org 9.0") +(define-obsolete-function-alias 'org-bound-and-true-p 'bound-and-true-p "Org 9.0") +(define-obsolete-function-alias 'org-decompose-region 'decompose-region "Org 9.0") +(define-obsolete-function-alias 'org-defvaralias 'defvaralias "Org 9.0") +(define-obsolete-function-alias 'org-detach-overlay 'delete-overlay "Org 9.0") +(define-obsolete-function-alias 'org-file-equal-p 'file-equal-p "Org 9.0") +(define-obsolete-function-alias 'org-float-time 'float-time "Org 9.0") +(define-obsolete-function-alias 'org-indent-line-to 'indent-line-to "Org 9.0") +(define-obsolete-function-alias 'org-indent-to-column 'indent-to-column "Org 9.0") +(define-obsolete-function-alias 'org-looking-at-p 'looking-at-p "Org 9.0") +(define-obsolete-function-alias 'org-looking-back 'looking-back "Org 9.0") +(define-obsolete-function-alias 'org-match-string-no-properties 'match-string-no-properties "Org 9.0") +(define-obsolete-function-alias 'org-propertize 'propertize "Org 9.0") +(define-obsolete-function-alias 'org-select-frame-set-input-focus 'select-frame-set-input-focus "Org 9.0") + +(defmacro org-re (s) + "Replace posix classes in regular expression S." + (declare (debug (form)) + (obsolete "you can safely remove it." "Org 9.0")) + s) + +;;;; Functions from cl-lib that Org used to have its own implementation of. +(define-obsolete-function-alias 'org-count 'cl-count "Org 9.0") +(define-obsolete-function-alias 'org-every 'cl-every "Org 9.0") +(define-obsolete-function-alias 'org-find-if 'cl-find-if "Org 9.0") +(define-obsolete-function-alias 'org-reduce 'cl-reduce "Org 9.0") +(define-obsolete-function-alias 'org-remove-if 'cl-remove-if "Org 9.0") +(define-obsolete-function-alias 'org-remove-if-not 'cl-remove-if-not "Org 9.0") +(define-obsolete-function-alias 'org-some 'cl-some "Org 9.0") +(define-obsolete-function-alias 'org-floor* 'cl-floor "Org 9.0") + +(defun org-sublist (list start end) + "Return a section of LIST, from START to END. +Counting starts at 1." + (cl-subseq list (1- start) end)) +(make-obsolete 'org-sublist + "use cl-subseq (note the 0-based counting)." + "Org 9.0") + + +;;;; Functions available since Emacs 24.3 +(define-obsolete-function-alias 'org-buffer-narrowed-p 'buffer-narrowed-p "Org 9.0") +(define-obsolete-function-alias 'org-called-interactively-p 'called-interactively-p "Org 9.0") +(define-obsolete-function-alias 'org-char-to-string 'char-to-string "Org 9.0") +(define-obsolete-function-alias 'org-delete-directory 'delete-directory "Org 9.0") +(define-obsolete-function-alias 'org-format-seconds 'format-seconds "Org 9.0") +(define-obsolete-function-alias 'org-link-escape-browser 'url-encode-url "Org 9.0") +(define-obsolete-function-alias 'org-no-warnings 'with-no-warnings "Org 9.0") +(define-obsolete-function-alias 'org-number-sequence 'number-sequence "Org 9.0") +(define-obsolete-function-alias 'org-pop-to-buffer-same-window 'pop-to-buffer-same-window "Org 9.0") +(define-obsolete-function-alias 'org-string-match-p 'string-match-p "Org 9.0") + +;;;; Functions and variables from previous releases now obsolete. +(define-obsolete-function-alias 'org-element-remove-indentation + 'org-remove-indentation "Org 9.0") +(define-obsolete-variable-alias 'org-hierarchical-checkbox-statistics + 'org-checkbox-hierarchical-statistics "Org 8.0") +(define-obsolete-variable-alias 'org-description-max-indent + 'org-list-description-max-indent "Org 8.0") +(define-obsolete-variable-alias 'org-latex-create-formula-image-program + 'org-preview-latex-default-process "Org 9.0") +(define-obsolete-variable-alias 'org-latex-preview-ltxpng-directory + 'org-preview-latex-image-directory "Org 9.0") +(define-obsolete-function-alias 'org-table-p 'org-at-table-p "Org 9.0") +(define-obsolete-function-alias 'org-on-heading-p 'org-at-heading-p "Org 9.0") +(define-obsolete-function-alias 'org-at-regexp-p 'org-in-regexp "Org 8.3") +(define-obsolete-function-alias 'org-speed-command-default-hook + 'org-speed-command-activate "Org 8.0") +(define-obsolete-function-alias 'org-babel-speed-command-hook + 'org-babel-speed-command-activate "Org 8.0") +(define-obsolete-function-alias 'org-image-file-name-regexp + 'image-file-name-regexp "Org 9.0") +(define-obsolete-function-alias 'org-get-legal-level + 'org-get-valid-level "Org 7.8") +(define-obsolete-function-alias 'org-completing-read-no-i + 'completing-read "Org 9.0") +(define-obsolete-function-alias 'org-icompleting-read + 'completing-read "Org 9.0") +(define-obsolete-function-alias 'org-iread-file-name 'read-file-name "Org 9.0") +(define-obsolete-function-alias 'org-days-to-time + 'org-time-stamp-to-now "Org 8.2") +(define-obsolete-variable-alias 'org-agenda-ignore-drawer-properties + 'org-agenda-ignore-properties "Org 9.0") +(define-obsolete-function-alias 'org-preview-latex-fragment + 'org-toggle-latex-fragment "Org 8.3") +(define-obsolete-function-alias 'org-display-inline-modification-hook + 'org-display-inline-remove-overlay "Org 8.0") +(define-obsolete-function-alias 'org-export-get-genealogy + 'org-element-lineage "Org 9.0") +(define-obsolete-variable-alias 'org-latex-with-hyperref + 'org-latex-hyperref-template "Org 9.0") +(define-obsolete-variable-alias 'org-link-to-org-use-id + 'org-id-link-to-org-use-id "Org 8.0") +(define-obsolete-variable-alias 'hfy-optimisations 'hfy-optimizations "Org 9.0") +(define-obsolete-variable-alias 'org-clock-modeline-total + 'org-clock-mode-line-total "Org 8.0") +(define-obsolete-function-alias 'org-protocol-unhex-compound + 'org-link-unescape-compound "Org 7.8") +(define-obsolete-function-alias 'org-protocol-unhex-string + 'org-link-unescape "Org 7.8") +(define-obsolete-function-alias 'org-protocol-unhex-single-byte-sequence + 'org-link-unescape-single-byte-sequence "Org 7.8") +(define-obsolete-variable-alias 'org-export-htmlized-org-css-url + 'org-org-htmlized-css-url "Org 8.2") +(define-obsolete-variable-alias 'org-alphabetical-lists + 'org-list-allow-alphabetical "Org 8.0") +(define-obsolete-function-alias 'org-list-parse-list 'org-list-to-lisp "Org 9.0") +(define-obsolete-variable-alias 'org-agenda-menu-two-column + 'org-agenda-menu-two-columns "Org 8.0") +(define-obsolete-variable-alias 'org-finalize-agenda-hook + 'org-agenda-finalize-hook "Org 8.0") +(make-obsolete-variable 'org-agenda-ndays 'org-agenda-span "Org 7.8") +(define-obsolete-function-alias 'org-agenda-post-command-hook + 'org-agenda-update-agenda-type "Org 8.0") +(define-obsolete-function-alias 'org-agenda-todayp + 'org-agenda-today-p "Org 9.0") +(define-obsolete-function-alias 'org-babel-examplize-region + 'org-babel-examplify-region "Org 9.0") +(define-obsolete-function-alias 'org-babel-trim 'org-trim "Org 9.0") +(define-obsolete-variable-alias 'org-html-style-include-scripts + 'org-html-head-include-scripts "Org 8.0") +(define-obsolete-variable-alias 'org-html-style-include-default + 'org-html-head-include-default-style "Org 8.0") +(define-obsolete-variable-alias 'org-html-style 'org-html-head "24.4") +(define-obsolete-function-alias 'org-insert-columns-dblock + 'org-columns-insert-dblock "Org 9.0") +(define-obsolete-function-alias 'org-activate-bracket-links + 'org-activate-links "Org 9.0") +(define-obsolete-function-alias 'org-activate-plain-links 'ignore "Org 9.0") +(define-obsolete-function-alias 'org-activate-angle-links 'ignore "Org 9.0") + +(defun org-in-fixed-width-region-p () + "Non-nil if point in a fixed-width region." + (save-match-data + (eq 'fixed-width (org-element-type (org-element-at-point))))) +(make-obsolete 'org-in-fixed-width-region-p + "use `org-element' library" + "Org 9.0") + +(defcustom org-read-date-minibuffer-setup-hook nil + "Hook to be used to set up keys for the date/time interface. +Add key definitions to `minibuffer-local-map', which will be a +temporary copy." + :group 'org-time + :type 'hook) +(make-obsolete-variable + 'org-read-date-minibuffer-setup-hook + "set `org-read-date-minibuffer-local-map' instead." "Org 8.0") (defun org-compatible-face (inherits specs) "Make a compatible face specification. -If INHERITS is an existing face and if the Emacs version supports it, -just inherit the face. If INHERITS is set and the Emacs version does -not support it, copy the face specification from the inheritance face. -If INHERITS is not given and SPECS is, use SPECS to define the face. -XEmacs and Emacs 21 do not know about the `min-colors' attribute. -For them we convert a (min-colors 8) entry to a `tty' entry and move it -to the top of the list. The `min-colors' attribute will be removed from -any other entries, and any resulting duplicates will be removed entirely." - (when (and inherits (facep inherits) (not specs)) - (setq specs (or specs - (get inherits 'saved-face) - (get inherits 'face-defface-spec)))) - (cond - ((and inherits (facep inherits) - (not (featurep 'xemacs)) - (>= emacs-major-version 22) - ;; do not inherit outline faces before Emacs 23 - (or (>= emacs-major-version 23) - (not (string-match "\\`outline-[0-9]+" - (symbol-name inherits))))) - (list (list t :inherit inherits))) - ((or (featurep 'xemacs) (< emacs-major-version 22)) - ;; These do not understand the `min-colors' attribute. - (let (r e a) - (while (setq e (pop specs)) - (cond - ((memq (car e) '(t default)) (push e r)) - ((setq a (member '(min-colors 8) (car e))) - (nconc r (list (cons (cons '(type tty) (delq (car a) (car e))) - (cdr e))))) - ((setq a (assq 'min-colors (car e))) - (setq e (cons (delq a (car e)) (cdr e))) - (or (assoc (car e) r) (push e r))) - (t (or (assoc (car e) r) (push e r))))) - (nreverse r))) - (t specs))) -(put 'org-compatible-face 'lisp-indent-function 1) +If INHERITS is an existing face and if the Emacs version supports +it, just inherit the face. If INHERITS is not given and SPECS +is, use SPECS to define the face." + (declare (indent 1)) + (if (facep inherits) + (list (list t :inherit inherits)) + specs)) +(make-obsolete 'org-compatible-face "you can remove it." "Org 9.0") + +(defun org-add-link-type (type &optional follow export) + "Add a new TYPE link. +FOLLOW and EXPORT are two functions. + +FOLLOW should take the link path as the single argument and do whatever +is necessary to follow the link, for example find a file or display +a mail message. + +EXPORT should format the link path for export to one of the export formats. +It should be a function accepting three arguments: + + path the path of the link, the text after the prefix (like \"http:\") + desc the description of the link, if any + format the export format, a symbol like `html' or `latex' or `ascii'. + +The function may use the FORMAT information to return different values +depending on the format. The return value will be put literally into +the exported file. If the return value is nil, this means Org should +do what it normally does with links which do not have EXPORT defined. + +Org mode has a built-in default for exporting links. If you are happy with +this default, there is no need to define an export function for the link +type. For a simple example of an export function, see `org-bbdb.el'. + +If TYPE already exists, update it with the arguments. +See `org-link-parameters' for documentation on the other parameters." + (org-link-set-parameters type :follow follow :export export) + (message "Created %s link." type)) + +(make-obsolete 'org-add-link-type "use `org-link-set-parameters' instead." "Org 9.0") + +(defun org-table-recognize-table.el () + "If there is a table.el table nearby, recognize it and move into it." + (when (and org-table-tab-recognizes-table.el (org-at-table.el-p)) + (beginning-of-line) + (unless (or (looking-at org-table-dataline-regexp) + (not (looking-at org-table1-hline-regexp))) + (forward-line) + (when (looking-at org-table-any-border-regexp) + (forward-line -2))) + (if (re-search-forward "|" (org-table-end t) t) + (progn + (require 'table) + (if (table--at-cell-p (point)) t + (message "recognizing table.el table...") + (table-recognize-table) + (message "recognizing table.el table...done"))) + (error "This should not happen")))) + +;; Not used by Org core since commit 6d1e3082, Feb 2010. +(make-obsolete 'org-table-recognize-table.el + "please notify the org mailing list if you use this function." + "Org 9.0") + +(define-obsolete-function-alias + 'org-minutes-to-hh:mm-string 'org-minutes-to-clocksum-string "Org 8.0") + +(defun org-remove-angle-brackets (s) + (org-unbracket-string "<" ">" s)) +(make-obsolete 'org-remove-angle-brackets 'org-unbracket-string "Org 9.0") + +(defun org-remove-double-quotes (s) + (org-unbracket-string "\"" "\"" s)) +(make-obsolete 'org-remove-double-quotes 'org-unbracket-string "Org 9.0") + +(define-obsolete-function-alias 'org-babel-number-p + 'org-babel--string-to-number "Org 9.0") + + + +;;;; Obsolete link types + +(eval-after-load 'org + '(progn + (org-link-set-parameters "file+emacs") ;since Org 9.0 + (org-link-set-parameters "file+sys"))) ;since Org 9.0 + + + +;;; Miscellaneous functions (defun org-version-check (version feature level) (let* ((v1 (mapcar 'string-to-number (split-string version "[.]"))) @@ -108,110 +330,19 @@ any other entries, and any resulting duplicates will be removed entirely." t)) t))) - -;;;; Emacs/XEmacs compatibility - -(eval-and-compile - (defun org-defvaralias (new-alias base-variable &optional docstring) - "Compatibility function for defvaralias. -Don't do the aliasing when `defvaralias' is not bound." - (declare (indent 1)) - (when (fboundp 'defvaralias) - (defvaralias new-alias base-variable docstring))) - - (when (and (not (boundp 'user-emacs-directory)) - (boundp 'user-init-directory)) - (org-defvaralias 'user-emacs-directory 'user-init-directory))) - -(when (featurep 'xemacs) - (defadvice custom-handle-keyword - (around org-custom-handle-keyword - activate preactivate) - "Remove custom keywords not recognized to avoid producing an error." - (cond - ((eq (ad-get-arg 1) :package-version)) - (t ad-do-it))) - (defadvice define-obsolete-variable-alias - (around org-define-obsolete-variable-alias - (obsolete-name current-name &optional when docstring) - activate preactivate) - "Declare arguments defined in later versions of Emacs." - ad-do-it) - (defadvice define-obsolete-function-alias - (around org-define-obsolete-function-alias - (obsolete-name current-name &optional when docstring) - activate preactivate) - "Declare arguments defined in later versions of Emacs." - ad-do-it) - (defvar customize-package-emacs-version-alist nil) - (defvar temporary-file-directory (temp-directory))) - -;; Keys -(defconst org-xemacs-key-equivalents - '(([mouse-1] . [button1]) - ([mouse-2] . [button2]) - ([mouse-3] . [button3]) - ([C-mouse-4] . [(control mouse-4)]) - ([C-mouse-5] . [(control mouse-5)])) - "Translation alist for a couple of keys.") - -;; Overlay compatibility functions -(defun org-detach-overlay (ovl) - (if (featurep 'xemacs) (detach-extent ovl) (delete-overlay ovl))) -(defun org-overlay-display (ovl text &optional face evap) - "Make overlay OVL display TEXT with face FACE." - (if (featurep 'xemacs) - (let ((gl (make-glyph text))) - (and face (set-glyph-face gl face)) - (set-extent-property ovl 'invisible t) - (set-extent-property ovl 'end-glyph gl)) - (overlay-put ovl 'display text) - (if face (overlay-put ovl 'face face)) - (if evap (overlay-put ovl 'evaporate t)))) -(defun org-overlay-before-string (ovl text &optional face evap) - "Make overlay OVL display TEXT with face FACE." - (if (featurep 'xemacs) - (let ((gl (make-glyph text))) - (and face (set-glyph-face gl face)) - (set-extent-property ovl 'begin-glyph gl)) - (if face (org-add-props text nil 'face face)) - (overlay-put ovl 'before-string text) - (if evap (overlay-put ovl 'evaporate t)))) -(defun org-find-overlays (prop &optional pos delete) - "Find all overlays specifying PROP at POS or point. -If DELETE is non-nil, delete all those overlays." - (let ((overlays (overlays-at (or pos (point)))) - ov found) - (while (setq ov (pop overlays)) - (if (overlay-get ov prop) - (if delete (delete-overlay ov) (push ov found)))) - found)) - (defun org-get-x-clipboard (value) - "Get the value of the x or Windows clipboard, compatible with XEmacs, and GNU Emacs 21." - (cond ((eq window-system 'x) - (let ((x (org-get-x-clipboard-compat value))) - (if x (org-no-properties x)))) + "Get the value of the X or Windows clipboard." + (cond ((and (eq window-system 'x) + (fboundp 'gui-get-selection)) ;Silence byte-compiler. + (org-no-properties + (ignore-errors + (or (gui-get-selection value 'UTF8_STRING) + (gui-get-selection value 'COMPOUND_TEXT) + (gui-get-selection value 'STRING) + (gui-get-selection value 'TEXT))))) ((and (eq window-system 'w32) (fboundp 'w32-get-clipboard-data)) (w32-get-clipboard-data)))) -(defsubst org-decompose-region (beg end) - "Decompose from BEG to END." - (if (featurep 'xemacs) - (let ((modified-p (buffer-modified-p)) - (buffer-read-only nil)) - (remove-text-properties beg end '(composition nil)) - (set-buffer-modified-p modified-p)) - (decompose-region beg end))) - -;; Miscellaneous functions - -(defun org-add-hook (hook function &optional append local) - "Add-hook, compatible with both Emacsen." - (if (and local (featurep 'xemacs)) - (add-local-hook hook function append) - (add-hook hook function append local))) - (defun org-add-props (string plist &rest props) "Add text properties to entire string, from beginning to end. PLIST may be a list of properties, PROPS are individual properties and values @@ -238,66 +369,29 @@ ignored in this case." (shrink-window-if-larger-than-buffer window))) (or window (selected-window))) -(defun org-number-sequence (from &optional to inc) - "Call `number-sequence' or emulate it." - (if (fboundp 'number-sequence) - (number-sequence from to inc) - (if (or (not to) (= from to)) - (list from) - (or inc (setq inc 1)) - (when (zerop inc) (error "The increment can not be zero")) - (let (seq (n 0) (next from)) - (if (> inc 0) - (while (<= next to) - (setq seq (cons next seq) - n (1+ n) - next (+ from (* n inc)))) - (while (>= next to) - (setq seq (cons next seq) - n (1+ n) - next (+ from (* n inc))))) - (nreverse seq))))) - ;; `set-transient-map' is only in Emacs >= 24.4 (defalias 'org-set-transient-map (if (fboundp 'set-transient-map) 'set-transient-map 'set-temporary-overlay-map)) -;; Region compatibility +;;; Region compatibility (defvar org-ignore-region nil "Non-nil means temporarily disable the active region.") (defun org-region-active-p () - "Is `transient-mark-mode' on and the region active? -Works on both Emacs and XEmacs." - (if org-ignore-region - nil - (if (featurep 'xemacs) - (and zmacs-regions (region-active-p)) - (if (fboundp 'use-region-p) - (use-region-p) - (and transient-mark-mode mark-active))))) ; Emacs 22 and before + "Non-nil when the region active. +Unlike to `use-region-p', this function also checks +`org-ignore-region'." + (and (not org-ignore-region) (use-region-p))) (defun org-cursor-to-region-beginning () (when (and (org-region-active-p) (> (point) (region-beginning))) (exchange-point-and-mark))) -;; Emacs 22 misses `activate-mark' -(if (fboundp 'activate-mark) - (defalias 'org-activate-mark 'activate-mark) - (defun org-activate-mark () - (when (mark t) - (setq mark-active t) - (when (and (boundp 'transient-mark-mode) - (not transient-mark-mode)) - (set (make-local-variable 'transient-mark-mode) 'lambda)) - (when (boundp 'zmacs-regions) - (setq zmacs-regions t))))) - -;; Invisibility compatibility +;;; Invisibility compatibility (defun org-remove-from-invisibility-spec (arg) "Remove elements from `buffer-invisibility-spec'." @@ -312,63 +406,14 @@ Works on both Emacs and XEmacs." (if (consp buffer-invisibility-spec) (member arg buffer-invisibility-spec))) -(defmacro org-xemacs-without-invisibility (&rest body) - "Turn off extents with invisibility while executing BODY." - `(let ((ext-inv (extent-list nil (point-at-bol) (point-at-eol) - 'all-extents-closed-open 'invisible)) - ext-inv-specs) - (dolist (ext ext-inv) - (when (extent-property ext 'invisible) - (add-to-list 'ext-inv-specs (list ext (extent-property - ext 'invisible))) - (set-extent-property ext 'invisible nil))) - ,@body - (dolist (ext-inv-spec ext-inv-specs) - (set-extent-property (car ext-inv-spec) 'invisible - (cadr ext-inv-spec))))) -(def-edebug-spec org-xemacs-without-invisibility (body)) - -(defun org-indent-to-column (column &optional minimum buffer) - "Work around a bug with extents with invisibility in XEmacs." - (if (featurep 'xemacs) - (org-xemacs-without-invisibility (indent-to-column column minimum buffer)) - (indent-to-column column minimum))) - -(defun org-indent-line-to (column) - "Work around a bug with extents with invisibility in XEmacs." - (if (featurep 'xemacs) - (org-xemacs-without-invisibility (indent-line-to column)) - (indent-line-to column))) - -(defun org-move-to-column (column &optional force buffer) +(defun org-move-to-column (column &optional force _buffer) "Move to column COLUMN. -Pass COLUMN and FORCE to `move-to-column'. -Pass BUFFER to the XEmacs version of `move-to-column'." +Pass COLUMN and FORCE to `move-to-column'." (let ((buffer-invisibility-spec - (remove '(org-filtered) buffer-invisibility-spec))) - (if (featurep 'xemacs) - (org-xemacs-without-invisibility - (move-to-column column force buffer)) - (move-to-column column force)))) - -(defun org-get-x-clipboard-compat (value) - "Get the clipboard value on XEmacs or Emacs 21." - (cond ((featurep 'xemacs) - (org-no-warnings (get-selection-no-error value))) - ((fboundp 'x-get-selection) - (condition-case nil - (or (x-get-selection value 'UTF8_STRING) - (x-get-selection value 'COMPOUND_TEXT) - (x-get-selection value 'STRING) - (x-get-selection value 'TEXT)) - (error nil))))) - -(defun org-propertize (string &rest properties) - (if (featurep 'xemacs) - (progn - (add-text-properties 0 (length string) properties string) - string) - (apply 'propertize string properties))) + (if (listp buffer-invisibility-spec) + (remove '(org-filtered) buffer-invisibility-spec) + buffer-invisibility-spec))) + (move-to-column column force))) (defmacro org-find-library-dir (library) `(file-name-directory (or (locate-library ,library) ""))) @@ -387,37 +432,20 @@ Pass BUFFER to the XEmacs version of `move-to-column'." string) (apply 'kill-new string args)) -(defun org-select-frame-set-input-focus (frame) - "Select FRAME, raise it, and set input focus, if possible." - (cond ((featurep 'xemacs) - (if (fboundp 'select-frame-set-input-focus) - (select-frame-set-input-focus frame) - (raise-frame frame) - (select-frame frame) - (focus-frame frame))) - ;; `select-frame-set-input-focus' defined in Emacs 21 will not - ;; set the input focus. - ((>= emacs-major-version 22) - (select-frame-set-input-focus frame)) - (t - (raise-frame frame) - (select-frame frame) - (cond ((memq window-system '(x ns mac)) - (x-focus-frame frame)) - ((eq window-system 'w32) - (w32-focus-frame frame))) - (when focus-follows-mouse - (set-mouse-position frame (1- (frame-width frame)) 0))))) - -(define-obsolete-function-alias 'org-float-time 'float-time "26.1") - -;; `user-error' is only available from 24.3 on -(unless (fboundp 'user-error) - (defalias 'user-error 'error)) - -;; ‘format-message’ is available only from 25 on -(unless (fboundp 'format-message) - (defalias 'format-message 'format)) +;; `font-lock-ensure' is only available from 24.4.50 on +(defalias 'org-font-lock-ensure + (if (fboundp 'font-lock-ensure) + #'font-lock-ensure + (lambda (&optional _beg _end) + (with-no-warnings (font-lock-fontify-buffer))))) + +;; `file-local-name' was added in Emacs 26.1. +(defalias 'org-babel-local-file-name + (if (fboundp 'file-local-name) + 'file-local-name + (lambda (file) + "Return the local name component of FILE." + (or (file-remote-p file 'localname) file)))) (defmacro org-no-popups (&rest body) "Suppress popup windows. @@ -429,93 +457,6 @@ effect, which variables to use depends on the Emacs version." `(let (pop-up-frames special-display-buffer-names special-display-regexps special-display-function) ,@body))) -(if (fboundp 'string-match-p) - (defalias 'org-string-match-p 'string-match-p) - (defun org-string-match-p (regexp string &optional start) - (save-match-data - (funcall 'string-match regexp string start)))) - -(if (fboundp 'looking-at-p) - (defalias 'org-looking-at-p 'looking-at-p) - (defun org-looking-at-p (&rest args) - (save-match-data - (apply 'looking-at args)))) - -;; XEmacs does not have `looking-back'. -(if (fboundp 'looking-back) - (defalias 'org-looking-back 'looking-back) - (defun org-looking-back (regexp &optional limit greedy) - "Return non-nil if text before point matches regular expression REGEXP. -Like `looking-at' except matches before point, and is slower. -LIMIT if non-nil speeds up the search by specifying a minimum -starting position, to avoid checking matches that would start -before LIMIT. - -If GREEDY is non-nil, extend the match backwards as far as -possible, stopping when a single additional previous character -cannot be part of a match for REGEXP. When the match is -extended, its starting position is allowed to occur before -LIMIT." - (let ((start (point)) - (pos - (save-excursion - (and (re-search-backward (concat "\\(?:" regexp "\\)\\=") limit t) - (point))))) - (if (and greedy pos) - (save-restriction - (narrow-to-region (point-min) start) - (while (and (> pos (point-min)) - (save-excursion - (goto-char pos) - (backward-char 1) - (looking-at (concat "\\(?:" regexp "\\)\\'")))) - (setq pos (1- pos))) - (save-excursion - (goto-char pos) - (looking-at (concat "\\(?:" regexp "\\)\\'"))))) - (not (null pos))))) - -(defalias 'org-font-lock-ensure - (if (fboundp 'font-lock-ensure) - #'font-lock-ensure - (lambda (&optional _beg _end) (font-lock-fontify-buffer)))) - -(defun org-floor* (x &optional y) - "Return a list of the floor of X and the fractional part of X. -With two arguments, return floor and remainder of their quotient." - (let ((q (floor x y))) - (list q (- x (if y (* y q) q))))) - -;; `pop-to-buffer-same-window' has been introduced in Emacs 24.1. -(defun org-pop-to-buffer-same-window - (&optional buffer-or-name norecord label) - "Pop to buffer specified by BUFFER-OR-NAME in the selected window." - (if (fboundp 'pop-to-buffer-same-window) - (funcall - 'pop-to-buffer-same-window buffer-or-name norecord) - (funcall 'switch-to-buffer buffer-or-name norecord))) - -;; RECURSIVE has been introduced with Emacs 23.2. -;; This is copying and adapted from `tramp-compat-delete-directory' -(defun org-delete-directory (directory &optional recursive) - "Compatibility function for `delete-directory'." - (if (null recursive) - (delete-directory directory) - (condition-case nil - (funcall 'delete-directory directory recursive) - ;; This Emacs version does not support the RECURSIVE flag. We - ;; use the implementation from Emacs 23.2. - (wrong-number-of-arguments - (setq directory (directory-file-name (expand-file-name directory))) - (if (not (file-symlink-p directory)) - (mapc (lambda (file) - (if (eq t (car (file-attributes file))) - (org-delete-directory file recursive) - (delete-file file))) - (directory-files - directory 'full "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"))) - (delete-directory directory))))) - ;;;###autoload (defmacro org-check-version () "Try very hard to provide sensible version strings." @@ -534,29 +475,33 @@ With two arguments, return floor and remainder of their quotient." (defun org-release () "N/A") (defun org-git-version () "N/A !!check installation!!")))))) -(defun org-file-equal-p (f1 f2) - "Return t if files F1 and F2 are the same. -Implements `file-equal-p' for older emacsen and XEmacs." - (if (fboundp 'file-equal-p) - (file-equal-p f1 f2) - (let (f1-attr f2-attr) - (and (setq f1-attr (file-attributes (file-truename f1))) - (setq f2-attr (file-attributes (file-truename f2))) - (equal f1-attr f2-attr))))) - -;; `buffer-narrowed-p' is available for Emacs >=24.3 -(defun org-buffer-narrowed-p () - "Compatibility function for `buffer-narrowed-p'." - (if (fboundp 'buffer-narrowed-p) - (buffer-narrowed-p) - (/= (- (point-max) (point-min)) (buffer-size)))) - (defmacro org-with-silent-modifications (&rest body) (if (fboundp 'with-silent-modifications) `(with-silent-modifications ,@body) `(org-unmodified ,@body))) (def-edebug-spec org-with-silent-modifications (body)) +;; Functions for Emacs < 24.4 compatibility +(defun org-define-error (name message) + "Define NAME as a new error signal. +MESSAGE is a string that will be output to the echo area if such +an error is signaled without being caught by a `condition-case'. +Implements `define-error' for older emacsen." + (if (fboundp 'define-error) (define-error name message) + (put name 'error-conditions + (copy-sequence (cons name (get 'error 'error-conditions)))))) + +(unless (fboundp 'string-suffix-p) + ;; From Emacs subr.el. + (defun string-suffix-p (suffix string &optional ignore-case) + "Return non-nil if SUFFIX is a suffix of STRING. +If IGNORE-CASE is non-nil, the comparison is done without paying +attention to case differences." + (let ((start-pos (- (length string) (length suffix)))) + (and (>= start-pos 0) + (eq t (compare-strings suffix nil nil + string start-pos nil ignore-case)))))) + (provide 'org-compat) ;;; org-compat.el ends here diff --git a/lisp/org/org-crypt.el b/lisp/org/org-crypt.el index 36144e25309..3c431e4fddb 100644 --- a/lisp/org/org-crypt.el +++ b/lisp/org/org-crypt.el @@ -1,5 +1,4 @@ -;;; org-crypt.el --- Public key encryption for org-mode entries - +;;; org-crypt.el --- Public Key Encryption for Org Entries -*- lexical-binding: t; -*- ;; Copyright (C) 2007-2017 Free Software Foundation, Inc. ;; Emacs Lisp Archive Entry @@ -7,7 +6,7 @@ ;; Keywords: org-mode ;; Author: John Wiegley ;; Maintainer: Peter Jones -;; Description: Adds public key encryption to org-mode buffers +;; Description: Adds public key encryption to Org buffers ;; URL: http://www.newartisans.com/software/emacs.html ;; Compatibility: Emacs22 @@ -104,10 +103,10 @@ t : Disable auto-save-mode for the current buffer nil : Leave auto-save-mode enabled. This may cause data to be written to disk unencrypted! -'ask : Ask user whether or not to disable auto-save-mode +`ask' : Ask user whether or not to disable auto-save-mode for the current buffer. -'encrypt : Leave auto-save-mode enabled for the current buffer, +`encrypt': Leave auto-save-mode enabled for the current buffer, but automatically re-encrypt all decrypted entries *before* auto-saving. NOTE: This only works for entries which have a tag @@ -142,7 +141,7 @@ See `org-crypt-disable-auto-save'." (message "org-decrypt: Decrypting entry with auto-save-mode enabled. This may cause leakage.")) ((eq org-crypt-disable-auto-save 'encrypt) (message "org-decrypt: Enabling re-encryption on auto-save.") - (org-add-hook 'auto-save-hook + (add-hook 'auto-save-hook (lambda () (message "org-crypt: Re-encrypting all decrypted entries due to auto-save.") (org-encrypt-entries)) @@ -164,96 +163,96 @@ See `org-crypt-disable-auto-save'." (if (and (string= crypt-key (get-text-property 0 'org-crypt-key str)) (string= (sha1 str) (get-text-property 0 'org-crypt-checksum str))) (get-text-property 0 'org-crypt-text str) - (set (make-local-variable 'epg-context) (epg-make-context nil t t)) + (setq-local epg-context (epg-make-context nil t t)) (epg-encrypt-string epg-context str (epg-list-keys epg-context crypt-key)))) (defun org-encrypt-entry () "Encrypt the content of the current headline." (interactive) (require 'epg) - (save-excursion - (org-back-to-heading t) - (set (make-local-variable 'epg-context) (epg-make-context nil t t)) - (let ((start-heading (point))) - (forward-line) - (when (not (looking-at "-----BEGIN PGP MESSAGE-----")) - (let ((folded (outline-invisible-p)) - (crypt-key (org-crypt-key-for-heading)) - (beg (point)) - end encrypted-text) - (goto-char start-heading) - (org-end-of-subtree t t) - (org-back-over-empty-lines) - (setq end (point) - encrypted-text - (org-encrypt-string (buffer-substring beg end) crypt-key)) - (delete-region beg end) - (insert encrypted-text) - (when folded - (goto-char start-heading) - (hide-subtree)) - nil))))) + (org-with-wide-buffer + (org-back-to-heading t) + (setq-local epg-context (epg-make-context nil t t)) + (let ((start-heading (point))) + (org-end-of-meta-data) + (unless (looking-at-p "-----BEGIN PGP MESSAGE-----") + (let ((folded (org-invisible-p)) + (crypt-key (org-crypt-key-for-heading)) + (beg (point))) + (goto-char start-heading) + (org-end-of-subtree t t) + (org-back-over-empty-lines) + (let ((contents (delete-and-extract-region beg (point)))) + (condition-case err + (insert (org-encrypt-string contents crypt-key)) + ;; If encryption failed, make sure to insert back entry + ;; contents in the buffer. + (error (insert contents) (error (nth 1 err))))) + (when folded + (goto-char start-heading) + (outline-hide-subtree)) + nil))))) (defun org-decrypt-entry () "Decrypt the content of the current headline." (interactive) (require 'epg) (unless (org-before-first-heading-p) - (save-excursion - (org-back-to-heading t) - (let ((heading-point (point)) - (heading-was-invisible-p - (save-excursion - (outline-end-of-heading) - (outline-invisible-p)))) - (forward-line) - (when (looking-at "-----BEGIN PGP MESSAGE-----") - (org-crypt-check-auto-save) - (set (make-local-variable 'epg-context) (epg-make-context nil t t)) - (let* ((end (save-excursion - (search-forward "-----END PGP MESSAGE-----") - (forward-line) - (point))) - (encrypted-text (buffer-substring-no-properties (point) end)) - (decrypted-text - (decode-coding-string - (epg-decrypt-string - epg-context - encrypted-text) - 'utf-8))) - ;; Delete region starting just before point, because the - ;; outline property starts at the \n of the heading. - (delete-region (1- (point)) end) - ;; Store a checksum of the decrypted and the encrypted - ;; text value. This allow reusing the same encrypted text - ;; if the text does not change, and therefore avoid a - ;; re-encryption process. - (insert "\n" (propertize decrypted-text - 'org-crypt-checksum (sha1 decrypted-text) - 'org-crypt-key (org-crypt-key-for-heading) - 'org-crypt-text encrypted-text)) - (when heading-was-invisible-p - (goto-char heading-point) - (org-flag-subtree t)) - nil)))))) + (org-with-wide-buffer + (org-back-to-heading t) + (let ((heading-point (point)) + (heading-was-invisible-p + (save-excursion + (outline-end-of-heading) + (org-invisible-p)))) + (org-end-of-meta-data) + (when (looking-at "-----BEGIN PGP MESSAGE-----") + (org-crypt-check-auto-save) + (setq-local epg-context (epg-make-context nil t t)) + (let* ((end (save-excursion + (search-forward "-----END PGP MESSAGE-----") + (forward-line) + (point))) + (encrypted-text (buffer-substring-no-properties (point) end)) + (decrypted-text + (decode-coding-string + (epg-decrypt-string + epg-context + encrypted-text) + 'utf-8))) + ;; Delete region starting just before point, because the + ;; outline property starts at the \n of the heading. + (delete-region (1- (point)) end) + ;; Store a checksum of the decrypted and the encrypted + ;; text value. This allows reusing the same encrypted text + ;; if the text does not change, and therefore avoid a + ;; re-encryption process. + (insert "\n" (propertize decrypted-text + 'org-crypt-checksum (sha1 decrypted-text) + 'org-crypt-key (org-crypt-key-for-heading) + 'org-crypt-text encrypted-text)) + (when heading-was-invisible-p + (goto-char heading-point) + (org-flag-subtree t)) + nil)))))) (defun org-encrypt-entries () "Encrypt all top-level entries in the current buffer." (interactive) - (let (todo-only) + (let ((org--matcher-tags-todo-only nil)) (org-scan-tags 'org-encrypt-entry (cdr (org-make-tags-matcher org-crypt-tag-matcher)) - todo-only))) + org--matcher-tags-todo-only))) (defun org-decrypt-entries () "Decrypt all entries in the current buffer." (interactive) - (let (todo-only) + (let ((org--matcher-tags-todo-only nil)) (org-scan-tags 'org-decrypt-entry (cdr (org-make-tags-matcher org-crypt-tag-matcher)) - todo-only))) + org--matcher-tags-todo-only))) (defun org-at-encrypted-entry-p () "Is the current entry encrypted?" @@ -267,7 +266,7 @@ See `org-crypt-disable-auto-save'." "Add a hook to automatically encrypt entries before a file is saved to disk." (add-hook 'org-mode-hook - (lambda () (org-add-hook 'before-save-hook 'org-encrypt-entries nil t)))) + (lambda () (add-hook 'before-save-hook 'org-encrypt-entries nil t)))) (add-hook 'org-reveal-start-hook 'org-decrypt-entry) diff --git a/lisp/org/org-ctags.el b/lisp/org/org-ctags.el index 1ecf6744821..98eb8068a85 100644 --- a/lisp/org/org-ctags.el +++ b/lisp/org/org-ctags.el @@ -1,4 +1,4 @@ -;;; org-ctags.el - Integrate Emacs "tags" facility with org mode. +;;; org-ctags.el - Integrate Emacs "tags" Facility with Org -*- lexical-binding: t; -*- ;; ;; Copyright (C) 2007-2017 Free Software Foundation, Inc. @@ -26,20 +26,21 @@ ;; Synopsis ;; ======== ;; -;; Allows org-mode to make use of the Emacs `etags' system. Defines tag -;; destinations in org-mode files as any text between <>. This allows the tags-generation program `exuberant ctags' to -;; parse these files and create tag tables that record where these -;; destinations are found. Plain [[links]] in org mode files which do not have -;; <> within the same file will then be interpreted as -;; links to these 'tagged' destinations, allowing seamless navigation between -;; multiple org-mode files. Topics can be created in any org mode file and -;; will always be found by plain links from other files. Other file types -;; recognized by ctags (source code files, latex files, etc) will also be -;; available as destinations for plain links, and similarly, org-mode links -;; will be available as tags from source files. Finally, the function -;; `org-ctags-find-tag-interactive' lets you choose any known tag, using -;; autocompletion, and quickly jump to it. +;; Allows Org mode to make use of the Emacs `etags' system. Defines +;; tag destinations in Org files as any text between <>. This allows the tags-generation program `exuberant +;; ctags' to parse these files and create tag tables that record where +;; these destinations are found. Plain [[links]] in org mode files +;; which do not have <> within the same file +;; will then be interpreted as links to these 'tagged' destinations, +;; allowing seamless navigation between multiple Org files. Topics +;; can be created in any org mode file and will always be found by +;; plain links from other files. Other file types recognized by ctags +;; (source code files, latex files, etc) will also be available as +;; destinations for plain links, and similarly, Org links will be +;; available as tags from source files. Finally, the function +;; `org-ctags-find-tag-interactive' lets you choose any known tag, +;; using autocompletion, and quickly jump to it. ;; ;; Installation ;; ============ @@ -110,8 +111,9 @@ ;; Keeping the TAGS file up to date ;; ================================ ;; -;; Tags mode has no way of knowing that you have created new tags by typing in -;; your org-mode buffer. New tags make it into the TAGS file in 3 ways: +;; Tags mode has no way of knowing that you have created new tags by +;; typing in your Org buffer. New tags make it into the TAGS file in +;; 3 ways: ;; ;; 1. You re-run (org-ctags-create-tags "directory") to rebuild the file. ;; 2. You put the function `org-ctags-ask-rebuild-tags-file-then-find-tag' in @@ -135,12 +137,8 @@ ;;; Code: -(eval-when-compile (require 'cl)) - (require 'org) -(declare-function org-pop-to-buffer-same-window "org-compat" (&optional buffer-or-name norecord label)) - (defgroup org-ctags nil "Options concerning use of ctags within org mode." :tag "Org-Ctags" @@ -151,7 +149,7 @@ (defvar org-ctags-tag-regexp "/<<([^>]+)>>/\\1/d,definition/" "Regexp expression used by ctags external program. -The regexp matches tag destinations in org-mode files. +The regexp matches tag destinations in Org files. Format is: /REGEXP/TAGNAME/FLAGS,TAGTYPE/ See the ctags documentation for more information.") @@ -210,8 +208,8 @@ The following patterns are replaced in the string: (defadvice visit-tags-table (after org-ctags-load-tag-list activate compile) (when (and org-ctags-enabled-p tags-file-name) - (set (make-local-variable 'org-ctags-tag-list) - (org-ctags-all-tags-in-current-tags-table)))) + (setq-local org-ctags-tag-list + (org-ctags-all-tags-in-current-tags-table)))) (defun org-ctags-enable () @@ -273,11 +271,6 @@ Return the list." (replace-regexp-in-string (regexp-quote search) replace string t t)) -(defun y-or-n-minibuffer (prompt) - (let ((use-dialog-box nil)) - (y-or-n-p prompt))) - - ;;; Internal functions ======================================================= @@ -285,29 +278,28 @@ Return the list." "Visit or create a file called `NAME.org', and insert a new topic. The new topic will be titled NAME (or TITLE if supplied)." (interactive "sFile name: ") - (let ((filename (substitute-in-file-name (expand-file-name name)))) - (condition-case v - (progn - (org-open-file name t) - (message "Opened file OK") - (goto-char (point-max)) - (insert (org-ctags-string-search-and-replace - "%t" (capitalize (or title name)) - org-ctags-new-topic-template)) - (message "Inserted new file text OK") - (org-mode-restart)) - (error (error "Error %S in org-ctags-open-file" v))))) + (condition-case v + (progn + (org-open-file name t) + (message "Opened file OK") + (goto-char (point-max)) + (insert (org-ctags-string-search-and-replace + "%t" (capitalize (or title name)) + org-ctags-new-topic-template)) + (message "Inserted new file text OK") + (org-mode-restart)) + (error (error "Error %S in org-ctags-open-file" v)))) ;;;; Misc interoperability with etags system ================================= -(defadvice find-tag (before org-ctags-set-org-mark-before-finding-tag - activate compile) +(defadvice xref-find-definitions + (before org-ctags-set-org-mark-before-finding-tag activate compile) "Before trying to find a tag, save our current position on org mark ring." (save-excursion - (if (and (derived-mode-p 'org-mode) org-ctags-enabled-p) - (org-mark-ring-push)))) + (when (and (derived-mode-p 'org-mode) org-ctags-enabled-p) + (org-mark-ring-push)))) @@ -359,7 +351,7 @@ visit the file and location where the tag is found." (old-pnt (point-marker)) (old-mark (copy-marker (mark-marker)))) (condition-case nil - (progn (find-tag name) + (progn (xref-find-definitions name) t) (error ;; only restore old location if find-tag raises error @@ -386,7 +378,7 @@ the new file." (cond ((get-buffer (concat name ".org")) ;; Buffer is already open - (org-pop-to-buffer-same-window (get-buffer (concat name ".org")))) + (pop-to-buffer-same-window (get-buffer (concat name ".org")))) ((file-exists-p filename) ;; File exists but is not open --> open it (message "Opening existing org file `%S'..." @@ -421,7 +413,6 @@ the heading a destination for the tag `NAME'." (insert (org-ctags-string-search-and-replace "%t" (capitalize name) org-ctags-new-topic-template)) (backward-char 4) - (org-update-radio-target-regexp) (end-of-line) (forward-line 2) (when narrowp @@ -464,10 +455,10 @@ Wrapper for org-ctags-rebuild-tags-file-then-find-tag." nil)) -(defun org-ctags-fail-silently (name) +(defun org-ctags-fail-silently (_name) "This function is intended to be used in ORG-OPEN-LINK-FUNCTIONS. -Put as the last function in the list if you want to prevent org's default -behavior of free text search." +Put as the last function in the list if you want to prevent Org's +default behavior of free text search." t) @@ -484,7 +475,7 @@ end up in one file, called TAGS, located in the directory. This function may take several seconds to finish if the directory or its subdirectories contain large numbers of taggable files." (interactive) - (assert (buffer-file-name)) + (cl-assert (buffer-file-name)) (let ((dir-name (or directory-name (file-name-directory (buffer-file-name)))) (exitcode nil)) @@ -499,8 +490,8 @@ its subdirectories contain large numbers of taggable files." (expand-file-name (concat dir-name "/*"))))) (cond ((eql 0 exitcode) - (set (make-local-variable 'org-ctags-tag-list) - (org-ctags-all-tags-in-current-tags-table))) + (setq-local org-ctags-tag-list + (org-ctags-all-tags-in-current-tags-table))) (t ;; This seems to behave differently on Linux, so just ignore ;; error codes for now @@ -528,7 +519,7 @@ a new topic." ((member tag org-ctags-tag-list) ;; Existing tag (push tag org-ctags-find-tag-history) - (find-tag tag)) + (xref-find-definitions tag)) (t ;; New tag (run-hook-with-args-until-success diff --git a/lisp/org/org-datetree.el b/lisp/org/org-datetree.el index 891e64f9095..540753d67cd 100644 --- a/lisp/org/org-datetree.el +++ b/lisp/org/org-datetree.el @@ -1,4 +1,4 @@ -;;; org-datetree.el --- Create date entries in a tree +;;; org-datetree.el --- Create date entries in a tree -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -34,12 +34,14 @@ (defvar org-datetree-base-level 1 "The level at which years should be placed in the date tree. -This is normally one, but if the buffer has an entry with a DATE_TREE -property (any value), the date tree will become a subtree under that entry, -so the base level will be properly adjusted.") +This is normally one, but if the buffer has an entry with a +DATE_TREE (or WEEK_TREE for ISO week entries) property (any +value), the date tree will become a subtree under that entry, so +the base level will be properly adjusted.") (defcustom org-datetree-add-timestamp nil - "When non-nil, add a time stamp when create a datetree entry." + "When non-nil, add a time stamp matching date of entry. +Added time stamp is active unless value is `inactive'." :group 'org-capture :version "24.3" :type '(choice @@ -48,115 +50,129 @@ so the base level will be properly adjusted.") (const :tag "Add an active time stamp" active))) ;;;###autoload -(defun org-datetree-find-date-create (date &optional keep-restriction) - "Find or create an entry for DATE. +(defun org-datetree-find-date-create (d &optional keep-restriction) + "Find or create an entry for date D. If KEEP-RESTRICTION is non-nil, do not widen the buffer. When it is nil, the buffer will be widened to make sure an existing date tree can be found." - (let ((year (nth 2 date)) - (month (car date)) - (day (nth 1 date))) - (org-set-local 'org-datetree-base-level 1) - (or keep-restriction (widen)) + (setq-local org-datetree-base-level 1) + (or keep-restriction (widen)) + (save-restriction + (let ((prop (org-find-property "DATE_TREE"))) + (when prop + (goto-char prop) + (setq-local org-datetree-base-level + (org-get-valid-level (org-current-level) 1)) + (org-narrow-to-subtree))) (goto-char (point-min)) - (save-restriction - (when (re-search-forward "^[ \t]*:DATE_TREE:[ \t]+\\S-" nil t) - (org-back-to-heading t) - (org-set-local 'org-datetree-base-level - (org-get-valid-level (funcall outline-level) 1)) - (org-narrow-to-subtree)) - (goto-char (point-min)) - (org-datetree-find-year-create year) - (org-datetree-find-month-create year month) - (org-datetree-find-day-create year month day) - (goto-char (prog1 (point) (widen)))))) - -(defun org-datetree-find-year-create (year) - "Find the YEAR datetree or create it." - (let ((re "^\\*+[ \t]+\\([12][0-9]\\{3\\}\\)\\(\\s-*?\\([ \t]:[[:alnum:]:_@#%]+:\\)?\\s-*$\\)") - match) - (goto-char (point-min)) - (while (and (setq match (re-search-forward re nil t)) - (goto-char (match-beginning 1)) - (< (string-to-number (match-string 1)) year))) - (cond - ((not match) - (goto-char (point-max)) - (or (bolp) (newline)) - (org-datetree-insert-line year)) - ((= (string-to-number (match-string 1)) year) - (goto-char (point-at-bol))) - (t - (beginning-of-line 1) - (org-datetree-insert-line year))))) + (let ((year (calendar-extract-year d)) + (month (calendar-extract-month d)) + (day (calendar-extract-day d))) + (org-datetree--find-create + "^\\*+[ \t]+\\([12][0-9]\\{3\\}\\)\\(\\s-*?\ +\\([ \t]:[[:alnum:]:_@#%%]+:\\)?\\s-*$\\)" + year) + (org-datetree--find-create + "^\\*+[ \t]+%d-\\([01][0-9]\\) \\w+$" + year month) + (org-datetree--find-create + "^\\*+[ \t]+%d-%02d-\\([0123][0-9]\\) \\w+$" + year month day)))) -(defun org-datetree-find-month-create (year month) - "Find the datetree for YEAR and MONTH or create it." - (org-narrow-to-subtree) - (let ((re (format "^\\*+[ \t]+%d-\\([01][0-9]\\) \\w+$" year)) - match) +;;;###autoload +(defun org-datetree-find-iso-week-create (d &optional keep-restriction) + "Find or create an ISO week entry for date D. +Compared to `org-datetree-find-date-create' this function creates +entries ordered by week instead of months. +If KEEP-RESTRICTION is non-nil, do not widen the buffer. When it +is nil, the buffer will be widened to make sure an existing date +tree can be found." + (setq-local org-datetree-base-level 1) + (or keep-restriction (widen)) + (save-restriction + (let ((prop (org-find-property "WEEK_TREE"))) + (when prop + (goto-char prop) + (setq-local org-datetree-base-level + (org-get-valid-level (org-current-level) 1)) + (org-narrow-to-subtree))) (goto-char (point-min)) - (while (and (setq match (re-search-forward re nil t)) - (goto-char (match-beginning 1)) - (< (string-to-number (match-string 1)) month))) - (cond - ((not match) - (goto-char (point-max)) - (or (bolp) (newline)) - (org-datetree-insert-line year month)) - ((= (string-to-number (match-string 1)) month) - (goto-char (point-at-bol))) - (t - (beginning-of-line 1) - (org-datetree-insert-line year month))))) - -(defun org-datetree-find-day-create (year month day) - "Find the datetree for YEAR, MONTH and DAY or create it." - (org-narrow-to-subtree) - (let ((re (format "^\\*+[ \t]+%d-%02d-\\([0123][0-9]\\) \\w+$" year month)) + (require 'cal-iso) + (let* ((year (calendar-extract-year d)) + (month (calendar-extract-month d)) + (day (calendar-extract-day d)) + (time (encode-time 0 0 0 day month year)) + (iso-date (calendar-iso-from-absolute + (calendar-absolute-from-gregorian d))) + (weekyear (nth 2 iso-date)) + (week (nth 0 iso-date))) + ;; ISO 8601 week format is %G-W%V(-%u) + (org-datetree--find-create + "^\\*+[ \t]+\\([12][0-9]\\{3\\}\\)\\(\\s-*?\ +\\([ \t]:[[:alnum:]:_@#%%]+:\\)?\\s-*$\\)" + weekyear nil nil + (format-time-string "%G" time)) + (org-datetree--find-create + "^\\*+[ \t]+%d-W\\([0-5][0-9]\\)$" + weekyear week nil + (format-time-string "%G-W%V" time)) + ;; For the actual day we use the regular date instead of ISO week. + (org-datetree--find-create + "^\\*+[ \t]+%d-%02d-\\([0123][0-9]\\) \\w+$" + year month day)))) + +(defun org-datetree--find-create (regex year &optional month day insert) + "Find the datetree matched by REGEX for YEAR, MONTH, or DAY. +REGEX is passed to `format' with YEAR, MONTH, and DAY as +arguments. Match group 1 is compared against the specified date +component. If INSERT is non-nil and there is no match then it is +inserted into the buffer." + (when (or month day) + (org-narrow-to-subtree)) + (let ((re (format regex year month day)) match) (goto-char (point-min)) (while (and (setq match (re-search-forward re nil t)) (goto-char (match-beginning 1)) - (< (string-to-number (match-string 1)) day))) + (< (string-to-number (match-string 1)) (or day month year)))) (cond ((not match) (goto-char (point-max)) - (or (bolp) (newline)) - (org-datetree-insert-line year month day)) - ((= (string-to-number (match-string 1)) day) - (goto-char (point-at-bol))) + (unless (bolp) (insert "\n")) + (org-datetree-insert-line year month day insert)) + ((= (string-to-number (match-string 1)) (or day month year)) + (beginning-of-line)) (t - (beginning-of-line 1) - (org-datetree-insert-line year month day))))) - -(defun org-datetree-insert-line (year &optional month day) - (let ((pos (point)) ts-type) - (skip-chars-backward " \t\n") - (delete-region (point) pos) - (insert "\n" (make-string org-datetree-base-level ?*) " \n") - (backward-char 1) - (if month (org-do-demote)) - (if day (org-do-demote)) + (beginning-of-line) + (org-datetree-insert-line year month day insert))))) + +(defun org-datetree-insert-line (year &optional month day text) + (delete-region (save-excursion (skip-chars-backward " \t\n") (point)) (point)) + (insert "\n" (make-string org-datetree-base-level ?*) " \n") + (backward-char) + (when month (org-do-demote)) + (when day (org-do-demote)) + (if text + (insert text) (insert (format "%d" year)) (when month - (insert (format "-%02d" month)) - (if day - (insert (format "-%02d %s" - day (format-time-string - "%A" (encode-time 0 0 0 day month year)))) - (insert (format " %s" - (format-time-string - "%B" (encode-time 0 0 0 1 month year)))))) - (when (and day (setq ts-type org-datetree-add-timestamp)) + (insert + (if day + (format-time-string "-%m-%d %A" (encode-time 0 0 0 day month year)) + (format-time-string "-%m %B" (encode-time 0 0 0 1 month year)))))) + (when (and day org-datetree-add-timestamp) + (save-excursion (insert "\n") (org-indent-line) - (org-insert-time-stamp (encode-time 0 0 0 day month year) nil ts-type)) - (beginning-of-line 1))) - -(defun org-datetree-file-entry-under (txt date) - "Insert a node TXT into the date tree under DATE." - (org-datetree-find-date-create date) + (org-insert-time-stamp + (encode-time 0 0 0 day month year) + nil + (eq org-datetree-add-timestamp 'inactive)))) + (beginning-of-line)) + +(defun org-datetree-file-entry-under (txt d) + "Insert a node TXT into the date tree under date D." + (org-datetree-find-date-create d) (let ((level (org-get-valid-level (funcall outline-level) 1))) (org-end-of-subtree t t) (org-back-over-empty-lines) @@ -169,44 +185,42 @@ before running this command, even though the command tries to be smart." (interactive) (goto-char (point-min)) (let ((dre (concat "\\<" org-deadline-string "\\>[ \t]*\\'")) - (sre (concat "\\<" org-scheduled-string "\\>[ \t]*\\'")) - dct ts tmp date year month day pos hdl-pos) + (sre (concat "\\<" org-scheduled-string "\\>[ \t]*\\'"))) (while (re-search-forward org-ts-regexp nil t) (catch 'next - (setq ts (match-string 0)) - (setq tmp (buffer-substring - (max (point-at-bol) (- (match-beginning 0) - org-ds-keyword-length)) - (match-beginning 0))) - (if (or (string-match "-\\'" tmp) - (string-match dre tmp) - (string-match sre tmp)) + (let ((tmp (buffer-substring + (max (line-beginning-position) + (- (match-beginning 0) org-ds-keyword-length)) + (match-beginning 0)))) + (when (or (string-suffix-p "-" tmp) + (string-match dre tmp) + (string-match sre tmp)) (throw 'next nil)) - (setq dct (decode-time (org-time-string-to-time (match-string 0))) - date (list (nth 4 dct) (nth 3 dct) (nth 5 dct)) - year (nth 2 date) - month (car date) - day (nth 1 date) - pos (point)) - (org-back-to-heading t) - (setq hdl-pos (point)) - (unless (org-up-heading-safe) - ;; No parent, we are not in a date tree - (goto-char pos) - (throw 'next nil)) - (unless (looking-at "\\*+[ \t]+[0-9]+-[0-1][0-9]-[0-3][0-9]") - ;; Parent looks wrong, we are not in a date tree - (goto-char pos) - (throw 'next nil)) - (when (looking-at (format "\\*+[ \t]+%d-%02d-%02d" year month day)) - ;; At correct date already, do nothing - (progn (goto-char pos) (throw 'next nil))) - ;; OK, we need to refile this entry - (goto-char hdl-pos) - (org-cut-subtree) - (save-excursion - (save-restriction - (org-datetree-file-entry-under (current-kill 0) date))))))) + (let* ((dct (decode-time (org-time-string-to-time (match-string 0)))) + (date (list (nth 4 dct) (nth 3 dct) (nth 5 dct))) + (year (nth 2 date)) + (month (car date)) + (day (nth 1 date)) + (pos (point)) + (hdl-pos (progn (org-back-to-heading t) (point)))) + (unless (org-up-heading-safe) + ;; No parent, we are not in a date tree. + (goto-char pos) + (throw 'next nil)) + (unless (looking-at "\\*+[ \t]+[0-9]+-[0-1][0-9]-[0-3][0-9]") + ;; Parent looks wrong, we are not in a date tree. + (goto-char pos) + (throw 'next nil)) + (when (looking-at (format "\\*+[ \t]+%d-%02d-%02d" year month day)) + ;; At correct date already, do nothing. + (goto-char pos) + (throw 'next nil)) + ;; OK, we need to refile this entry. + (goto-char hdl-pos) + (org-cut-subtree) + (save-excursion + (save-restriction + (org-datetree-file-entry-under (current-kill 0) date))))))))) (provide 'org-datetree) diff --git a/lisp/org/org-docview.el b/lisp/org/org-docview.el index c5d01158c9c..dfad89332a6 100644 --- a/lisp/org/org-docview.el +++ b/lisp/org/org-docview.el @@ -1,4 +1,4 @@ -;;; org-docview.el --- support for links to doc-view-mode buffers +;;; org-docview.el --- Support for links to doc-view-mode buffers -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -25,7 +25,7 @@ ;;; Commentary: ;; This file implements links to open files in doc-view-mode. -;; Org-mode loads this module by default - if this is not what you want, +;; Org mode loads this module by default - if this is not what you want, ;; configure the variable `org-modules'. ;; The links take the form @@ -49,13 +49,15 @@ (declare-function doc-view-goto-page "doc-view" (page)) (declare-function image-mode-window-get "image-mode" (prop &optional winprops)) -(org-add-link-type "docview" 'org-docview-open 'org-docview-export) -(add-hook 'org-store-link-functions 'org-docview-store-link) +(org-link-set-parameters "docview" + :follow #'org-docview-open + :export #'org-docview-export + :store #'org-docview-store-link) (defun org-docview-export (link description format) "Export a docview link from Org files." - (let* ((path (when (string-match "\\(.+\\)::.+" link) - (match-string 1 link))) + (let* ((path (if (string-match "\\(.+\\)::.+" link) (match-string 1 link) + link)) (desc (or description link))) (when (stringp path) (setq path (org-link-escape (expand-file-name path))) @@ -66,13 +68,14 @@ (t path))))) (defun org-docview-open (link) - (when (string-match "\\(.*\\)::\\([0-9]+\\)$" link) - (let* ((path (match-string 1 link)) - (page (string-to-number (match-string 2 link)))) - (org-open-file path 1) ;; let org-mode open the file (in-emacs = 1) - ;; to ensure org-link-frame-setup is respected - (doc-view-goto-page page) - ))) + (string-match "\\(.*?\\)\\(?:::\\([0-9]+\\)\\)?$" link) + (let ((path (match-string 1 link)) + (page (and (match-beginning 2) + (string-to-number (match-string 2 link))))) + ;; Let Org mode open the file (in-emacs = 1) to ensure + ;; org-link-frame-setup is respected. + (org-open-file path 1) + (when page (doc-view-goto-page page)))) (defun org-docview-store-link () "Store a link to a docview buffer." @@ -80,8 +83,7 @@ ;; This buffer is in doc-view-mode (let* ((path buffer-file-name) (page (image-mode-window-get 'page)) - (link (concat "docview:" path "::" (number-to-string page))) - (description "")) + (link (concat "docview:" path "::" (number-to-string page)))) (org-store-link-props :type "docview" :link link diff --git a/lisp/org/org-element.el b/lisp/org/org-element.el index e9731c17836..41b4a3ac78c 100644 --- a/lisp/org/org-element.el +++ b/lisp/org/org-element.el @@ -1,4 +1,4 @@ -;;; org-element.el --- Parser And Applications for Org syntax +;;; org-element.el --- Parser for Org Syntax -*- lexical-binding: t; -*- ;; Copyright (C) 2012-2017 Free Software Foundation, Inc. @@ -22,80 +22,21 @@ ;;; Commentary: ;; -;; Org syntax can be divided into three categories: "Greater -;; elements", "Elements" and "Objects". +;; See for details about +;; Org syntax. ;; -;; Elements are related to the structure of the document. Indeed, all -;; elements are a cover for the document: each position within belongs -;; to at least one element. -;; -;; An element always starts and ends at the beginning of a line. With -;; a few exceptions (`clock', `headline', `inlinetask', `item', -;; `planning', `node-property', `quote-section' `section' and -;; `table-row' types), it can also accept a fixed set of keywords as -;; attributes. Those are called "affiliated keywords" to distinguish -;; them from other keywords, which are full-fledged elements. Almost -;; all affiliated keywords are referenced in -;; `org-element-affiliated-keywords'; the others are export attributes -;; and start with "ATTR_" prefix. -;; -;; Element containing other elements (and only elements) are called -;; greater elements. Concerned types are: `center-block', `drawer', -;; `dynamic-block', `footnote-definition', `headline', `inlinetask', -;; `item', `plain-list', `property-drawer', `quote-block', `section' -;; and `special-block'. -;; -;; Other element types are: `babel-call', `clock', `comment', -;; `comment-block', `diary-sexp', `example-block', `export-block', -;; `fixed-width', `horizontal-rule', `keyword', `latex-environment', -;; `node-property', `paragraph', `planning', `quote-section', -;; `src-block', `table', `table-row' and `verse-block'. Among them, -;; `paragraph' and `verse-block' types can contain Org objects and -;; plain text. -;; -;; Objects are related to document's contents. Some of them are -;; recursive. Associated types are of the following: `bold', `code', -;; `entity', `export-snippet', `footnote-reference', -;; `inline-babel-call', `inline-src-block', `italic', -;; `latex-fragment', `line-break', `link', `macro', `radio-target', -;; `statistics-cookie', `strike-through', `subscript', `superscript', -;; `table-cell', `target', `timestamp', `underline' and `verbatim'. -;; -;; Some elements also have special properties whose value can hold -;; objects themselves (e.g. an item tag or a headline name). Such -;; values are called "secondary strings". Any object belongs to -;; either an element or a secondary string. -;; -;; Notwithstanding affiliated keywords, each greater element, element -;; and object has a fixed set of properties attached to it. Among -;; them, four are shared by all types: `:begin' and `:end', which -;; refer to the beginning and ending buffer positions of the -;; considered element or object, `:post-blank', which holds the number -;; of blank lines, or white spaces, at its end and `:parent' which -;; refers to the element or object containing it. Greater elements, -;; elements and objects containing objects will also have -;; `:contents-begin' and `:contents-end' properties to delimit -;; contents. Eventually, greater elements and elements accepting -;; affiliated keywords will have a `:post-affiliated' property, -;; referring to the buffer position after all such keywords. -;; -;; At the lowest level, a `:parent' property is also attached to any -;; string, as a text property. -;; -;; Lisp-wise, an element or an object can be represented as a list. +;; Lisp-wise, a syntax object can be represented as a list. ;; It follows the pattern (TYPE PROPERTIES CONTENTS), where: -;; TYPE is a symbol describing the Org element or object. +;; TYPE is a symbol describing the object. ;; PROPERTIES is the property list attached to it. See docstring of -;; appropriate parsing function to get an exhaustive -;; list. -;; CONTENTS is a list of elements, objects or raw strings contained -;; in the current element or object, when applicable. +;; appropriate parsing function to get an exhaustive list. +;; CONTENTS is a list of syntax objects or raw strings contained +;; in the current object, when applicable. ;; -;; An Org buffer is a nested list of such elements and objects, whose -;; type is `org-data' and properties is nil. +;; For the whole document, TYPE is `org-data' and PROPERTIES is nil. ;; -;; The first part of this file defines Org syntax, while the second -;; one provide accessors and setters functions. +;; The first part of this file defines constants for the Org syntax, +;; while the second one provide accessors and setters functions. ;; ;; The next part implements a parser and an interpreter for each ;; element and object type in Org syntax. @@ -111,13 +52,15 @@ ;; ;; The library ends by furnishing `org-element-at-point' function, and ;; a way to give information about document structure around point -;; with `org-element-context'. +;; with `org-element-context'. A cache mechanism is also provided for +;; these functions. ;;; Code: -(eval-when-compile (require 'cl)) (require 'org) +(require 'avl-tree) +(require 'cl-lib) @@ -127,56 +70,116 @@ ;; along with the affiliated keywords recognized. Also set up ;; restrictions on recursive objects combinations. ;; -;; These variables really act as a control center for the parsing -;; process. - -(defconst org-element-paragraph-separate - (concat "^\\(?:" - ;; Headlines, inlinetasks. - org-outline-regexp "\\|" - ;; Footnote definitions. - "\\[\\(?:[0-9]+\\|fn:[-_[:word:]]+\\)\\]" "\\|" - ;; Diary sexps. - "%%(" "\\|" - "[ \t]*\\(?:" - ;; Empty lines. - "$" "\\|" - ;; Tables (any type). - "\\(?:|\\|\\+-[-+]\\)" "\\|" - ;; Blocks (any type), Babel calls and keywords. Note: this - ;; is only an indication and need some thorough check. - "#\\(?:[+ ]\\|$\\)" "\\|" - ;; Drawers (any type) and fixed-width areas. This is also - ;; only an indication. - ":" "\\|" - ;; Horizontal rules. - "-\\{5,\\}[ \t]*$" "\\|" - ;; LaTeX environments. - "\\\\begin{\\([A-Za-z0-9]+\\*?\\)}" "\\|" - ;; Planning and Clock lines. - (regexp-opt (list org-scheduled-string - org-deadline-string - org-closed-string - org-clock-string)) - "\\|" - ;; Lists. - (let ((term (case org-plain-list-ordered-item-terminator - (?\) ")") (?. "\\.") (otherwise "[.)]"))) - (alpha (and org-list-allow-alphabetical "\\|[A-Za-z]"))) - (concat "\\(?:[-+*]\\|\\(?:[0-9]+" alpha "\\)" term "\\)" - "\\(?:[ \t]\\|$\\)")) - "\\)\\)") +;; `org-element-update-syntax' builds proper syntax regexps according +;; to current setup. + +(defvar org-element-paragraph-separate nil "Regexp to separate paragraphs in an Org buffer. In the case of lines starting with \"#\" and \":\", this regexp is not sufficient to know if point is at a paragraph ending. See `org-element-paragraph-parser' for more information.") +(defvar org-element--object-regexp nil + "Regexp possibly matching the beginning of an object. +This regexp allows false positives. Dedicated parser (e.g., +`org-export-bold-parser') will take care of further filtering. +Radio links are not matched by this regexp, as they are treated +specially in `org-element--object-lex'.") + +(defun org-element--set-regexps () + "Build variable syntax regexps." + (setq org-element-paragraph-separate + (concat "^\\(?:" + ;; Headlines, inlinetasks. + org-outline-regexp "\\|" + ;; Footnote definitions. + "\\[fn:[-_[:word:]]+\\]" "\\|" + ;; Diary sexps. + "%%(" "\\|" + "[ \t]*\\(?:" + ;; Empty lines. + "$" "\\|" + ;; Tables (any type). + "|" "\\|" + "\\+\\(?:-+\\+\\)+[ \t]*$" "\\|" + ;; Comments, keyword-like or block-like constructs. + ;; Blocks and keywords with dual values need to be + ;; double-checked. + "#\\(?: \\|$\\|\\+\\(?:" + "BEGIN_\\S-+" "\\|" + "\\S-+\\(?:\\[.*\\]\\)?:[ \t]*\\)\\)" + "\\|" + ;; Drawers (any type) and fixed-width areas. Drawers + ;; need to be double-checked. + ":\\(?: \\|$\\|[-_[:word:]]+:[ \t]*$\\)" "\\|" + ;; Horizontal rules. + "-\\{5,\\}[ \t]*$" "\\|" + ;; LaTeX environments. + "\\\\begin{\\([A-Za-z0-9*]+\\)}" "\\|" + ;; Clock lines. + (regexp-quote org-clock-string) "\\|" + ;; Lists. + (let ((term (pcase org-plain-list-ordered-item-terminator + (?\) ")") (?. "\\.") (_ "[.)]"))) + (alpha (and org-list-allow-alphabetical "\\|[A-Za-z]"))) + (concat "\\(?:[-+*]\\|\\(?:[0-9]+" alpha "\\)" term "\\)" + "\\(?:[ \t]\\|$\\)")) + "\\)\\)") + org-element--object-regexp + (mapconcat #'identity + (let ((link-types (regexp-opt (org-link-types)))) + (list + ;; Sub/superscript. + "\\(?:[_^][-{(*+.,[:alnum:]]\\)" + ;; Bold, code, italic, strike-through, underline + ;; and verbatim. + (concat "[*~=+_/]" + (format "[^%s]" + (nth 2 org-emphasis-regexp-components))) + ;; Plain links. + (concat "\\<" link-types ":") + ;; Objects starting with "[": regular link, + ;; footnote reference, statistics cookie, + ;; timestamp (inactive). + (concat "\\[\\(?:" + "fn:" "\\|" + "\\[" "\\|" + "[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}" "\\|" + "[0-9]*\\(?:%\\|/[0-9]*\\)\\]" + "\\)") + ;; Objects starting with "@": export snippets. + "@@" + ;; Objects starting with "{": macro. + "{{{" + ;; Objects starting with "<" : timestamp + ;; (active, diary), target, radio target and + ;; angular links. + (concat "<\\(?:%%\\|<\\|[0-9]\\|" link-types "\\)") + ;; Objects starting with "$": latex fragment. + "\\$" + ;; Objects starting with "\": line break, + ;; entity, latex fragment. + "\\\\\\(?:[a-zA-Z[(]\\|\\\\[ \t]*$\\|_ +\\)" + ;; Objects starting with raw text: inline Babel + ;; source block, inline Babel call. + "\\(?:call\\|src\\)_")) + "\\|"))) + +(org-element--set-regexps) + +;;;###autoload +(defun org-element-update-syntax () + "Update parser internals." + (interactive) + (org-element--set-regexps) + (org-element-cache-reset 'all)) + (defconst org-element-all-elements '(babel-call center-block clock comment comment-block diary-sexp drawer dynamic-block example-block export-block fixed-width footnote-definition headline horizontal-rule inlinetask item keyword latex-environment node-property paragraph plain-list - planning property-drawer quote-block quote-section section + planning property-drawer quote-block section special-block src-block table table-row verse-block) "Complete list of element types.") @@ -186,23 +189,6 @@ is not sufficient to know if point is at a paragraph ending. See special-block table) "List of recursive element types aka Greater Elements.") -(defconst org-element-all-successors - '(link export-snippet footnote-reference inline-babel-call - inline-src-block latex-or-entity line-break macro plain-link - radio-target statistics-cookie sub/superscript table-cell target - text-markup timestamp) - "Complete list of successors.") - -(defconst org-element-object-successor-alist - '((subscript . sub/superscript) (superscript . sub/superscript) - (bold . text-markup) (code . text-markup) (italic . text-markup) - (strike-through . text-markup) (underline . text-markup) - (verbatim . text-markup) (entity . latex-or-entity) - (latex-fragment . latex-or-entity)) - "Alist of translations between object type and successor name. -Sharing the same successor comes handy when, for example, the -regexp matching one object can also match the other object.") - (defconst org-element-all-objects '(bold code entity export-snippet footnote-reference inline-babel-call inline-src-block italic line-break latex-fragment link macro @@ -211,26 +197,13 @@ regexp matching one object can also match the other object.") "Complete list of object types.") (defconst org-element-recursive-objects - '(bold italic link subscript radio-target strike-through superscript - table-cell underline) + '(bold footnote-reference italic link subscript radio-target strike-through + superscript table-cell underline) "List of recursive object types.") -(defvar org-element-block-name-alist - '(("CENTER" . org-element-center-block-parser) - ("COMMENT" . org-element-comment-block-parser) - ("EXAMPLE" . org-element-example-block-parser) - ("QUOTE" . org-element-quote-block-parser) - ("SRC" . org-element-src-block-parser) - ("VERSE" . org-element-verse-block-parser)) - "Alist between block names and the associated parsing function. -Names must be uppercase. Any block whose name has no association -is parsed with `org-element-special-block-parser'.") - -(defconst org-element-link-type-is-file - '("file" "file+emacs" "file+sys" "docview") - "List of link types equivalent to \"file\". -Only these types can accept search options and an explicit -application to open them.") +(defconst org-element-object-containers + (append org-element-recursive-objects '(paragraph table-row verse-block)) + "List of object or element types that can directly contain objects.") (defconst org-element-affiliated-keywords '("CAPTION" "DATA" "HEADER" "HEADERS" "LABEL" "NAME" "PLOT" "RESNAME" "RESULT" @@ -268,6 +241,13 @@ strings and objects. This list is checked after translations have been applied. See `org-element-keyword-translation-alist'.") +(defconst org-element--parsed-properties-alist + (mapcar (lambda (k) (cons k (intern (concat ":" (downcase k))))) + org-element-parsed-keywords) + "Alist of parsed keywords and associated properties. +This is generated from `org-element-parsed-keywords', which +see.") + (defconst org-element-dual-keywords '("CAPTION" "RESULTS") "List of affiliated keywords which can have a secondary value. @@ -280,13 +260,8 @@ associated to a hash value with the following: This list is checked after translations have been applied. See `org-element-keyword-translation-alist'.") -(defconst org-element-document-properties '("AUTHOR" "DATE" "TITLE") - "List of properties associated to the whole document. -Any keyword in this list will have its value parsed and stored as -a secondary string.") - (defconst org-element--affiliated-re - (format "[ \t]*#\\+\\(?:%s\\):\\(?: \\|$\\)" + (format "[ \t]*#\\+\\(?:%s\\):[ \t]*" (concat ;; Dual affiliated keywords. (format "\\(?1:%s\\)\\(?:\\[\\(.*\\)\\]\\)?" @@ -295,9 +270,8 @@ a secondary string.") ;; Regular affiliated keywords. (format "\\(?1:%s\\)" (regexp-opt - (org-remove-if - #'(lambda (keyword) - (member keyword org-element-dual-keywords)) + (cl-remove-if + (lambda (k) (member k org-element-dual-keywords)) org-element-affiliated-keywords))) "\\|" ;; Export attributes. @@ -311,8 +285,7 @@ match group 2. Don't modify it, set `org-element-affiliated-keywords' instead.") (defconst org-element-object-restrictions - (let* ((standard-set - (remq 'plain-link (remq 'table-cell org-element-all-successors))) + (let* ((standard-set (remq 'table-cell org-element-all-objects)) (standard-set-no-line-break (remq 'line-break standard-set))) `((bold ,@standard-set) (footnote-reference ,@standard-set) @@ -320,30 +293,34 @@ Don't modify it, set `org-element-affiliated-keywords' instead.") (inlinetask ,@standard-set-no-line-break) (italic ,@standard-set) (item ,@standard-set-no-line-break) - (keyword ,@standard-set) - ;; Ignore all links excepted plain links in a link description. - ;; Also ignore radio-targets and line breaks. - (link export-snippet inline-babel-call inline-src-block latex-or-entity - macro plain-link statistics-cookie sub/superscript text-markup) + (keyword ,@(remq 'footnote-reference standard-set)) + ;; Ignore all links excepted plain links and angular links in + ;; a link description. Also ignore radio-targets and line + ;; breaks. + (link bold code entity export-snippet inline-babel-call inline-src-block + italic latex-fragment macro simple-link statistics-cookie + strike-through subscript superscript underline verbatim) (paragraph ,@standard-set) ;; Remove any variable object from radio target as it would ;; prevent it from being properly recognized. - (radio-target latex-or-entity sub/superscript text-markup) + (radio-target bold code entity italic latex-fragment strike-through + subscript superscript underline superscript) (strike-through ,@standard-set) (subscript ,@standard-set) (superscript ,@standard-set) ;; Ignore inline babel call and inline src block as formulas are ;; possible. Also ignore line breaks and statistics cookies. - (table-cell link export-snippet footnote-reference latex-or-entity macro - radio-target sub/superscript target text-markup timestamp) + (table-cell bold code entity export-snippet footnote-reference italic + latex-fragment link macro radio-target strike-through + subscript superscript target timestamp underline verbatim) (table-row table-cell) (underline ,@standard-set) (verse-block ,@standard-set))) "Alist of objects restrictions. -CAR is an element or object type containing objects and CDR is -a list of successors that will be called within an element or -object of such type. +key is an element or object type containing objects and value is +a list of types that can be contained within an element or object +of such type. For example, in a `radio-target' object, one can only find entities, latex-fragments, subscript, superscript and text @@ -354,12 +331,56 @@ This alist also applies to secondary string. For example, an still has an entry since one of its properties (`:title') does.") (defconst org-element-secondary-value-alist - '((headline . :title) - (inlinetask . :title) - (item . :tag) - (footnote-reference . :inline-definition)) - "Alist between element types and location of secondary value.") - + '((headline :title) + (inlinetask :title) + (item :tag)) + "Alist between element types and locations of secondary values.") + +(defconst org-element--pair-round-table + (let ((table (make-syntax-table))) + (modify-syntax-entry ?\( "()" table) + (modify-syntax-entry ?\) ")(" table) + (dolist (char '(?\{ ?\} ?\[ ?\] ?\< ?\>) table) + (modify-syntax-entry char " " table))) + "Table used internally to pair only round brackets. +Other brackets are treated as spaces.") + +(defconst org-element--pair-square-table + (let ((table (make-syntax-table))) + (modify-syntax-entry ?\[ "(]" table) + (modify-syntax-entry ?\] ")[" table) + (dolist (char '(?\{ ?\} ?\( ?\) ?\< ?\>) table) + (modify-syntax-entry char " " table))) + "Table used internally to pair only square brackets. +Other brackets are treated as spaces.") + +(defconst org-element--pair-curly-table + (let ((table (make-syntax-table))) + (modify-syntax-entry ?\{ "(}" table) + (modify-syntax-entry ?\} "){" table) + (dolist (char '(?\[ ?\] ?\( ?\) ?\< ?\>) table) + (modify-syntax-entry char " " table))) + "Table used internally to pair only curly brackets. +Other brackets are treated as spaces.") + +(defun org-element--parse-paired-brackets (char) + "Parse paired brackets at point. +CHAR is the opening bracket to consider, as a character. Return +contents between brackets, as a string, or nil. Also move point +past the brackets." + (when (eq char (char-after)) + (let ((syntax-table (pcase char + (?\{ org-element--pair-curly-table) + (?\[ org-element--pair-square-table) + (?\( org-element--pair-round-table) + (_ nil))) + (pos (point))) + (when syntax-table + (with-syntax-table syntax-table + (let ((end (ignore-errors (scan-lists pos 1 0)))) + (when end + (goto-char end) + (buffer-substring-no-properties (1+ pos) (1- end))))))))) ;;; Accessors and Setters @@ -368,10 +389,18 @@ still has an entry since one of its properties (`:title') does.") ;; `org-element-contents' and `org-element-restriction'. ;; ;; Setter functions allow modification of elements by side effect. -;; There is `org-element-put-property', `org-element-set-contents', -;; `org-element-set-element' and `org-element-adopt-element'. Note -;; that `org-element-set-element' and `org-element-adopt-elements' are -;; higher level functions since also update `:parent' property. +;; There is `org-element-put-property', `org-element-set-contents'. +;; These low-level functions are useful to build a parse tree. +;; +;; `org-element-adopt-elements', `org-element-set-element', +;; `org-element-extract-element' and `org-element-insert-before' are +;; high-level functions useful to modify a parse tree. +;; +;; `org-element-secondary-p' is a predicate used to know if a given +;; object belongs to a secondary string. `org-element-class' tells if +;; some parsed data is an element or an object, handling pseudo +;; elements and objects. `org-element-copy' returns an element or +;; object, stripping its parent property in the process. (defsubst org-element-type (element) "Return type of ELEMENT. @@ -411,29 +440,49 @@ Return modified element." element)) (defsubst org-element-set-contents (element &rest contents) - "Set ELEMENT contents to CONTENTS. -Return modified element." - (cond ((not element) (list contents)) + "Set ELEMENT's contents to CONTENTS. +Return ELEMENT." + (cond ((null element) contents) ((not (symbolp (car element))) contents) - ((cdr element) (setcdr (cdr element) contents)) + ((cdr element) (setcdr (cdr element) contents) element) (t (nconc element contents)))) -(defsubst org-element-set-element (old new) - "Replace element or object OLD with element or object NEW. -The function takes care of setting `:parent' property for NEW." - ;; Since OLD is going to be changed into NEW by side-effect, first - ;; make sure that every element or object within NEW has OLD as - ;; parent. - (mapc (lambda (blob) (org-element-put-property blob :parent old)) - (org-element-contents new)) - ;; Transfer contents. - (apply 'org-element-set-contents old (org-element-contents new)) - ;; Ensure NEW has same parent as OLD, then overwrite OLD properties - ;; with NEW's. - (org-element-put-property new :parent (org-element-property :parent old)) - (setcar (cdr old) (nth 1 new)) - ;; Transfer type. - (setcar old (car new))) +(defun org-element-secondary-p (object) + "Non-nil when OBJECT directly belongs to a secondary string. +Return value is the property name, as a keyword, or nil." + (let* ((parent (org-element-property :parent object)) + (properties (cdr (assq (org-element-type parent) + org-element-secondary-value-alist)))) + (catch 'exit + (dolist (p properties) + (and (memq object (org-element-property p parent)) + (throw 'exit p)))))) + +(defun org-element-class (datum &optional parent) + "Return class for ELEMENT, as a symbol. +Class is either `element' or `object'. Optional argument PARENT +is the element or object containing DATUM. It defaults to the +value of DATUM `:parent' property." + (let ((type (org-element-type datum)) + (parent (or parent (org-element-property :parent datum)))) + (cond + ;; Trivial cases. + ((memq type org-element-all-objects) 'object) + ((memq type org-element-all-elements) 'element) + ;; Special cases. + ((eq type 'org-data) 'element) + ((eq type 'plain-text) 'object) + ((not type) 'object) + ;; Pseudo object or elements. Make a guess about its class. + ;; Basically a pseudo object is contained within another object, + ;; a secondary string or a container element. + ((not parent) 'element) + (t + (let ((parent-type (org-element-type parent))) + (cond ((not parent-type) 'object) + ((memq parent-type org-element-object-containers) 'object) + ((org-element-secondary-p datum) 'object) + (t 'element))))))) (defsubst org-element-adopt-elements (parent &rest children) "Append elements to the contents of another element. @@ -443,18 +492,108 @@ objects, or a strings. The function takes care of setting `:parent' property for CHILD. Return parent element." - ;; Link every child to PARENT. If PARENT is nil, it is a secondary - ;; string: parent is the list itself. - (mapc (lambda (child) - (org-element-put-property child :parent (or parent children))) - children) - ;; Add CHILDREN at the end of PARENT contents. - (when parent - (apply 'org-element-set-contents - parent - (nconc (org-element-contents parent) children))) - ;; Return modified PARENT element. - (or parent children)) + (if (not children) parent + ;; Link every child to PARENT. If PARENT is nil, it is a secondary + ;; string: parent is the list itself. + (dolist (child children) + (org-element-put-property child :parent (or parent children))) + ;; Add CHILDREN at the end of PARENT contents. + (when parent + (apply #'org-element-set-contents + parent + (nconc (org-element-contents parent) children))) + ;; Return modified PARENT element. + (or parent children))) + +(defun org-element-extract-element (element) + "Extract ELEMENT from parse tree. +Remove element from the parse tree by side-effect, and return it +with its `:parent' property stripped out." + (let ((parent (org-element-property :parent element)) + (secondary (org-element-secondary-p element))) + (if secondary + (org-element-put-property + parent secondary + (delq element (org-element-property secondary parent))) + (apply #'org-element-set-contents + parent + (delq element (org-element-contents parent)))) + ;; Return ELEMENT with its :parent removed. + (org-element-put-property element :parent nil))) + +(defun org-element-insert-before (element location) + "Insert ELEMENT before LOCATION in parse tree. +LOCATION is an element, object or string within the parse tree. +Parse tree is modified by side effect." + (let* ((parent (org-element-property :parent location)) + (property (org-element-secondary-p location)) + (siblings (if property (org-element-property property parent) + (org-element-contents parent))) + ;; Special case: LOCATION is the first element of an + ;; independent secondary string (e.g. :title property). Add + ;; ELEMENT in-place. + (specialp (and (not property) + (eq siblings parent) + (eq (car parent) location)))) + ;; Install ELEMENT at the appropriate LOCATION within SIBLINGS. + (cond (specialp) + ((or (null siblings) (eq (car siblings) location)) + (push element siblings)) + ((null location) (nconc siblings (list element))) + (t + (let ((index (cl-position location siblings))) + (unless index (error "No location found to insert element")) + (push element (cdr (nthcdr (1- index) siblings)))))) + ;; Store SIBLINGS at appropriate place in parse tree. + (cond + (specialp (setcdr parent (copy-sequence parent)) (setcar parent element)) + (property (org-element-put-property parent property siblings)) + (t (apply #'org-element-set-contents parent siblings))) + ;; Set appropriate :parent property. + (org-element-put-property element :parent parent))) + +(defun org-element-set-element (old new) + "Replace element or object OLD with element or object NEW. +The function takes care of setting `:parent' property for NEW." + ;; Ensure OLD and NEW have the same parent. + (org-element-put-property new :parent (org-element-property :parent old)) + (if (or (memq (org-element-type old) '(plain-text nil)) + (memq (org-element-type new) '(plain-text nil))) + ;; We cannot replace OLD with NEW since one of them is not an + ;; object or element. We take the long path. + (progn (org-element-insert-before new old) + (org-element-extract-element old)) + ;; Since OLD is going to be changed into NEW by side-effect, first + ;; make sure that every element or object within NEW has OLD as + ;; parent. + (dolist (blob (org-element-contents new)) + (org-element-put-property blob :parent old)) + ;; Transfer contents. + (apply #'org-element-set-contents old (org-element-contents new)) + ;; Overwrite OLD's properties with NEW's. + (setcar (cdr old) (nth 1 new)) + ;; Transfer type. + (setcar old (car new)))) + +(defun org-element-create (type &optional props &rest children) + "Create a new element of type TYPE. +Optional argument PROPS, when non-nil, is a plist defining the +properties of the element. CHILDREN can be elements, objects or +strings." + (apply #'org-element-adopt-elements (list type props) children)) + +(defun org-element-copy (datum) + "Return a copy of DATUM. +DATUM is an element, object, string or nil. `:parent' property +is cleared and contents are removed in the process." + (when datum + (let ((type (org-element-type datum))) + (pcase type + (`org-data (list 'org-data nil)) + (`plain-text (substring-no-properties datum)) + (`nil (copy-sequence datum)) + (_ + (list type (plist-put (copy-sequence (nth 1 datum)) :parent nil))))))) @@ -467,7 +606,7 @@ Return parent element." ;; Most of them accepts no argument. Though, exceptions exist. Hence ;; every element containing a secondary string (see ;; `org-element-secondary-value-alist') will accept an optional -;; argument to toggle parsing of that secondary string. Moreover, +;; argument to toggle parsing of these secondary strings. Moreover, ;; `item' parser requires current list's structure as its first ;; element. ;; @@ -503,8 +642,8 @@ keyword and CDR is a plist of affiliated keywords along with their value. Return a list whose CAR is `center-block' and CDR is a plist -containing `:begin', `:end', `:hiddenp', `:contents-begin', -`:contents-end', `:post-blank' and `:post-affiliated' keywords. +containing `:begin', `:end', `:contents-begin', `:contents-end', +`:post-blank' and `:post-affiliated' keywords. Assume point is at the beginning of the block." (let ((case-fold-search t)) @@ -520,7 +659,6 @@ Assume point is at the beginning of the block." (and (< (point) block-end-line) (point)))) (contents-end (and contents-begin block-end-line)) - (hidden (org-invisible-p2)) (pos-before-blank (progn (goto-char block-end-line) (forward-line) (point))) @@ -531,15 +669,14 @@ Assume point is at the beginning of the block." (nconc (list :begin begin :end end - :hiddenp hidden :contents-begin contents-begin :contents-end contents-end :post-blank (count-lines pos-before-blank end) :post-affiliated post-affiliated) (cdr affiliated)))))))) -(defun org-element-center-block-interpreter (center-block contents) - "Interpret CENTER-BLOCK element as Org syntax. +(defun org-element-center-block-interpreter (_ contents) + "Interpret a center-block element as Org syntax. CONTENTS is the contents of the element." (format "#+BEGIN_CENTER\n%s#+END_CENTER" contents)) @@ -555,7 +692,7 @@ keyword and CDR is a plist of affiliated keywords along with their value. Return a list whose CAR is `drawer' and CDR is a plist containing -`:drawer-name', `:begin', `:end', `:hiddenp', `:contents-begin', +`:drawer-name', `:begin', `:end', `:contents-begin', `:contents-end', `:post-blank' and `:post-affiliated' keywords. Assume point is at beginning of drawer." @@ -566,7 +703,7 @@ Assume point is at beginning of drawer." (save-excursion (let* ((drawer-end-line (match-beginning 0)) (name (progn (looking-at org-drawer-regexp) - (org-match-string-no-properties 1))) + (match-string-no-properties 1))) (begin (car affiliated)) (post-affiliated (point)) ;; Empty drawers have no contents. @@ -574,7 +711,6 @@ Assume point is at beginning of drawer." (and (< (point) drawer-end-line) (point)))) (contents-end (and contents-begin drawer-end-line)) - (hidden (org-invisible-p2)) (pos-before-blank (progn (goto-char drawer-end-line) (forward-line) (point))) @@ -585,7 +721,6 @@ Assume point is at beginning of drawer." (list :begin begin :end end :drawer-name name - :hiddenp hidden :contents-begin contents-begin :contents-end contents-end :post-blank (count-lines pos-before-blank end) @@ -611,9 +746,9 @@ keyword and CDR is a plist of affiliated keywords along with their value. Return a list whose CAR is `dynamic-block' and CDR is a plist -containing `:block-name', `:begin', `:end', `:hiddenp', -`:contents-begin', `:contents-end', `:arguments', `:post-blank' -and `:post-affiliated' keywords. +containing `:block-name', `:begin', `:end', `:contents-begin', +`:contents-end', `:arguments', `:post-blank' and +`:post-affiliated' keywords. Assume point is at beginning of dynamic block." (let ((case-fold-search t)) @@ -624,8 +759,8 @@ Assume point is at beginning of dynamic block." (let ((block-end-line (match-beginning 0))) (save-excursion (let* ((name (progn (looking-at org-dblock-start-re) - (org-match-string-no-properties 1))) - (arguments (org-match-string-no-properties 3)) + (match-string-no-properties 1))) + (arguments (match-string-no-properties 3)) (begin (car affiliated)) (post-affiliated (point)) ;; Empty blocks have no contents. @@ -633,7 +768,6 @@ Assume point is at beginning of dynamic block." (and (< (point) block-end-line) (point)))) (contents-end (and contents-begin block-end-line)) - (hidden (org-invisible-p2)) (pos-before-blank (progn (goto-char block-end-line) (forward-line) (point))) @@ -645,7 +779,6 @@ Assume point is at beginning of dynamic block." :end end :block-name name :arguments arguments - :hiddenp hidden :contents-begin contents-begin :contents-end contents-end :post-blank (count-lines pos-before-blank end) @@ -658,12 +791,18 @@ CONTENTS is the contents of the element." (format "#+BEGIN: %s%s\n%s#+END:" (org-element-property :block-name dynamic-block) (let ((args (org-element-property :arguments dynamic-block))) - (and args (concat " " args))) + (if args (concat " " args) "")) contents)) ;;;; Footnote Definition +(defconst org-element--footnote-separator + (concat org-outline-regexp-bol "\\|" + org-footnote-definition-re "\\|" + "^\\([ \t]*\n\\)\\{2,\\}") + "Regexp used as a footnote definition separator.") + (defun org-element-footnote-definition-parser (limit affiliated) "Parse a footnote definition. @@ -679,59 +818,104 @@ a plist containing `:label', `:begin' `:end', `:contents-begin', Assume point is at the beginning of the footnote definition." (save-excursion (let* ((label (progn (looking-at org-footnote-definition-re) - (org-match-string-no-properties 1))) + (match-string-no-properties 1))) (begin (car affiliated)) (post-affiliated (point)) - (ending (save-excursion - (if (progn - (end-of-line) - (re-search-forward - (concat org-outline-regexp-bol "\\|" - org-footnote-definition-re "\\|" - "^\\([ \t]*\n\\)\\{2,\\}") limit 'move)) - (match-beginning 0) - (point)))) - (contents-begin (progn - (search-forward "]") - (skip-chars-forward " \r\t\n" ending) - (cond ((= (point) ending) nil) - ((= (line-beginning-position) begin) (point)) - (t (line-beginning-position))))) - (contents-end (and contents-begin ending)) - (end (progn (goto-char ending) - (skip-chars-forward " \r\t\n" limit) - (if (eobp) (point) (line-beginning-position))))) + (end + (save-excursion + (end-of-line) + (cond + ((not + (re-search-forward org-element--footnote-separator limit t)) + limit) + ((eq ?\[ (char-after (match-beginning 0))) + ;; At a new footnote definition, make sure we end + ;; before any affiliated keyword above. + (forward-line -1) + (while (and (> (point) post-affiliated) + (looking-at-p org-element--affiliated-re)) + (forward-line -1)) + (line-beginning-position 2)) + ((eq ?* (char-after (match-beginning 0))) (match-beginning 0)) + (t (skip-chars-forward " \r\t\n" limit) + (if (= limit (point)) limit (line-beginning-position)))))) + (contents-begin + (progn (search-forward "]") + (skip-chars-forward " \r\t\n" end) + (cond ((= (point) end) nil) + ((= (line-beginning-position) post-affiliated) (point)) + (t (line-beginning-position))))) + (contents-end + (progn (goto-char end) + (skip-chars-backward " \r\t\n") + (line-beginning-position 2)))) (list 'footnote-definition (nconc (list :label label :begin begin :end end :contents-begin contents-begin - :contents-end contents-end - :post-blank (count-lines ending end) + :contents-end (and contents-begin contents-end) + :post-blank (count-lines contents-end end) :post-affiliated post-affiliated) (cdr affiliated)))))) (defun org-element-footnote-definition-interpreter (footnote-definition contents) "Interpret FOOTNOTE-DEFINITION element as Org syntax. CONTENTS is the contents of the footnote-definition." - (concat (format "[%s]" (org-element-property :label footnote-definition)) + (concat (format "[fn:%s]" (org-element-property :label footnote-definition)) " " contents)) ;;;; Headline +(defun org-element--get-node-properties () + "Return node properties associated to headline at point. +Upcase property names. It avoids confusion between properties +obtained through property drawer and default properties from the +parser (e.g. `:end' and :END:). Return value is a plist." + (save-excursion + (forward-line) + (when (looking-at-p org-planning-line-re) (forward-line)) + (when (looking-at org-property-drawer-re) + (forward-line) + (let ((end (match-end 0)) properties) + (while (< (line-end-position) end) + (looking-at org-property-re) + (push (match-string-no-properties 3) properties) + (push (intern (concat ":" (upcase (match-string 2)))) properties) + (forward-line)) + properties)))) + +(defun org-element--get-time-properties () + "Return time properties associated to headline at point. +Return value is a plist." + (save-excursion + (when (progn (forward-line) (looking-at org-planning-line-re)) + (let ((end (line-end-position)) plist) + (while (re-search-forward org-keyword-time-not-clock-regexp end t) + (goto-char (match-end 1)) + (skip-chars-forward " \t") + (let ((keyword (match-string 1)) + (time (org-element-timestamp-parser))) + (cond ((equal keyword org-scheduled-string) + (setq plist (plist-put plist :scheduled time))) + ((equal keyword org-deadline-string) + (setq plist (plist-put plist :deadline time))) + (t (setq plist (plist-put plist :closed time)))))) + plist)))) + (defun org-element-headline-parser (limit &optional raw-secondary-p) "Parse a headline. Return a list whose CAR is `headline' and CDR is a plist -containing `:raw-value', `:title', `:alt-title', `:begin', -`:end', `:pre-blank', `:hiddenp', `:contents-begin', -`:contents-end', `:level', `:priority', `:tags', -`:todo-keyword',`:todo-type', `:scheduled', `:deadline', -`:closed', `:quotedp', `:archivedp', `:commentedp', -`:footnote-section-p' and `:post-blank' keywords. +containing `:raw-value', `:title', `:begin', `:end', +`:pre-blank', `:contents-begin' and `:contents-end', `:level', +`:priority', `:tags', `:todo-keyword',`:todo-type', `:scheduled', +`:deadline', `:closed', `:archivedp', `:commentedp' +`:footnote-section-p', `:post-blank' and `:post-affiliated' +keywords. The plist also contains any property set in the property drawer, with its name in upper cases and colons added at the @@ -744,80 +928,46 @@ parsed as a secondary string, but as a plain string instead. Assume point is at beginning of the headline." (save-excursion - (let* ((components (org-heading-components)) - (level (nth 1 components)) - (todo (nth 2 components)) + (let* ((begin (point)) + (level (prog1 (org-reduced-level (skip-chars-forward "*")) + (skip-chars-forward " \t"))) + (todo (and org-todo-regexp + (let (case-fold-search) (looking-at org-todo-regexp)) + (progn (goto-char (match-end 0)) + (skip-chars-forward " \t") + (match-string 0)))) (todo-type (and todo (if (member todo org-done-keywords) 'done 'todo))) - (tags (let ((raw-tags (nth 5 components))) - (and raw-tags (org-split-string raw-tags ":")))) - (raw-value (or (nth 4 components) "")) - (quotedp - (let ((case-fold-search nil)) - (string-match (format "^%s\\( \\|$\\)" org-quote-string) - raw-value))) + (priority (and (looking-at "\\[#.\\][ \t]*") + (progn (goto-char (match-end 0)) + (aref (match-string 0) 2)))) (commentedp - (let ((case-fold-search nil)) - (string-match (format "^%s\\( \\|$\\)" org-comment-string) - raw-value))) + (and (let (case-fold-search) (looking-at org-comment-string)) + (goto-char (match-end 0)))) + (title-start (point)) + (tags (when (re-search-forward + "[ \t]+\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$" + (line-end-position) + 'move) + (goto-char (match-beginning 0)) + (org-split-string (match-string 1) ":"))) + (title-end (point)) + (raw-value (org-trim + (buffer-substring-no-properties title-start title-end))) (archivedp (member org-archive-tag tags)) (footnote-section-p (and org-footnote-section (string= org-footnote-section raw-value))) - ;; Upcase property names. It avoids confusion between - ;; properties obtained through property drawer and default - ;; properties from the parser (e.g. `:end' and :END:) - (standard-props - (let (plist) - (mapc - (lambda (p) - (setq plist - (plist-put plist - (intern (concat ":" (upcase (car p)))) - (cdr p)))) - (org-entry-properties nil 'standard)) - plist)) - (time-props - ;; Read time properties on the line below the headline. - (save-excursion - (when (progn (forward-line) - (looking-at org-planning-or-clock-line-re)) - (let ((end (line-end-position)) plist) - (while (re-search-forward - org-keyword-time-not-clock-regexp end t) - (goto-char (match-end 1)) - (skip-chars-forward " \t") - (let ((keyword (match-string 1)) - (time (org-element-timestamp-parser))) - (cond ((equal keyword org-scheduled-string) - (setq plist (plist-put plist :scheduled time))) - ((equal keyword org-deadline-string) - (setq plist (plist-put plist :deadline time))) - (t (setq plist (plist-put plist :closed time)))))) - plist)))) - (begin (point)) + (standard-props (org-element--get-node-properties)) + (time-props (org-element--get-time-properties)) (end (min (save-excursion (org-end-of-subtree t t)) limit)) - (pos-after-head (progn (forward-line) (point))) (contents-begin (save-excursion + (forward-line) (skip-chars-forward " \r\t\n" end) (and (/= (point) end) (line-beginning-position)))) - (hidden (org-invisible-p2)) (contents-end (and contents-begin (progn (goto-char end) (skip-chars-backward " \r\t\n") - (forward-line) - (point))))) - ;; Clean RAW-VALUE from any quote or comment string. - (when (or quotedp commentedp) - (let ((case-fold-search nil)) - (setq raw-value - (replace-regexp-in-string - (concat - (regexp-opt (list org-quote-string org-comment-string)) - "\\(?: \\|$\\)") - "" - raw-value)))) - ;; Clean TAGS from archive tag, if any. - (when archivedp (setq tags (delete org-archive-tag tags))) + (line-beginning-position 2))))) (let ((headline (list 'headline (nconc @@ -826,36 +976,37 @@ Assume point is at beginning of the headline." :end end :pre-blank (if (not contents-begin) 0 - (count-lines pos-after-head contents-begin)) - :hiddenp hidden + (1- (count-lines begin contents-begin))) :contents-begin contents-begin :contents-end contents-end :level level - :priority (nth 3 components) + :priority priority :tags tags :todo-keyword todo :todo-type todo-type - :post-blank (count-lines - (or contents-end pos-after-head) - end) + :post-blank + (if contents-end + (count-lines contents-end end) + (1- (count-lines begin end))) :footnote-section-p footnote-section-p :archivedp archivedp :commentedp commentedp - :quotedp quotedp) + :post-affiliated begin) time-props standard-props)))) - (let ((alt-title (org-element-property :ALT_TITLE headline))) - (when alt-title - (org-element-put-property - headline :alt-title - (if raw-secondary-p alt-title - (org-element-parse-secondary-string - alt-title (org-element-restriction 'headline) headline))))) (org-element-put-property headline :title (if raw-secondary-p raw-value - (org-element-parse-secondary-string - raw-value (org-element-restriction 'headline) headline))))))) + (org-element--parse-objects + (progn (goto-char title-start) + (skip-chars-forward " \t") + (point)) + (progn (goto-char title-end) + (skip-chars-backward " \t") + (point)) + nil + (org-element-restriction 'headline) + headline))))))) (defun org-element-headline-interpreter (headline contents) "Interpret HEADLINE element as Org syntax. @@ -865,22 +1016,17 @@ CONTENTS is the contents of the element." (priority (org-element-property :priority headline)) (title (org-element-interpret-data (org-element-property :title headline))) - (tags (let ((tag-list (if (org-element-property :archivedp headline) - (cons org-archive-tag - (org-element-property :tags headline)) - (org-element-property :tags headline)))) + (tags (let ((tag-list (org-element-property :tags headline))) (and tag-list (format ":%s:" (mapconcat #'identity tag-list ":"))))) (commentedp (org-element-property :commentedp headline)) - (quotedp (org-element-property :quotedp headline)) (pre-blank (or (org-element-property :pre-blank headline) 0)) (heading (concat (make-string (if org-odd-levels-only (1- (* level 2)) level) ?*) (and todo (concat " " todo)) - (and quotedp (concat " " org-quote-string)) (and commentedp (concat " " org-comment-string)) - (and priority (format " [#%s]" (char-to-string priority))) + (and priority (format " [#%c]" priority)) " " (if (and org-footnote-section (org-element-property :footnote-section-p headline)) @@ -912,10 +1058,11 @@ CONTENTS is the contents of the element." "Parse an inline task. Return a list whose CAR is `inlinetask' and CDR is a plist -containing `:title', `:begin', `:end', `:hiddenp', +containing `:title', `:begin', `:end', `:pre-blank', `:contents-begin' and `:contents-end', `:level', `:priority', `:raw-value', `:tags', `:todo-keyword', `:todo-type', -`:scheduled', `:deadline', `:closed' and `:post-blank' keywords. +`:scheduled', `:deadline', `:closed', `:post-blank' and +`:post-affiliated' keywords. The plist also contains any property set in the property drawer, with its name in upper cases and colons added at the @@ -928,59 +1075,45 @@ string instead. Assume point is at beginning of the inline task." (save-excursion (let* ((begin (point)) - (components (org-heading-components)) - (todo (nth 2 components)) + (level (prog1 (org-reduced-level (skip-chars-forward "*")) + (skip-chars-forward " \t"))) + (todo (and org-todo-regexp + (let (case-fold-search) (looking-at org-todo-regexp)) + (progn (goto-char (match-end 0)) + (skip-chars-forward " \t") + (match-string 0)))) (todo-type (and todo (if (member todo org-done-keywords) 'done 'todo))) - (tags (let ((raw-tags (nth 5 components))) - (and raw-tags (org-split-string raw-tags ":")))) - (raw-value (or (nth 4 components) "")) - ;; Upcase property names. It avoids confusion between - ;; properties obtained through property drawer and default - ;; properties from the parser (e.g. `:end' and :END:) - (standard-props - (let (plist) - (mapc - (lambda (p) - (setq plist - (plist-put plist - (intern (concat ":" (upcase (car p)))) - (cdr p)))) - (org-entry-properties nil 'standard)) - plist)) - (time-props - ;; Read time properties on the line below the inlinetask - ;; opening string. - (save-excursion - (when (progn (forward-line) - (looking-at org-planning-or-clock-line-re)) - (let ((end (line-end-position)) plist) - (while (re-search-forward - org-keyword-time-not-clock-regexp end t) - (goto-char (match-end 1)) - (skip-chars-forward " \t") - (let ((keyword (match-string 1)) - (time (org-element-timestamp-parser))) - (cond ((equal keyword org-scheduled-string) - (setq plist (plist-put plist :scheduled time))) - ((equal keyword org-deadline-string) - (setq plist (plist-put plist :deadline time))) - (t (setq plist (plist-put plist :closed time)))))) - plist)))) + (priority (and (looking-at "\\[#.\\][ \t]*") + (progn (goto-char (match-end 0)) + (aref (match-string 0) 2)))) + (title-start (point)) + (tags (when (re-search-forward + "[ \t]+\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$" + (line-end-position) + 'move) + (goto-char (match-beginning 0)) + (org-split-string (match-string 1) ":"))) + (title-end (point)) + (raw-value (org-trim + (buffer-substring-no-properties title-start title-end))) (task-end (save-excursion (end-of-line) (and (re-search-forward org-outline-regexp-bol limit t) - (org-looking-at-p "END[ \t]*$") + (looking-at-p "[ \t]*END[ \t]*$") (line-beginning-position)))) - (contents-begin (progn (forward-line) - (and task-end (< (point) task-end) (point)))) - (hidden (and contents-begin (org-invisible-p2))) + (standard-props (and task-end (org-element--get-node-properties))) + (time-props (and task-end (org-element--get-time-properties))) + (contents-begin (and task-end + (< (point) task-end) + (progn + (forward-line) + (skip-chars-forward " \t\n") + (line-beginning-position)))) (contents-end (and contents-begin task-end)) - (before-blank (if (not task-end) (point) - (goto-char task-end) - (forward-line) - (point))) - (end (progn (skip-chars-forward " \r\t\n" limit) + (end (progn (when task-end (goto-char task-end)) + (forward-line) + (skip-chars-forward " \r\t\n" limit) (if (eobp) (point) (line-beginning-position)))) (inlinetask (list 'inlinetask @@ -988,22 +1121,31 @@ Assume point is at beginning of the inline task." (list :raw-value raw-value :begin begin :end end - :hiddenp hidden + :pre-blank + (if (not contents-begin) 0 + (1- (count-lines begin contents-begin))) :contents-begin contents-begin :contents-end contents-end - :level (nth 1 components) - :priority (nth 3 components) + :level level + :priority priority :tags tags :todo-keyword todo :todo-type todo-type - :post-blank (count-lines before-blank end)) + :post-blank (1- (count-lines (or task-end begin) end)) + :post-affiliated begin) time-props standard-props)))) (org-element-put-property inlinetask :title (if raw-secondary-p raw-value - (org-element-parse-secondary-string - raw-value + (org-element--parse-objects + (progn (goto-char title-start) + (skip-chars-forward " \t") + (point)) + (progn (goto-char title-end) + (skip-chars-backward " \t") + (point)) + nil (org-element-restriction 'inlinetask) inlinetask)))))) @@ -1020,8 +1162,7 @@ CONTENTS is the contents of inlinetask." (format ":%s:" (mapconcat 'identity tag-list ":"))))) (task (concat (make-string level ?*) (and todo (concat " " todo)) - (and priority - (format " [#%s]" (char-to-string priority))) + (and priority (format " [#%c]" priority)) (and title (concat " " title))))) (concat task ;; Align tags. @@ -1048,15 +1189,15 @@ CONTENTS is the contents of inlinetask." ;;;; Item -(defun org-element-item-parser (limit struct &optional raw-secondary-p) +(defun org-element-item-parser (_ struct &optional raw-secondary-p) "Parse an item. STRUCT is the structure of the plain list. Return a list whose CAR is `item' and CDR is a plist containing `:bullet', `:begin', `:end', `:contents-begin', `:contents-end', -`:checkbox', `:counter', `:tag', `:structure', `:hiddenp' and -`:post-blank' keywords. +`:checkbox', `:counter', `:tag', `:structure', `:post-blank' and +`:post-affiliated' keywords. When optional argument RAW-SECONDARY-P is non-nil, item's tag, if any, will not be parsed as a secondary string, but as a plain @@ -1067,12 +1208,12 @@ Assume point is at the beginning of the item." (beginning-of-line) (looking-at org-list-full-item-re) (let* ((begin (point)) - (bullet (org-match-string-no-properties 1)) - (checkbox (let ((box (org-match-string-no-properties 3))) + (bullet (match-string-no-properties 1)) + (checkbox (let ((box (match-string 3))) (cond ((equal "[ ]" box) 'off) ((equal "[X]" box) 'on) ((equal "[-]" box) 'trans)))) - (counter (let ((c (org-match-string-no-properties 2))) + (counter (let ((c (match-string 2))) (save-match-data (cond ((not c) nil) @@ -1081,9 +1222,8 @@ Assume point is at the beginning of the item." 64)) ((string-match "[0-9]+" c) (string-to-number (match-string 0 c))))))) - (end (save-excursion (goto-char (org-list-get-item-end begin struct)) - (unless (bolp) (forward-line)) - (point))) + (end (progn (goto-char (nth 6 (assq (point) struct))) + (if (bolp) (point) (line-beginning-position 2)))) (contents-begin (progn (goto-char ;; Ignore tags in un-ordered lists: they are just @@ -1092,40 +1232,37 @@ Assume point is at the beginning of the item." (save-match-data (string-match "[.)]" bullet))) (match-beginning 4) (match-end 0))) - (skip-chars-forward " \r\t\n" limit) - ;; If first line isn't empty, contents really start - ;; at the text after item's meta-data. - (if (= (point-at-bol) begin) (point) (point-at-bol)))) - (hidden (progn (forward-line) - (and (not (= (point) end)) (org-invisible-p2)))) - (contents-end (progn (goto-char end) - (skip-chars-backward " \r\t\n") - (forward-line) - (point))) + (skip-chars-forward " \r\t\n" end) + (cond ((= (point) end) nil) + ;; If first line isn't empty, contents really + ;; start at the text after item's meta-data. + ((= (line-beginning-position) begin) (point)) + (t (line-beginning-position))))) + (contents-end (and contents-begin + (progn (goto-char end) + (skip-chars-backward " \r\t\n") + (line-beginning-position 2)))) (item (list 'item (list :bullet bullet :begin begin :end end - ;; CONTENTS-BEGIN and CONTENTS-END may be - ;; mixed up in the case of an empty item - ;; separated from the next by a blank line. - ;; Thus ensure the former is always the - ;; smallest. - :contents-begin (min contents-begin contents-end) - :contents-end (max contents-begin contents-end) + :contents-begin contents-begin + :contents-end contents-end :checkbox checkbox :counter counter - :hiddenp hidden :structure struct - :post-blank (count-lines contents-end end))))) + :post-blank (count-lines (or contents-end begin) end) + :post-affiliated begin)))) (org-element-put-property item :tag - (let ((raw-tag (org-list-get-tag begin struct))) - (and raw-tag - (if raw-secondary-p raw-tag - (org-element-parse-secondary-string - raw-tag (org-element-restriction 'item) item)))))))) + (let ((raw (org-list-get-tag begin struct))) + (when raw + (if raw-secondary-p raw + (org-element--parse-objects + (match-beginning 4) (match-end 4) nil + (org-element-restriction 'item) + item)))))))) (defun org-element-item-interpreter (item contents) "Interpret ITEM element as Org syntax. @@ -1148,10 +1285,11 @@ CONTENTS is the contents of the element." (concat bullet (and counter (format "[@%d] " counter)) - (case checkbox - (on "[X] ") - (off "[ ] ") - (trans "[-] ")) + (pcase checkbox + (`on "[X] ") + (`off "[ ] ") + (`trans "[-] ") + (_ nil)) (and tag (format "%s :: " tag)) (when contents (let ((contents (replace-regexp-in-string @@ -1168,9 +1306,6 @@ CONTENTS is the contents of the element." (let ((case-fold-search t) (top-ind limit) (item-re (org-item-re)) - (drawers-re (concat ":\\(" - (mapconcat 'regexp-quote org-drawers "\\|") - "\\):[ \t]*$")) (inlinetask-re (and (featurep 'org-inlinetask) "^\\*+ ")) items struct) (save-excursion @@ -1222,11 +1357,12 @@ CONTENTS is the contents of the element." (forward-line) (let ((origin (point))) (when (re-search-forward inlinetask-re limit t) - (if (org-looking-at-p "END[ \t]*$") (forward-line) + (if (looking-at-p "END[ \t]*$") (forward-line) (goto-char origin))))) ;; At some text line. Check if it ends any previous item. (t - (let ((ind (progn (skip-chars-forward " \t") (current-column)))) + (let ((ind (save-excursion (skip-chars-forward " \t") + (current-column)))) (when (<= ind top-ind) (skip-chars-backward " \r\t\n") (forward-line)) @@ -1235,15 +1371,14 @@ CONTENTS is the contents of the element." (setcar (nthcdr 6 item) (line-beginning-position)) (push item struct) (unless items - (throw 'exit (sort struct 'car-less-than-car)))))) + (throw 'exit (sort struct #'car-less-than-car)))))) ;; Skip blocks (any type) and drawers contents. (cond - ((and (looking-at "#\\+BEGIN\\(:\\|_\\S-+\\)") + ((and (looking-at "[ \t]*#\\+BEGIN\\(:\\|_\\S-+\\)") (re-search-forward - (format "^[ \t]*#\\+END%s[ \t]*$" - (org-match-string-no-properties 1)) + (format "^[ \t]*#\\+END%s[ \t]*$" (match-string 1)) limit t))) - ((and (looking-at drawers-re) + ((and (looking-at org-drawer-regexp) (re-search-forward "^[ \t]*:END:[ \t]*$" limit t)))) (forward-line)))))))) @@ -1264,15 +1399,20 @@ containing `:type', `:begin', `:end', `:contents-begin' and Assume point is at the beginning of the list." (save-excursion (let* ((struct (or structure (org-element--list-struct limit))) - (prevs (org-list-prevs-alist struct)) - (type (org-list-get-list-type (point) struct prevs)) + (type (cond ((looking-at-p "[ \t]*[A-Za-z0-9]") 'ordered) + ((nth 5 (assq (point) struct)) 'descriptive) + (t 'unordered))) (contents-begin (point)) (begin (car affiliated)) - (contents-end - (progn (goto-char (org-list-get-list-end (point) struct prevs)) - (unless (bolp) (forward-line)) - (point))) - (end (progn (skip-chars-forward " \r\t\n" limit) + (contents-end (let* ((item (assq contents-begin struct)) + (ind (nth 1 item)) + (pos (nth 6 item))) + (while (and (setq item (assq pos struct)) + (= (nth 1 item) ind)) + (setq pos (nth 6 item))) + pos)) + (end (progn (goto-char contents-end) + (skip-chars-forward " \r\t\n" limit) (if (= (point) limit) limit (line-beginning-position))))) ;; Return value. (list 'plain-list @@ -1287,8 +1427,8 @@ Assume point is at the beginning of the list." :post-affiliated contents-begin) (cdr affiliated)))))) -(defun org-element-plain-list-interpreter (plain-list contents) - "Interpret PLAIN-LIST element as Org syntax. +(defun org-element-plain-list-interpreter (_ contents) + "Interpret plain-list element as Org syntax. CONTENTS is the contents of the element." (with-temp-buffer (insert contents) @@ -1299,52 +1439,36 @@ CONTENTS is the contents of the element." ;;;; Property Drawer -(defun org-element-property-drawer-parser (limit affiliated) +(defun org-element-property-drawer-parser (limit) "Parse a property drawer. -LIMIT bounds the search. AFFILIATED is a list of which CAR is -the buffer position at the beginning of the first affiliated -keyword and CDR is a plist of affiliated keywords along with -their value. +LIMIT bounds the search. -Return a list whose CAR is `property-drawer' and CDR is a plist -containing `:begin', `:end', `:hiddenp', `:contents-begin', -`:contents-end', `:post-blank' and `:post-affiliated' keywords. +Return a list whose car is `property-drawer' and cdr is a plist +containing `:begin', `:end', `:contents-begin', `:contents-end', +`:post-blank' and `:post-affiliated' keywords. Assume point is at the beginning of the property drawer." - (let ((case-fold-search t)) - (if (not (save-excursion (re-search-forward "^[ \t]*:END:[ \t]*$" limit t))) - ;; Incomplete drawer: parse it as a paragraph. - (org-element-paragraph-parser limit affiliated) - (save-excursion - (let* ((drawer-end-line (match-beginning 0)) - (begin (car affiliated)) - (post-affiliated (point)) - (contents-begin - (progn - (forward-line) - (and (re-search-forward org-property-re drawer-end-line t) - (line-beginning-position)))) - (contents-end (and contents-begin drawer-end-line)) - (hidden (org-invisible-p2)) - (pos-before-blank (progn (goto-char drawer-end-line) - (forward-line) - (point))) - (end (progn (skip-chars-forward " \r\t\n" limit) - (if (eobp) (point) (line-beginning-position))))) - (list 'property-drawer - (nconc - (list :begin begin - :end end - :hiddenp hidden - :contents-begin contents-begin - :contents-end contents-end - :post-blank (count-lines pos-before-blank end) - :post-affiliated post-affiliated) - (cdr affiliated)))))))) - -(defun org-element-property-drawer-interpreter (property-drawer contents) - "Interpret PROPERTY-DRAWER element as Org syntax. + (save-excursion + (let ((case-fold-search t) + (begin (point)) + (contents-begin (line-beginning-position 2))) + (re-search-forward "^[ \t]*:END:[ \t]*$" limit t) + (let ((contents-end (and (> (match-beginning 0) contents-begin) + (match-beginning 0))) + (before-blank (progn (forward-line) (point))) + (end (progn (skip-chars-forward " \r\t\n" limit) + (if (eobp) (point) (line-beginning-position))))) + (list 'property-drawer + (list :begin begin + :end end + :contents-begin (and contents-end contents-begin) + :contents-end contents-end + :post-blank (count-lines before-blank end) + :post-affiliated begin)))))) + +(defun org-element-property-drawer-interpreter (_ contents) + "Interpret property-drawer element as Org syntax. CONTENTS is the properties within the drawer." (format ":PROPERTIES:\n%s:END:" contents)) @@ -1360,8 +1484,8 @@ keyword and CDR is a plist of affiliated keywords along with their value. Return a list whose CAR is `quote-block' and CDR is a plist -containing `:begin', `:end', `:hiddenp', `:contents-begin', -`:contents-end', `:post-blank' and `:post-affiliated' keywords. +containing `:begin', `:end', `:contents-begin', `:contents-end', +`:post-blank' and `:post-affiliated' keywords. Assume point is at the beginning of the block." (let ((case-fold-search t)) @@ -1378,7 +1502,6 @@ Assume point is at the beginning of the block." (and (< (point) block-end-line) (point)))) (contents-end (and contents-begin block-end-line)) - (hidden (org-invisible-p2)) (pos-before-blank (progn (goto-char block-end-line) (forward-line) (point))) @@ -1388,29 +1511,26 @@ Assume point is at the beginning of the block." (nconc (list :begin begin :end end - :hiddenp hidden :contents-begin contents-begin :contents-end contents-end :post-blank (count-lines pos-before-blank end) :post-affiliated post-affiliated) (cdr affiliated))))))))) -(defun org-element-quote-block-interpreter (quote-block contents) - "Interpret QUOTE-BLOCK element as Org syntax. +(defun org-element-quote-block-interpreter (_ contents) + "Interpret quote-block element as Org syntax. CONTENTS is the contents of the element." (format "#+BEGIN_QUOTE\n%s#+END_QUOTE" contents)) ;;;; Section -(defun org-element-section-parser (limit) +(defun org-element-section-parser (_) "Parse a section. -LIMIT bounds the search. - Return a list whose CAR is `section' and CDR is a plist -containing `:begin', `:end', `:contents-begin', `contents-end' -and `:post-blank' keywords." +containing `:begin', `:end', `:contents-begin', `contents-end', +`:post-blank' and `:post-affiliated' keywords." (save-excursion ;; Beginning of section is the beginning of the first non-blank ;; line after previous headline. @@ -1418,17 +1538,17 @@ and `:post-blank' keywords." (end (progn (org-with-limited-levels (outline-next-heading)) (point))) (pos-before-blank (progn (skip-chars-backward " \r\t\n") - (forward-line) - (point)))) + (line-beginning-position 2)))) (list 'section (list :begin begin :end end :contents-begin begin :contents-end pos-before-blank - :post-blank (count-lines pos-before-blank end)))))) + :post-blank (count-lines pos-before-blank end) + :post-affiliated begin))))) -(defun org-element-section-interpreter (section contents) - "Interpret SECTION element as Org syntax. +(defun org-element-section-interpreter (_ contents) + "Interpret section element as Org syntax. CONTENTS is the contents of the element." contents) @@ -1444,14 +1564,13 @@ keyword and CDR is a plist of affiliated keywords along with their value. Return a list whose CAR is `special-block' and CDR is a plist -containing `:type', `:begin', `:end', `:hiddenp', -`:contents-begin', `:contents-end', `:post-blank' and -`:post-affiliated' keywords. +containing `:type', `:begin', `:end', `:contents-begin', +`:contents-end', `:post-blank' and `:post-affiliated' keywords. Assume point is at the beginning of the block." (let* ((case-fold-search t) (type (progn (looking-at "[ \t]*#\\+BEGIN_\\(\\S-+\\)") - (upcase (match-string-no-properties 1))))) + (match-string-no-properties 1)))) (if (not (save-excursion (re-search-forward (format "^[ \t]*#\\+END_%s[ \t]*$" (regexp-quote type)) @@ -1467,7 +1586,6 @@ Assume point is at the beginning of the block." (and (< (point) block-end-line) (point)))) (contents-end (and contents-begin block-end-line)) - (hidden (org-invisible-p2)) (pos-before-blank (progn (goto-char block-end-line) (forward-line) (point))) @@ -1478,7 +1596,6 @@ Assume point is at the beginning of the block." (list :type type :begin begin :end end - :hiddenp hidden :contents-begin contents-begin :contents-end contents-end :post-blank (count-lines pos-before-blank end) @@ -1502,9 +1619,6 @@ CONTENTS is the contents of the element." ;; through the following steps: implement a parser and an interpreter, ;; tweak `org-element--current-element' so that it recognizes the new ;; type and add that new type to `org-element-all-elements'. -;; -;; As a special case, when the newly defined type is a block type, -;; `org-element-block-name-alist' has to be modified accordingly. ;;;; Babel Call @@ -1512,43 +1626,61 @@ CONTENTS is the contents of the element." (defun org-element-babel-call-parser (limit affiliated) "Parse a babel call. -LIMIT bounds the search. AFFILIATED is a list of which CAR is +LIMIT bounds the search. AFFILIATED is a list of which car is the buffer position at the beginning of the first affiliated -keyword and CDR is a plist of affiliated keywords along with +keyword and cdr is a plist of affiliated keywords along with their value. -Return a list whose CAR is `babel-call' and CDR is a plist -containing `:begin', `:end', `:info', `:post-blank' and +Return a list whose car is `babel-call' and cdr is a plist +containing `:call', `:inside-header', `:arguments', +`:end-header', `:begin', `:end', `:value', `:post-blank' and `:post-affiliated' as keywords." (save-excursion - (let ((case-fold-search t) - (info (progn (looking-at org-babel-block-lob-one-liner-regexp) - (org-babel-lob-get-info))) - (begin (car affiliated)) - (post-affiliated (point)) - (pos-before-blank (progn (forward-line) (point))) - (end (progn (skip-chars-forward " \r\t\n" limit) - (if (eobp) (point) (line-beginning-position))))) + (let* ((begin (car affiliated)) + (post-affiliated (point)) + (before-blank (line-beginning-position 2)) + (value (progn (search-forward ":" before-blank t) + (skip-chars-forward " \t") + (org-trim + (buffer-substring-no-properties + (point) (line-end-position))))) + (call + (or (org-string-nw-p + (buffer-substring-no-properties + (point) (progn (skip-chars-forward "^[]()" before-blank) + (point)))))) + (inside-header (org-element--parse-paired-brackets ?\[)) + (arguments (org-string-nw-p + (org-element--parse-paired-brackets ?\())) + (end-header + (org-string-nw-p + (org-trim + (buffer-substring-no-properties (point) (line-end-position))))) + (end (progn (forward-line) + (skip-chars-forward " \r\t\n" limit) + (if (eobp) (point) (line-beginning-position))))) (list 'babel-call (nconc - (list :begin begin + (list :call call + :inside-header inside-header + :arguments arguments + :end-header end-header + :begin begin :end end - :info info - :post-blank (count-lines pos-before-blank end) + :value value + :post-blank (count-lines before-blank end) :post-affiliated post-affiliated) (cdr affiliated)))))) -(defun org-element-babel-call-interpreter (babel-call contents) - "Interpret BABEL-CALL element as Org syntax. -CONTENTS is nil." - (let* ((babel-info (org-element-property :info babel-call)) - (main (car babel-info)) - (post-options (nth 1 babel-info))) - (concat "#+CALL: " - (if (not (string-match "\\[\\(\\[.*?\\]\\)\\]" main)) main - ;; Remove redundant square brackets. - (replace-match (match-string 1 main) nil nil main)) - (and post-options (format "[%s]" post-options))))) +(defun org-element-babel-call-interpreter (babel-call _) + "Interpret BABEL-CALL element as Org syntax." + (concat "#+CALL: " + (org-element-property :call babel-call) + (let ((h (org-element-property :inside-header babel-call))) + (and h (format "[%s]" h))) + (concat "(" (org-element-property :arguments babel-call) ")") + (let ((h (org-element-property :end-header babel-call))) + (and h (concat " " h))))) ;;;; Clock @@ -1559,8 +1691,8 @@ CONTENTS is nil." LIMIT bounds the search. Return a list whose CAR is `clock' and CDR is a plist containing -`:status', `:value', `:time', `:begin', `:end' and `:post-blank' -as keywords." +`:status', `:value', `:time', `:begin', `:end', `:post-blank' and +`:post-affiliated' as keywords." (save-excursion (let* ((case-fold-search nil) (begin (point)) @@ -1570,7 +1702,7 @@ as keywords." (duration (and (search-forward " => " (line-end-position) t) (progn (skip-chars-forward " \t") (looking-at "\\(\\S-+\\)[ \t]*$")) - (org-match-string-no-properties 1))) + (match-string-no-properties 1))) (status (if duration 'closed 'running)) (post-blank (let ((before-blank (progn (forward-line) (point)))) (skip-chars-forward " \r\t\n" limit) @@ -1584,11 +1716,11 @@ as keywords." :duration duration :begin begin :end end - :post-blank post-blank))))) + :post-blank post-blank + :post-affiliated begin))))) -(defun org-element-clock-interpreter (clock contents) - "Interpret CLOCK element as Org syntax. -CONTENTS is nil." +(defun org-element-clock-interpreter (clock _) + "Interpret CLOCK element as Org syntax." (concat org-clock-string " " (org-element-timestamp-interpreter (org-element-property :value clock) nil) @@ -1647,7 +1779,7 @@ Assume point is at comment beginning." :post-affiliated post-affiliated) (cdr affiliated)))))) -(defun org-element-comment-interpreter (comment contents) +(defun org-element-comment-interpreter (comment _) "Interpret COMMENT element as Org syntax. CONTENTS is nil." (replace-regexp-in-string "^" "# " (org-element-property :value comment))) @@ -1664,8 +1796,8 @@ keyword and CDR is a plist of affiliated keywords along with their value. Return a list whose CAR is `comment-block' and CDR is a plist -containing `:begin', `:end', `:hiddenp', `:value', `:post-blank' -and `:post-affiliated' keywords. +containing `:begin', `:end', `:value', `:post-blank' and +`:post-affiliated' keywords. Assume point is at comment block beginning." (let ((case-fold-search t)) @@ -1678,7 +1810,6 @@ Assume point is at comment block beginning." (let* ((begin (car affiliated)) (post-affiliated (point)) (contents-begin (progn (forward-line) (point))) - (hidden (org-invisible-p2)) (pos-before-blank (progn (goto-char contents-end) (forward-line) (point))) @@ -1691,16 +1822,16 @@ Assume point is at comment block beginning." (list :begin begin :end end :value value - :hiddenp hidden :post-blank (count-lines pos-before-blank end) :post-affiliated post-affiliated) (cdr affiliated))))))))) -(defun org-element-comment-block-interpreter (comment-block contents) - "Interpret COMMENT-BLOCK element as Org syntax. -CONTENTS is nil." +(defun org-element-comment-block-interpreter (comment-block _) + "Interpret COMMENT-BLOCK element as Org syntax." (format "#+BEGIN_COMMENT\n%s#+END_COMMENT" - (org-remove-indentation (org-element-property :value comment-block)))) + (org-element-normalize-string + (org-remove-indentation + (org-element-property :value comment-block))))) ;;;; Diary Sexp @@ -1720,7 +1851,7 @@ containing `:begin', `:end', `:value', `:post-blank' and (let ((begin (car affiliated)) (post-affiliated (point)) (value (progn (looking-at "\\(%%(.*\\)[ \t]*$") - (org-match-string-no-properties 1))) + (match-string-no-properties 1))) (pos-before-blank (progn (forward-line) (point))) (end (progn (skip-chars-forward " \r\t\n" limit) (if (eobp) (point) (line-beginning-position))))) @@ -1733,43 +1864,13 @@ containing `:begin', `:end', `:value', `:post-blank' and :post-affiliated post-affiliated) (cdr affiliated)))))) -(defun org-element-diary-sexp-interpreter (diary-sexp contents) - "Interpret DIARY-SEXP as Org syntax. -CONTENTS is nil." +(defun org-element-diary-sexp-interpreter (diary-sexp _) + "Interpret DIARY-SEXP as Org syntax." (org-element-property :value diary-sexp)) ;;;; Example Block -(defun org-element--remove-indentation (s &optional n) - "Remove maximum common indentation in string S and return it. -When optional argument N is a positive integer, remove exactly -that much characters from indentation, if possible, or return -S as-is otherwise. Unlike to `org-remove-indentation', this -function doesn't call `untabify' on S." - (catch 'exit - (with-temp-buffer - (insert s) - (goto-char (point-min)) - ;; Find maximum common indentation, if not specified. - (setq n (or n - (let ((min-ind (point-max))) - (save-excursion - (while (re-search-forward "^[ \t]*\\S-" nil t) - (let ((ind (1- (current-column)))) - (if (zerop ind) (throw 'exit s) - (setq min-ind (min min-ind ind)))))) - min-ind))) - (if (zerop n) s - ;; Remove exactly N indentation, but give up if not possible. - (while (not (eobp)) - (let ((ind (progn (skip-chars-forward " \t") (current-column)))) - (cond ((eolp) (delete-region (line-beginning-position) (point))) - ((< ind n) (throw 'exit s)) - (t (org-indent-line-to (- ind n)))) - (forward-line))) - (buffer-string))))) - (defun org-element-example-block-parser (limit affiliated) "Parse an example block. @@ -1780,9 +1881,8 @@ their value. Return a list whose CAR is `example-block' and CDR is a plist containing `:begin', `:end', `:number-lines', `:preserve-indent', -`:retain-labels', `:use-labels', `:label-fmt', `:hiddenp', -`:switches', `:value', `:post-blank' and `:post-affiliated' -keywords." +`:retain-labels', `:use-labels', `:label-fmt', `:switches', +`:value', `:post-blank' and `:post-affiliated' keywords." (let ((case-fold-search t)) (if (not (save-excursion (re-search-forward "^[ \t]*#\\+END_EXAMPLE[ \t]*$" limit t))) @@ -1793,15 +1893,22 @@ keywords." (let* ((switches (progn (looking-at "^[ \t]*#\\+BEGIN_EXAMPLE\\(?: +\\(.*\\)\\)?") - (org-match-string-no-properties 1))) - ;; Switches analysis + (match-string-no-properties 1))) + ;; Switches analysis. (number-lines - (cond ((not switches) nil) - ((string-match "-n\\>" switches) 'new) - ((string-match "+n\\>" switches) 'continued))) + (and switches + (string-match "\\([-+]\\)n\\(?: *\\([0-9]+\\)\\)?\\>" + switches) + (cons + (if (equal (match-string 1 switches) "-") + 'new + 'continued) + (if (not (match-end 2)) 0 + ;; Subtract 1 to give number of lines before + ;; first line. + (1- (string-to-number (match-string 2 switches))))))) (preserve-indent - (or org-src-preserve-indentation - (and switches (string-match "-i\\>" switches)))) + (and switches (string-match "-i\\>" switches))) ;; Should labels be retained in (or stripped from) example ;; blocks? (retain-labels @@ -1821,14 +1928,10 @@ keywords." ;; Standard block parsing. (begin (car affiliated)) (post-affiliated (point)) - (block-ind (progn (skip-chars-forward " \t") (current-column))) - (contents-begin (progn (forward-line) (point))) - (hidden (org-invisible-p2)) - (value (org-element--remove-indentation - (org-unescape-code-in-string - (buffer-substring-no-properties - contents-begin contents-end)) - (and preserve-indent block-ind))) + (contents-begin (line-beginning-position 2)) + (value (org-unescape-code-in-string + (buffer-substring-no-properties + contents-begin contents-end))) (pos-before-blank (progn (goto-char contents-end) (forward-line) (point))) @@ -1845,18 +1948,21 @@ keywords." :retain-labels retain-labels :use-labels use-labels :label-fmt label-fmt - :hiddenp hidden :post-blank (count-lines pos-before-blank end) :post-affiliated post-affiliated) (cdr affiliated))))))))) -(defun org-element-example-block-interpreter (example-block contents) - "Interpret EXAMPLE-BLOCK element as Org syntax. -CONTENTS is nil." - (let ((switches (org-element-property :switches example-block))) +(defun org-element-example-block-interpreter (example-block _) + "Interpret EXAMPLE-BLOCK element as Org syntax." + (let ((switches (org-element-property :switches example-block)) + (value (org-element-property :value example-block))) (concat "#+BEGIN_EXAMPLE" (and switches (concat " " switches)) "\n" - (org-escape-code-in-string - (org-element-property :value example-block)) + (org-element-normalize-string + (org-escape-code-in-string + (if (or org-src-preserve-indentation + (org-element-property :preserve-indent example-block)) + value + (org-remove-indentation value)))) "#+END_EXAMPLE"))) @@ -1871,49 +1977,48 @@ keyword and CDR is a plist of affiliated keywords along with their value. Return a list whose CAR is `export-block' and CDR is a plist -containing `:begin', `:end', `:type', `:hiddenp', `:value', -`:post-blank' and `:post-affiliated' keywords. +containing `:begin', `:end', `:type', `:value', `:post-blank' and +`:post-affiliated' keywords. Assume point is at export-block beginning." - (let* ((case-fold-search t) - (type (progn (looking-at "[ \t]*#\\+BEGIN_\\(\\S-+\\)") - (upcase (org-match-string-no-properties 1))))) + (let* ((case-fold-search t)) (if (not (save-excursion - (re-search-forward - (format "^[ \t]*#\\+END_%s[ \t]*$" type) limit t))) + (re-search-forward "^[ \t]*#\\+END_EXPORT[ \t]*$" limit t))) ;; Incomplete block: parse it as a paragraph. (org-element-paragraph-parser limit affiliated) - (let ((contents-end (match-beginning 0))) - (save-excursion - (let* ((begin (car affiliated)) - (post-affiliated (point)) - (contents-begin (progn (forward-line) (point))) - (hidden (org-invisible-p2)) - (pos-before-blank (progn (goto-char contents-end) - (forward-line) - (point))) - (end (progn (skip-chars-forward " \r\t\n" limit) - (if (eobp) (point) (line-beginning-position)))) - (value (buffer-substring-no-properties contents-begin - contents-end))) - (list 'export-block - (nconc - (list :begin begin - :end end - :type type - :value value - :hiddenp hidden - :post-blank (count-lines pos-before-blank end) - :post-affiliated post-affiliated) - (cdr affiliated))))))))) + (save-excursion + (let* ((contents-end (match-beginning 0)) + (backend + (progn + (looking-at + "[ \t]*#\\+BEGIN_EXPORT\\(?:[ \t]+\\(\\S-+\\)\\)?[ \t]*$") + (match-string-no-properties 1))) + (begin (car affiliated)) + (post-affiliated (point)) + (contents-begin (progn (forward-line) (point))) + (pos-before-blank (progn (goto-char contents-end) + (forward-line) + (point))) + (end (progn (skip-chars-forward " \r\t\n" limit) + (if (eobp) (point) (line-beginning-position)))) + (value (org-unescape-code-in-string + (buffer-substring-no-properties contents-begin + contents-end)))) + (list 'export-block + (nconc + (list :type (and backend (upcase backend)) + :begin begin + :end end + :value value + :post-blank (count-lines pos-before-blank end) + :post-affiliated post-affiliated) + (cdr affiliated)))))))) -(defun org-element-export-block-interpreter (export-block contents) - "Interpret EXPORT-BLOCK element as Org syntax. -CONTENTS is nil." - (let ((type (org-element-property :type export-block))) - (concat (format "#+BEGIN_%s\n" type) - (org-element-property :value export-block) - (format "#+END_%s" type)))) +(defun org-element-export-block-interpreter (export-block _) + "Interpret EXPORT-BLOCK element as Org syntax." + (format "#+BEGIN_EXPORT %s\n%s#+END_EXPORT" + (org-element-property :type export-block) + (org-element-property :value export-block))) ;;;; Fixed-width @@ -1958,9 +2063,8 @@ Assume point is at the beginning of the fixed-width area." :post-affiliated post-affiliated) (cdr affiliated)))))) -(defun org-element-fixed-width-interpreter (fixed-width contents) - "Interpret FIXED-WIDTH element as Org syntax. -CONTENTS is nil." +(defun org-element-fixed-width-interpreter (fixed-width _) + "Interpret FIXED-WIDTH element as Org syntax." (let ((value (org-element-property :value fixed-width))) (and value (replace-regexp-in-string @@ -1995,9 +2099,8 @@ keywords." :post-affiliated post-affiliated) (cdr affiliated)))))) -(defun org-element-horizontal-rule-interpreter (horizontal-rule contents) - "Interpret HORIZONTAL-RULE element as Org syntax. -CONTENTS is nil." +(defun org-element-horizontal-rule-interpreter (&rest _) + "Interpret HORIZONTAL-RULE element as Org syntax." "-----") @@ -2015,10 +2118,13 @@ Return a list whose CAR is `keyword' and CDR is a plist containing `:key', `:value', `:begin', `:end', `:post-blank' and `:post-affiliated' keywords." (save-excursion - (let ((begin (car affiliated)) + ;; An orphaned affiliated keyword is considered as a regular + ;; keyword. In this case AFFILIATED is nil, so we take care of + ;; this corner case. + (let ((begin (or (car affiliated) (point))) (post-affiliated (point)) (key (progn (looking-at "[ \t]*#\\+\\(\\S-+*\\):") - (upcase (org-match-string-no-properties 1)))) + (upcase (match-string-no-properties 1)))) (value (org-trim (buffer-substring-no-properties (match-end 0) (point-at-eol)))) (pos-before-blank (progn (forward-line) (point))) @@ -2034,9 +2140,8 @@ containing `:key', `:value', `:begin', `:end', `:post-blank' and :post-affiliated post-affiliated) (cdr affiliated)))))) -(defun org-element-keyword-interpreter (keyword contents) - "Interpret KEYWORD element as Org syntax. -CONTENTS is nil." +(defun org-element-keyword-interpreter (keyword _) + "Interpret KEYWORD element as Org syntax." (format "#+%s: %s" (org-element-property :key keyword) (org-element-property :value keyword))) @@ -2044,6 +2149,18 @@ CONTENTS is nil." ;;;; Latex Environment +(defconst org-element--latex-begin-environment + "^[ \t]*\\\\begin{\\([A-Za-z0-9*]+\\)}" + "Regexp matching the beginning of a LaTeX environment. +The environment is captured by the first group. + +See also `org-element--latex-end-environment'.") + +(defconst org-element--latex-end-environment + "\\\\end{%s}[ \t]*$" + "Format string matching the ending of a LaTeX environment. +See also `org-element--latex-begin-environment'.") + (defun org-element-latex-environment-parser (limit affiliated) "Parse a LaTeX environment. @@ -2060,8 +2177,8 @@ Assume point is at the beginning of the latex environment." (save-excursion (let ((case-fold-search t) (code-begin (point))) - (looking-at "[ \t]*\\\\begin{\\([A-Za-z0-9]+\\*?\\)}") - (if (not (re-search-forward (format "^[ \t]*\\\\end{%s}[ \t]*$" + (looking-at org-element--latex-begin-environment) + (if (not (re-search-forward (format org-element--latex-end-environment (regexp-quote (match-string 1))) limit t)) ;; Incomplete latex environment: parse it as a paragraph. @@ -2080,9 +2197,8 @@ Assume point is at the beginning of the latex environment." :post-affiliated code-begin) (cdr affiliated)))))))) -(defun org-element-latex-environment-interpreter (latex-environment contents) - "Interpret LATEX-ENVIRONMENT element as Org syntax. -CONTENTS is nil." +(defun org-element-latex-environment-interpreter (latex-environment _) + "Interpret LATEX-ENVIRONMENT element as Org syntax." (org-element-property :value latex-environment)) @@ -2094,12 +2210,13 @@ CONTENTS is nil." LIMIT bounds the search. Return a list whose CAR is `node-property' and CDR is a plist -containing `:key', `:value', `:begin', `:end' and `:post-blank' -keywords." +containing `:key', `:value', `:begin', `:end', `:post-blank' and +`:post-affiliated' keywords." (looking-at org-property-re) - (let ((begin (point)) - (key (org-match-string-no-properties 2)) - (value (org-match-string-no-properties 3)) + (let ((case-fold-search t) + (begin (point)) + (key (match-string-no-properties 2)) + (value (match-string-no-properties 3)) (end (save-excursion (end-of-line) (if (re-search-forward org-property-re limit t) @@ -2110,11 +2227,11 @@ keywords." :value value :begin begin :end end - :post-blank 0)))) + :post-blank 0 + :post-affiliated begin)))) -(defun org-element-node-property-interpreter (node-property contents) - "Interpret NODE-PROPERTY element as Org syntax. -CONTENTS is nil." +(defun org-element-node-property-interpreter (node-property _) + "Interpret NODE-PROPERTY element as Org syntax." (format org-property-format (format ":%s:" (org-element-property :key node-property)) (or (org-element-property :value node-property) ""))) @@ -2141,66 +2258,42 @@ Assume point is at the beginning of the paragraph." (before-blank (let ((case-fold-search t)) (end-of-line) - (if (not (re-search-forward - org-element-paragraph-separate limit 'm)) - limit - ;; A matching `org-element-paragraph-separate' is not - ;; necessarily the end of the paragraph. In - ;; particular, lines starting with # or : as a first - ;; non-space character are ambiguous. We have to - ;; check if they are valid Org syntax (e.g., not an - ;; incomplete keyword). - (beginning-of-line) - (while (not - (or - ;; There's no ambiguity for other symbols or - ;; empty lines: stop here. - (looking-at "[ \t]*\\(?:[^:#]\\|$\\)") - ;; Stop at valid fixed-width areas. - (looking-at "[ \t]*:\\(?: \\|$\\)") - ;; Stop at drawers. - (and (looking-at org-drawer-regexp) - (save-excursion - (re-search-forward - "^[ \t]*:END:[ \t]*$" limit t))) - ;; Stop at valid comments. - (looking-at "[ \t]*#\\(?: \\|$\\)") - ;; Stop at valid dynamic blocks. - (and (looking-at org-dblock-start-re) - (save-excursion - (re-search-forward - "^[ \t]*#\\+END:?[ \t]*$" limit t))) - ;; Stop at valid blocks. - (and (looking-at "[ \t]*#\\+BEGIN_\\(\\S-+\\)") - (save-excursion - (re-search-forward - (format "^[ \t]*#\\+END_%s[ \t]*$" - (regexp-quote - (org-match-string-no-properties 1))) - limit t))) - ;; Stop at valid latex environments. - (and (looking-at - "[ \t]*\\\\begin{\\([A-Za-z0-9]+\\*?\\)}") - (save-excursion - (re-search-forward - (format "^[ \t]*\\\\end{%s}[ \t]*$" - (regexp-quote - (org-match-string-no-properties 1))) - limit t))) - ;; Stop at valid keywords. - (looking-at "[ \t]*#\\+\\S-+:") - ;; Skip everything else. - (not - (progn - (end-of-line) - (re-search-forward org-element-paragraph-separate - limit 'm))))) - (beginning-of-line))) + ;; A matching `org-element-paragraph-separate' is not + ;; necessarily the end of the paragraph. In particular, + ;; drawers, blocks or LaTeX environments opening lines + ;; must be closed. Moreover keywords with a secondary + ;; value must belong to "dual keywords". + (while (not + (cond + ((not (and (re-search-forward + org-element-paragraph-separate limit 'move) + (progn (beginning-of-line) t)))) + ((looking-at org-drawer-regexp) + (save-excursion + (re-search-forward "^[ \t]*:END:[ \t]*$" limit t))) + ((looking-at "[ \t]*#\\+BEGIN_\\(\\S-+\\)") + (save-excursion + (re-search-forward + (format "^[ \t]*#\\+END_%s[ \t]*$" + (regexp-quote (match-string 1))) + limit t))) + ((looking-at org-element--latex-begin-environment) + (save-excursion + (re-search-forward + (format org-element--latex-end-environment + (regexp-quote (match-string 1))) + limit t))) + ((looking-at "[ \t]*#\\+\\(\\S-+\\)\\[.*\\]:") + (member-ignore-case (match-string 1) + org-element-dual-keywords)) + ;; Everything else is unambiguous. + (t))) + (end-of-line)) (if (= (point) limit) limit (goto-char (line-beginning-position))))) - (contents-end (progn (skip-chars-backward " \r\t\n" contents-begin) - (forward-line) - (point))) + (contents-end (save-excursion + (skip-chars-backward " \r\t\n" contents-begin) + (line-beginning-position 2))) (end (progn (skip-chars-forward " \r\t\n" limit) (if (eobp) (point) (line-beginning-position))))) (list 'paragraph @@ -2213,8 +2306,8 @@ Assume point is at the beginning of the paragraph." :post-affiliated contents-begin) (cdr affiliated)))))) -(defun org-element-paragraph-interpreter (paragraph contents) - "Interpret PARAGRAPH element as Org syntax. +(defun org-element-paragraph-interpreter (_ contents) + "Interpret paragraph element as Org syntax. CONTENTS is the contents of the element." contents) @@ -2227,8 +2320,8 @@ CONTENTS is the contents of the element." LIMIT bounds the search. Return a list whose CAR is `planning' and CDR is a plist -containing `:closed', `:deadline', `:scheduled', `:begin', `:end' -and `:post-blank' keywords." +containing `:closed', `:deadline', `:scheduled', `:begin', +`:end', `:post-blank' and `:post-affiliated' keywords." (save-excursion (let* ((case-fold-search nil) (begin (point)) @@ -2254,13 +2347,13 @@ and `:post-blank' keywords." :scheduled scheduled :begin begin :end end - :post-blank post-blank))))) + :post-blank post-blank + :post-affiliated begin))))) -(defun org-element-planning-interpreter (planning contents) - "Interpret PLANNING element as Org syntax. -CONTENTS is nil." +(defun org-element-planning-interpreter (planning _) + "Interpret PLANNING element as Org syntax." (mapconcat - 'identity + #'identity (delq nil (list (let ((deadline (org-element-property :deadline planning))) (when deadline @@ -2277,37 +2370,6 @@ CONTENTS is nil." " ")) -;;;; Quote Section - -(defun org-element-quote-section-parser (limit) - "Parse a quote section. - -LIMIT bounds the search. - -Return a list whose CAR is `quote-section' and CDR is a plist -containing `:begin', `:end', `:value' and `:post-blank' keywords. - -Assume point is at beginning of the section." - (save-excursion - (let* ((begin (point)) - (end (progn (org-with-limited-levels (outline-next-heading)) - (point))) - (pos-before-blank (progn (skip-chars-backward " \r\t\n") - (forward-line) - (point))) - (value (buffer-substring-no-properties begin pos-before-blank))) - (list 'quote-section - (list :begin begin - :end end - :value value - :post-blank (count-lines pos-before-blank end)))))) - -(defun org-element-quote-section-interpreter (quote-section contents) - "Interpret QUOTE-SECTION element as Org syntax. -CONTENTS is nil." - (org-element-property :value quote-section)) - - ;;;; Src Block (defun org-element-src-block-parser (limit affiliated) @@ -2320,9 +2382,9 @@ their value. Return a list whose CAR is `src-block' and CDR is a plist containing `:language', `:switches', `:parameters', `:begin', -`:end', `:hiddenp', `:number-lines', `:retain-labels', -`:use-labels', `:label-fmt', `:preserve-indent', `:value', -`:post-blank' and `:post-affiliated' keywords. +`:end', `:number-lines', `:retain-labels', `:use-labels', +`:label-fmt', `:preserve-indent', `:value', `:post-blank' and +`:post-affiliated' keywords. Assume point is at the beginning of the block." (let ((case-fold-search t)) @@ -2338,23 +2400,30 @@ Assume point is at the beginning of the block." (language (progn (looking-at - (concat "^[ \t]*#\\+BEGIN_SRC" - "\\(?: +\\(\\S-+\\)\\)?" - "\\(\\(?: +\\(?:-l \".*?\"\\|[-+][A-Za-z]\\)\\)+\\)?" - "\\(.*\\)[ \t]*$")) - (org-match-string-no-properties 1))) + "^[ \t]*#\\+BEGIN_SRC\ +\\(?: +\\(\\S-+\\)\\)?\ +\\(\\(?: +\\(?:-\\(?:l \".+\"\\|[ikr]\\)\\|[-+]n\\(?: *[0-9]+\\)?\\)\\)+\\)?\ +\\(.*\\)[ \t]*$") + (match-string-no-properties 1))) ;; Get switches. - (switches (org-match-string-no-properties 2)) + (switches (match-string-no-properties 2)) ;; Get parameters. - (parameters (org-match-string-no-properties 3)) - ;; Switches analysis + (parameters (match-string-no-properties 3)) + ;; Switches analysis. (number-lines - (cond ((not switches) nil) - ((string-match "-n\\>" switches) 'new) - ((string-match "+n\\>" switches) 'continued))) - (preserve-indent (or org-src-preserve-indentation - (and switches - (string-match "-i\\>" switches)))) + (and switches + (string-match "\\([-+]\\)n\\(?: *\\([0-9]+\\)\\)?\\>" + switches) + (cons + (if (equal (match-string 1 switches) "-") + 'new + 'continued) + (if (not (match-end 2)) 0 + ;; Subtract 1 to give number of lines before + ;; first line. + (1- (string-to-number (match-string 2 switches))))))) + (preserve-indent (and switches + (string-match "-i\\>" switches))) (label-fmt (and switches (string-match "-l +\"\\([^\"\n]+\\)\"" switches) @@ -2371,16 +2440,10 @@ Assume point is at the beginning of the block." (or (not switches) (and retain-labels (not (string-match "-k\\>" switches))))) - ;; Indentation. - (block-ind (progn (skip-chars-forward " \t") (current-column))) - ;; Get visibility status. - (hidden (progn (forward-line) (org-invisible-p2))) ;; Retrieve code. - (value (org-element--remove-indentation - (org-unescape-code-in-string - (buffer-substring-no-properties - (point) contents-end)) - (and preserve-indent block-ind))) + (value (org-unescape-code-in-string + (buffer-substring-no-properties + (line-beginning-position 2) contents-end))) (pos-before-blank (progn (goto-char contents-end) (forward-line) (point))) @@ -2401,32 +2464,33 @@ Assume point is at the beginning of the block." :retain-labels retain-labels :use-labels use-labels :label-fmt label-fmt - :hiddenp hidden :value value :post-blank (count-lines pos-before-blank end) :post-affiliated post-affiliated) (cdr affiliated))))))))) -(defun org-element-src-block-interpreter (src-block contents) - "Interpret SRC-BLOCK element as Org syntax. -CONTENTS is nil." +(defun org-element-src-block-interpreter (src-block _) + "Interpret SRC-BLOCK element as Org syntax." (let ((lang (org-element-property :language src-block)) (switches (org-element-property :switches src-block)) (params (org-element-property :parameters src-block)) - (value (let ((val (org-element-property :value src-block))) - (cond - ((org-element-property :preserve-indent src-block) val) - ((zerop org-edit-src-content-indentation) val) - (t - (let ((ind (make-string - org-edit-src-content-indentation 32))) - (replace-regexp-in-string - "\\(^\\)[ \t]*\\S-" ind val nil nil 1))))))) + (value + (let ((val (org-element-property :value src-block))) + (cond + ((or org-src-preserve-indentation + (org-element-property :preserve-indent src-block)) + val) + ((zerop org-edit-src-content-indentation) + (org-remove-indentation val)) + (t + (let ((ind (make-string org-edit-src-content-indentation ?\s))) + (replace-regexp-in-string + "^" ind (org-remove-indentation val)))))))) (concat (format "#+BEGIN_SRC%s\n" (concat (and lang (concat " " lang)) (and switches (concat " " switches)) (and params (concat " " params)))) - (org-escape-code-in-string value) + (org-element-normalize-string (org-escape-code-in-string value)) "#+END_SRC"))) @@ -2449,15 +2513,17 @@ Assume point is at the beginning of the table." (save-excursion (let* ((case-fold-search t) (table-begin (point)) - (type (if (org-at-table.el-p) 'table.el 'org)) + (type (if (looking-at "[ \t]*|") 'org 'table.el)) + (end-re (format "^[ \t]*\\($\\|[^| \t%s]\\)" + (if (eq type 'org) "" "+"))) (begin (car affiliated)) (table-end - (if (re-search-forward org-table-any-border-regexp limit 'm) + (if (re-search-forward end-re limit 'move) (goto-char (match-beginning 0)) (point))) (tblfm (let (acc) (while (looking-at "[ \t]*#\\+TBLFM: +\\(.*\\)[ \t]*$") - (push (org-match-string-no-properties 1) acc) + (push (match-string-no-properties 1) acc) (forward-line)) acc)) (pos-before-blank (point)) @@ -2496,41 +2562,38 @@ CONTENTS is a string, if table's type is `org', or nil." ;;;; Table Row -(defun org-element-table-row-parser (limit) +(defun org-element-table-row-parser (_) "Parse table row at point. -LIMIT bounds the search. - Return a list whose CAR is `table-row' and CDR is a plist containing `:begin', `:end', `:contents-begin', `:contents-end', -`:type' and `:post-blank' keywords." +`:type', `:post-blank' and `:post-affiliated' keywords." (save-excursion (let* ((type (if (looking-at "^[ \t]*|-") 'rule 'standard)) (begin (point)) ;; A table rule has no contents. In that case, ensure ;; CONTENTS-BEGIN matches CONTENTS-END. - (contents-begin (and (eq type 'standard) - (search-forward "|") - (point))) + (contents-begin (and (eq type 'standard) (search-forward "|"))) (contents-end (and (eq type 'standard) (progn (end-of-line) (skip-chars-backward " \t") (point)))) - (end (progn (forward-line) (point)))) + (end (line-beginning-position 2))) (list 'table-row (list :type type :begin begin :end end :contents-begin contents-begin :contents-end contents-end - :post-blank 0))))) + :post-blank 0 + :post-affiliated begin))))) (defun org-element-table-row-interpreter (table-row contents) "Interpret TABLE-ROW element as Org syntax. CONTENTS is the contents of the table row." (if (eq (org-element-property :type table-row) 'rule) "|-" - (concat "| " contents))) + (concat "|" contents))) ;;;; Verse Block @@ -2545,7 +2608,7 @@ their value. Return a list whose CAR is `verse-block' and CDR is a plist containing `:begin', `:end', `:contents-begin', `:contents-end', -`:hiddenp', `:post-blank' and `:post-affiliated' keywords. +`:post-blank' and `:post-affiliated' keywords. Assume point is at beginning of the block." (let ((case-fold-search t)) @@ -2557,8 +2620,7 @@ Assume point is at beginning of the block." (save-excursion (let* ((begin (car affiliated)) (post-affiliated (point)) - (hidden (progn (forward-line) (org-invisible-p2))) - (contents-begin (point)) + (contents-begin (progn (forward-line) (point))) (pos-before-blank (progn (goto-char contents-end) (forward-line) (point))) @@ -2570,13 +2632,12 @@ Assume point is at beginning of the block." :end end :contents-begin contents-begin :contents-end contents-end - :hiddenp hidden :post-blank (count-lines pos-before-blank end) :post-affiliated post-affiliated) (cdr affiliated))))))))) -(defun org-element-verse-block-interpreter (verse-block contents) - "Interpret VERSE-BLOCK element as Org syntax. +(defun org-element-verse-block-interpreter (_ contents) + "Interpret verse-block element as Org syntax. CONTENTS is verse block contents." (format "#+BEGIN_VERSE\n%s#+END_VERSE" contents)) @@ -2584,373 +2645,289 @@ CONTENTS is verse block contents." ;;; Objects ;; -;; Unlike to elements, interstices can be found between objects. -;; That's why, along with the parser, successor functions are provided -;; for each object. Some objects share the same successor (e.g., -;; `code' and `verbatim' objects). -;; -;; A successor must accept a single argument bounding the search. It -;; will return either a cons cell whose CAR is the object's type, as -;; a symbol, and CDR the position of its next occurrence, or nil. -;; -;; Successors follow the naming convention: -;; org-element-NAME-successor, where NAME is the name of the -;; successor, as defined in `org-element-all-successors'. +;; Unlike to elements, raw text can be found between objects. Hence, +;; `org-element--object-lex' is provided to find the next object in +;; buffer. ;; ;; Some object types (e.g., `italic') are recursive. Restrictions on ;; object types they can contain will be specified in ;; `org-element-object-restrictions'. ;; -;; Adding a new type of object is simple. Implement a successor, -;; a parser, and an interpreter for it, all following the naming -;; convention. Register type in `org-element-all-objects' and -;; successor in `org-element-all-successors'. Maybe tweak -;; restrictions about it, and that's it. - +;; Creating a new type of object requires to alter +;; `org-element--object-regexp' and `org-element--object-lex', add the +;; new type in `org-element-all-objects', and possibly add +;; restrictions in `org-element-object-restrictions'. ;;;; Bold (defun org-element-bold-parser () - "Parse bold object at point. + "Parse bold object at point, if any. -Return a list whose CAR is `bold' and CDR is a plist with -`:begin', `:end', `:contents-begin' and `:contents-end' and -`:post-blank' keywords. +When at a bold object, return a list whose car is `bold' and cdr +is a plist with `:begin', `:end', `:contents-begin' and +`:contents-end' and `:post-blank' keywords. Otherwise, return +nil. Assume point is at the first star marker." (save-excursion (unless (bolp) (backward-char 1)) - (looking-at org-emph-re) - (let ((begin (match-beginning 2)) - (contents-begin (match-beginning 4)) - (contents-end (match-end 4)) - (post-blank (progn (goto-char (match-end 2)) - (skip-chars-forward " \t"))) - (end (point))) - (list 'bold - (list :begin begin - :end end - :contents-begin contents-begin - :contents-end contents-end - :post-blank post-blank))))) - -(defun org-element-bold-interpreter (bold contents) - "Interpret BOLD object as Org syntax. + (when (looking-at org-emph-re) + (let ((begin (match-beginning 2)) + (contents-begin (match-beginning 4)) + (contents-end (match-end 4)) + (post-blank (progn (goto-char (match-end 2)) + (skip-chars-forward " \t"))) + (end (point))) + (list 'bold + (list :begin begin + :end end + :contents-begin contents-begin + :contents-end contents-end + :post-blank post-blank)))))) + +(defun org-element-bold-interpreter (_ contents) + "Interpret bold object as Org syntax. CONTENTS is the contents of the object." (format "*%s*" contents)) -(defun org-element-text-markup-successor () - "Search for the next text-markup object. - -Return value is a cons cell whose CAR is a symbol among `bold', -`italic', `underline', `strike-through', `code' and `verbatim' -and CDR is beginning position." - (save-excursion - (unless (bolp) (backward-char)) - (when (re-search-forward org-emph-re nil t) - (let ((marker (match-string 3))) - (cons (cond - ((equal marker "*") 'bold) - ((equal marker "/") 'italic) - ((equal marker "_") 'underline) - ((equal marker "+") 'strike-through) - ((equal marker "~") 'code) - ((equal marker "=") 'verbatim) - (t (error "Unknown marker at %d" (match-beginning 3)))) - (match-beginning 2)))))) - ;;;; Code (defun org-element-code-parser () - "Parse code object at point. + "Parse code object at point, if any. -Return a list whose CAR is `code' and CDR is a plist with -`:value', `:begin', `:end' and `:post-blank' keywords. +When at a code object, return a list whose car is `code' and cdr +is a plist with `:value', `:begin', `:end' and `:post-blank' +keywords. Otherwise, return nil. Assume point is at the first tilde marker." (save-excursion (unless (bolp) (backward-char 1)) - (looking-at org-emph-re) - (let ((begin (match-beginning 2)) - (value (org-match-string-no-properties 4)) - (post-blank (progn (goto-char (match-end 2)) - (skip-chars-forward " \t"))) - (end (point))) - (list 'code - (list :value value - :begin begin - :end end - :post-blank post-blank))))) - -(defun org-element-code-interpreter (code contents) - "Interpret CODE object as Org syntax. -CONTENTS is nil." + (when (looking-at org-emph-re) + (let ((begin (match-beginning 2)) + (value (match-string-no-properties 4)) + (post-blank (progn (goto-char (match-end 2)) + (skip-chars-forward " \t"))) + (end (point))) + (list 'code + (list :value value + :begin begin + :end end + :post-blank post-blank)))))) + +(defun org-element-code-interpreter (code _) + "Interpret CODE object as Org syntax." (format "~%s~" (org-element-property :value code))) ;;;; Entity (defun org-element-entity-parser () - "Parse entity at point. + "Parse entity at point, if any. -Return a list whose CAR is `entity' and CDR a plist with -`:begin', `:end', `:latex', `:latex-math-p', `:html', `:latin1', -`:utf-8', `:ascii', `:use-brackets-p' and `:post-blank' as -keywords. +When at an entity, return a list whose car is `entity' and cdr +a plist with `:begin', `:end', `:latex', `:latex-math-p', +`:html', `:latin1', `:utf-8', `:ascii', `:use-brackets-p' and +`:post-blank' as keywords. Otherwise, return nil. Assume point is at the beginning of the entity." - (save-excursion - (looking-at "\\\\\\(there4\\|sup[123]\\|frac[13][24]\\|[a-zA-Z]+\\)\\($\\|{}\\|[^[:alpha:]]\\)") - (let* ((value (org-entity-get (match-string 1))) - (begin (match-beginning 0)) - (bracketsp (string= (match-string 2) "{}")) - (post-blank (progn (goto-char (match-end 1)) - (when bracketsp (forward-char 2)) - (skip-chars-forward " \t"))) - (end (point))) - (list 'entity - (list :name (car value) - :latex (nth 1 value) - :latex-math-p (nth 2 value) - :html (nth 3 value) - :ascii (nth 4 value) - :latin1 (nth 5 value) - :utf-8 (nth 6 value) - :begin begin - :end end - :use-brackets-p bracketsp - :post-blank post-blank))))) - -(defun org-element-entity-interpreter (entity contents) - "Interpret ENTITY object as Org syntax. -CONTENTS is nil." + (catch 'no-object + (when (looking-at "\\\\\\(?:\\(?1:_ +\\)\\|\\(?1:there4\\|sup[123]\\|frac[13][24]\\|[a-zA-Z]+\\)\\(?2:$\\|{}\\|[^[:alpha:]]\\)\\)") + (save-excursion + (let* ((value (or (org-entity-get (match-string 1)) + (throw 'no-object nil))) + (begin (match-beginning 0)) + (bracketsp (string= (match-string 2) "{}")) + (post-blank (progn (goto-char (match-end 1)) + (when bracketsp (forward-char 2)) + (skip-chars-forward " \t"))) + (end (point))) + (list 'entity + (list :name (car value) + :latex (nth 1 value) + :latex-math-p (nth 2 value) + :html (nth 3 value) + :ascii (nth 4 value) + :latin1 (nth 5 value) + :utf-8 (nth 6 value) + :begin begin + :end end + :use-brackets-p bracketsp + :post-blank post-blank))))))) + +(defun org-element-entity-interpreter (entity _) + "Interpret ENTITY object as Org syntax." (concat "\\" (org-element-property :name entity) (when (org-element-property :use-brackets-p entity) "{}"))) -(defun org-element-latex-or-entity-successor () - "Search for the next latex-fragment or entity object. - -Return value is a cons cell whose CAR is `entity' or -`latex-fragment' and CDR is beginning position." - (save-excursion - (unless (bolp) (backward-char)) - (let ((matchers (cdr org-latex-regexps)) - ;; ENTITY-RE matches both LaTeX commands and Org entities. - (entity-re - "\\\\\\(there4\\|sup[123]\\|frac[13][24]\\|[a-zA-Z]+\\)\\($\\|{}\\|[^[:alpha:]]\\)")) - (when (re-search-forward - (concat (mapconcat #'cadr matchers "\\|") "\\|" entity-re) nil t) - (goto-char (match-beginning 0)) - (if (looking-at entity-re) - ;; Determine if it's a real entity or a LaTeX command. - (cons (if (org-entity-get (match-string 1)) 'entity 'latex-fragment) - (match-beginning 0)) - ;; No entity nor command: point is at a LaTeX fragment. - ;; Determine its type to get the correct beginning position. - (cons 'latex-fragment - (catch 'return - (dolist (e matchers) - (when (looking-at (nth 1 e)) - (throw 'return (match-beginning (nth 2 e))))) - (point)))))))) - ;;;; Export Snippet (defun org-element-export-snippet-parser () "Parse export snippet at point. -Return a list whose CAR is `export-snippet' and CDR a plist with -`:begin', `:end', `:back-end', `:value' and `:post-blank' as -keywords. +When at an export snippet, return a list whose car is +`export-snippet' and cdr a plist with `:begin', `:end', +`:back-end', `:value' and `:post-blank' as keywords. Otherwise, +return nil. Assume point is at the beginning of the snippet." (save-excursion - (re-search-forward "@@\\([-A-Za-z0-9]+\\):" nil t) - (let* ((begin (match-beginning 0)) - (back-end (org-match-string-no-properties 1)) - (value (buffer-substring-no-properties - (point) - (progn (re-search-forward "@@" nil t) (match-beginning 0)))) - (post-blank (skip-chars-forward " \t")) - (end (point))) - (list 'export-snippet - (list :back-end back-end - :value value - :begin begin - :end end - :post-blank post-blank))))) - -(defun org-element-export-snippet-interpreter (export-snippet contents) - "Interpret EXPORT-SNIPPET object as Org syntax. -CONTENTS is nil." + (let (contents-end) + (when (and (looking-at "@@\\([-A-Za-z0-9]+\\):") + (setq contents-end + (save-match-data (goto-char (match-end 0)) + (re-search-forward "@@" nil t) + (match-beginning 0)))) + (let* ((begin (match-beginning 0)) + (back-end (match-string-no-properties 1)) + (value (buffer-substring-no-properties + (match-end 0) contents-end)) + (post-blank (skip-chars-forward " \t")) + (end (point))) + (list 'export-snippet + (list :back-end back-end + :value value + :begin begin + :end end + :post-blank post-blank))))))) + +(defun org-element-export-snippet-interpreter (export-snippet _) + "Interpret EXPORT-SNIPPET object as Org syntax." (format "@@%s:%s@@" (org-element-property :back-end export-snippet) (org-element-property :value export-snippet))) -(defun org-element-export-snippet-successor () - "Search for the next export-snippet object. - -Return value is a cons cell whose CAR is `export-snippet' and CDR -its beginning position." - (save-excursion - (let (beg) - (when (and (re-search-forward "@@[-A-Za-z0-9]+:" nil t) - (setq beg (match-beginning 0)) - (search-forward "@@" nil t)) - (cons 'export-snippet beg))))) - ;;;; Footnote Reference (defun org-element-footnote-reference-parser () - "Parse footnote reference at point. - -Return a list whose CAR is `footnote-reference' and CDR a plist -with `:label', `:type', `:inline-definition', `:begin', `:end' -and `:post-blank' as keywords." - (save-excursion - (looking-at org-footnote-re) - (let* ((begin (point)) - (label (or (org-match-string-no-properties 2) - (org-match-string-no-properties 3) - (and (match-string 1) - (concat "fn:" (org-match-string-no-properties 1))))) - (type (if (or (not label) (match-string 1)) 'inline 'standard)) - (inner-begin (match-end 0)) - (inner-end - (let ((count 1)) - (forward-char) - (while (and (> count 0) (re-search-forward "[][]" nil t)) - (if (equal (match-string 0) "[") (incf count) (decf count))) - (1- (point)))) - (post-blank (progn (goto-char (1+ inner-end)) - (skip-chars-forward " \t"))) - (end (point)) - (footnote-reference + "Parse footnote reference at point, if any. + +When at a footnote reference, return a list whose car is +`footnote-reference' and cdr a plist with `:label', `:type', +`:begin', `:end', `:content-begin', `:contents-end' and +`:post-blank' as keywords. Otherwise, return nil." + (when (looking-at org-footnote-re) + (let ((closing (with-syntax-table org-element--pair-square-table + (ignore-errors (scan-lists (point) 1 0))))) + (when closing + (save-excursion + (let* ((begin (point)) + (label (match-string-no-properties 1)) + (inner-begin (match-end 0)) + (inner-end (1- closing)) + (type (if (match-end 2) 'inline 'standard)) + (post-blank (progn (goto-char closing) + (skip-chars-forward " \t"))) + (end (point))) (list 'footnote-reference (list :label label :type type :begin begin :end end - :post-blank post-blank)))) - (org-element-put-property - footnote-reference :inline-definition - (and (eq type 'inline) - (org-element-parse-secondary-string - (buffer-substring inner-begin inner-end) - (org-element-restriction 'footnote-reference) - footnote-reference)))))) + :contents-begin (and (eq type 'inline) inner-begin) + :contents-end (and (eq type 'inline) inner-end) + :post-blank post-blank)))))))) (defun org-element-footnote-reference-interpreter (footnote-reference contents) "Interpret FOOTNOTE-REFERENCE object as Org syntax. -CONTENTS is nil." - (let ((label (or (org-element-property :label footnote-reference) "fn:")) - (def - (let ((inline-def - (org-element-property :inline-definition footnote-reference))) - (if (not inline-def) "" - (concat ":" (org-element-interpret-data inline-def)))))) - (format "[%s]" (concat label def)))) - -(defun org-element-footnote-reference-successor () - "Search for the next footnote-reference object. - -Return value is a cons cell whose CAR is `footnote-reference' and -CDR is beginning position." - (save-excursion - (catch 'exit - (while (re-search-forward org-footnote-re nil t) - (save-excursion - (let ((beg (match-beginning 0)) - (count 1)) - (backward-char) - (while (re-search-forward "[][]" nil t) - (if (equal (match-string 0) "[") (incf count) (decf count)) - (when (zerop count) - (throw 'exit (cons 'footnote-reference beg)))))))))) +CONTENTS is its definition, when inline, or nil." + (format "[fn:%s%s]" + (or (org-element-property :label footnote-reference) "") + (if contents (concat ":" contents) ""))) ;;;; Inline Babel Call (defun org-element-inline-babel-call-parser () - "Parse inline babel call at point. + "Parse inline babel call at point, if any. -Return a list whose CAR is `inline-babel-call' and CDR a plist -with `:begin', `:end', `:info' and `:post-blank' as keywords. +When at an inline babel call, return a list whose car is +`inline-babel-call' and cdr a plist with `:call', +`:inside-header', `:arguments', `:end-header', `:begin', `:end', +`:value' and `:post-blank' as keywords. Otherwise, return nil. Assume point is at the beginning of the babel call." (save-excursion - (unless (bolp) (backward-char)) - (looking-at org-babel-inline-lob-one-liner-regexp) - (let ((info (save-match-data (org-babel-lob-get-info))) - (begin (match-end 1)) - (post-blank (progn (goto-char (match-end 0)) - (skip-chars-forward " \t"))) - (end (point))) - (list 'inline-babel-call - (list :begin begin - :end end - :info info - :post-blank post-blank))))) - -(defun org-element-inline-babel-call-interpreter (inline-babel-call contents) - "Interpret INLINE-BABEL-CALL object as Org syntax. -CONTENTS is nil." - (let* ((babel-info (org-element-property :info inline-babel-call)) - (main-source (car babel-info)) - (post-options (nth 1 babel-info))) - (concat "call_" - (if (string-match "\\[\\(\\[.*?\\]\\)\\]" main-source) - ;; Remove redundant square brackets. - (replace-match - (match-string 1 main-source) nil nil main-source) - main-source) - (and post-options (format "[%s]" post-options))))) - -(defun org-element-inline-babel-call-successor () - "Search for the next inline-babel-call object. - -Return value is a cons cell whose CAR is `inline-babel-call' and -CDR is beginning position." - (save-excursion - (when (re-search-forward org-babel-inline-lob-one-liner-regexp nil t) - (cons 'inline-babel-call (match-end 1))))) + (catch :no-object + (when (let ((case-fold-search nil)) + (looking-at "\\ + (setq format 'plain) + (setq raw-link (match-string-no-properties 0)) + (setq type (match-string-no-properties 1)) + (setq link-end (match-end 0)) + (setq path (match-string-no-properties 2))) + ;; Type 4: Angular link, e.g., . Unlike to + ;; bracket links, follow RFC 3986 and remove any extra + ;; whitespace in URI. ((looking-at org-angle-link-re) - (setq raw-link (buffer-substring-no-properties - (match-beginning 1) (match-end 2)) - type (org-match-string-no-properties 1) - link-end (match-end 0) - path (org-match-string-no-properties 2)))) + (setq format 'angle) + (setq type (match-string-no-properties 1)) + (setq link-end (match-end 0)) + (setq raw-link + (buffer-substring-no-properties + (match-beginning 1) (match-end 2))) + (setq path (replace-regexp-in-string + "[ \t]*\n[ \t]*" "" (match-string-no-properties 2)))) + (t (throw 'no-object nil))) ;; In any case, deduce end point after trailing white space from ;; LINK-END variable. - (setq post-blank (progn (goto-char link-end) (skip-chars-forward " \t")) - end (point)) - ;; Special "file" type link processing. - (when (member type org-element-link-type-is-file) - ;; Extract opening application and search option. - (cond ((string-match "^file\\+\\(.*\\)$" type) - (setq application (match-string 1 type))) - ((not (string-match "^file" type)) - (setq application type))) + (save-excursion + (setq post-blank + (progn (goto-char link-end) (skip-chars-forward " \t"))) + (setq end (point))) + ;; Special "file" type link processing. Extract opening + ;; application and search option, if any. Also normalize URI. + (when (string-match "\\`file\\(?:\\+\\(.+\\)\\)?\\'" type) + (setq application (match-string 1 type) type "file") (when (string-match "::\\(.*\\)\\'" path) - (setq search-option (match-string 1 path) - path (replace-match "" nil nil path))) - ;; Normalize URI. - (when (and (not (org-string-match-p "\\`//" path)) - (file-name-absolute-p path)) - (setq path (concat "//" (expand-file-name path)))) - ;; Make sure TYPE always reports "file". - (setq type "file")) + (setq search-option (match-string 1 path)) + (setq path (replace-match "" nil nil path))) + (setq path (replace-regexp-in-string "\\`///*\\(.:\\)?/" "\\1/" path))) + ;; Translate link, if `org-link-translation-function' is set. + (let ((trans (and (functionp org-link-translation-function) + (funcall org-link-translation-function type path)))) + (when trans + (setq type (car trans)) + (setq path (cdr trans)))) (list 'link (list :type type :path path + :format format :raw-link (or raw-link path) :application application :search-option search-option @@ -3180,197 +3170,167 @@ Assume point is at the beginning of the link." "Interpret LINK object as Org syntax. CONTENTS is the contents of the object, or nil." (let ((type (org-element-property :type link)) - (raw-link (org-element-property :raw-link link))) - (if (string= type "radio") raw-link - (format "[[%s]%s]" - raw-link - (if contents (format "[%s]" contents) ""))))) - -(defun org-element-link-successor () - "Search for the next link object. - -Return value is a cons cell whose CAR is `link' and CDR is -beginning position." - (save-excursion - (let ((link-regexp - (if (not org-target-link-regexp) org-any-link-re - (concat org-any-link-re "\\|" org-target-link-regexp)))) - (when (re-search-forward link-regexp nil t) - (cons 'link (match-beginning 0)))))) - -(defun org-element-plain-link-successor () - "Search for the next plain link object. - -Return value is a cons cell whose CAR is `link' and CDR is -beginning position." - (and (save-excursion (re-search-forward org-plain-link-re nil t)) - (cons 'link (match-beginning 0)))) + (path (org-element-property :path link))) + (if (string= type "radio") path + (let ((fmt (pcase (org-element-property :format link) + ;; Links with contents and internal links have to + ;; use bracket syntax. Ignore `:format' in these + ;; cases. This is also the default syntax when the + ;; property is not defined, e.g., when the object + ;; was crafted by the user. + ((guard contents) + (format "[[%%s][%s]]" + ;; Since this is going to be used as + ;; a format string, escape percent signs + ;; in description. + (replace-regexp-in-string "%" "%%" contents))) + ((or `bracket + `nil + (guard (member type '("coderef" "custom-id" "fuzzy")))) + "[[%s]]") + ;; Otherwise, just obey to `:format'. + (`angle "<%s>") + (`plain "%s") + (f (error "Wrong `:format' value: %s" f))))) + (format fmt + (pcase type + ("coderef" (format "(%s)" path)) + ("custom-id" (concat "#" path)) + ("file" + (let ((app (org-element-property :application link)) + (opt (org-element-property :search-option link))) + (concat type (and app (concat "+" app)) ":" + path + (and opt (concat "::" opt))))) + ("fuzzy" path) + (_ (concat type ":" path)))))))) ;;;; Macro (defun org-element-macro-parser () - "Parse macro at point. + "Parse macro at point, if any. -Return a list whose CAR is `macro' and CDR a plist with `:key', -`:args', `:begin', `:end', `:value' and `:post-blank' as -keywords. +When at a macro, return a list whose car is `macro' and cdr +a plist with `:key', `:args', `:begin', `:end', `:value' and +`:post-blank' as keywords. Otherwise, return nil. Assume point is at the macro." (save-excursion - (looking-at "{{{\\([a-zA-Z][-a-zA-Z0-9_]*\\)\\(([ \t\n]*\\([^\000]*?\\))\\)?}}}") - (let ((begin (point)) - (key (downcase (org-match-string-no-properties 1))) - (value (org-match-string-no-properties 0)) - (post-blank (progn (goto-char (match-end 0)) - (skip-chars-forward " \t"))) - (end (point)) - (args (let ((args (org-match-string-no-properties 3))) - (when args - ;; Do not use `org-split-string' since empty - ;; strings are meaningful here. - (split-string - (replace-regexp-in-string - "\\(\\\\*\\)\\(,\\)" - (lambda (str) - (let ((len (length (match-string 1 str)))) - (concat (make-string (/ len 2) ?\\) - (if (zerop (mod len 2)) "\000" ",")))) - args nil t) - "\000"))))) - (list 'macro - (list :key key - :value value - :args args - :begin begin - :end end - :post-blank post-blank))))) - -(defun org-element-macro-interpreter (macro contents) - "Interpret MACRO object as Org syntax. -CONTENTS is nil." + (when (looking-at "{{{\\([a-zA-Z][-a-zA-Z0-9_]*\\)\\(([ \t\n]*\\([^\000]*?\\))\\)?}}}") + (let ((begin (point)) + (key (downcase (match-string-no-properties 1))) + (value (match-string-no-properties 0)) + (post-blank (progn (goto-char (match-end 0)) + (skip-chars-forward " \t"))) + (end (point)) + (args (let ((args (match-string-no-properties 3))) + (and args (org-macro-extract-arguments args))))) + (list 'macro + (list :key key + :value value + :args args + :begin begin + :end end + :post-blank post-blank)))))) + +(defun org-element-macro-interpreter (macro _) + "Interpret MACRO object as Org syntax." (org-element-property :value macro)) -(defun org-element-macro-successor () - "Search for the next macro object. - -Return value is cons cell whose CAR is `macro' and CDR is -beginning position." - (save-excursion - (when (re-search-forward - "{{{\\([a-zA-Z][-a-zA-Z0-9_]*\\)\\(([ \t\n]*\\([^\000]*?\\))\\)?}}}" - nil t) - (cons 'macro (match-beginning 0))))) - ;;;; Radio-target (defun org-element-radio-target-parser () - "Parse radio target at point. + "Parse radio target at point, if any. -Return a list whose CAR is `radio-target' and CDR a plist with -`:begin', `:end', `:contents-begin', `:contents-end', `:value' -and `:post-blank' as keywords. +When at a radio target, return a list whose car is `radio-target' +and cdr a plist with `:begin', `:end', `:contents-begin', +`:contents-end', `:value' and `:post-blank' as keywords. +Otherwise, return nil. Assume point is at the radio target." (save-excursion - (looking-at org-radio-target-regexp) - (let ((begin (point)) - (contents-begin (match-beginning 1)) - (contents-end (match-end 1)) - (value (org-match-string-no-properties 1)) - (post-blank (progn (goto-char (match-end 0)) - (skip-chars-forward " \t"))) - (end (point))) - (list 'radio-target - (list :begin begin - :end end - :contents-begin contents-begin - :contents-end contents-end - :post-blank post-blank - :value value))))) - -(defun org-element-radio-target-interpreter (target contents) - "Interpret TARGET object as Org syntax. + (when (looking-at org-radio-target-regexp) + (let ((begin (point)) + (contents-begin (match-beginning 1)) + (contents-end (match-end 1)) + (value (match-string-no-properties 1)) + (post-blank (progn (goto-char (match-end 0)) + (skip-chars-forward " \t"))) + (end (point))) + (list 'radio-target + (list :begin begin + :end end + :contents-begin contents-begin + :contents-end contents-end + :post-blank post-blank + :value value)))))) + +(defun org-element-radio-target-interpreter (_ contents) + "Interpret target object as Org syntax. CONTENTS is the contents of the object." (concat "<<<" contents ">>>")) -(defun org-element-radio-target-successor () - "Search for the next radio-target object. - -Return value is a cons cell whose CAR is `radio-target' and CDR -is beginning position." - (save-excursion - (when (re-search-forward org-radio-target-regexp nil t) - (cons 'radio-target (match-beginning 0))))) - ;;;; Statistics Cookie (defun org-element-statistics-cookie-parser () - "Parse statistics cookie at point. + "Parse statistics cookie at point, if any. -Return a list whose CAR is `statistics-cookie', and CDR a plist -with `:begin', `:end', `:value' and `:post-blank' keywords. +When at a statistics cookie, return a list whose car is +`statistics-cookie', and cdr a plist with `:begin', `:end', +`:value' and `:post-blank' keywords. Otherwise, return nil. Assume point is at the beginning of the statistics-cookie." (save-excursion - (looking-at "\\[[0-9]*\\(%\\|/[0-9]*\\)\\]") - (let* ((begin (point)) - (value (buffer-substring-no-properties - (match-beginning 0) (match-end 0))) - (post-blank (progn (goto-char (match-end 0)) - (skip-chars-forward " \t"))) - (end (point))) - (list 'statistics-cookie - (list :begin begin - :end end - :value value - :post-blank post-blank))))) - -(defun org-element-statistics-cookie-interpreter (statistics-cookie contents) - "Interpret STATISTICS-COOKIE object as Org syntax. -CONTENTS is nil." + (when (looking-at "\\[[0-9]*\\(%\\|/[0-9]*\\)\\]") + (let* ((begin (point)) + (value (buffer-substring-no-properties + (match-beginning 0) (match-end 0))) + (post-blank (progn (goto-char (match-end 0)) + (skip-chars-forward " \t"))) + (end (point))) + (list 'statistics-cookie + (list :begin begin + :end end + :value value + :post-blank post-blank)))))) + +(defun org-element-statistics-cookie-interpreter (statistics-cookie _) + "Interpret STATISTICS-COOKIE object as Org syntax." (org-element-property :value statistics-cookie)) -(defun org-element-statistics-cookie-successor () - "Search for the next statistics cookie object. - -Return value is a cons cell whose CAR is `statistics-cookie' and -CDR is beginning position." - (save-excursion - (when (re-search-forward "\\[[0-9]*\\(%\\|/[0-9]*\\)\\]" nil t) - (cons 'statistics-cookie (match-beginning 0))))) - ;;;; Strike-Through (defun org-element-strike-through-parser () - "Parse strike-through object at point. + "Parse strike-through object at point, if any. -Return a list whose CAR is `strike-through' and CDR is a plist -with `:begin', `:end', `:contents-begin' and `:contents-end' and -`:post-blank' keywords. +When at a strike-through object, return a list whose car is +`strike-through' and cdr is a plist with `:begin', `:end', +`:contents-begin' and `:contents-end' and `:post-blank' keywords. +Otherwise, return nil. Assume point is at the first plus sign marker." (save-excursion (unless (bolp) (backward-char 1)) - (looking-at org-emph-re) - (let ((begin (match-beginning 2)) - (contents-begin (match-beginning 4)) - (contents-end (match-end 4)) - (post-blank (progn (goto-char (match-end 2)) - (skip-chars-forward " \t"))) - (end (point))) - (list 'strike-through - (list :begin begin - :end end - :contents-begin contents-begin - :contents-end contents-end - :post-blank post-blank))))) - -(defun org-element-strike-through-interpreter (strike-through contents) - "Interpret STRIKE-THROUGH object as Org syntax. + (when (looking-at org-emph-re) + (let ((begin (match-beginning 2)) + (contents-begin (match-beginning 4)) + (contents-end (match-end 4)) + (post-blank (progn (goto-char (match-end 2)) + (skip-chars-forward " \t"))) + (end (point))) + (list 'strike-through + (list :begin begin + :end end + :contents-begin contents-begin + :contents-end contents-end + :post-blank post-blank)))))) + +(defun org-element-strike-through-interpreter (_ contents) + "Interpret strike-through object as Org syntax. CONTENTS is the contents of the object." (format "+%s+" contents)) @@ -3378,32 +3338,32 @@ CONTENTS is the contents of the object." ;;;; Subscript (defun org-element-subscript-parser () - "Parse subscript at point. + "Parse subscript at point, if any. -Return a list whose CAR is `subscript' and CDR a plist with -`:begin', `:end', `:contents-begin', `:contents-end', -`:use-brackets-p' and `:post-blank' as keywords. +When at a subscript object, return a list whose car is +`subscript' and cdr a plist with `:begin', `:end', +`:contents-begin', `:contents-end', `:use-brackets-p' and +`:post-blank' as keywords. Otherwise, return nil. Assume point is at the underscore." (save-excursion (unless (bolp) (backward-char)) - (let ((bracketsp (if (looking-at org-match-substring-with-braces-regexp) - t - (not (looking-at org-match-substring-regexp)))) - (begin (match-beginning 2)) - (contents-begin (or (match-beginning 5) - (match-beginning 3))) - (contents-end (or (match-end 5) (match-end 3))) - (post-blank (progn (goto-char (match-end 0)) - (skip-chars-forward " \t"))) - (end (point))) - (list 'subscript - (list :begin begin - :end end - :use-brackets-p bracketsp - :contents-begin contents-begin - :contents-end contents-end - :post-blank post-blank))))) + (when (looking-at org-match-substring-regexp) + (let ((bracketsp (match-beginning 4)) + (begin (match-beginning 2)) + (contents-begin (or (match-beginning 4) + (match-beginning 3))) + (contents-end (or (match-end 4) (match-end 3))) + (post-blank (progn (goto-char (match-end 0)) + (skip-chars-forward " \t"))) + (end (point))) + (list 'subscript + (list :begin begin + :end end + :use-brackets-p bracketsp + :contents-begin contents-begin + :contents-end contents-end + :post-blank post-blank)))))) (defun org-element-subscript-interpreter (subscript contents) "Interpret SUBSCRIPT object as Org syntax. @@ -3412,46 +3372,36 @@ CONTENTS is the contents of the object." (if (org-element-property :use-brackets-p subscript) "_{%s}" "_%s") contents)) -(defun org-element-sub/superscript-successor () - "Search for the next sub/superscript object. - -Return value is a cons cell whose CAR is either `subscript' or -`superscript' and CDR is beginning position." - (save-excursion - (unless (bolp) (backward-char)) - (when (re-search-forward org-match-substring-regexp nil t) - (cons (if (string= (match-string 2) "_") 'subscript 'superscript) - (match-beginning 2))))) - ;;;; Superscript (defun org-element-superscript-parser () - "Parse superscript at point. + "Parse superscript at point, if any. -Return a list whose CAR is `superscript' and CDR a plist with -`:begin', `:end', `:contents-begin', `:contents-end', -`:use-brackets-p' and `:post-blank' as keywords. +When at a superscript object, return a list whose car is +`superscript' and cdr a plist with `:begin', `:end', +`:contents-begin', `:contents-end', `:use-brackets-p' and +`:post-blank' as keywords. Otherwise, return nil. Assume point is at the caret." (save-excursion (unless (bolp) (backward-char)) - (let ((bracketsp (if (looking-at org-match-substring-with-braces-regexp) t - (not (looking-at org-match-substring-regexp)))) - (begin (match-beginning 2)) - (contents-begin (or (match-beginning 5) - (match-beginning 3))) - (contents-end (or (match-end 5) (match-end 3))) - (post-blank (progn (goto-char (match-end 0)) - (skip-chars-forward " \t"))) - (end (point))) - (list 'superscript - (list :begin begin - :end end - :use-brackets-p bracketsp - :contents-begin contents-begin - :contents-end contents-end - :post-blank post-blank))))) + (when (looking-at org-match-substring-regexp) + (let ((bracketsp (match-beginning 4)) + (begin (match-beginning 2)) + (contents-begin (or (match-beginning 4) + (match-beginning 3))) + (contents-end (or (match-end 4) (match-end 3))) + (post-blank (progn (goto-char (match-end 0)) + (skip-chars-forward " \t"))) + (end (point))) + (list 'superscript + (list :begin begin + :end end + :use-brackets-p bracketsp + :contents-begin contents-begin + :contents-end contents-end + :post-blank post-blank)))))) (defun org-element-superscript-interpreter (superscript contents) "Interpret SUPERSCRIPT object as Org syntax. @@ -3465,8 +3415,7 @@ CONTENTS is the contents of the object." (defun org-element-table-cell-parser () "Parse table cell at point. - -Return a list whose CAR is `table-cell' and CDR is a plist +Return a list whose car is `table-cell' and cdr is a plist containing `:begin', `:end', `:contents-begin', `:contents-end' and `:post-blank' keywords." (looking-at "[ \t]*\\(.*?\\)[ \t]*\\(?:|\\|$\\)") @@ -3481,299 +3430,275 @@ and `:post-blank' keywords." :contents-end contents-end :post-blank 0)))) -(defun org-element-table-cell-interpreter (table-cell contents) - "Interpret TABLE-CELL element as Org syntax. +(defun org-element-table-cell-interpreter (_ contents) + "Interpret table-cell element as Org syntax. CONTENTS is the contents of the cell, or nil." (concat " " contents " |")) -(defun org-element-table-cell-successor () - "Search for the next table-cell object. - -Return value is a cons cell whose CAR is `table-cell' and CDR is -beginning position." - (when (looking-at "[ \t]*.*?[ \t]*\\(|\\|$\\)") (cons 'table-cell (point)))) - ;;;; Target (defun org-element-target-parser () - "Parse target at point. + "Parse target at point, if any. -Return a list whose CAR is `target' and CDR a plist with -`:begin', `:end', `:value' and `:post-blank' as keywords. +When at a target, return a list whose car is `target' and cdr +a plist with `:begin', `:end', `:value' and `:post-blank' as +keywords. Otherwise, return nil. Assume point is at the target." (save-excursion - (looking-at org-target-regexp) - (let ((begin (point)) - (value (org-match-string-no-properties 1)) - (post-blank (progn (goto-char (match-end 0)) - (skip-chars-forward " \t"))) - (end (point))) - (list 'target - (list :begin begin - :end end - :value value - :post-blank post-blank))))) - -(defun org-element-target-interpreter (target contents) - "Interpret TARGET object as Org syntax. -CONTENTS is nil." + (when (looking-at org-target-regexp) + (let ((begin (point)) + (value (match-string-no-properties 1)) + (post-blank (progn (goto-char (match-end 0)) + (skip-chars-forward " \t"))) + (end (point))) + (list 'target + (list :begin begin + :end end + :value value + :post-blank post-blank)))))) + +(defun org-element-target-interpreter (target _) + "Interpret TARGET object as Org syntax." (format "<<%s>>" (org-element-property :value target))) -(defun org-element-target-successor () - "Search for the next target object. - -Return value is a cons cell whose CAR is `target' and CDR is -beginning position." - (save-excursion - (when (re-search-forward org-target-regexp nil t) - (cons 'target (match-beginning 0))))) - ;;;; Timestamp +(defconst org-element--timestamp-regexp + (concat org-ts-regexp-both + "\\|" + "\\(?:<[0-9]+-[0-9]+-[0-9]+[^>\n]+?\\+[0-9]+[dwmy]>\\)" + "\\|" + "\\(?:<%%\\(?:([^>\n]+)\\)>\\)") + "Regexp matching any timestamp type object.") + (defun org-element-timestamp-parser () - "Parse time stamp at point. + "Parse time stamp at point, if any. -Return a list whose CAR is `timestamp', and CDR a plist with -`:type', `:raw-value', `:year-start', `:month-start', -`:day-start', `:hour-start', `:minute-start', `:year-end', -`:month-end', `:day-end', `:hour-end', `:minute-end', -`:repeater-type', `:repeater-value', `:repeater-unit', -`:warning-type', `:warning-value', `:warning-unit', `:begin', -`:end' and `:post-blank' keywords. +When at a time stamp, return a list whose car is `timestamp', and +cdr a plist with `:type', `:raw-value', `:year-start', +`:month-start', `:day-start', `:hour-start', `:minute-start', +`:year-end', `:month-end', `:day-end', `:hour-end', +`:minute-end', `:repeater-type', `:repeater-value', +`:repeater-unit', `:warning-type', `:warning-value', +`:warning-unit', `:begin', `:end' and `:post-blank' keywords. +Otherwise, return nil. Assume point is at the beginning of the timestamp." - (save-excursion - (let* ((begin (point)) - (activep (eq (char-after) ?<)) - (raw-value - (progn - (looking-at "\\([<[]\\(%%\\)?.*?\\)[]>]\\(?:--\\([<[].*?[]>]\\)\\)?") - (match-string-no-properties 0))) - (date-start (match-string-no-properties 1)) - (date-end (match-string 3)) - (diaryp (match-beginning 2)) - (post-blank (progn (goto-char (match-end 0)) - (skip-chars-forward " \t"))) - (end (point)) - (time-range - (and (not diaryp) - (string-match - "[012]?[0-9]:[0-5][0-9]\\(-\\([012]?[0-9]\\):\\([0-5][0-9]\\)\\)" - date-start) - (cons (string-to-number (match-string 2 date-start)) - (string-to-number (match-string 3 date-start))))) - (type (cond (diaryp 'diary) - ((and activep (or date-end time-range)) 'active-range) - (activep 'active) - ((or date-end time-range) 'inactive-range) - (t 'inactive))) - (repeater-props - (and (not diaryp) - (string-match "\\([.+]?\\+\\)\\([0-9]+\\)\\([hdwmy]\\)" - raw-value) - (list - :repeater-type - (let ((type (match-string 1 raw-value))) - (cond ((equal "++" type) 'catch-up) - ((equal ".+" type) 'restart) - (t 'cumulate))) - :repeater-value (string-to-number (match-string 2 raw-value)) - :repeater-unit - (case (string-to-char (match-string 3 raw-value)) - (?h 'hour) (?d 'day) (?w 'week) (?m 'month) (t 'year))))) - (warning-props - (and (not diaryp) - (string-match "\\(-\\)?-\\([0-9]+\\)\\([hdwmy]\\)" raw-value) - (list - :warning-type (if (match-string 1 raw-value) 'first 'all) - :warning-value (string-to-number (match-string 2 raw-value)) - :warning-unit - (case (string-to-char (match-string 3 raw-value)) - (?h 'hour) (?d 'day) (?w 'week) (?m 'month) (t 'year))))) - year-start month-start day-start hour-start minute-start year-end - month-end day-end hour-end minute-end) - ;; Parse date-start. - (unless diaryp - (let ((date (org-parse-time-string date-start t))) - (setq year-start (nth 5 date) - month-start (nth 4 date) - day-start (nth 3 date) - hour-start (nth 2 date) - minute-start (nth 1 date)))) - ;; Compute date-end. It can be provided directly in time-stamp, - ;; or extracted from time range. Otherwise, it defaults to the - ;; same values as date-start. - (unless diaryp - (let ((date (and date-end (org-parse-time-string date-end t)))) - (setq year-end (or (nth 5 date) year-start) - month-end (or (nth 4 date) month-start) - day-end (or (nth 3 date) day-start) - hour-end (or (nth 2 date) (car time-range) hour-start) - minute-end (or (nth 1 date) (cdr time-range) minute-start)))) - (list 'timestamp - (nconc (list :type type - :raw-value raw-value - :year-start year-start - :month-start month-start - :day-start day-start - :hour-start hour-start - :minute-start minute-start - :year-end year-end - :month-end month-end - :day-end day-end - :hour-end hour-end - :minute-end minute-end - :begin begin - :end end - :post-blank post-blank) - repeater-props - warning-props))))) - -(defun org-element-timestamp-interpreter (timestamp contents) - "Interpret TIMESTAMP object as Org syntax. -CONTENTS is nil." - ;; Use `:raw-value' if specified. - (or (org-element-property :raw-value timestamp) - ;; Otherwise, build timestamp string. - (let* ((repeat-string - (concat - (case (org-element-property :repeater-type timestamp) - (cumulate "+") (catch-up "++") (restart ".+")) - (let ((val (org-element-property :repeater-value timestamp))) - (and val (number-to-string val))) - (case (org-element-property :repeater-unit timestamp) - (hour "h") (day "d") (week "w") (month "m") (year "y")))) - (warning-string - (concat - (case (org-element-property :warning-type timestamp) - (first "--") - (all "-")) - (let ((val (org-element-property :warning-value timestamp))) - (and val (number-to-string val))) - (case (org-element-property :warning-unit timestamp) - (hour "h") (day "d") (week "w") (month "m") (year "y")))) - (build-ts-string - ;; Build an Org timestamp string from TIME. ACTIVEP is - ;; non-nil when time stamp is active. If WITH-TIME-P is - ;; non-nil, add a time part. HOUR-END and MINUTE-END - ;; specify a time range in the timestamp. REPEAT-STRING - ;; is the repeater string, if any. - (lambda (time activep &optional with-time-p hour-end minute-end) - (let ((ts (format-time-string - (funcall (if with-time-p 'cdr 'car) - org-time-stamp-formats) - time))) - (when (and hour-end minute-end) - (string-match "[012]?[0-9]:[0-5][0-9]" ts) - (setq ts - (replace-match - (format "\\&-%02d:%02d" hour-end minute-end) - nil nil ts))) - (unless activep (setq ts (format "[%s]" (substring ts 1 -1)))) - (dolist (s (list repeat-string warning-string)) - (when (org-string-nw-p s) - (setq ts (concat (substring ts 0 -1) - " " - s - (substring ts -1))))) - ;; Return value. - ts))) - (type (org-element-property :type timestamp))) - (case type - ((active inactive) - (let* ((minute-start (org-element-property :minute-start timestamp)) - (minute-end (org-element-property :minute-end timestamp)) - (hour-start (org-element-property :hour-start timestamp)) - (hour-end (org-element-property :hour-end timestamp)) - (time-range-p (and hour-start hour-end minute-start minute-end - (or (/= hour-start hour-end) - (/= minute-start minute-end))))) - (funcall - build-ts-string - (encode-time 0 - (or minute-start 0) - (or hour-start 0) - (org-element-property :day-start timestamp) - (org-element-property :month-start timestamp) - (org-element-property :year-start timestamp)) - (eq type 'active) - (and hour-start minute-start) - (and time-range-p hour-end) - (and time-range-p minute-end)))) - ((active-range inactive-range) - (let ((minute-start (org-element-property :minute-start timestamp)) - (minute-end (org-element-property :minute-end timestamp)) - (hour-start (org-element-property :hour-start timestamp)) - (hour-end (org-element-property :hour-end timestamp))) - (concat - (funcall - build-ts-string (encode-time - 0 - (or minute-start 0) - (or hour-start 0) - (org-element-property :day-start timestamp) - (org-element-property :month-start timestamp) - (org-element-property :year-start timestamp)) - (eq type 'active-range) - (and hour-start minute-start)) - "--" - (funcall build-ts-string - (encode-time 0 - (or minute-end 0) - (or hour-end 0) - (org-element-property :day-end timestamp) - (org-element-property :month-end timestamp) - (org-element-property :year-end timestamp)) - (eq type 'active-range) - (and hour-end minute-end))))))))) - -(defun org-element-timestamp-successor () - "Search for the next timestamp object. - -Return value is a cons cell whose CAR is `timestamp' and CDR is -beginning position." - (save-excursion - (when (re-search-forward - (concat org-ts-regexp-both - "\\|" - "\\(?:<[0-9]+-[0-9]+-[0-9]+[^>\n]+?\\+[0-9]+[dwmy]>\\)" - "\\|" - "\\(?:<%%\\(?:([^>\n]+)\\)>\\)") - nil t) - (cons 'timestamp (match-beginning 0))))) + (when (looking-at-p org-element--timestamp-regexp) + (save-excursion + (let* ((begin (point)) + (activep (eq (char-after) ?<)) + (raw-value + (progn + (looking-at "\\([<[]\\(%%\\)?.*?\\)[]>]\\(?:--\\([<[].*?[]>]\\)\\)?") + (match-string-no-properties 0))) + (date-start (match-string-no-properties 1)) + (date-end (match-string 3)) + (diaryp (match-beginning 2)) + (post-blank (progn (goto-char (match-end 0)) + (skip-chars-forward " \t"))) + (end (point)) + (time-range + (and (not diaryp) + (string-match + "[012]?[0-9]:[0-5][0-9]\\(-\\([012]?[0-9]\\):\\([0-5][0-9]\\)\\)" + date-start) + (cons (string-to-number (match-string 2 date-start)) + (string-to-number (match-string 3 date-start))))) + (type (cond (diaryp 'diary) + ((and activep (or date-end time-range)) 'active-range) + (activep 'active) + ((or date-end time-range) 'inactive-range) + (t 'inactive))) + (repeater-props + (and (not diaryp) + (string-match "\\([.+]?\\+\\)\\([0-9]+\\)\\([hdwmy]\\)" + raw-value) + (list + :repeater-type + (let ((type (match-string 1 raw-value))) + (cond ((equal "++" type) 'catch-up) + ((equal ".+" type) 'restart) + (t 'cumulate))) + :repeater-value (string-to-number (match-string 2 raw-value)) + :repeater-unit + (pcase (string-to-char (match-string 3 raw-value)) + (?h 'hour) (?d 'day) (?w 'week) (?m 'month) (_ 'year))))) + (warning-props + (and (not diaryp) + (string-match "\\(-\\)?-\\([0-9]+\\)\\([hdwmy]\\)" raw-value) + (list + :warning-type (if (match-string 1 raw-value) 'first 'all) + :warning-value (string-to-number (match-string 2 raw-value)) + :warning-unit + (pcase (string-to-char (match-string 3 raw-value)) + (?h 'hour) (?d 'day) (?w 'week) (?m 'month) (_ 'year))))) + year-start month-start day-start hour-start minute-start year-end + month-end day-end hour-end minute-end) + ;; Parse date-start. + (unless diaryp + (let ((date (org-parse-time-string date-start t))) + (setq year-start (nth 5 date) + month-start (nth 4 date) + day-start (nth 3 date) + hour-start (nth 2 date) + minute-start (nth 1 date)))) + ;; Compute date-end. It can be provided directly in time-stamp, + ;; or extracted from time range. Otherwise, it defaults to the + ;; same values as date-start. + (unless diaryp + (let ((date (and date-end (org-parse-time-string date-end t)))) + (setq year-end (or (nth 5 date) year-start) + month-end (or (nth 4 date) month-start) + day-end (or (nth 3 date) day-start) + hour-end (or (nth 2 date) (car time-range) hour-start) + minute-end (or (nth 1 date) (cdr time-range) minute-start)))) + (list 'timestamp + (nconc (list :type type + :raw-value raw-value + :year-start year-start + :month-start month-start + :day-start day-start + :hour-start hour-start + :minute-start minute-start + :year-end year-end + :month-end month-end + :day-end day-end + :hour-end hour-end + :minute-end minute-end + :begin begin + :end end + :post-blank post-blank) + repeater-props + warning-props)))))) + +(defun org-element-timestamp-interpreter (timestamp _) + "Interpret TIMESTAMP object as Org syntax." + (let* ((repeat-string + (concat + (pcase (org-element-property :repeater-type timestamp) + (`cumulate "+") (`catch-up "++") (`restart ".+")) + (let ((val (org-element-property :repeater-value timestamp))) + (and val (number-to-string val))) + (pcase (org-element-property :repeater-unit timestamp) + (`hour "h") (`day "d") (`week "w") (`month "m") (`year "y")))) + (warning-string + (concat + (pcase (org-element-property :warning-type timestamp) + (`first "--") (`all "-")) + (let ((val (org-element-property :warning-value timestamp))) + (and val (number-to-string val))) + (pcase (org-element-property :warning-unit timestamp) + (`hour "h") (`day "d") (`week "w") (`month "m") (`year "y")))) + (build-ts-string + ;; Build an Org timestamp string from TIME. ACTIVEP is + ;; non-nil when time stamp is active. If WITH-TIME-P is + ;; non-nil, add a time part. HOUR-END and MINUTE-END + ;; specify a time range in the timestamp. REPEAT-STRING is + ;; the repeater string, if any. + (lambda (time activep &optional with-time-p hour-end minute-end) + (let ((ts (format-time-string + (funcall (if with-time-p #'cdr #'car) + org-time-stamp-formats) + time))) + (when (and hour-end minute-end) + (string-match "[012]?[0-9]:[0-5][0-9]" ts) + (setq ts + (replace-match + (format "\\&-%02d:%02d" hour-end minute-end) + nil nil ts))) + (unless activep (setq ts (format "[%s]" (substring ts 1 -1)))) + (dolist (s (list repeat-string warning-string)) + (when (org-string-nw-p s) + (setq ts (concat (substring ts 0 -1) + " " + s + (substring ts -1))))) + ;; Return value. + ts))) + (type (org-element-property :type timestamp))) + (pcase type + ((or `active `inactive) + (let* ((minute-start (org-element-property :minute-start timestamp)) + (minute-end (org-element-property :minute-end timestamp)) + (hour-start (org-element-property :hour-start timestamp)) + (hour-end (org-element-property :hour-end timestamp)) + (time-range-p (and hour-start hour-end minute-start minute-end + (or (/= hour-start hour-end) + (/= minute-start minute-end))))) + (funcall + build-ts-string + (encode-time 0 + (or minute-start 0) + (or hour-start 0) + (org-element-property :day-start timestamp) + (org-element-property :month-start timestamp) + (org-element-property :year-start timestamp)) + (eq type 'active) + (and hour-start minute-start) + (and time-range-p hour-end) + (and time-range-p minute-end)))) + ((or `active-range `inactive-range) + (let ((minute-start (org-element-property :minute-start timestamp)) + (minute-end (org-element-property :minute-end timestamp)) + (hour-start (org-element-property :hour-start timestamp)) + (hour-end (org-element-property :hour-end timestamp))) + (concat + (funcall + build-ts-string (encode-time + 0 + (or minute-start 0) + (or hour-start 0) + (org-element-property :day-start timestamp) + (org-element-property :month-start timestamp) + (org-element-property :year-start timestamp)) + (eq type 'active-range) + (and hour-start minute-start)) + "--" + (funcall build-ts-string + (encode-time 0 + (or minute-end 0) + (or hour-end 0) + (org-element-property :day-end timestamp) + (org-element-property :month-end timestamp) + (org-element-property :year-end timestamp)) + (eq type 'active-range) + (and hour-end minute-end))))) + (_ (org-element-property :raw-value timestamp))))) ;;;; Underline (defun org-element-underline-parser () - "Parse underline object at point. + "Parse underline object at point, if any. -Return a list whose CAR is `underline' and CDR is a plist with -`:begin', `:end', `:contents-begin' and `:contents-end' and -`:post-blank' keywords. +When at an underline object, return a list whose car is +`underline' and cdr is a plist with `:begin', `:end', +`:contents-begin' and `:contents-end' and `:post-blank' keywords. +Otherwise, return nil. Assume point is at the first underscore marker." (save-excursion (unless (bolp) (backward-char 1)) - (looking-at org-emph-re) - (let ((begin (match-beginning 2)) - (contents-begin (match-beginning 4)) - (contents-end (match-end 4)) - (post-blank (progn (goto-char (match-end 2)) - (skip-chars-forward " \t"))) - (end (point))) - (list 'underline - (list :begin begin - :end end - :contents-begin contents-begin - :contents-end contents-end - :post-blank post-blank))))) - -(defun org-element-underline-interpreter (underline contents) - "Interpret UNDERLINE object as Org syntax. + (when (looking-at org-emph-re) + (let ((begin (match-beginning 2)) + (contents-begin (match-beginning 4)) + (contents-end (match-end 4)) + (post-blank (progn (goto-char (match-end 2)) + (skip-chars-forward " \t"))) + (end (point))) + (list 'underline + (list :begin begin + :end end + :contents-begin contents-begin + :contents-end contents-end + :post-blank post-blank)))))) + +(defun org-element-underline-interpreter (_ contents) + "Interpret underline object as Org syntax. CONTENTS is the contents of the object." (format "_%s_" contents)) @@ -3781,29 +3706,29 @@ CONTENTS is the contents of the object." ;;;; Verbatim (defun org-element-verbatim-parser () - "Parse verbatim object at point. + "Parse verbatim object at point, if any. -Return a list whose CAR is `verbatim' and CDR is a plist with -`:value', `:begin', `:end' and `:post-blank' keywords. +When at a verbatim object, return a list whose car is `verbatim' +and cdr is a plist with `:value', `:begin', `:end' and +`:post-blank' keywords. Otherwise, return nil. Assume point is at the first equal sign marker." (save-excursion (unless (bolp) (backward-char 1)) - (looking-at org-emph-re) - (let ((begin (match-beginning 2)) - (value (org-match-string-no-properties 4)) - (post-blank (progn (goto-char (match-end 2)) - (skip-chars-forward " \t"))) - (end (point))) - (list 'verbatim - (list :value value - :begin begin - :end end - :post-blank post-blank))))) - -(defun org-element-verbatim-interpreter (verbatim contents) - "Interpret VERBATIM object as Org syntax. -CONTENTS is nil." + (when (looking-at org-emph-re) + (let ((begin (match-beginning 2)) + (value (match-string-no-properties 4)) + (post-blank (progn (goto-char (match-end 2)) + (skip-chars-forward " \t"))) + (end (point))) + (list 'verbatim + (list :value value + :begin begin + :end end + :post-blank post-blank)))))) + +(defun org-element-verbatim-interpreter (verbatim _) + "Interpret VERBATIM object as Org syntax." (format "=%s=" (org-element-property :value verbatim))) @@ -3818,10 +3743,9 @@ CONTENTS is nil." ;; are activated for fixed element chaining (e.g., `plain-list' > ;; `item') or fixed conditional element chaining (e.g., `headline' > ;; `section'). Special modes are: `first-section', `item', -;; `node-property', `quote-section', `section' and `table-row'. +;; `node-property', `section' and `table-row'. -(defun org-element--current-element - (limit &optional granularity special structure) +(defun org-element--current-element (limit &optional granularity mode structure) "Parse the element starting at point. Return value is a list like (TYPE PROPS) where TYPE is the type @@ -3838,12 +3762,12 @@ recursion. Allowed values are `headline', `greater-element', nil), secondary values will not be parsed, since they only contain objects. -Optional argument SPECIAL, when non-nil, can be either -`first-section', `item', `node-property', `quote-section', -`section', and `table-row'. +Optional argument MODE, when non-nil, can be either +`first-section', `section', `planning', `item', `node-property' +and `table-row'. -If STRUCTURE isn't provided but SPECIAL is set to `item', it will -be computed. +If STRUCTURE isn't provided but MODE is set to `item', it will be +computed. This function assumes point is always at the beginning of the element it has to parse." @@ -3855,30 +3779,37 @@ element it has to parse." (raw-secondary-p (and granularity (not (eq granularity 'object))))) (cond ;; Item. - ((eq special 'item) + ((eq mode 'item) (org-element-item-parser limit structure raw-secondary-p)) ;; Table Row. - ((eq special 'table-row) (org-element-table-row-parser limit)) + ((eq mode 'table-row) (org-element-table-row-parser limit)) ;; Node Property. - ((eq special 'node-property) (org-element-node-property-parser limit)) + ((eq mode 'node-property) (org-element-node-property-parser limit)) ;; Headline. ((org-with-limited-levels (org-at-heading-p)) (org-element-headline-parser limit raw-secondary-p)) ;; Sections (must be checked after headline). - ((eq special 'section) (org-element-section-parser limit)) - ((eq special 'quote-section) (org-element-quote-section-parser limit)) - ((eq special 'first-section) + ((eq mode 'section) (org-element-section-parser limit)) + ((eq mode 'first-section) (org-element-section-parser (or (save-excursion (org-with-limited-levels (outline-next-heading))) limit))) + ;; Planning. + ((and (eq mode 'planning) + (eq ?* (char-after (line-beginning-position 0))) + (looking-at org-planning-line-re)) + (org-element-planning-parser limit)) + ;; Property drawer. + ((and (memq mode '(planning property-drawer)) + (eq ?* (char-after (line-beginning-position + (if (eq mode 'planning) 0 -1)))) + (looking-at org-property-drawer-re)) + (org-element-property-drawer-parser limit)) ;; When not at bol, point is at the beginning of an item or ;; a footnote definition: next item is always a paragraph. ((not (bolp)) (org-element-paragraph-parser limit (list (point)))) - ;; Planning and Clock. - ((looking-at org-planning-or-clock-line-re) - (if (equal (match-string 1) org-clock-string) - (org-element-clock-parser limit) - (org-element-planning-parser limit))) + ;; Clock. + ((looking-at org-clock-line-re) (org-element-clock-parser limit)) ;; Inlinetask. ((org-at-heading-p) (org-element-inlinetask-parser limit raw-secondary-p)) @@ -3891,13 +3822,11 @@ element it has to parse." (goto-char (car affiliated)) (org-element-keyword-parser limit nil)) ;; LaTeX Environment. - ((looking-at "[ \t]*\\\\begin{\\([A-Za-z0-9]+\\*?\\)}\\(\\[.*?\\]\\|{.*?}\\)*[ \t]*$") + ((looking-at org-element--latex-begin-environment) (org-element-latex-environment-parser limit affiliated)) ;; Drawer and Property Drawer. ((looking-at org-drawer-regexp) - (if (equal (match-string 1) "PROPERTIES") - (org-element-property-drawer-parser limit affiliated) - (org-element-drawer-parser limit affiliated))) + (org-element-drawer-parser limit affiliated)) ;; Fixed Width ((looking-at "[ \t]*:\\( \\|$\\)") (org-element-fixed-width-parser limit affiliated)) @@ -3905,27 +3834,35 @@ element it has to parse." ;; Keywords. ((looking-at "[ \t]*#") (goto-char (match-end 0)) - (cond ((looking-at "\\(?: \\|$\\)") - (beginning-of-line) - (org-element-comment-parser limit affiliated)) - ((looking-at "\\+BEGIN_\\(\\S-+\\)") - (beginning-of-line) - (let ((parser (assoc (upcase (match-string 1)) - org-element-block-name-alist))) - (if parser (funcall (cdr parser) limit affiliated) - (org-element-special-block-parser limit affiliated)))) - ((looking-at "\\+CALL:") - (beginning-of-line) - (org-element-babel-call-parser limit affiliated)) - ((looking-at "\\+BEGIN:? ") - (beginning-of-line) - (org-element-dynamic-block-parser limit affiliated)) - ((looking-at "\\+\\S-+:") - (beginning-of-line) - (org-element-keyword-parser limit affiliated)) - (t - (beginning-of-line) - (org-element-paragraph-parser limit affiliated)))) + (cond + ((looking-at "\\(?: \\|$\\)") + (beginning-of-line) + (org-element-comment-parser limit affiliated)) + ((looking-at "\\+BEGIN_\\(\\S-+\\)") + (beginning-of-line) + (funcall (pcase (upcase (match-string 1)) + ("CENTER" #'org-element-center-block-parser) + ("COMMENT" #'org-element-comment-block-parser) + ("EXAMPLE" #'org-element-example-block-parser) + ("EXPORT" #'org-element-export-block-parser) + ("QUOTE" #'org-element-quote-block-parser) + ("SRC" #'org-element-src-block-parser) + ("VERSE" #'org-element-verse-block-parser) + (_ #'org-element-special-block-parser)) + limit + affiliated)) + ((looking-at "\\+CALL:") + (beginning-of-line) + (org-element-babel-call-parser limit affiliated)) + ((looking-at "\\+BEGIN:? ") + (beginning-of-line) + (org-element-dynamic-block-parser limit affiliated)) + ((looking-at "\\+\\S-+:") + (beginning-of-line) + (org-element-keyword-parser limit affiliated)) + (t + (beginning-of-line) + (org-element-paragraph-parser limit affiliated)))) ;; Footnote Definition. ((looking-at org-footnote-definition-re) (org-element-footnote-definition-parser limit affiliated)) @@ -3936,7 +3873,8 @@ element it has to parse." ((looking-at "%%(") (org-element-diary-sexp-parser limit affiliated)) ;; Table. - ((org-at-table-p t) (org-element-table-parser limit affiliated)) + ((looking-at "[ \t]*\\(|\\|\\+\\(-+\\+\\)+[ \t]*$\\)") + (org-element-table-parser limit affiliated)) ;; List. ((looking-at (org-item-re)) (org-element-plain-list-parser @@ -3980,7 +3918,7 @@ position of point and CDR is nil." (save-match-data (org-trim (buffer-substring-no-properties - (match-end 0) (point-at-eol))))) + (match-end 0) (line-end-position))))) ;; PARSEDP is non-nil when keyword should have its ;; value parsed. (parsedp (member kwd org-element-parsed-keywords)) @@ -3989,14 +3927,20 @@ position of point and CDR is nil." (dualp (member kwd org-element-dual-keywords)) (dual-value (and dualp - (let ((sec (org-match-string-no-properties 2))) + (let ((sec (match-string-no-properties 2))) (if (or (not sec) (not parsedp)) sec - (org-element-parse-secondary-string sec restrict))))) + (save-match-data + (org-element--parse-objects + (match-beginning 2) (match-end 2) nil restrict)))))) ;; Attribute a property name to KWD. (kwd-sym (and kwd (intern (concat ":" (downcase kwd)))))) ;; Now set final shape for VALUE. (when parsedp - (setq value (org-element-parse-secondary-string value restrict))) + (setq value + (org-element--parse-objects + (match-end 0) + (progn (end-of-line) (skip-chars-backward " \t") (point)) + nil restrict))) (when dualp (setq value (and (or value dual-value) (cons value dual-value)))) (when (or (member kwd org-element-multiple-keywords) @@ -4037,7 +3981,7 @@ Optional argument GRANULARITY determines the depth of the recursion. It can be set to the following symbols: `headline' Only parse headlines. -`greater-element' Don't recurse into greater elements excepted +`greater-element' Don't recurse into greater elements except headlines and sections. Thus, elements parsed are the top-level ones. `element' Parse everything but objects and plain text. @@ -4046,7 +3990,7 @@ recursion. It can be set to the following symbols: When VISIBLE-ONLY is non-nil, don't parse contents of hidden elements. -An element or an objects is represented as a list with the +An element or object is represented as a list with the pattern (TYPE PROPERTIES CONTENTS), where : TYPE is a symbol describing the element or object. See @@ -4089,23 +4033,25 @@ looked after. Optional argument PARENT, when non-nil, is the element or object containing the secondary string. It is used to set correctly -`:parent' property within the string." - (let ((local-variables (buffer-local-variables))) - (with-temp-buffer - (dolist (v local-variables) - (ignore-errors - (if (symbolp v) (makunbound v) - (org-set-local (car v) (cdr v))))) - (insert string) - (restore-buffer-modified-p nil) - (let ((secondary (org-element--parse-objects - (point-min) (point-max) nil restriction))) - (when parent - (dolist (o secondary) (org-element-put-property o :parent parent))) - secondary)))) +`:parent' property within the string. + +If STRING is the empty string or nil, return nil." + (cond + ((not string) nil) + ((equal string "") nil) + (t (let ((local-variables (buffer-local-variables))) + (with-temp-buffer + (dolist (v local-variables) + (ignore-errors + (if (symbolp v) (makunbound v) + (set (make-local-variable (car v)) (cdr v))))) + (insert string) + (restore-buffer-modified-p nil) + (org-element--parse-objects + (point-min) (point-max) nil restriction parent)))))) (defun org-element-map - (data types fun &optional info first-match no-recursion with-affiliated) + (data types fun &optional info first-match no-recursion with-affiliated) "Map a function on selected elements or objects. DATA is a parse tree, an element, an object, a string, or a list @@ -4141,7 +4087,7 @@ Assuming TREE is a variable containing an Org buffer parse tree, the following example will return a flat list of all `src-block' and `example-block' elements in it: - (org-element-map tree \\='(example-block src-block) \\='identity) + (org-element-map tree \\='(example-block src-block) #\\='identity) The following snippet will find the first headline with a level of 1 and a \"phone\" tag, and will return its beginning position: @@ -4156,7 +4102,7 @@ of 1 and a \"phone\" tag, and will return its beginning position: The next example will return a flat list of all `plain-list' type elements in TREE that are not a sub-list themselves: - (org-element-map tree \\='plain-list \\='identity nil nil \\='plain-list) + (org-element-map tree \\='plain-list #\\='identity nil nil \\='plain-list) Eventually, this example will return a flat list of all `bold' type objects containing a `latex-snippet' type object, even @@ -4164,116 +4110,101 @@ looking into captions: (org-element-map tree \\='bold (lambda (b) - (and (org-element-map b \\='latex-snippet \\='identity nil t) b)) + (and (org-element-map b \\='latex-snippet #\\='identity nil t) b)) nil nil nil t)" ;; Ensure TYPES and NO-RECURSION are a list, even of one element. - (unless (listp types) (setq types (list types))) - (unless (listp no-recursion) (setq no-recursion (list no-recursion))) - ;; Recursion depth is determined by --CATEGORY. - (let* ((--category - (catch 'found - (let ((category 'greater-elements)) - (mapc (lambda (type) - (cond ((or (memq type org-element-all-objects) - (eq type 'plain-text)) - ;; If one object is found, the function - ;; has to recurse into every object. - (throw 'found 'objects)) - ((not (memq type org-element-greater-elements)) - ;; If one regular element is found, the - ;; function has to recurse, at least, - ;; into every element it encounters. - (and (not (eq category 'elements)) - (setq category 'elements))))) - types) - category))) - ;; Compute properties for affiliated keywords if necessary. - (--affiliated-alist - (and with-affiliated - (mapcar (lambda (kwd) - (cons kwd (intern (concat ":" (downcase kwd))))) - org-element-affiliated-keywords))) - --acc - --walk-tree - (--walk-tree - (function - (lambda (--data) - ;; Recursively walk DATA. INFO, if non-nil, is a plist - ;; holding contextual information. - (let ((--type (org-element-type --data))) - (cond - ((not --data)) - ;; Ignored element in an export context. - ((and info (memq --data (plist-get info :ignore-list)))) - ;; List of elements or objects. - ((not --type) (mapc --walk-tree --data)) - ;; Unconditionally enter parse trees. - ((eq --type 'org-data) - (mapc --walk-tree (org-element-contents --data))) - (t - ;; Check if TYPE is matching among TYPES. If so, - ;; apply FUN to --DATA and accumulate return value - ;; into --ACC (or exit if FIRST-MATCH is non-nil). - (when (memq --type types) - (let ((result (funcall fun --data))) - (cond ((not result)) - (first-match (throw '--map-first-match result)) - (t (push result --acc))))) - ;; If --DATA has a secondary string that can contain - ;; objects with their type among TYPES, look into it. - (when (and (eq --category 'objects) (not (stringp --data))) - (let ((sec-prop - (assq --type org-element-secondary-value-alist))) - (when sec-prop - (funcall --walk-tree - (org-element-property (cdr sec-prop) --data))))) - ;; If --DATA has any affiliated keywords and - ;; WITH-AFFILIATED is non-nil, look for objects in - ;; them. - (when (and with-affiliated - (eq --category 'objects) - (memq --type org-element-all-elements)) - (mapc (lambda (kwd-pair) - (let ((kwd (car kwd-pair)) - (value (org-element-property - (cdr kwd-pair) --data))) - ;; Pay attention to the type of value. - ;; Preserve order for multiple keywords. - (cond - ((not value)) - ((and (member kwd org-element-multiple-keywords) - (member kwd org-element-dual-keywords)) - (mapc (lambda (line) - (funcall --walk-tree (cdr line)) - (funcall --walk-tree (car line))) - (reverse value))) - ((member kwd org-element-multiple-keywords) - (mapc (lambda (line) (funcall --walk-tree line)) - (reverse value))) - ((member kwd org-element-dual-keywords) - (funcall --walk-tree (cdr value)) - (funcall --walk-tree (car value))) - (t (funcall --walk-tree value))))) - --affiliated-alist)) - ;; Determine if a recursion into --DATA is possible. - (cond - ;; --TYPE is explicitly removed from recursion. - ((memq --type no-recursion)) - ;; --DATA has no contents. - ((not (org-element-contents --data))) - ;; Looking for greater elements but --DATA is simply - ;; an element or an object. - ((and (eq --category 'greater-elements) - (not (memq --type org-element-greater-elements)))) - ;; Looking for elements but --DATA is an object. - ((and (eq --category 'elements) - (memq --type org-element-all-objects))) - ;; In any other case, map contents. - (t (mapc --walk-tree (org-element-contents --data))))))))))) - (catch '--map-first-match - (funcall --walk-tree data) - ;; Return value in a proper order. - (nreverse --acc)))) + (let* ((types (if (listp types) types (list types))) + (no-recursion (if (listp no-recursion) no-recursion + (list no-recursion))) + ;; Recursion depth is determined by --CATEGORY. + (--category + (catch :--found + (let ((category 'greater-elements) + (all-objects (cons 'plain-text org-element-all-objects))) + (dolist (type types category) + (cond ((memq type all-objects) + ;; If one object is found, the function has + ;; to recurse into every object. + (throw :--found 'objects)) + ((not (memq type org-element-greater-elements)) + ;; If one regular element is found, the + ;; function has to recurse, at least, into + ;; every element it encounters. + (and (not (eq category 'elements)) + (setq category 'elements)))))))) + --acc) + (letrec ((--walk-tree + (lambda (--data) + ;; Recursively walk DATA. INFO, if non-nil, is a plist + ;; holding contextual information. + (let ((--type (org-element-type --data))) + (cond + ((not --data)) + ;; Ignored element in an export context. + ((and info (memq --data (plist-get info :ignore-list)))) + ;; List of elements or objects. + ((not --type) (mapc --walk-tree --data)) + ;; Unconditionally enter parse trees. + ((eq --type 'org-data) + (mapc --walk-tree (org-element-contents --data))) + (t + ;; Check if TYPE is matching among TYPES. If so, + ;; apply FUN to --DATA and accumulate return value + ;; into --ACC (or exit if FIRST-MATCH is non-nil). + (when (memq --type types) + (let ((result (funcall fun --data))) + (cond ((not result)) + (first-match (throw :--map-first-match result)) + (t (push result --acc))))) + ;; If --DATA has a secondary string that can contain + ;; objects with their type among TYPES, look inside. + (when (and (eq --category 'objects) (not (stringp --data))) + (dolist (p (cdr (assq --type + org-element-secondary-value-alist))) + (funcall --walk-tree (org-element-property p --data)))) + ;; If --DATA has any parsed affiliated keywords and + ;; WITH-AFFILIATED is non-nil, look for objects in + ;; them. + (when (and with-affiliated + (eq --category 'objects) + (eq (org-element-class --data) 'element)) + (dolist (kwd-pair org-element--parsed-properties-alist) + (let ((kwd (car kwd-pair)) + (value (org-element-property (cdr kwd-pair) --data))) + ;; Pay attention to the type of parsed + ;; keyword. In particular, preserve order for + ;; multiple keywords. + (cond + ((not value)) + ((member kwd org-element-dual-keywords) + (if (member kwd org-element-multiple-keywords) + (dolist (line (reverse value)) + (funcall --walk-tree (cdr line)) + (funcall --walk-tree (car line))) + (funcall --walk-tree (cdr value)) + (funcall --walk-tree (car value)))) + ((member kwd org-element-multiple-keywords) + (mapc --walk-tree (reverse value))) + (t (funcall --walk-tree value)))))) + ;; Determine if a recursion into --DATA is possible. + (cond + ;; --TYPE is explicitly removed from recursion. + ((memq --type no-recursion)) + ;; --DATA has no contents. + ((not (org-element-contents --data))) + ;; Looking for greater elements but --DATA is + ;; simply an element or an object. + ((and (eq --category 'greater-elements) + (not (memq --type org-element-greater-elements)))) + ;; Looking for elements but --DATA is an object. + ((and (eq --category 'elements) + (eq (org-element-class --data) 'object))) + ;; In any other case, map contents. + (t (mapc --walk-tree (org-element-contents --data)))))))))) + (catch :--map-first-match + (funcall --walk-tree data) + ;; Return value in a proper order. + (nreverse --acc))))) (put 'org-element-map 'lisp-indent-function 2) ;; The following functions are internal parts of the parser. @@ -4282,24 +4213,38 @@ looking into captions: ;; level. ;; ;; The second one, `org-element--parse-objects' applies on all objects -;; of a paragraph or a secondary string. It uses -;; `org-element--get-next-object-candidates' to optimize the search of -;; the next object in the buffer. -;; -;; More precisely, that function looks for every allowed object type -;; first. Then, it discards failed searches, keeps further matches, -;; and searches again types matched behind point, for subsequent -;; calls. Thus, searching for a given type fails only once, and every -;; object is searched only once at top level (but sometimes more for -;; nested types). +;; of a paragraph or a secondary string. It calls +;; `org-element--object-lex' to find the next object in the current +;; container. + +(defsubst org-element--next-mode (type parentp) + "Return next special mode according to TYPE, or nil. +TYPE is a symbol representing the type of an element or object +containing next element if PARENTP is non-nil, or before it +otherwise. Modes can be either `first-section', `item', +`node-property', `planning', `property-drawer', `section', +`table-row' or nil." + (if parentp + (pcase type + (`headline 'section) + (`inlinetask 'planning) + (`plain-list 'item) + (`property-drawer 'node-property) + (`section 'planning) + (`table 'table-row)) + (pcase type + (`item 'item) + (`node-property 'node-property) + (`planning 'property-drawer) + (`table-row 'table-row)))) (defun org-element--parse-elements - (beg end special structure granularity visible-only acc) + (beg end mode structure granularity visible-only acc) "Parse elements between BEG and END positions. -SPECIAL prioritize some elements over the others. It can be set -to `first-section', `quote-section', `section' `item' or -`table-row'. +MODE prioritizes some elements over the others. It can be set to +`first-section', `section', `planning', `item', `node-property' +or `table-row'. When value is `item', STRUCTURE will be used as the current list structure. @@ -4320,140 +4265,205 @@ Elements are accumulated into ACC." ;; When parsing only headlines, skip any text before first one. (when (and (eq granularity 'headline) (not (org-at-heading-p))) (org-with-limited-levels (outline-next-heading))) - ;; Main loop start. - (while (< (point) end) - ;; Find current element's type and parse it accordingly to - ;; its category. - (let* ((element (org-element--current-element - end granularity special structure)) - (type (org-element-type element)) - (cbeg (org-element-property :contents-begin element))) - (goto-char (org-element-property :end element)) - ;; Visible only: skip invisible parts between siblings. - (when (and visible-only (org-invisible-p2)) - (goto-char (min (1+ (org-find-visible)) end))) - ;; Fill ELEMENT contents by side-effect. - (cond - ;; If element has no contents, don't modify it. - ((not cbeg)) - ;; Greater element: parse it between `contents-begin' and - ;; `contents-end'. Make sure GRANULARITY allows the - ;; recursion, or ELEMENT is a headline, in which case going - ;; inside is mandatory, in order to get sub-level headings. - ((and (memq type org-element-greater-elements) - (or (memq granularity '(element object nil)) - (and (eq granularity 'greater-element) - (eq type 'section)) - (eq type 'headline))) - (org-element--parse-elements - cbeg (org-element-property :contents-end element) - ;; Possibly switch to a special mode. - (case type - (headline - (if (org-element-property :quotedp element) 'quote-section - 'section)) - (plain-list 'item) - (property-drawer 'node-property) - (table 'table-row)) - (and (memq type '(item plain-list)) - (org-element-property :structure element)) - granularity visible-only element)) - ;; ELEMENT has contents. Parse objects inside, if - ;; GRANULARITY allows it. - ((memq granularity '(object nil)) - (org-element--parse-objects - cbeg (org-element-property :contents-end element) element - (org-element-restriction type)))) - (org-element-adopt-elements acc element))) - ;; Return result. - acc)) - -(defun org-element--parse-objects (beg end acc restriction) + (let (elements) + (while (< (point) end) + ;; Find current element's type and parse it accordingly to + ;; its category. + (let* ((element (org-element--current-element + end granularity mode structure)) + (type (org-element-type element)) + (cbeg (org-element-property :contents-begin element))) + (goto-char (org-element-property :end element)) + ;; Visible only: skip invisible parts between siblings. + (when (and visible-only (org-invisible-p2)) + (goto-char (min (1+ (org-find-visible)) end))) + ;; Fill ELEMENT contents by side-effect. + (cond + ;; If element has no contents, don't modify it. + ((not cbeg)) + ;; Greater element: parse it between `contents-begin' and + ;; `contents-end'. Make sure GRANULARITY allows the + ;; recursion, or ELEMENT is a headline, in which case going + ;; inside is mandatory, in order to get sub-level headings. + ((and (memq type org-element-greater-elements) + (or (memq granularity '(element object nil)) + (and (eq granularity 'greater-element) + (eq type 'section)) + (eq type 'headline))) + (org-element--parse-elements + cbeg (org-element-property :contents-end element) + ;; Possibly switch to a special mode. + (org-element--next-mode type t) + (and (memq type '(item plain-list)) + (org-element-property :structure element)) + granularity visible-only element)) + ;; ELEMENT has contents. Parse objects inside, if + ;; GRANULARITY allows it. + ((memq granularity '(object nil)) + (org-element--parse-objects + cbeg (org-element-property :contents-end element) element + (org-element-restriction type)))) + (push (org-element-put-property element :parent acc) elements) + ;; Update mode. + (setq mode (org-element--next-mode type nil)))) + ;; Return result. + (apply #'org-element-set-contents acc (nreverse elements))))) + +(defun org-element--object-lex (restriction) + "Return next object in current buffer or nil. +RESTRICTION is a list of object types, as symbols, that should be +looked after. This function assumes that the buffer is narrowed +to an appropriate container (e.g., a paragraph)." + (if (memq 'table-cell restriction) (org-element-table-cell-parser) + (let* ((start (point)) + (limit + ;; Object regexp sometimes needs to have a peek at + ;; a character ahead. Therefore, when there is a hard + ;; limit, make it one more than the true beginning of the + ;; radio target. + (save-excursion + (cond ((not org-target-link-regexp) nil) + ((not (memq 'link restriction)) nil) + ((progn + (unless (bolp) (forward-char -1)) + (not (re-search-forward org-target-link-regexp nil t))) + nil) + ;; Since we moved backward, we do not want to + ;; match again an hypothetical 1-character long + ;; radio link before us. Realizing that this can + ;; only happen if such a radio link starts at + ;; beginning of line, we prevent this here. + ((and (= start (1+ (line-beginning-position))) + (= start (match-end 1))) + (and (re-search-forward org-target-link-regexp nil t) + (1+ (match-beginning 1)))) + (t (1+ (match-beginning 1)))))) + found) + (save-excursion + (while (and (not found) + (re-search-forward org-element--object-regexp limit 'move)) + (goto-char (match-beginning 0)) + (let ((result (match-string 0))) + (setq found + (cond + ((string-prefix-p "call_" result t) + (and (memq 'inline-babel-call restriction) + (org-element-inline-babel-call-parser))) + ((string-prefix-p "src_" result t) + (and (memq 'inline-src-block restriction) + (org-element-inline-src-block-parser))) + (t + (pcase (char-after) + (?^ (and (memq 'superscript restriction) + (org-element-superscript-parser))) + (?_ (or (and (memq 'subscript restriction) + (org-element-subscript-parser)) + (and (memq 'underline restriction) + (org-element-underline-parser)))) + (?* (and (memq 'bold restriction) + (org-element-bold-parser))) + (?/ (and (memq 'italic restriction) + (org-element-italic-parser))) + (?~ (and (memq 'code restriction) + (org-element-code-parser))) + (?= (and (memq 'verbatim restriction) + (org-element-verbatim-parser))) + (?+ (and (memq 'strike-through restriction) + (org-element-strike-through-parser))) + (?@ (and (memq 'export-snippet restriction) + (org-element-export-snippet-parser))) + (?{ (and (memq 'macro restriction) + (org-element-macro-parser))) + (?$ (and (memq 'latex-fragment restriction) + (org-element-latex-fragment-parser))) + (?< + (if (eq (aref result 1) ?<) + (or (and (memq 'radio-target restriction) + (org-element-radio-target-parser)) + (and (memq 'target restriction) + (org-element-target-parser))) + (or (and (memq 'timestamp restriction) + (org-element-timestamp-parser)) + (and (or (memq 'link restriction) + (memq 'simple-link restriction)) + (org-element-link-parser))))) + (?\\ + (if (eq (aref result 1) ?\\) + (and (memq 'line-break restriction) + (org-element-line-break-parser)) + (or (and (memq 'entity restriction) + (org-element-entity-parser)) + (and (memq 'latex-fragment restriction) + (org-element-latex-fragment-parser))))) + (?\[ + (if (eq (aref result 1) ?\[) + (and (memq 'link restriction) + (org-element-link-parser)) + (or (and (memq 'footnote-reference restriction) + (org-element-footnote-reference-parser)) + (and (memq 'timestamp restriction) + (org-element-timestamp-parser)) + (and (memq 'statistics-cookie restriction) + (org-element-statistics-cookie-parser))))) + ;; This is probably a plain link. + (_ (and (or (memq 'link restriction) + (memq 'simple-link restriction)) + (org-element-link-parser))))))) + (or (eobp) (forward-char)))) + (cond (found) + (limit (forward-char -1) + (org-element-link-parser)) ;radio link + (t nil)))))) + +(defun org-element--parse-objects (beg end acc restriction &optional parent) "Parse objects between BEG and END and return recursive structure. -Objects are accumulated in ACC. +Objects are accumulated in ACC. RESTRICTION is a list of object +successors which are allowed in the current object. -RESTRICTION is a list of object successors which are allowed in -the current object." - (let ((candidates 'initial)) - (save-excursion - (save-restriction - (narrow-to-region beg end) - (goto-char (point-min)) +ACC becomes the parent for all parsed objects. However, if ACC +is nil (i.e., a secondary string is being parsed) and optional +argument PARENT is non-nil, use it as the parent for all objects. +Eventually, if both ACC and PARENT are nil, the common parent is +the list of objects itself." + (save-excursion + (save-restriction + (narrow-to-region beg end) + (goto-char (point-min)) + (let (next-object contents) (while (and (not (eobp)) - (setq candidates - (org-element--get-next-object-candidates - restriction candidates))) - (let ((next-object - (let ((pos (apply 'min (mapcar 'cdr candidates)))) - (save-excursion - (goto-char pos) - (funcall (intern (format "org-element-%s-parser" - (car (rassq pos candidates))))))))) - ;; 1. Text before any object. Untabify it. - (let ((obj-beg (org-element-property :begin next-object))) - (unless (= (point) obj-beg) - (setq acc - (org-element-adopt-elements - acc - (replace-regexp-in-string - "\t" (make-string tab-width ? ) - (buffer-substring-no-properties (point) obj-beg)))))) - ;; 2. Object... - (let ((obj-end (org-element-property :end next-object)) - (cont-beg (org-element-property :contents-begin next-object))) - ;; Fill contents of NEXT-OBJECT by side-effect, if it has - ;; a recursive type. - (when (and cont-beg - (memq (car next-object) org-element-recursive-objects)) - (org-element--parse-objects - cont-beg (org-element-property :contents-end next-object) - next-object (org-element-restriction next-object))) - (setq acc (org-element-adopt-elements acc next-object)) - (goto-char obj-end)))) - ;; 3. Text after last object. Untabify it. + (setq next-object (org-element--object-lex restriction))) + ;; Text before any object. + (let ((obj-beg (org-element-property :begin next-object))) + (unless (= (point) obj-beg) + (let ((text (buffer-substring-no-properties (point) obj-beg))) + (push (if acc (org-element-put-property text :parent acc) text) + contents)))) + ;; Object... + (let ((obj-end (org-element-property :end next-object)) + (cont-beg (org-element-property :contents-begin next-object))) + (when acc (org-element-put-property next-object :parent acc)) + (push (if cont-beg + ;; Fill contents of NEXT-OBJECT if possible. + (org-element--parse-objects + cont-beg + (org-element-property :contents-end next-object) + next-object + (org-element-restriction next-object)) + next-object) + contents) + (goto-char obj-end))) + ;; Text after last object. (unless (eobp) - (setq acc - (org-element-adopt-elements - acc - (replace-regexp-in-string - "\t" (make-string tab-width ? ) - (buffer-substring-no-properties (point) end))))) - ;; Result. - acc)))) - -(defun org-element--get-next-object-candidates (restriction objects) - "Return an alist of candidates for the next object. - -RESTRICTION is a list of object types, as symbols. Only -candidates with such types are looked after. - -OBJECTS is the previous candidates alist. If it is set to -`initial', no search has been done before, and all symbols in -RESTRICTION should be looked after. - -Return value is an alist whose CAR is the object type and CDR its -beginning position." - (delq - nil - (if (eq objects 'initial) - ;; When searching for the first time, look for every successor - ;; allowed in RESTRICTION. - (mapcar - (lambda (res) - (funcall (intern (format "org-element-%s-successor" res)))) - restriction) - ;; Focus on objects returned during last search. Keep those - ;; still after point. Search again objects before it. - (mapcar - (lambda (obj) - (if (>= (cdr obj) (point)) obj - (let* ((type (car obj)) - (succ (or (cdr (assq type org-element-object-successor-alist)) - type))) - (and succ - (funcall (intern (format "org-element-%s-successor" succ))))))) - objects)))) + (let ((text (buffer-substring-no-properties (point) end))) + (push (if acc (org-element-put-property text :parent acc) text) + contents))) + ;; Result. Set appropriate parent. + (if acc (apply #'org-element-set-contents acc (nreverse contents)) + (let* ((contents (nreverse contents)) + (parent (or parent contents))) + (dolist (datum contents contents) + (org-element-put-property datum :parent parent)))))))) @@ -4468,71 +4478,74 @@ beginning position." ;; `org-element--interpret-affiliated-keywords'. ;;;###autoload -(defun org-element-interpret-data (data &optional parent) +(defun org-element-interpret-data (data) "Interpret DATA as Org syntax. - DATA is a parse tree, an element, an object or a secondary string -to interpret. - -Optional argument PARENT is used for recursive calls. It contains -the element or object containing data, or nil. - -Return Org syntax as a string." - (let* ((type (org-element-type data)) - (results - (cond - ;; Secondary string. - ((not type) - (mapconcat - (lambda (obj) (org-element-interpret-data obj parent)) - data "")) - ;; Full Org document. - ((eq type 'org-data) - (mapconcat - (lambda (obj) (org-element-interpret-data obj parent)) - (org-element-contents data) "")) - ;; Plain text: return it. - ((stringp data) data) - ;; Element/Object without contents. - ((not (org-element-contents data)) - (funcall (intern (format "org-element-%s-interpreter" type)) - data nil)) - ;; Element/Object with contents. - (t - (let* ((greaterp (memq type org-element-greater-elements)) - (objectp (and (not greaterp) - (memq type org-element-recursive-objects))) - (contents - (mapconcat - (lambda (obj) (org-element-interpret-data obj data)) - (org-element-contents - (if (or greaterp objectp) data - ;; Elements directly containing objects must - ;; have their indentation normalized first. - (org-element-normalize-contents +to interpret. Return Org syntax as a string." + (letrec ((fun + (lambda (data parent) + (let* ((type (org-element-type data)) + ;; Find interpreter for current object or + ;; element. If it doesn't exist (e.g. this is + ;; a pseudo object or element), return contents, + ;; if any. + (interpret + (let ((fun (intern + (format "org-element-%s-interpreter" type)))) + (if (fboundp fun) fun (lambda (_ contents) contents)))) + (results + (cond + ;; Secondary string. + ((not type) + (mapconcat (lambda (obj) (funcall fun obj parent)) + data + "")) + ;; Full Org document. + ((eq type 'org-data) + (mapconcat (lambda (obj) (funcall fun obj parent)) + (org-element-contents data) + "")) + ;; Plain text: return it. + ((stringp data) data) + ;; Element or object without contents. + ((not (org-element-contents data)) + (funcall interpret data nil)) + ;; Element or object with contents. + (t + (funcall + interpret data - ;; When normalizing first paragraph of an - ;; item or a footnote-definition, ignore - ;; first line's indentation. - (and (eq type 'paragraph) - (equal data (car (org-element-contents parent))) - (memq (org-element-type parent) - '(footnote-definition item)))))) - ""))) - (funcall (intern (format "org-element-%s-interpreter" type)) - data - (if greaterp (org-element-normalize-contents contents) - contents))))))) - (if (memq type '(org-data plain-text nil)) results - ;; Build white spaces. If no `:post-blank' property is - ;; specified, assume its value is 0. - (let ((post-blank (or (org-element-property :post-blank data) 0))) - (if (memq type org-element-all-objects) - (concat results (make-string post-blank 32)) - (concat - (org-element--interpret-affiliated-keywords data) - (org-element-normalize-string results) - (make-string post-blank 10))))))) + ;; Recursively interpret contents. + (mapconcat + (lambda (datum) (funcall fun datum data)) + (org-element-contents + (if (not (memq type '(paragraph verse-block))) + data + ;; Fix indentation of elements containing + ;; objects. We ignore `table-row' + ;; elements as they are one line long + ;; anyway. + (org-element-normalize-contents + data + ;; When normalizing first paragraph of + ;; an item or a footnote-definition, + ;; ignore first line's indentation. + (and (eq type 'paragraph) + (memq (org-element-type parent) + '(footnote-definition item)) + (eq data + (car (org-element-contents parent))))))) + "")))))) + (if (memq type '(org-data plain-text nil)) results + ;; Build white spaces. If no `:post-blank' property + ;; is specified, assume its value is 0. + (let ((blank (or (org-element-property :post-blank data) 0))) + (if (eq (org-element-class data parent) 'object) + (concat results (make-string blank ?\s)) + (concat (org-element--interpret-affiliated-keywords data) + (org-element-normalize-string results) + (make-string blank ?\n))))))))) + (funcall fun data nil))) (defun org-element--interpret-affiliated-keywords (element) "Return ELEMENT's affiliated keywords as Org syntax. @@ -4566,14 +4579,14 @@ If there is no affiliated keyword, return the empty string." ;; List all ELEMENT's properties matching an attribute line or an ;; affiliated keyword, but ignore translated keywords since they ;; cannot belong to the property list. - (loop for prop in (nth 1 element) by 'cddr - when (let ((keyword (upcase (substring (symbol-name prop) 1)))) - (or (string-match "^ATTR_" keyword) - (and - (member keyword org-element-affiliated-keywords) - (not (assoc keyword - org-element-keyword-translation-alist))))) - collect prop) + (cl-loop for prop in (nth 1 element) by 'cddr + when (let ((keyword (upcase (substring (symbol-name prop) 1)))) + (or (string-match "^ATTR_" keyword) + (and + (member keyword org-element-affiliated-keywords) + (not (assoc keyword + org-element-keyword-translation-alist))))) + collect prop) ""))) ;; Because interpretation of the parse tree must return the same @@ -4609,67 +4622,1109 @@ If optional argument IGNORE-FIRST is non-nil, ignore first line's indentation to compute maximal common indentation. Return the normalized element that is element with global -indentation removed from its contents. The function assumes that -indentation is not done with TAB characters." - (let* ((min-ind most-positive-fixnum) - find-min-ind ; For byte-compiler. - (find-min-ind - ;; Return minimal common indentation within BLOB. This is - ;; done by walking recursively BLOB and updating MIN-IND - ;; along the way. FIRST-FLAG is non-nil when the first - ;; string hasn't been seen yet. It is required as this - ;; string is the only one whose indentation doesn't happen - ;; after a newline character. - (lambda (blob first-flag) - (dolist (object (org-element-contents blob)) - (when (and first-flag (stringp object)) - (setq first-flag nil) - (string-match "\\` *" object) - (let ((len (match-end 0))) - ;; An indentation of zero means no string will be - ;; modified. Quit the process. - (if (zerop len) (throw 'zero (setq min-ind 0)) - (setq min-ind (min len min-ind))))) - (cond - ((stringp object) - (dolist (line (cdr (org-split-string object " *\n"))) - (unless (string= line "") - (setq min-ind (min (org-get-indentation line) min-ind))))) - ((memq (org-element-type object) org-element-recursive-objects) - (funcall find-min-ind object first-flag))))))) - ;; Find minimal indentation in ELEMENT. - (catch 'zero (funcall find-min-ind element (not ignore-first))) +indentation removed from its contents." + (letrec ((find-min-ind + ;; Return minimal common indentation within BLOB. This is + ;; done by walking recursively BLOB and updating MIN-IND + ;; along the way. FIRST-FLAG is non-nil when the next + ;; object is expected to be a string that doesn't start + ;; with a newline character. It happens for strings at + ;; the beginnings of the contents or right after a line + ;; break. + (lambda (blob first-flag min-ind) + (dolist (datum (org-element-contents blob) min-ind) + (when first-flag + (setq first-flag nil) + (cond + ;; Objects cannot start with spaces: in this + ;; case, indentation is 0. + ((not (stringp datum)) (throw :zero 0)) + ((not (string-match + "\\`\\([ \t]+\\)\\([^ \t\n]\\|\n\\|\\'\\)" datum)) + (throw :zero 0)) + ((equal (match-string 2 datum) "\n") + (put-text-property + (match-beginning 1) (match-end 1) 'org-ind 'empty datum)) + (t + (let ((i (string-width (match-string 1 datum)))) + (put-text-property + (match-beginning 1) (match-end 1) 'org-ind i datum) + (setq min-ind (min i min-ind)))))) + (cond + ((stringp datum) + (let ((s 0)) + (while (string-match + "\n\\([ \t]*\\)\\([^ \t\n]\\|\n\\|\\'\\)" datum s) + (setq s (match-end 1)) + (cond + ((equal (match-string 1 datum) "") + (unless (member (match-string 2 datum) '("" "\n")) + (throw :zero 0))) + ((equal (match-string 2 datum) "\n") + (put-text-property (match-beginning 1) (match-end 1) + 'org-ind 'empty datum)) + (t + (let ((i (string-width (match-string 1 datum)))) + (put-text-property (match-beginning 1) (match-end 1) + 'org-ind i datum) + (setq min-ind (min i min-ind)))))))) + ((eq (org-element-type datum) 'line-break) + (setq first-flag t)) + ((memq (org-element-type datum) org-element-recursive-objects) + (setq min-ind + (funcall find-min-ind datum first-flag min-ind))))))) + (min-ind + (catch :zero + (funcall find-min-ind + element (not ignore-first) most-positive-fixnum)))) (if (or (zerop min-ind) (= min-ind most-positive-fixnum)) element ;; Build ELEMENT back, replacing each string with the same ;; string minus common indentation. - (let* (build ; For byte compiler. - (build - (function - (lambda (blob first-flag) - ;; Return BLOB with all its strings indentation - ;; shortened from MIN-IND white spaces. FIRST-FLAG - ;; is non-nil when the first string hasn't been seen - ;; yet. - (setcdr (cdr blob) - (mapcar - #'(lambda (object) - (when (and first-flag (stringp object)) - (setq first-flag nil) - (setq object - (replace-regexp-in-string - (format "\\` \\{%d\\}" min-ind) - "" object))) - (cond - ((stringp object) - (replace-regexp-in-string - (format "\n \\{%d\\}" min-ind) "\n" object)) - ((memq (org-element-type object) - org-element-recursive-objects) - (funcall build object first-flag)) - (t object))) - (org-element-contents blob))) - blob)))) - (funcall build element (not ignore-first)))))) + (letrec ((build + (lambda (datum) + ;; Return DATUM with all its strings indentation + ;; shortened from MIN-IND white spaces. + (setcdr + (cdr datum) + (mapcar + (lambda (object) + (cond + ((stringp object) + (with-temp-buffer + (insert object) + (let ((s (point-min))) + (while (setq s (text-property-not-all + s (point-max) 'org-ind nil)) + (goto-char s) + (let ((i (get-text-property s 'org-ind))) + (delete-region s (progn + (skip-chars-forward " \t") + (point))) + (when (integerp i) (indent-to (- i min-ind)))))) + (buffer-string))) + ((memq (org-element-type object) + org-element-recursive-objects) + (funcall build object)) + (t object))) + (org-element-contents datum))) + datum))) + (funcall build element))))) + + + +;;; Cache +;; +;; Implement a caching mechanism for `org-element-at-point' and +;; `org-element-context', which see. +;; +;; A single public function is provided: `org-element-cache-reset'. +;; +;; Cache is enabled by default, but can be disabled globally with +;; `org-element-use-cache'. `org-element-cache-sync-idle-time', +;; org-element-cache-sync-duration' and `org-element-cache-sync-break' +;; can be tweaked to control caching behaviour. +;; +;; Internally, parsed elements are stored in an AVL tree, +;; `org-element--cache'. This tree is updated lazily: whenever +;; a change happens to the buffer, a synchronization request is +;; registered in `org-element--cache-sync-requests' (see +;; `org-element--cache-submit-request'). During idle time, requests +;; are processed by `org-element--cache-sync'. Synchronization also +;; happens when an element is required from the cache. In this case, +;; the process stops as soon as the needed element is up-to-date. +;; +;; A synchronization request can only apply on a synchronized part of +;; the cache. Therefore, the cache is updated at least to the +;; location where the new request applies. Thus, requests are ordered +;; from left to right and all elements starting before the first +;; request are correct. This property is used by functions like +;; `org-element--cache-find' to retrieve elements in the part of the +;; cache that can be trusted. +;; +;; A request applies to every element, starting from its original +;; location (or key, see below). When a request is processed, it +;; moves forward and may collide the next one. In this case, both +;; requests are merged into a new one that starts from that element. +;; As a consequence, the whole synchronization complexity does not +;; depend on the number of pending requests, but on the number of +;; elements the very first request will be applied on. +;; +;; Elements cannot be accessed through their beginning position, which +;; may or may not be up-to-date. Instead, each element in the tree is +;; associated to a key, obtained with `org-element--cache-key'. This +;; mechanism is robust enough to preserve total order among elements +;; even when the tree is only partially synchronized. +;; +;; Objects contained in an element are stored in a hash table, +;; `org-element--cache-objects'. + + +(defvar org-element-use-cache nil + "Non-nil when Org parser should cache its results. + +WARNING: for the time being, using cache sometimes triggers +freezes. Therefore, it is disabled by default. Activate it if +you want to help debugging the issue.") + +(defvar org-element-cache-sync-idle-time 0.6 + "Length, in seconds, of idle time before syncing cache.") + +(defvar org-element-cache-sync-duration (seconds-to-time 0.04) + "Maximum duration, as a time value, for a cache synchronization. +If the synchronization is not over after this delay, the process +pauses and resumes after `org-element-cache-sync-break' +seconds.") + +(defvar org-element-cache-sync-break (seconds-to-time 0.3) + "Duration, as a time value, of the pause between synchronizations. +See `org-element-cache-sync-duration' for more information.") + + +;;;; Data Structure + +(defvar org-element--cache nil + "AVL tree used to cache elements. +Each node of the tree contains an element. Comparison is done +with `org-element--cache-compare'. This cache is used in +`org-element-at-point'.") + +(defvar org-element--cache-objects nil + "Hash table used as to cache objects. +Key is an element, as returned by `org-element-at-point', and +value is an alist where each association is: + + (PARENT COMPLETEP . OBJECTS) + +where PARENT is an element or object, COMPLETEP is a boolean, +non-nil when all direct children of parent are already cached and +OBJECTS is a list of such children, as objects, from farthest to +closest. + +In the following example, \\alpha, bold object and \\beta are +contained within a paragraph + + \\alpha *\\beta* + +If the paragraph is completely parsed, OBJECTS-DATA will be + + ((PARAGRAPH t BOLD-OBJECT ENTITY-OBJECT) + (BOLD-OBJECT t ENTITY-OBJECT)) + +whereas in a partially parsed paragraph, it could be + + ((PARAGRAPH nil ENTITY-OBJECT)) + +This cache is used in `org-element-context'.") + +(defvar org-element--cache-sync-requests nil + "List of pending synchronization requests. + +A request is a vector with the following pattern: + + \[NEXT BEG END OFFSET PARENT PHASE] + +Processing a synchronization request consists of three phases: + + 0. Delete modified elements, + 1. Fill missing area in cache, + 2. Shift positions and re-parent elements after the changes. + +During phase 0, NEXT is the key of the first element to be +removed, BEG and END is buffer position delimiting the +modifications. Elements starting between them (inclusive) are +removed. So are elements whose parent is removed. PARENT, when +non-nil, is the parent of the first element to be removed. + +During phase 1, NEXT is the key of the next known element in +cache and BEG its beginning position. Parse buffer between that +element and the one before it in order to determine the parent of +the next element. Set PARENT to the element containing NEXT. + +During phase 2, NEXT is the key of the next element to shift in +the parse tree. All elements starting from this one have their +properties relatives to buffer positions shifted by integer +OFFSET and, if they belong to element PARENT, are adopted by it. + +PHASE specifies the phase number, as an integer.") + +(defvar org-element--cache-sync-timer nil + "Timer used for cache synchronization.") + +(defvar org-element--cache-sync-keys nil + "Hash table used to store keys during synchronization. +See `org-element--cache-key' for more information.") + +(defsubst org-element--cache-key (element) + "Return a unique key for ELEMENT in cache tree. + +Keys are used to keep a total order among elements in the cache. +Comparison is done with `org-element--cache-key-less-p'. + +When no synchronization is taking place, a key is simply the +beginning position of the element, or that position plus one in +the case of an first item (respectively row) in +a list (respectively a table). + +During a synchronization, the key is the one the element had when +the cache was synchronized for the last time. Elements added to +cache during the synchronization get a new key generated with +`org-element--cache-generate-key'. + +Such keys are stored in `org-element--cache-sync-keys'. The hash +table is cleared once the synchronization is complete." + (or (gethash element org-element--cache-sync-keys) + (let* ((begin (org-element-property :begin element)) + ;; Increase beginning position of items (respectively + ;; table rows) by one, so the first item can get + ;; a different key from its parent list (respectively + ;; table). + (key (if (memq (org-element-type element) '(item table-row)) + (1+ begin) + begin))) + (if org-element--cache-sync-requests + (puthash element key org-element--cache-sync-keys) + key)))) + +(defun org-element--cache-generate-key (lower upper) + "Generate a key between LOWER and UPPER. + +LOWER and UPPER are integers or lists, possibly empty. + +If LOWER and UPPER are equals, return LOWER. Otherwise, return +a unique key, as an integer or a list of integers, according to +the following rules: + + - LOWER and UPPER are compared level-wise until values differ. + + - If, at a given level, LOWER and UPPER differ from more than + 2, the new key shares all the levels above with LOWER and + gets a new level. Its value is the mean between LOWER and + UPPER: + + (1 2) + (1 4) --> (1 3) + + - If LOWER has no value to compare with, it is assumed that its + value is `most-negative-fixnum'. E.g., + + (1 1) + (1 1 2) + + is equivalent to + + (1 1 m) + (1 1 2) + + where m is `most-negative-fixnum'. Likewise, if UPPER is + short of levels, the current value is `most-positive-fixnum'. + + - If they differ from only one, the new key inherits from + current LOWER level and fork it at the next level. E.g., + + (2 1) + (3 3) + + is equivalent to + + (2 1) + (2 M) + + where M is `most-positive-fixnum'. + + - If the key is only one level long, it is returned as an + integer: + + (1 2) + (3 2) --> 2 + +When they are not equals, the function assumes that LOWER is +lesser than UPPER, per `org-element--cache-key-less-p'." + (if (equal lower upper) lower + (let ((lower (if (integerp lower) (list lower) lower)) + (upper (if (integerp upper) (list upper) upper)) + skip-upper key) + (catch 'exit + (while t + (let ((min (or (car lower) most-negative-fixnum)) + (max (cond (skip-upper most-positive-fixnum) + ((car upper)) + (t most-positive-fixnum)))) + (if (< (1+ min) max) + (let ((mean (+ (ash min -1) (ash max -1) (logand min max 1)))) + (throw 'exit (if key (nreverse (cons mean key)) mean))) + (when (and (< min max) (not skip-upper)) + ;; When at a given level, LOWER and UPPER differ from + ;; 1, ignore UPPER altogether. Instead create a key + ;; between LOWER and the greatest key with the same + ;; prefix as LOWER so far. + (setq skip-upper t)) + (push min key) + (setq lower (cdr lower) upper (cdr upper))))))))) + +(defsubst org-element--cache-key-less-p (a b) + "Non-nil if key A is less than key B. +A and B are either integers or lists of integers, as returned by +`org-element--cache-key'." + (if (integerp a) (if (integerp b) (< a b) (<= a (car b))) + (if (integerp b) (< (car a) b) + (catch 'exit + (while (and a b) + (cond ((car-less-than-car a b) (throw 'exit t)) + ((car-less-than-car b a) (throw 'exit nil)) + (t (setq a (cdr a) b (cdr b))))) + ;; If A is empty, either keys are equal (B is also empty) and + ;; we return nil, or A is lesser than B (B is longer) and we + ;; return a non-nil value. + ;; + ;; If A is not empty, B is necessarily empty and A is greater + ;; than B (A is longer). Therefore, return nil. + (and (null a) b))))) + +(defun org-element--cache-compare (a b) + "Non-nil when element A is located before element B." + (org-element--cache-key-less-p (org-element--cache-key a) + (org-element--cache-key b))) + +(defsubst org-element--cache-root () + "Return root value in cache. +This function assumes `org-element--cache' is a valid AVL tree." + (avl-tree--node-left (avl-tree--dummyroot org-element--cache))) + + +;;;; Tools + +(defsubst org-element--cache-active-p () + "Non-nil when cache is active in current buffer." + (and org-element-use-cache + org-element--cache + (derived-mode-p 'org-mode))) + +(defun org-element--cache-find (pos &optional side) + "Find element in cache starting at POS or before. + +POS refers to a buffer position. + +When optional argument SIDE is non-nil, the function checks for +elements starting at or past POS instead. If SIDE is `both', the +function returns a cons cell where car is the first element +starting at or before POS and cdr the first element starting +after POS. + +The function can only find elements in the synchronized part of +the cache." + (let ((limit (and org-element--cache-sync-requests + (aref (car org-element--cache-sync-requests) 0))) + (node (org-element--cache-root)) + lower upper) + (while node + (let* ((element (avl-tree--node-data node)) + (begin (org-element-property :begin element))) + (cond + ((and limit + (not (org-element--cache-key-less-p + (org-element--cache-key element) limit))) + (setq node (avl-tree--node-left node))) + ((> begin pos) + (setq upper element + node (avl-tree--node-left node))) + ((< begin pos) + (setq lower element + node (avl-tree--node-right node))) + ;; We found an element in cache starting at POS. If `side' + ;; is `both' we also want the next one in order to generate + ;; a key in-between. + ;; + ;; If the element is the first row or item in a table or + ;; a plain list, we always return the table or the plain + ;; list. + ;; + ;; In any other case, we return the element found. + ((eq side 'both) + (setq lower element) + (setq node (avl-tree--node-right node))) + ((and (memq (org-element-type element) '(item table-row)) + (let ((parent (org-element-property :parent element))) + (and (= (org-element-property :begin element) + (org-element-property :contents-begin parent)) + (setq node nil + lower parent + upper parent))))) + (t + (setq node nil + lower element + upper element))))) + (pcase side + (`both (cons lower upper)) + (`nil lower) + (_ upper)))) + +(defun org-element--cache-put (element &optional data) + "Store ELEMENT in current buffer's cache, if allowed. +When optional argument DATA is non-nil, assume is it object data +relative to ELEMENT and store it in the objects cache." + (cond ((not (org-element--cache-active-p)) nil) + ((not data) + (when org-element--cache-sync-requests + ;; During synchronization, first build an appropriate key + ;; for the new element so `avl-tree-enter' can insert it at + ;; the right spot in the cache. + (let ((keys (org-element--cache-find + (org-element-property :begin element) 'both))) + (puthash element + (org-element--cache-generate-key + (and (car keys) (org-element--cache-key (car keys))) + (cond ((cdr keys) (org-element--cache-key (cdr keys))) + (org-element--cache-sync-requests + (aref (car org-element--cache-sync-requests) 0)))) + org-element--cache-sync-keys))) + (avl-tree-enter org-element--cache element)) + ;; Headlines are not stored in cache, so objects in titles are + ;; not stored either. + ((eq (org-element-type element) 'headline) nil) + (t (puthash element data org-element--cache-objects)))) + +(defsubst org-element--cache-remove (element) + "Remove ELEMENT from cache. +Assume ELEMENT belongs to cache and that a cache is active." + (avl-tree-delete org-element--cache element) + (remhash element org-element--cache-objects)) + + +;;;; Synchronization + +(defsubst org-element--cache-set-timer (buffer) + "Set idle timer for cache synchronization in BUFFER." + (when org-element--cache-sync-timer + (cancel-timer org-element--cache-sync-timer)) + (setq org-element--cache-sync-timer + (run-with-idle-timer + (let ((idle (current-idle-time))) + (if idle (time-add idle org-element-cache-sync-break) + org-element-cache-sync-idle-time)) + nil + #'org-element--cache-sync + buffer))) + +(defsubst org-element--cache-interrupt-p (time-limit) + "Non-nil when synchronization process should be interrupted. +TIME-LIMIT is a time value or nil." + (and time-limit + (or (input-pending-p) + (time-less-p time-limit (current-time))))) + +(defsubst org-element--cache-shift-positions (element offset &optional props) + "Shift ELEMENT properties relative to buffer positions by OFFSET. + +Properties containing buffer positions are `:begin', `:end', +`:contents-begin', `:contents-end' and `:structure'. When +optional argument PROPS is a list of keywords, only shift +properties provided in that list. + +Properties are modified by side-effect." + (let ((properties (nth 1 element))) + ;; Shift `:structure' property for the first plain list only: it + ;; is the only one that really matters and it prevents from + ;; shifting it more than once. + (when (and (or (not props) (memq :structure props)) + (eq (org-element-type element) 'plain-list) + (not (eq (org-element-type (plist-get properties :parent)) + 'item))) + (dolist (item (plist-get properties :structure)) + (cl-incf (car item) offset) + (cl-incf (nth 6 item) offset))) + (dolist (key '(:begin :contents-begin :contents-end :end :post-affiliated)) + (let ((value (and (or (not props) (memq key props)) + (plist-get properties key)))) + (and value (plist-put properties key (+ offset value))))))) + +(defun org-element--cache-sync (buffer &optional threshold future-change) + "Synchronize cache with recent modification in BUFFER. + +When optional argument THRESHOLD is non-nil, do the +synchronization for all elements starting before or at threshold, +then exit. Otherwise, synchronize cache for as long as +`org-element-cache-sync-duration' or until Emacs leaves idle +state. + +FUTURE-CHANGE, when non-nil, is a buffer position where changes +not registered yet in the cache are going to happen. It is used +in `org-element--cache-submit-request', where cache is partially +updated before current modification are actually submitted." + (when (buffer-live-p buffer) + (with-current-buffer buffer + (let ((inhibit-quit t) request next) + (when org-element--cache-sync-timer + (cancel-timer org-element--cache-sync-timer)) + (catch 'interrupt + (while org-element--cache-sync-requests + (setq request (car org-element--cache-sync-requests) + next (nth 1 org-element--cache-sync-requests)) + (org-element--cache-process-request + request + (and next (aref next 0)) + threshold + (and (not threshold) + (time-add (current-time) + org-element-cache-sync-duration)) + future-change) + ;; Request processed. Merge current and next offsets and + ;; transfer ending position. + (when next + (cl-incf (aref next 3) (aref request 3)) + (aset next 2 (aref request 2))) + (setq org-element--cache-sync-requests + (cdr org-element--cache-sync-requests)))) + ;; If more requests are awaiting, set idle timer accordingly. + ;; Otherwise, reset keys. + (if org-element--cache-sync-requests + (org-element--cache-set-timer buffer) + (clrhash org-element--cache-sync-keys)))))) + +(defun org-element--cache-process-request + (request next threshold time-limit future-change) + "Process synchronization REQUEST for all entries before NEXT. + +REQUEST is a vector, built by `org-element--cache-submit-request'. + +NEXT is a cache key, as returned by `org-element--cache-key'. + +When non-nil, THRESHOLD is a buffer position. Synchronization +stops as soon as a shifted element begins after it. + +When non-nil, TIME-LIMIT is a time value. Synchronization stops +after this time or when Emacs exits idle state. + +When non-nil, FUTURE-CHANGE is a buffer position where changes +not registered yet in the cache are going to happen. See +`org-element--cache-submit-request' for more information. + +Throw `interrupt' if the process stops before completing the +request." + (catch 'quit + (when (= (aref request 5) 0) + ;; Phase 0. + ;; + ;; Delete all elements starting after BEG, but not after buffer + ;; position END or past element with key NEXT. Also delete + ;; elements contained within a previously removed element + ;; (stored in `last-container'). + ;; + ;; At each iteration, we start again at tree root since + ;; a deletion modifies structure of the balanced tree. + (catch 'end-phase + (while t + (when (org-element--cache-interrupt-p time-limit) + (throw 'interrupt nil)) + ;; Find first element in cache with key BEG or after it. + (let ((beg (aref request 0)) + (end (aref request 2)) + (node (org-element--cache-root)) + data data-key last-container) + (while node + (let* ((element (avl-tree--node-data node)) + (key (org-element--cache-key element))) + (cond + ((org-element--cache-key-less-p key beg) + (setq node (avl-tree--node-right node))) + ((org-element--cache-key-less-p beg key) + (setq data element + data-key key + node (avl-tree--node-left node))) + (t (setq data element + data-key key + node nil))))) + (if data + (let ((pos (org-element-property :begin data))) + (if (if (or (not next) + (org-element--cache-key-less-p data-key next)) + (<= pos end) + (and last-container + (let ((up data)) + (while (and up (not (eq up last-container))) + (setq up (org-element-property :parent up))) + up))) + (progn (when (and (not last-container) + (> (org-element-property :end data) + end)) + (setq last-container data)) + (org-element--cache-remove data)) + (aset request 0 data-key) + (aset request 1 pos) + (aset request 5 1) + (throw 'end-phase nil))) + ;; No element starting after modifications left in + ;; cache: further processing is futile. + (throw 'quit t)))))) + (when (= (aref request 5) 1) + ;; Phase 1. + ;; + ;; Phase 0 left a hole in the cache. Some elements after it + ;; could have parents within. For example, in the following + ;; buffer: + ;; + ;; - item + ;; + ;; + ;; Paragraph1 + ;; + ;; Paragraph2 + ;; + ;; if we remove a blank line between "item" and "Paragraph1", + ;; everything down to "Paragraph2" is removed from cache. But + ;; the paragraph now belongs to the list, and its `:parent' + ;; property no longer is accurate. + ;; + ;; Therefore we need to parse again elements in the hole, or at + ;; least in its last section, so that we can re-parent + ;; subsequent elements, during phase 2. + ;; + ;; Note that we only need to get the parent from the first + ;; element in cache after the hole. + ;; + ;; When next key is lesser or equal to the current one, delegate + ;; phase 1 processing to next request in order to preserve key + ;; order among requests. + (let ((key (aref request 0))) + (when (and next (not (org-element--cache-key-less-p key next))) + (let ((next-request (nth 1 org-element--cache-sync-requests))) + (aset next-request 0 key) + (aset next-request 1 (aref request 1)) + (aset next-request 5 1)) + (throw 'quit t))) + ;; Next element will start at its beginning position plus + ;; offset, since it hasn't been shifted yet. Therefore, LIMIT + ;; contains the real beginning position of the first element to + ;; shift and re-parent. + (let ((limit (+ (aref request 1) (aref request 3)))) + (cond ((and threshold (> limit threshold)) (throw 'interrupt nil)) + ((and future-change (>= limit future-change)) + ;; Changes are going to happen around this element and + ;; they will trigger another phase 1 request. Skip the + ;; current one. + (aset request 5 2)) + (t + (let ((parent (org-element--parse-to limit t time-limit))) + (aset request 4 parent) + (aset request 5 2)))))) + ;; Phase 2. + ;; + ;; Shift all elements starting from key START, but before NEXT, by + ;; OFFSET, and re-parent them when appropriate. + ;; + ;; Elements are modified by side-effect so the tree structure + ;; remains intact. + ;; + ;; Once THRESHOLD, if any, is reached, or once there is an input + ;; pending, exit. Before leaving, the current synchronization + ;; request is updated. + (let ((start (aref request 0)) + (offset (aref request 3)) + (parent (aref request 4)) + (node (org-element--cache-root)) + (stack (list nil)) + (leftp t) + exit-flag) + ;; No re-parenting nor shifting planned: request is over. + (when (and (not parent) (zerop offset)) (throw 'quit t)) + (while node + (let* ((data (avl-tree--node-data node)) + (key (org-element--cache-key data))) + (if (and leftp (avl-tree--node-left node) + (not (org-element--cache-key-less-p key start))) + (progn (push node stack) + (setq node (avl-tree--node-left node))) + (unless (org-element--cache-key-less-p key start) + ;; We reached NEXT. Request is complete. + (when (equal key next) (throw 'quit t)) + ;; Handle interruption request. Update current request. + (when (or exit-flag (org-element--cache-interrupt-p time-limit)) + (aset request 0 key) + (aset request 4 parent) + (throw 'interrupt nil)) + ;; Shift element. + (unless (zerop offset) + (org-element--cache-shift-positions data offset) + ;; Shift associated objects data, if any. + (dolist (object-data (gethash data org-element--cache-objects)) + (dolist (object (cddr object-data)) + (org-element--cache-shift-positions object offset)))) + (let ((begin (org-element-property :begin data))) + ;; Update PARENT and re-parent DATA, only when + ;; necessary. Propagate new structures for lists. + (while (and parent + (<= (org-element-property :end parent) begin)) + (setq parent (org-element-property :parent parent))) + (cond ((and (not parent) (zerop offset)) (throw 'quit nil)) + ((and parent + (let ((p (org-element-property :parent data))) + (or (not p) + (< (org-element-property :begin p) + (org-element-property :begin parent))))) + (org-element-put-property data :parent parent) + (let ((s (org-element-property :structure parent))) + (when (and s (org-element-property :structure data)) + (org-element-put-property data :structure s))))) + ;; Cache is up-to-date past THRESHOLD. Request + ;; interruption. + (when (and threshold (> begin threshold)) (setq exit-flag t)))) + (setq node (if (setq leftp (avl-tree--node-right node)) + (avl-tree--node-right node) + (pop stack)))))) + ;; We reached end of tree: synchronization complete. + t))) + +(defun org-element--parse-to (pos &optional syncp time-limit) + "Parse elements in current section, down to POS. + +Start parsing from the closest between the last known element in +cache or headline above. Return the smallest element containing +POS. + +When optional argument SYNCP is non-nil, return the parent of the +element containing POS instead. In that case, it is also +possible to provide TIME-LIMIT, which is a time value specifying +when the parsing should stop. The function throws `interrupt' if +the process stopped before finding the expected result." + (catch 'exit + (org-with-wide-buffer + (goto-char pos) + (let* ((cached (and (org-element--cache-active-p) + (org-element--cache-find pos nil))) + (begin (org-element-property :begin cached)) + element next mode) + (cond + ;; Nothing in cache before point: start parsing from first + ;; element following headline above, or first element in + ;; buffer. + ((not cached) + (when (org-with-limited-levels (outline-previous-heading)) + (setq mode 'planning) + (forward-line)) + (skip-chars-forward " \r\t\n") + (beginning-of-line)) + ;; Cache returned exact match: return it. + ((= pos begin) + (throw 'exit (if syncp (org-element-property :parent cached) cached))) + ;; There's a headline between cached value and POS: cached + ;; value is invalid. Start parsing from first element + ;; following the headline. + ((re-search-backward + (org-with-limited-levels org-outline-regexp-bol) begin t) + (forward-line) + (skip-chars-forward " \r\t\n") + (beginning-of-line) + (setq mode 'planning)) + ;; Check if CACHED or any of its ancestors contain point. + ;; + ;; If there is such an element, we inspect it in order to know + ;; if we return it or if we need to parse its contents. + ;; Otherwise, we just start parsing from current location, + ;; which is right after the top-most element containing + ;; CACHED. + ;; + ;; As a special case, if POS is at the end of the buffer, we + ;; want to return the innermost element ending there. + ;; + ;; Also, if we find an ancestor and discover that we need to + ;; parse its contents, make sure we don't start from + ;; `:contents-begin', as we would otherwise go past CACHED + ;; again. Instead, in that situation, we will resume parsing + ;; from NEXT, which is located after CACHED or its higher + ;; ancestor not containing point. + (t + (let ((up cached) + (pos (if (= (point-max) pos) (1- pos) pos))) + (goto-char (or (org-element-property :contents-begin cached) begin)) + (while (let ((end (org-element-property :end up))) + (and (<= end pos) + (goto-char end) + (setq up (org-element-property :parent up))))) + (cond ((not up)) + ((eobp) (setq element up)) + (t (setq element up next (point))))))) + ;; Parse successively each element until we reach POS. + (let ((end (or (org-element-property :end element) + (save-excursion + (org-with-limited-levels (outline-next-heading)) + (point)))) + (parent element)) + (while t + (when syncp + (cond ((= (point) pos) (throw 'exit parent)) + ((org-element--cache-interrupt-p time-limit) + (throw 'interrupt nil)))) + (unless element + (setq element (org-element--current-element + end 'element mode + (org-element-property :structure parent))) + (org-element-put-property element :parent parent) + (org-element--cache-put element)) + (let ((elem-end (org-element-property :end element)) + (type (org-element-type element))) + (cond + ;; Skip any element ending before point. Also skip + ;; element ending at point (unless it is also the end of + ;; buffer) since we're sure that another element begins + ;; after it. + ((and (<= elem-end pos) (/= (point-max) elem-end)) + (goto-char elem-end) + (setq mode (org-element--next-mode type nil))) + ;; A non-greater element contains point: return it. + ((not (memq type org-element-greater-elements)) + (throw 'exit element)) + ;; Otherwise, we have to decide if ELEMENT really + ;; contains POS. In that case we start parsing from + ;; contents' beginning. + ;; + ;; If POS is at contents' beginning but it is also at + ;; the beginning of the first item in a list or a table. + ;; In that case, we need to create an anchor for that + ;; list or table, so return it. + ;; + ;; Also, if POS is at the end of the buffer, no element + ;; can start after it, but more than one may end there. + ;; Arbitrarily, we choose to return the innermost of + ;; such elements. + ((let ((cbeg (org-element-property :contents-begin element)) + (cend (org-element-property :contents-end element))) + (when (or syncp + (and cbeg cend + (or (< cbeg pos) + (and (= cbeg pos) + (not (memq type '(plain-list table))))) + (or (> cend pos) + (and (= cend pos) (= (point-max) pos))))) + (goto-char (or next cbeg)) + (setq next nil + mode (org-element--next-mode type t) + parent element + end cend)))) + ;; Otherwise, return ELEMENT as it is the smallest + ;; element containing POS. + (t (throw 'exit element)))) + (setq element nil))))))) + + +;;;; Staging Buffer Changes + +(defconst org-element--cache-sensitive-re + (concat + org-outline-regexp-bol "\\|" + "\\\\end{[A-Za-z0-9*]+}[ \t]*$" "\\|" + "^[ \t]*\\(?:" + "#\\+\\(?:BEGIN[:_]\\|END\\(?:_\\|:?[ \t]*$\\)\\)" "\\|" + "\\\\begin{[A-Za-z0-9*]+}" "\\|" + ":\\(?:\\w\\|[-_]\\)+:[ \t]*$" + "\\)") + "Regexp matching a sensitive line, structure wise. +A sensitive line is a headline, inlinetask, block, drawer, or +latex-environment boundary. When such a line is modified, +structure changes in the document may propagate in the whole +section, possibly making cache invalid.") + +(defvar org-element--cache-change-warning nil + "Non-nil when a sensitive line is about to be changed. +It is a symbol among nil, t and `headline'.") + +(defun org-element--cache-before-change (beg end) + "Request extension of area going to be modified if needed. +BEG and END are the beginning and end of the range of changed +text. See `before-change-functions' for more information." + (when (org-element--cache-active-p) + (org-with-wide-buffer + (goto-char beg) + (beginning-of-line) + (let ((bottom (save-excursion (goto-char end) (line-end-position)))) + (setq org-element--cache-change-warning + (save-match-data + (if (and (org-with-limited-levels (org-at-heading-p)) + (= (line-end-position) bottom)) + 'headline + (let ((case-fold-search t)) + (re-search-forward + org-element--cache-sensitive-re bottom t))))))))) + +(defun org-element--cache-after-change (beg end pre) + "Update buffer modifications for current buffer. +BEG and END are the beginning and end of the range of changed +text, and the length in bytes of the pre-change text replaced by +that range. See `after-change-functions' for more information." + (when (org-element--cache-active-p) + (org-with-wide-buffer + (goto-char beg) + (beginning-of-line) + (save-match-data + (let ((top (point)) + (bottom (save-excursion (goto-char end) (line-end-position)))) + ;; Determine if modified area needs to be extended, according + ;; to both previous and current state. We make a special + ;; case for headline editing: if a headline is modified but + ;; not removed, do not extend. + (when (pcase org-element--cache-change-warning + (`t t) + (`headline + (not (and (org-with-limited-levels (org-at-heading-p)) + (= (line-end-position) bottom)))) + (_ + (let ((case-fold-search t)) + (re-search-forward + org-element--cache-sensitive-re bottom t)))) + ;; Effectively extend modified area. + (org-with-limited-levels + (setq top (progn (goto-char top) + (when (outline-previous-heading) (forward-line)) + (point))) + (setq bottom (progn (goto-char bottom) + (if (outline-next-heading) (1- (point)) + (point)))))) + ;; Store synchronization request. + (let ((offset (- end beg pre))) + (org-element--cache-submit-request top (- bottom offset) offset))))) + ;; Activate a timer to process the request during idle time. + (org-element--cache-set-timer (current-buffer)))) + +(defun org-element--cache-for-removal (beg end offset) + "Return first element to remove from cache. + +BEG and END are buffer positions delimiting buffer modifications. +OFFSET is the size of the changes. + +Returned element is usually the first element in cache containing +any position between BEG and END. As an exception, greater +elements around the changes that are robust to contents +modifications are preserved and updated according to the +changes." + (let* ((elements (org-element--cache-find (1- beg) 'both)) + (before (car elements)) + (after (cdr elements))) + (if (not before) after + (let ((up before) + (robust-flag t)) + (while up + (if (let ((type (org-element-type up))) + (and (or (memq type '(center-block dynamic-block quote-block + special-block)) + ;; Drawers named "PROPERTIES" are probably + ;; a properties drawer being edited. Force + ;; parsing to check if editing is over. + (and (eq type 'drawer) + (not (string= + (org-element-property :drawer-name up) + "PROPERTIES")))) + (let ((cbeg (org-element-property :contents-begin up))) + (and cbeg + (<= cbeg beg) + (> (org-element-property :contents-end up) end))))) + ;; UP is a robust greater element containing changes. + ;; We only need to extend its ending boundaries. + (org-element--cache-shift-positions + up offset '(:contents-end :end)) + (setq before up) + (when robust-flag (setq robust-flag nil))) + (setq up (org-element-property :parent up))) + ;; We're at top level element containing ELEMENT: if it's + ;; altered by buffer modifications, it is first element in + ;; cache to be removed. Otherwise, that first element is the + ;; following one. + ;; + ;; As a special case, do not remove BEFORE if it is a robust + ;; container for current changes. + (if (or (< (org-element-property :end before) beg) robust-flag) after + before))))) + +(defun org-element--cache-submit-request (beg end offset) + "Submit a new cache synchronization request for current buffer. +BEG and END are buffer positions delimiting the minimal area +where cache data should be removed. OFFSET is the size of the +change, as an integer." + (let ((next (car org-element--cache-sync-requests)) + delete-to delete-from) + (if (and next + (zerop (aref next 5)) + (> (setq delete-to (+ (aref next 2) (aref next 3))) end) + (<= (setq delete-from (aref next 1)) end)) + ;; Current changes can be merged with first sync request: we + ;; can save a partial cache synchronization. + (progn + (cl-incf (aref next 3) offset) + ;; If last change happened within area to be removed, extend + ;; boundaries of robust parents, if any. Otherwise, find + ;; first element to remove and update request accordingly. + (if (> beg delete-from) + (let ((up (aref next 4))) + (while up + (org-element--cache-shift-positions + up offset '(:contents-end :end)) + (setq up (org-element-property :parent up)))) + (let ((first (org-element--cache-for-removal beg delete-to offset))) + (when first + (aset next 0 (org-element--cache-key first)) + (aset next 1 (org-element-property :begin first)) + (aset next 4 (org-element-property :parent first)))))) + ;; Ensure cache is correct up to END. Also make sure that NEXT, + ;; if any, is no longer a 0-phase request, thus ensuring that + ;; phases are properly ordered. We need to provide OFFSET as + ;; optional parameter since current modifications are not known + ;; yet to the otherwise correct part of the cache (i.e, before + ;; the first request). + (when next (org-element--cache-sync (current-buffer) end beg)) + (let ((first (org-element--cache-for-removal beg end offset))) + (if first + (push (let ((beg (org-element-property :begin first)) + (key (org-element--cache-key first))) + (cond + ;; When changes happen before the first known + ;; element, re-parent and shift the rest of the + ;; cache. + ((> beg end) (vector key beg nil offset nil 1)) + ;; Otherwise, we find the first non robust + ;; element containing END. All elements between + ;; FIRST and this one are to be removed. + ((let ((first-end (org-element-property :end first))) + (and (> first-end end) + (vector key beg first-end offset first 0)))) + (t + (let* ((element (org-element--cache-find end)) + (end (org-element-property :end element)) + (up element)) + (while (and (setq up (org-element-property :parent up)) + (>= (org-element-property :begin up) beg)) + (setq end (org-element-property :end up) + element up)) + (vector key beg end offset element 0))))) + org-element--cache-sync-requests) + ;; No element to remove. No need to re-parent either. + ;; Simply shift additional elements, if any, by OFFSET. + (when org-element--cache-sync-requests + (cl-incf (aref (car org-element--cache-sync-requests) 3) + offset))))))) + + +;;;; Public Functions + +;;;###autoload +(defun org-element-cache-reset (&optional all) + "Reset cache in current buffer. +When optional argument ALL is non-nil, reset cache in all Org +buffers." + (interactive "P") + (dolist (buffer (if all (buffer-list) (list (current-buffer)))) + (with-current-buffer buffer + (when (and org-element-use-cache (derived-mode-p 'org-mode)) + (setq-local org-element--cache + (avl-tree-create #'org-element--cache-compare)) + (setq-local org-element--cache-objects (make-hash-table :test #'eq)) + (setq-local org-element--cache-sync-keys + (make-hash-table :weakness 'key :test #'eq)) + (setq-local org-element--cache-change-warning nil) + (setq-local org-element--cache-sync-requests nil) + (setq-local org-element--cache-sync-timer nil) + (add-hook 'before-change-functions + #'org-element--cache-before-change nil t) + (add-hook 'after-change-functions + #'org-element--cache-after-change nil t))))) + +;;;###autoload +(defun org-element-cache-refresh (pos) + "Refresh cache at position POS." + (when (org-element--cache-active-p) + (org-element--cache-sync (current-buffer) pos) + (org-element--cache-submit-request pos pos 0) + (org-element--cache-set-timer (current-buffer)))) @@ -4678,7 +5733,7 @@ indentation is not done with TAB characters." ;; The first move is to implement a way to obtain the smallest element ;; containing point. This is the job of `org-element-at-point'. It ;; basically jumps back to the beginning of section containing point -;; and moves, element after element, with +;; and proceed, one element after the other, with ;; `org-element--current-element' until the container is found. Note: ;; When using `org-element-at-point', secondary values are never ;; parsed since the function focuses on elements, not on objects. @@ -4689,8 +5744,9 @@ indentation is not done with TAB characters." ;; `org-element-nested-p' and `org-element-swap-A-B' may be used ;; internally by navigation and manipulation tools. + ;;;###autoload -(defun org-element-at-point (&optional keep-trail) +(defun org-element-at-point () "Determine closest element around point. Return value is a list like (TYPE PROPS) where TYPE is the type @@ -4701,118 +5757,36 @@ Possible types are defined in `org-element-all-elements'. Properties depend on element or object type, but always include `:begin', `:end', `:parent' and `:post-blank' properties. -As a special case, if point is at the very beginning of a list or -sub-list, returned element will be that list instead of the first -item. In the same way, if point is at the beginning of the first -row of a table, returned element will be the table instead of the -first row. - -If optional argument KEEP-TRAIL is non-nil, the function returns -a list of elements leading to element at point. The list's CAR -is always the element at point. The following positions contain -element's siblings, then parents, siblings of parents, until the -first element of current section." +As a special case, if point is at the very beginning of the first +item in a list or sub-list, returned element will be that list +instead of the item. Likewise, if point is at the beginning of +the first row of a table, returned element will be the table +instead of the first row. + +When point is at the end of the buffer, return the innermost +element ending there." (org-with-wide-buffer - ;; If at a headline, parse it. It is the sole element that - ;; doesn't require to know about context. Be sure to disallow - ;; secondary string parsing, though. - (if (org-with-limited-levels (org-at-heading-p)) - (progn - (beginning-of-line) - (if (not keep-trail) (org-element-headline-parser (point-max) t) - (list (org-element-headline-parser (point-max) t)))) - ;; Otherwise move at the beginning of the section containing - ;; point. - (catch 'exit - (let ((origin (point)) - (end (save-excursion - (org-with-limited-levels (outline-next-heading)) (point))) - element type special-flag trail struct prevs parent) - (org-with-limited-levels - (if (org-before-first-heading-p) - ;; In empty lines at buffer's beginning, return nil. - (progn (goto-char (point-min)) - (org-skip-whitespace) - (when (or (eobp) (> (line-beginning-position) origin)) - (throw 'exit nil))) - (org-back-to-heading) - (forward-line) - (org-skip-whitespace) - (when (or (eobp) (> (line-beginning-position) origin)) - ;; In blank lines just after the headline, point still - ;; belongs to the headline. - (throw 'exit - (progn (skip-chars-backward " \r\t\n") - (beginning-of-line) - (if (not keep-trail) - (org-element-headline-parser (point-max) t) - (list (org-element-headline-parser - (point-max) t)))))))) - (beginning-of-line) - ;; Parse successively each element, skipping those ending - ;; before original position. - (while t - (setq element - (org-element--current-element end 'element special-flag struct) - type (car element)) - (org-element-put-property element :parent parent) - (when keep-trail (push element trail)) - (cond - ;; 1. Skip any element ending before point. Also skip - ;; element ending at point when we're sure that another - ;; element has started. - ((let ((elem-end (org-element-property :end element))) - (when (or (< elem-end origin) - (and (= elem-end origin) (/= elem-end end))) - (goto-char elem-end)))) - ;; 2. An element containing point is always the element at - ;; point. - ((not (memq type org-element-greater-elements)) - (throw 'exit (if keep-trail trail element))) - ;; 3. At any other greater element type, if point is - ;; within contents, move into it. - (t - (let ((cbeg (org-element-property :contents-begin element)) - (cend (org-element-property :contents-end element))) - (if (or (not cbeg) (not cend) (> cbeg origin) (< cend origin) - ;; Create an anchor for tables and plain lists: - ;; when point is at the very beginning of these - ;; elements, ignoring affiliated keywords, - ;; target them instead of their contents. - (and (= cbeg origin) (memq type '(plain-list table))) - ;; When point is at contents end, do not move - ;; into elements with an explicit ending, but - ;; return that element instead. - (and (= cend origin) - (or (memq type - '(center-block - drawer dynamic-block inlinetask - property-drawer quote-block - special-block)) - ;; Corner case: if a list ends at the - ;; end of a buffer without a final new - ;; line, return last element in last - ;; item instead. - (and (memq type '(item plain-list)) - (progn (goto-char cend) - (or (bolp) (not (eobp)))))))) - (throw 'exit (if keep-trail trail element)) - (setq parent element) - (case type - (plain-list - (setq special-flag 'item - struct (org-element-property :structure element))) - (item (setq special-flag nil)) - (property-drawer - (setq special-flag 'node-property struct nil)) - (table (setq special-flag 'table-row struct nil)) - (otherwise (setq special-flag nil struct nil))) - (setq end cend) - (goto-char cbeg))))))))))) + (let ((origin (point))) + (end-of-line) + (skip-chars-backward " \r\t\n") + (cond + ;; Within blank lines at the beginning of buffer, return nil. + ((bobp) nil) + ;; Within blank lines right after a headline, return that + ;; headline. + ((org-with-limited-levels (org-at-heading-p)) + (beginning-of-line) + (org-element-headline-parser (point-max) t)) + ;; Otherwise parse until we find element containing ORIGIN. + (t + (when (org-element--cache-active-p) + (if (not org-element--cache) (org-element-cache-reset) + (org-element--cache-sync (current-buffer) origin))) + (org-element--parse-to origin)))))) ;;;###autoload (defun org-element-context (&optional element) - "Return closest element or object around point. + "Return smallest element or object around point. Return value is a list like (TYPE PROPS) where TYPE is the type of the element or object and PROPS a plist of properties @@ -4823,34 +5797,36 @@ Possible types are defined in `org-element-all-elements' and object type, but always include `:begin', `:end', `:parent' and `:post-blank'. +As a special case, if point is right after an object and not at +the beginning of any other object, return that object. + Optional argument ELEMENT, when non-nil, is the closest element containing point, as returned by `org-element-at-point'. Providing it allows for quicker computation." (catch 'objects-forbidden (org-with-wide-buffer - (let* ((origin (point)) - (element (or element (org-element-at-point))) - (type (org-element-type element)) - context) - ;; Check if point is inside an element containing objects or at - ;; a secondary string. In that case, narrow buffer to the - ;; containing area. Otherwise, return ELEMENT. + (let* ((pos (point)) + (element (or element (org-element-at-point))) + (type (org-element-type element)) + (post (org-element-property :post-affiliated element))) + ;; If point is inside an element containing objects or + ;; a secondary string, narrow buffer to the container and + ;; proceed with parsing. Otherwise, return ELEMENT. (cond ;; At a parsed affiliated keyword, check if we're inside main ;; or dual value. - ((let ((post (org-element-property :post-affiliated element))) - (and post (< origin post))) + ((and post (< pos post)) (beginning-of-line) (let ((case-fold-search t)) (looking-at org-element--affiliated-re)) (cond ((not (member-ignore-case (match-string 1) org-element-parsed-keywords)) (throw 'objects-forbidden element)) - ((< (match-end 0) origin) + ((< (match-end 0) pos) (narrow-to-region (match-end 0) (line-end-position))) ((and (match-beginning 2) - (>= origin (match-beginning 2)) - (< origin (match-end 2))) + (>= pos (match-beginning 2)) + (< pos (match-end 2))) (narrow-to-region (match-beginning 2) (match-end 2))) (t (throw 'objects-forbidden element))) ;; Also change type to retrieve correct restrictions. @@ -4858,88 +5834,168 @@ Providing it allows for quicker computation." ;; At an item, objects can only be located within tag, if any. ((eq type 'item) (let ((tag (org-element-property :tag element))) - (if (not tag) (throw 'objects-forbidden element) + (if (or (not tag) (/= (line-beginning-position) post)) + (throw 'objects-forbidden element) (beginning-of-line) (search-forward tag (line-end-position)) (goto-char (match-beginning 0)) - (if (and (>= origin (point)) (< origin (match-end 0))) + (if (and (>= pos (point)) (< pos (match-end 0))) (narrow-to-region (point) (match-end 0)) (throw 'objects-forbidden element))))) - ;; At an headline or inlinetask, objects are located within - ;; their title. + ;; At an headline or inlinetask, objects are in title. ((memq type '(headline inlinetask)) - (goto-char (org-element-property :begin element)) - (skip-chars-forward "*") - (if (and (> origin (point)) (< origin (line-end-position))) - (narrow-to-region (point) (line-end-position)) - (throw 'objects-forbidden element))) + (let ((case-fold-search nil)) + (goto-char (org-element-property :begin element)) + (looking-at org-complex-heading-regexp) + (let ((end (match-end 4))) + (if (not end) (throw 'objects-forbidden element) + (goto-char (match-beginning 4)) + (when (looking-at org-comment-string) + (goto-char (match-end 0))) + (if (>= (point) end) (throw 'objects-forbidden element) + (narrow-to-region (point) end)))))) ;; At a paragraph, a table-row or a verse block, objects are ;; located within their contents. ((memq type '(paragraph table-row verse-block)) (let ((cbeg (org-element-property :contents-begin element)) (cend (org-element-property :contents-end element))) ;; CBEG is nil for table rules. - (if (and cbeg cend (>= origin cbeg) (< origin cend)) + (if (and cbeg cend (>= pos cbeg) + (or (< pos cend) (and (= pos cend) (eobp)))) (narrow-to-region cbeg cend) (throw 'objects-forbidden element)))) - ;; At a parsed keyword, objects are located within value. - ((eq type 'keyword) - (if (not (member (org-element-property :key element) - org-element-document-properties)) - (throw 'objects-forbidden element) - (beginning-of-line) - (search-forward ":") - (if (and (>= origin (point)) (< origin (line-end-position))) - (narrow-to-region (point) (line-end-position)) - (throw 'objects-forbidden element)))) ;; At a planning line, if point is at a timestamp, return it, ;; otherwise, return element. ((eq type 'planning) (dolist (p '(:closed :deadline :scheduled)) (let ((timestamp (org-element-property p element))) (when (and timestamp - (<= (org-element-property :begin timestamp) origin) - (> (org-element-property :end timestamp) origin)) + (<= (org-element-property :begin timestamp) pos) + (> (org-element-property :end timestamp) pos)) (throw 'objects-forbidden timestamp)))) + ;; All other locations cannot contain objects: bail out. (throw 'objects-forbidden element)) (t (throw 'objects-forbidden element))) (goto-char (point-min)) (let ((restriction (org-element-restriction type)) - (parent element) - (candidates 'initial)) - (catch 'exit - (while (setq candidates - (org-element--get-next-object-candidates - restriction candidates)) - (let ((closest-cand (rassq (apply 'min (mapcar 'cdr candidates)) - candidates))) - ;; If ORIGIN is before next object in element, there's - ;; no point in looking further. - (if (> (cdr closest-cand) origin) (throw 'exit parent) - (let* ((object - (progn (goto-char (cdr closest-cand)) - (funcall (intern (format "org-element-%s-parser" - (car closest-cand)))))) - (cbeg (org-element-property :contents-begin object)) - (cend (org-element-property :contents-end object)) - (obj-end (org-element-property :end object))) - (cond - ;; ORIGIN is after OBJECT, so skip it. - ((<= obj-end origin) (goto-char obj-end)) - ;; ORIGIN is within a non-recursive object or at - ;; an object boundaries: Return that object. - ((or (not cbeg) (< origin cbeg) (>= origin cend)) - (throw 'exit - (org-element-put-property object :parent parent))) - ;; Otherwise, move within current object and - ;; restrict search to the end of its contents. - (t (goto-char cbeg) - (narrow-to-region (point) cend) - (org-element-put-property object :parent parent) - (setq parent object - restriction (org-element-restriction object) - candidates 'initial))))))) - parent)))))) + (parent element) + (cache (cond ((not (org-element--cache-active-p)) nil) + (org-element--cache-objects + (gethash element org-element--cache-objects)) + (t (org-element-cache-reset) nil))) + next object-data last) + (prog1 + (catch 'exit + (while t + ;; When entering PARENT for the first time, get list + ;; of objects within known so far. Store it in + ;; OBJECT-DATA. + (unless next + (let ((data (assq parent cache))) + (if data (setq object-data data) + (push (setq object-data (list parent nil)) cache)))) + ;; Find NEXT object for analysis. + (catch 'found + ;; If NEXT is non-nil, we already exhausted the + ;; cache so we can parse buffer to find the object + ;; after it. + (if next (setq next (org-element--object-lex restriction)) + ;; Otherwise, check if cache can help us. + (let ((objects (cddr object-data)) + (completep (nth 1 object-data))) + (cond + ((and (not objects) completep) (throw 'exit parent)) + ((not objects) + (setq next (org-element--object-lex restriction))) + (t + (let ((cache-limit + (org-element-property :end (car objects)))) + (if (>= cache-limit pos) + ;; Cache contains the information needed. + (dolist (object objects (throw 'exit parent)) + (when (<= (org-element-property :begin object) + pos) + (if (>= (org-element-property :end object) + pos) + (throw 'found (setq next object)) + (throw 'exit parent)))) + (goto-char cache-limit) + (setq next + (org-element--object-lex restriction)))))))) + ;; If we have a new object to analyze, store it in + ;; cache. Otherwise record that there is nothing + ;; more to parse in this element at this depth. + (if next + (progn (org-element-put-property next :parent parent) + (push next (cddr object-data))) + (setcar (cdr object-data) t))) + ;; Process NEXT, if any, in order to know if we need + ;; to skip it, return it or move into it. + (if (or (not next) (> (org-element-property :begin next) pos)) + (throw 'exit (or last parent)) + (let ((end (org-element-property :end next)) + (cbeg (org-element-property :contents-begin next)) + (cend (org-element-property :contents-end next))) + (cond + ;; Skip objects ending before point. Also skip + ;; objects ending at point unless it is also the + ;; end of buffer, since we want to return the + ;; innermost object. + ((and (<= end pos) (/= (point-max) end)) + (goto-char end) + ;; For convenience, when object ends at POS, + ;; without any space, store it in LAST, as we + ;; will return it if no object starts here. + (when (and (= end pos) + (not (memq (char-before) '(?\s ?\t)))) + (setq last next))) + ;; If POS is within a container object, move + ;; into that object. + ((and cbeg cend + (>= pos cbeg) + (or (< pos cend) + ;; At contents' end, if there is no + ;; space before point, also move into + ;; object, for consistency with + ;; convenience feature above. + (and (= pos cend) + (or (= (point-max) pos) + (not (memq (char-before pos) + '(?\s ?\t))))))) + (goto-char cbeg) + (narrow-to-region (point) cend) + (setq parent next + restriction (org-element-restriction next) + next nil + object-data nil)) + ;; Otherwise, return NEXT. + (t (throw 'exit next))))))) + ;; Store results in cache, if applicable. + (org-element--cache-put element cache))))))) + +(defun org-element-lineage (blob &optional types with-self) + "List all ancestors of a given element or object. + +BLOB is an object or element. + +When optional argument TYPES is a list of symbols, return the +first element or object in the lineage whose type belongs to that +list. + +When optional argument WITH-SELF is non-nil, lineage includes +BLOB itself as the first element, and TYPES, if provided, also +apply to it. + +When BLOB is obtained through `org-element-context' or +`org-element-at-point', only ancestors from its section can be +found. There is no such limitation when BLOB belongs to a full +parse tree." + (let ((up (if with-self blob (org-element-property :parent blob))) + ancestors) + (while (and up (not (memq (org-element-type up) types))) + (unless types (push up ancestors)) + (setq up (org-element-property :parent up))) + (if types up (nreverse ancestors)))) (defun org-element-nested-p (elem-A elem-B) "Non-nil when elements ELEM-A and ELEM-B are nested." @@ -4982,39 +6038,44 @@ end of ELEM-A." (goto-char (org-element-property :end elem-B)) (skip-chars-backward " \r\t\n") (point-at-eol))) - ;; Store overlays responsible for visibility status. We - ;; also need to store their boundaries as they will be + ;; Store inner overlays responsible for visibility status. + ;; We also need to store their boundaries as they will be ;; removed from buffer. (overlays (cons - (mapcar (lambda (ov) (list ov (overlay-start ov) (overlay-end ov))) - (overlays-in beg-A end-A)) - (mapcar (lambda (ov) (list ov (overlay-start ov) (overlay-end ov))) - (overlays-in beg-B end-B)))) + (delq nil + (mapcar (lambda (o) + (and (>= (overlay-start o) beg-A) + (<= (overlay-end o) end-A) + (list o (overlay-start o) (overlay-end o)))) + (overlays-in beg-A end-A))) + (delq nil + (mapcar (lambda (o) + (and (>= (overlay-start o) beg-B) + (<= (overlay-end o) end-B) + (list o (overlay-start o) (overlay-end o)))) + (overlays-in beg-B end-B))))) ;; Get contents. (body-A (buffer-substring beg-A end-A)) (body-B (delete-and-extract-region beg-B end-B))) (goto-char beg-B) (when specialp (setq body-B (replace-regexp-in-string "\\`[ \t]*" "" body-B)) - (org-indent-to-column ind-B)) + (indent-to-column ind-B)) (insert body-A) ;; Restore ex ELEM-A overlays. (let ((offset (- beg-B beg-A))) - (mapc (lambda (ov) - (move-overlay - (car ov) (+ (nth 1 ov) offset) (+ (nth 2 ov) offset))) - (car overlays)) + (dolist (o (car overlays)) + (move-overlay (car o) (+ (nth 1 o) offset) (+ (nth 2 o) offset))) (goto-char beg-A) (delete-region beg-A end-A) (insert body-B) ;; Restore ex ELEM-B overlays. - (mapc (lambda (ov) - (move-overlay - (car ov) (- (nth 1 ov) offset) (- (nth 2 ov) offset))) - (cdr overlays))) + (dolist (o (cdr overlays)) + (move-overlay (car o) (- (nth 1 o) offset) (- (nth 2 o) offset)))) (goto-char (org-element-property :end elem-B))))) + (provide 'org-element) ;; Local variables: diff --git a/lisp/org/org-entities.el b/lisp/org/org-entities.el index 3ca2cceea7e..05ccf0cf5b4 100644 --- a/lisp/org/org-entities.el +++ b/lisp/org/org-entities.el @@ -1,4 +1,4 @@ -;;; org-entities.el --- Support for special entities in Org-mode +;;; org-entities.el --- Support for Special Entities -*- lexical-binding: t; -*- ;; Copyright (C) 2010-2017 Free Software Foundation, Inc. @@ -30,38 +30,36 @@ (declare-function org-toggle-pretty-entities "org" ()) (declare-function org-table-align "org-table" ()) -(eval-when-compile - (require 'cl)) - (defgroup org-entities nil - "Options concerning entities in Org-mode." + "Options concerning entities in Org mode." :tag "Org Entities" :group 'org) -(defcustom org-entities-ascii-explanatory nil - "Non-nil means replace special entities in ASCII. -For example, this will replace \"\\nsup\" with \"[not a superset of]\" -in backends where the corresponding character is not available." - :group 'org-entities - :version "24.1" - :type 'boolean) +(defun org-entities--user-safe-p (v) + "Non-nil if V is a safe value for `org-entities-user'." + (pcase v + (`nil t) + (`(,(and (pred stringp) + (pred (string-match-p "\\`[a-zA-Z][a-zA-Z0-9]*\\'"))) + ,(pred stringp) ,(pred booleanp) ,(pred stringp) + ,(pred stringp) ,(pred stringp) ,(pred stringp)) + t) + (_ nil))) (defcustom org-entities-user nil - "User-defined entities used in Org-mode to produce special characters. + "User-defined entities used in Org to produce special characters. Each entry in this list is a list of strings. It associates the name of the entity that can be inserted into an Org file as \\name with the appropriate replacements for the different export backends. The order of the fields is the following -name As a string, without the leading backslash -LaTeX replacement In ready LaTeX, no further processing will take place -LaTeX mathp A Boolean, either t or nil. t if this entity needs - to be in math mode. +name As a string, without the leading backslash. +LaTeX replacement In ready LaTeX, no further processing will take place. +LaTeX mathp Either t or nil. When t this entity needs to be in + math mode. HTML replacement In ready HTML, no further processing will take place. Usually this will be an &...; entity. -ASCII replacement Plain ASCII, no extensions. Symbols that cannot be - represented will be left as they are, but see the. - variable `org-entities-ascii-explanatory'. +ASCII replacement Plain ASCII, no extensions. Latin1 replacement Use the special characters available in latin1. utf-8 replacement Use the special characters available in utf-8. @@ -77,439 +75,454 @@ packages to be loaded, add these packages to `org-latex-packages-alist'." (string :tag "HTML ") (string :tag "ASCII ") (string :tag "Latin1") - (string :tag "utf-8 ")))) + (string :tag "utf-8 "))) + :safe #'org-entities--user-safe-p) (defconst org-entities - '( - "* Letters" - "** Latin" - ("Agrave" "\\`{A}" nil "À" "A" "À" "À") - ("agrave" "\\`{a}" nil "à" "a" "à" "à") - ("Aacute" "\\'{A}" nil "Á" "A" "Á" "Á") - ("aacute" "\\'{a}" nil "á" "a" "á" "á") - ("Acirc" "\\^{A}" nil "Â" "A" "Â" "Â") - ("acirc" "\\^{a}" nil "â" "a" "â" "â") - ("Atilde" "\\~{A}" nil "Ã" "A" "Ã" "Ã") - ("atilde" "\\~{a}" nil "ã" "a" "ã" "ã") - ("Auml" "\\\"{A}" nil "Ä" "Ae" "Ä" "Ä") - ("auml" "\\\"{a}" nil "ä" "ae" "ä" "ä") - ("Aring" "\\AA{}" nil "Å" "A" "Å" "Å") - ("AA" "\\AA{}" nil "Å" "A" "Å" "Å") - ("aring" "\\aa{}" nil "å" "a" "å" "å") - ("AElig" "\\AE{}" nil "Æ" "AE" "Æ" "Æ") - ("aelig" "\\ae{}" nil "æ" "ae" "æ" "æ") - ("Ccedil" "\\c{C}" nil "Ç" "C" "Ç" "Ç") - ("ccedil" "\\c{c}" nil "ç" "c" "ç" "ç") - ("Egrave" "\\`{E}" nil "È" "E" "È" "È") - ("egrave" "\\`{e}" nil "è" "e" "è" "è") - ("Eacute" "\\'{E}" nil "É" "E" "É" "É") - ("eacute" "\\'{e}" nil "é" "e" "é" "é") - ("Ecirc" "\\^{E}" nil "Ê" "E" "Ê" "Ê") - ("ecirc" "\\^{e}" nil "ê" "e" "ê" "ê") - ("Euml" "\\\"{E}" nil "Ë" "E" "Ë" "Ë") - ("euml" "\\\"{e}" nil "ë" "e" "ë" "ë") - ("Igrave" "\\`{I}" nil "Ì" "I" "Ì" "Ì") - ("igrave" "\\`{i}" nil "ì" "i" "ì" "ì") - ("Iacute" "\\'{I}" nil "Í" "I" "Í" "Í") - ("iacute" "\\'{i}" nil "í" "i" "í" "í") - ("Icirc" "\\^{I}" nil "Î" "I" "Î" "Î") - ("icirc" "\\^{i}" nil "î" "i" "î" "î") - ("Iuml" "\\\"{I}" nil "Ï" "I" "Ï" "Ï") - ("iuml" "\\\"{i}" nil "ï" "i" "ï" "ï") - ("Ntilde" "\\~{N}" nil "Ñ" "N" "Ñ" "Ñ") - ("ntilde" "\\~{n}" nil "ñ" "n" "ñ" "ñ") - ("Ograve" "\\`{O}" nil "Ò" "O" "Ò" "Ò") - ("ograve" "\\`{o}" nil "ò" "o" "ò" "ò") - ("Oacute" "\\'{O}" nil "Ó" "O" "Ó" "Ó") - ("oacute" "\\'{o}" nil "ó" "o" "ó" "ó") - ("Ocirc" "\\^{O}" nil "Ô" "O" "Ô" "Ô") - ("ocirc" "\\^{o}" nil "ô" "o" "ô" "ô") - ("Otilde" "\\~{O}" nil "Õ" "O" "Õ" "Õ") - ("otilde" "\\~{o}" nil "õ" "o" "õ" "õ") - ("Ouml" "\\\"{O}" nil "Ö" "Oe" "Ö" "Ö") - ("ouml" "\\\"{o}" nil "ö" "oe" "ö" "ö") - ("Oslash" "\\O" nil "Ø" "O" "Ø" "Ø") - ("oslash" "\\o{}" nil "ø" "o" "ø" "ø") - ("OElig" "\\OE{}" nil "Œ" "OE" "OE" "Œ") - ("oelig" "\\oe{}" nil "œ" "oe" "oe" "œ") - ("Scaron" "\\v{S}" nil "Š" "S" "S" "Š") - ("scaron" "\\v{s}" nil "š" "s" "s" "š") - ("szlig" "\\ss{}" nil "ß" "ss" "ß" "ß") - ("Ugrave" "\\`{U}" nil "Ù" "U" "Ù" "Ù") - ("ugrave" "\\`{u}" nil "ù" "u" "ù" "ù") - ("Uacute" "\\'{U}" nil "Ú" "U" "Ú" "Ú") - ("uacute" "\\'{u}" nil "ú" "u" "ú" "ú") - ("Ucirc" "\\^{U}" nil "Û" "U" "Û" "Û") - ("ucirc" "\\^{u}" nil "û" "u" "û" "û") - ("Uuml" "\\\"{U}" nil "Ü" "Ue" "Ü" "Ü") - ("uuml" "\\\"{u}" nil "ü" "ue" "ü" "ü") - ("Yacute" "\\'{Y}" nil "Ý" "Y" "Ý" "Ý") - ("yacute" "\\'{y}" nil "ý" "y" "ý" "ý") - ("Yuml" "\\\"{Y}" nil "Ÿ" "Y" "Y" "Ÿ") - ("yuml" "\\\"{y}" nil "ÿ" "y" "ÿ" "ÿ") - - "** Latin (special face)" - ("fnof" "\\textit{f}" nil "ƒ" "f" "f" "ƒ") - ("real" "\\Re" t "ℜ" "R" "R" "ℜ") - ("image" "\\Im" t "ℑ" "I" "I" "ℑ") - ("weierp" "\\wp" t "℘" "P" "P" "℘") - ("ell" "\\ell" t "ℓ" "ell" "ell" "ℓ") - ("imath" "\\imath" t "ı" "[dotless i]" "dotless i" "ı") - ("jmath" "\\jmath" t "ȷ" "[dotless j]" "dotless j" "ȷ") - - "** Greek" - ("Alpha" "A" nil "Α" "Alpha" "Alpha" "Α") - ("alpha" "\\alpha" t "α" "alpha" "alpha" "α") - ("Beta" "B" nil "Β" "Beta" "Beta" "Β") - ("beta" "\\beta" t "β" "beta" "beta" "β") - ("Gamma" "\\Gamma" t "Γ" "Gamma" "Gamma" "Γ") - ("gamma" "\\gamma" t "γ" "gamma" "gamma" "γ") - ("Delta" "\\Delta" t "Δ" "Delta" "Gamma" "Δ") - ("delta" "\\delta" t "δ" "delta" "delta" "δ") - ("Epsilon" "E" nil "Ε" "Epsilon" "Epsilon" "Ε") - ("epsilon" "\\epsilon" t "ε" "epsilon" "epsilon" "ε") - ("varepsilon" "\\varepsilon" t "ε" "varepsilon" "varepsilon" "ε") - ("Zeta" "Z" nil "Ζ" "Zeta" "Zeta" "Ζ") - ("zeta" "\\zeta" t "ζ" "zeta" "zeta" "ζ") - ("Eta" "H" nil "Η" "Eta" "Eta" "Η") - ("eta" "\\eta" t "η" "eta" "eta" "η") - ("Theta" "\\Theta" t "Θ" "Theta" "Theta" "Θ") - ("theta" "\\theta" t "θ" "theta" "theta" "θ") - ("thetasym" "\\vartheta" t "ϑ" "theta" "theta" "ϑ") - ("vartheta" "\\vartheta" t "ϑ" "theta" "theta" "ϑ") - ("Iota" "I" nil "Ι" "Iota" "Iota" "Ι") - ("iota" "\\iota" t "ι" "iota" "iota" "ι") - ("Kappa" "K" nil "Κ" "Kappa" "Kappa" "Κ") - ("kappa" "\\kappa" t "κ" "kappa" "kappa" "κ") - ("Lambda" "\\Lambda" t "Λ" "Lambda" "Lambda" "Λ") - ("lambda" "\\lambda" t "λ" "lambda" "lambda" "λ") - ("Mu" "M" nil "Μ" "Mu" "Mu" "Μ") - ("mu" "\\mu" t "μ" "mu" "mu" "μ") - ("nu" "\\nu" t "ν" "nu" "nu" "ν") - ("Nu" "N" nil "Ν" "Nu" "Nu" "Ν") - ("Xi" "\\Xi" t "Ξ" "Xi" "Xi" "Ξ") - ("xi" "\\xi" t "ξ" "xi" "xi" "ξ") - ("Omicron" "O" nil "Ο" "Omicron" "Omicron" "Ο") - ("omicron" "\\textit{o}" nil "ο" "omicron" "omicron" "ο") - ("Pi" "\\Pi" t "Π" "Pi" "Pi" "Π") - ("pi" "\\pi" t "π" "pi" "pi" "π") - ("Rho" "P" nil "Ρ" "Rho" "Rho" "Ρ") - ("rho" "\\rho" t "ρ" "rho" "rho" "ρ") - ("Sigma" "\\Sigma" t "Σ" "Sigma" "Sigma" "Σ") - ("sigma" "\\sigma" t "σ" "sigma" "sigma" "σ") - ("sigmaf" "\\varsigma" t "ς" "sigmaf" "sigmaf" "ς") - ("varsigma" "\\varsigma" t "ς" "varsigma" "varsigma" "ς") - ("Tau" "T" nil "Τ" "Tau" "Tau" "Τ") - ("Upsilon" "\\Upsilon" t "Υ" "Upsilon" "Upsilon" "Υ") - ("upsih" "\\Upsilon" t "ϒ" "upsilon" "upsilon" "ϒ") - ("upsilon" "\\upsilon" t "υ" "upsilon" "upsilon" "υ") - ("Phi" "\\Phi" t "Φ" "Phi" "Phi" "Φ") - ("phi" "\\phi" t "φ" "phi" "phi" "φ") - ("varphi" "\\varphi" t "ϕ" "varphi" "varphi" "ɸ") - ("Chi" "X" nil "Χ" "Chi" "Chi" "Χ") - ("chi" "\\chi" t "χ" "chi" "chi" "χ") - ("acutex" "\\acute x" t "´x" "'x" "'x" "𝑥́") - ("Psi" "\\Psi" t "Ψ" "Psi" "Psi" "Ψ") - ("psi" "\\psi" t "ψ" "psi" "psi" "ψ") - ("tau" "\\tau" t "τ" "tau" "tau" "τ") - ("Omega" "\\Omega" t "Ω" "Omega" "Omega" "Ω") - ("omega" "\\omega" t "ω" "omega" "omega" "ω") - ("piv" "\\varpi" t "ϖ" "omega-pi" "omega-pi" "ϖ") - ("varpi" "\\varpi" t "ϖ" "omega-pi" "omega-pi" "ϖ") - ("partial" "\\partial" t "∂" "[partial differential]" "[partial differential]" "∂") - - "** Hebrew" - ("alefsym" "\\aleph" t "ℵ" "aleph" "aleph" "ℵ") - ("aleph" "\\aleph" t "ℵ" "aleph" "aleph" "ℵ") - ("gimel" "\\gimel" t "ℷ" "gimel" "gimel" "ℷ") - ("beth" "\\beth" t "ℶ" "beth" "beth" "ב") - ("dalet" "\\daleth" t "ℸ" "dalet" "dalet" "ד") - - "** Dead languages" - ("ETH" "\\DH{}" nil "Ð" "D" "Ð" "Ð") - ("eth" "\\dh{}" nil "ð" "dh" "ð" "ð") - ("THORN" "\\TH{}" nil "Þ" "TH" "Þ" "Þ") - ("thorn" "\\th{}" nil "þ" "th" "þ" "þ") - - "* Punctuation" - "** Dots and Marks" - ("dots" "\\dots{}" nil "…" "..." "..." "…") - ("cdots" "\\cdots{}" t "⋯" "..." "..." "⋯") - ("hellip" "\\dots{}" nil "…" "..." "..." "…") - ("middot" "\\textperiodcentered{}" nil "·" "." "·" "·") - ("iexcl" "!`" nil "¡" "!" "¡" "¡") - ("iquest" "?`" nil "¿" "?" "¿" "¿") - - "** Dash-like" - ("shy" "\\-" nil "­" "" "" "") - ("ndash" "--" nil "–" "-" "-" "–") - ("mdash" "---" nil "—" "--" "--" "—") - - "** Quotations" - ("quot" "\\textquotedbl{}" nil """ "\"" "\"" "\"") - ("acute" "\\textasciiacute{}" nil "´" "'" "´" "´") - ("ldquo" "\\textquotedblleft{}" nil "“" "\"" "\"" "“") - ("rdquo" "\\textquotedblright{}" nil "”" "\"" "\"" "”") - ("bdquo" "\\quotedblbase{}" nil "„" "\"" "\"" "„") - ("lsquo" "\\textquoteleft{}" nil "‘" "`" "`" "‘") - ("rsquo" "\\textquoteright{}" nil "’" "'" "'" "’") - ("sbquo" "\\quotesinglbase{}" nil "‚" "," "," "‚") - ("laquo" "\\guillemotleft{}" nil "«" "<<" "«" "«") - ("raquo" "\\guillemotright{}" nil "»" ">>" "»" "»") - ("lsaquo" "\\guilsinglleft{}" nil "‹" "<" "<" "‹") - ("rsaquo" "\\guilsinglright{}" nil "›" ">" ">" "›") - - "* Other" - "** Misc. (often used)" - ("circ" "\\^{}" nil "ˆ" "^" "^" "ˆ") - ("vert" "\\vert{}" t "|" "|" "|" "|") - ("brvbar" "\\textbrokenbar{}" nil "¦" "|" "¦" "¦") - ("S" "\\S" nil "§" "paragraph" "§" "§") - ("sect" "\\S" nil "§" "paragraph" "§" "§") - ("amp" "\\&" nil "&" "&" "&" "&") - ("lt" "\\textless{}" nil "<" "<" "<" "<") - ("gt" "\\textgreater{}" nil ">" ">" ">" ">") - ("tilde" "\\textasciitilde{}" nil "~" "~" "~" "~") - ("slash" "/" nil "/" "/" "/" "/") - ("plus" "+" nil "+" "+" "+" "+") - ("under" "\\_" nil "_" "_" "_" "_") - ("equal" "=" nil "=" "=" "=" "=") - ("asciicirc" "\\textasciicircum{}" nil "^" "^" "^" "^") - ("dagger" "\\textdagger{}" nil "†" "[dagger]" "[dagger]" "†") - ("dag" "\\dag{}" nil "†" "[dagger]" "[dagger]" "†") - ("Dagger" "\\textdaggerdbl{}" nil "‡" "[doubledagger]" "[doubledagger]" "‡") - ("ddag" "\\ddag{}" nil "‡" "[doubledagger]" "[doubledagger]" "‡") - - "** Whitespace" - ("nbsp" "~" nil " " " " " " " ") - ("ensp" "\\hspace*{.5em}" nil " " " " " " " ") - ("emsp" "\\hspace*{1em}" nil " " " " " " " ") - ("thinsp" "\\hspace*{.2em}" nil " " " " " " " ") - - "** Currency" - ("curren" "\\textcurrency{}" nil "¤" "curr." "¤" "¤") - ("cent" "\\textcent{}" nil "¢" "cent" "¢" "¢") - ("pound" "\\pounds{}" nil "£" "pound" "£" "£") - ("yen" "\\textyen{}" nil "¥" "yen" "¥" "¥") - ("euro" "\\texteuro{}" nil "€" "EUR" "EUR" "€") - ("EUR" "\\EUR{}" nil "€" "EUR" "EUR" "€") - ("EURdig" "\\EURdig{}" nil "€" "EUR" "EUR" "€") - ("EURhv" "\\EURhv{}" nil "€" "EUR" "EUR" "€") - ("EURcr" "\\EURcr{}" nil "€" "EUR" "EUR" "€") - ("EURtm" "\\EURtm{}" nil "€" "EUR" "EUR" "€") - - "** Property Marks" - ("copy" "\\textcopyright{}" nil "©" "(c)" "©" "©") - ("reg" "\\textregistered{}" nil "®" "(r)" "®" "®") - ("trade" "\\texttrademark{}" nil "™" "TM" "TM" "™") - - "** Science et al." - ("minus" "\\minus" t "−" "-" "-" "−") - ("pm" "\\textpm{}" nil "±" "+-" "±" "±") - ("plusmn" "\\textpm{}" nil "±" "+-" "±" "±") - ("times" "\\texttimes{}" nil "×" "*" "×" "×") - ("frasl" "/" nil "⁄" "/" "/" "⁄") - ("colon" "\\colon" t ":" ":" ":" ":") - ("div" "\\textdiv{}" nil "÷" "/" "÷" "÷") - ("frac12" "\\textonehalf{}" nil "½" "1/2" "½" "½") - ("frac14" "\\textonequarter{}" nil "¼" "1/4" "¼" "¼") - ("frac34" "\\textthreequarters{}" nil "¾" "3/4" "¾" "¾") - ("permil" "\\textperthousand{}" nil "‰" "per thousand" "per thousand" "‰") - ("sup1" "\\textonesuperior{}" nil "¹" "^1" "¹" "¹") - ("sup2" "\\texttwosuperior{}" nil "²" "^2" "²" "²") - ("sup3" "\\textthreesuperior{}" nil "³" "^3" "³" "³") - ("radic" "\\sqrt{\\,}" t "√" "[square root]" "[square root]" "√") - ("sum" "\\sum" t "∑" "[sum]" "[sum]" "∑") - ("prod" "\\prod" t "∏" "[product]" "[n-ary product]" "∏") - ("micro" "\\textmu{}" nil "µ" "micro" "µ" "µ") - ("macr" "\\textasciimacron{}" nil "¯" "[macron]" "¯" "¯") - ("deg" "\\textdegree{}" nil "°" "degree" "°" "°") - ("prime" "\\prime" t "′" "'" "'" "′") - ("Prime" "\\prime{}\\prime" t "″" "''" "''" "″") - ("infin" "\\propto" t "∞" "[infinity]" "[infinity]" "∞") - ("infty" "\\infty" t "∞" "[infinity]" "[infinity]" "∞") - ("prop" "\\propto" t "∝" "[proportional to]" "[proportional to]" "∝") - ("propto" "\\propto" t "∝" "[proportional to]" "[proportional to]" "∝") - ("not" "\\textlnot{}" nil "¬" "[angled dash]" "¬" "¬") - ("neg" "\\neg{}" t "¬" "[angled dash]" "¬" "¬") - ("land" "\\land" t "∧" "[logical and]" "[logical and]" "∧") - ("wedge" "\\wedge" t "∧" "[logical and]" "[logical and]" "∧") - ("lor" "\\lor" t "∨" "[logical or]" "[logical or]" "∨") - ("vee" "\\vee" t "∨" "[logical or]" "[logical or]" "∨") - ("cap" "\\cap" t "∩" "[intersection]" "[intersection]" "∩") - ("cup" "\\cup" t "∪" "[union]" "[union]" "∪") - ("int" "\\int" t "∫" "[integral]" "[integral]" "∫") - ("therefore" "\\therefore" t "∴" "[therefore]" "[therefore]" "∴") - ("there4" "\\therefore" t "∴" "[therefore]" "[therefore]" "∴") - ("because" "\\because" t "∵" "[because]" "[because]" "∵") - ("sim" "\\sim" t "∼" "~" "~" "∼") - ("cong" "\\cong" t "≅" "[approx. equal to]" "[approx. equal to]" "≅") - ("simeq" "\\simeq" t "≅" "[approx. equal to]" "[approx. equal to]" "≅") - ("asymp" "\\asymp" t "≈" "[almost equal to]" "[almost equal to]" "≈") - ("approx" "\\approx" t "≈" "[almost equal to]" "[almost equal to]" "≈") - ("ne" "\\ne" t "≠" "[not equal to]" "[not equal to]" "≠") - ("neq" "\\neq" t "≠" "[not equal to]" "[not equal to]" "≠") - ("equiv" "\\equiv" t "≡" "[identical to]" "[identical to]" "≡") - - ("triangleq" "\\triangleq" t "≜" "[defined to]" "[defined to]" "≜") - ("le" "\\le" t "≤" "<=" "<=" "≤") - ("leq" "\\le" t "≤" "<=" "<=" "≤") - ("ge" "\\ge" t "≥" ">=" ">=" "≥") - ("geq" "\\ge" t "≥" ">=" ">=" "≥") - ("lessgtr" "\\lessgtr" t "≶" "[less than or greater than]" "[less than or greater than]" "≶") - ("lesseqgtr" "\\lesseqgtr" t "⋚" "[less than or equal or greater than or equal]" "[less than or equal or greater than or equal]" "⋚") - ("ll" "\\ll" t "≪" "<<" "<<" "≪") - ("Ll" "\\lll" t "⋘" "<<<" "<<<" "⋘") - ("lll" "\\lll" t "⋘" "<<<" "<<<" "⋘") - ("gg" "\\gg" t "≫" ">>" ">>" "≫") - ("Gg" "\\ggg" t "⋙" ">>>" ">>>" "⋙") - ("ggg" "\\ggg" t "⋙" ">>>" ">>>" "⋙") - ("prec" "\\prec" t "≺" "[precedes]" "[precedes]" "≺") - ("preceq" "\\preceq" t "≼" "[precedes or equal]" "[precedes or equal]" "≼") - ("preccurlyeq" "\\preccurlyeq" t "≼" "[precedes or equal]" "[precedes or equal]" "≼") - ("succ" "\\succ" t "≻" "[succeeds]" "[succeeds]" "≻") - ("succeq" "\\succeq" t "≽" "[succeeds or equal]" "[succeeds or equal]" "≽") - ("succcurlyeq" "\\succcurlyeq" t "≽" "[succeeds or equal]" "[succeeds or equal]" "≽") - ("sub" "\\subset" t "⊂" "[subset of]" "[subset of]" "⊂") - ("subset" "\\subset" t "⊂" "[subset of]" "[subset of]" "⊂") - ("sup" "\\supset" t "⊃" "[superset of]" "[superset of]" "⊃") - ("supset" "\\supset" t "⊃" "[superset of]" "[superset of]" "⊃") - ("nsub" "\\not\\subset" t "⊄" "[not a subset of]" "[not a subset of" "⊄") - ("sube" "\\subseteq" t "⊆" "[subset of or equal to]" "[subset of or equal to]" "⊆") - ("nsup" "\\not\\supset" t "⊅" "[not a superset of]" "[not a superset of]" "⊅") - ("supe" "\\supseteq" t "⊇" "[superset of or equal to]" "[superset of or equal to]" "⊇") - ("setminus" "\\setminus" t "∖" "\" "\" "⧵") - ("forall" "\\forall" t "∀" "[for all]" "[for all]" "∀") - ("exist" "\\exists" t "∃" "[there exists]" "[there exists]" "∃") - ("exists" "\\exists" t "∃" "[there exists]" "[there exists]" "∃") - ("nexist" "\\nexists" t "∃" "[there does not exists]" "[there does not exists]" "∄") - ("nexists" "\\nexists" t "∃" "[there does not exists]" "[there does not exists]" "∄") - ("empty" "\\empty" t "∅" "[empty set]" "[empty set]" "∅") - ("emptyset" "\\emptyset" t "∅" "[empty set]" "[empty set]" "∅") - ("isin" "\\in" t "∈" "[element of]" "[element of]" "∈") - ("in" "\\in" t "∈" "[element of]" "[element of]" "∈") - ("notin" "\\notin" t "∉" "[not an element of]" "[not an element of]" "∉") - ("ni" "\\ni" t "∋" "[contains as member]" "[contains as member]" "∋") - ("nabla" "\\nabla" t "∇" "[nabla]" "[nabla]" "∇") - ("ang" "\\angle" t "∠" "[angle]" "[angle]" "∠") - ("angle" "\\angle" t "∠" "[angle]" "[angle]" "∠") - ("perp" "\\perp" t "⊥" "[up tack]" "[up tack]" "⊥") - ("sdot" "\\cdot" t "⋅" "[dot]" "[dot]" "⋅") - ("cdot" "\\cdot" t "⋅" "[dot]" "[dot]" "⋅") - ("lceil" "\\lceil" t "⌈" "[left ceiling]" "[left ceiling]" "⌈") - ("rceil" "\\rceil" t "⌉" "[right ceiling]" "[right ceiling]" "⌉") - ("lfloor" "\\lfloor" t "⌊" "[left floor]" "[left floor]" "⌊") - ("rfloor" "\\rfloor" t "⌋" "[right floor]" "[right floor]" "⌋") - ("lang" "\\langle" t "⟨" "<" "<" "⟨") - ("rang" "\\rangle" t "⟩" ">" ">" "⟩") - ("hbar" "\\hbar" t "ℏ" "hbar" "hbar" "ℏ") - ("mho" "\\mho" t "℧" "mho" "mho" "℧") - - "** Arrows" - ("larr" "\\leftarrow" t "←" "<-" "<-" "←") - ("leftarrow" "\\leftarrow" t "←" "<-" "<-" "←") - ("gets" "\\gets" t "←" "<-" "<-" "←") - ("lArr" "\\Leftarrow" t "⇐" "<=" "<=" "⇐") - ("Leftarrow" "\\Leftarrow" t "⇐" "<=" "<=" "⇐") - ("uarr" "\\uparrow" t "↑" "[uparrow]" "[uparrow]" "↑") - ("uparrow" "\\uparrow" t "↑" "[uparrow]" "[uparrow]" "↑") - ("uArr" "\\Uparrow" t "⇑" "[dbluparrow]" "[dbluparrow]" "⇑") - ("Uparrow" "\\Uparrow" t "⇑" "[dbluparrow]" "[dbluparrow]" "⇑") - ("rarr" "\\rightarrow" t "→" "->" "->" "→") - ("to" "\\to" t "→" "->" "->" "→") - ("rightarrow" "\\rightarrow" t "→" "->" "->" "→") - ("rArr" "\\Rightarrow" t "⇒" "=>" "=>" "⇒") - ("Rightarrow" "\\Rightarrow" t "⇒" "=>" "=>" "⇒") - ("darr" "\\downarrow" t "↓" "[downarrow]" "[downarrow]" "↓") - ("downarrow" "\\downarrow" t "↓" "[downarrow]" "[downarrow]" "↓") - ("dArr" "\\Downarrow" t "⇓" "[dbldownarrow]" "[dbldownarrow]" "⇓") - ("Downarrow" "\\Downarrow" t "⇓" "[dbldownarrow]" "[dbldownarrow]" "⇓") - ("harr" "\\leftrightarrow" t "↔" "<->" "<->" "↔") - ("leftrightarrow" "\\leftrightarrow" t "↔" "<->" "<->" "↔") - ("hArr" "\\Leftrightarrow" t "⇔" "<=>" "<=>" "⇔") - ("Leftrightarrow" "\\Leftrightarrow" t "⇔" "<=>" "<=>" "⇔") - ("crarr" "\\hookleftarrow" t "↵" "<-'" "<-'" "↵") - ("hookleftarrow" "\\hookleftarrow" t "↵" "<-'" "<-'" "↵") - - "** Function names" - ("arccos" "\\arccos" t "arccos" "arccos" "arccos" "arccos") - ("arcsin" "\\arcsin" t "arcsin" "arcsin" "arcsin" "arcsin") - ("arctan" "\\arctan" t "arctan" "arctan" "arctan" "arctan") - ("arg" "\\arg" t "arg" "arg" "arg" "arg") - ("cos" "\\cos" t "cos" "cos" "cos" "cos") - ("cosh" "\\cosh" t "cosh" "cosh" "cosh" "cosh") - ("cot" "\\cot" t "cot" "cot" "cot" "cot") - ("coth" "\\coth" t "coth" "coth" "coth" "coth") - ("csc" "\\csc" t "csc" "csc" "csc" "csc") - ("deg" "\\deg" t "°" "deg" "deg" "deg") - ("det" "\\det" t "det" "det" "det" "det") - ("dim" "\\dim" t "dim" "dim" "dim" "dim") - ("exp" "\\exp" t "exp" "exp" "exp" "exp") - ("gcd" "\\gcd" t "gcd" "gcd" "gcd" "gcd") - ("hom" "\\hom" t "hom" "hom" "hom" "hom") - ("inf" "\\inf" t "inf" "inf" "inf" "inf") - ("ker" "\\ker" t "ker" "ker" "ker" "ker") - ("lg" "\\lg" t "lg" "lg" "lg" "lg") - ("lim" "\\lim" t "lim" "lim" "lim" "lim") - ("liminf" "\\liminf" t "liminf" "liminf" "liminf" "liminf") - ("limsup" "\\limsup" t "limsup" "limsup" "limsup" "limsup") - ("ln" "\\ln" t "ln" "ln" "ln" "ln") - ("log" "\\log" t "log" "log" "log" "log") - ("max" "\\max" t "max" "max" "max" "max") - ("min" "\\min" t "min" "min" "min" "min") - ("Pr" "\\Pr" t "Pr" "Pr" "Pr" "Pr") - ("sec" "\\sec" t "sec" "sec" "sec" "sec") - ("sin" "\\sin" t "sin" "sin" "sin" "sin") - ("sinh" "\\sinh" t "sinh" "sinh" "sinh" "sinh") - ("sup" "\\sup" t "⊃" "sup" "sup" "sup") - ("tan" "\\tan" t "tan" "tan" "tan" "tan") - ("tanh" "\\tanh" t "tanh" "tanh" "tanh" "tanh") - - "** Signs & Symbols" - ("bull" "\\textbullet{}" nil "•" "*" "*" "•") - ("bullet" "\\textbullet{}" nil "•" "*" "*" "•") - ("star" "\\star" t "*" "*" "*" "⋆") - ("lowast" "\\ast" t "∗" "*" "*" "∗") - ("ast" "\\ast" t "∗" "*" "*" "*") - ("odot" "\\odot" t "o" "[circled dot]" "[circled dot]" "ʘ") - ("oplus" "\\oplus" t "⊕" "[circled plus]" "[circled plus]" "⊕") - ("otimes" "\\otimes" t "⊗" "[circled times]" "[circled times]" "⊗") - ("check" "\\checkmark" t "✓" "[checkmark]" "[checkmark]" "✓") - ("checkmark" "\\checkmark" t "✓" "[checkmark]" "[checkmark]" "✓") - - "** Miscellaneous (seldom used)" - ("para" "\\P{}" nil "¶" "[pilcrow]" "¶" "¶") - ("ordf" "\\textordfeminine{}" nil "ª" "_a_" "ª" "ª") - ("ordm" "\\textordmasculine{}" nil "º" "_o_" "º" "º") - ("cedil" "\\c{}" nil "¸" "[cedilla]" "¸" "¸") - ("oline" "\\overline{~}" t "‾" "[overline]" "¯" "‾") - ("uml" "\\textasciidieresis{}" nil "¨" "[diaeresis]" "¨" "¨") - ("zwnj" "\\/{}" nil "‌" "" "" "‌") - ("zwj" "" nil "‍" "" "" "‍") - ("lrm" "" nil "‎" "" "" "‎") - ("rlm" "" nil "‏" "" "" "‏") - - "** Smilies" - ("smile" "\\smile" t "⌣" ":-)" ":-)" "⌣") - ("frown" "\\frown" t "⌢" ":-(" ":-(" "⌢") - ("smiley" "\\smiley{}" nil "☺" ":-)" ":-)" "☺") - ("blacksmile" "\\blacksmiley{}" nil "☻" ":-)" ":-)" "☻") - ("sad" "\\frownie{}" nil "☹" ":-(" ":-(" "☹") - - "** Suits" - ("clubs" "\\clubsuit" t "♣" "[clubs]" "[clubs]" "♣") - ("clubsuit" "\\clubsuit" t "♣" "[clubs]" "[clubs]" "♣") - ("spades" "\\spadesuit" t "♠" "[spades]" "[spades]" "♠") - ("spadesuit" "\\spadesuit" t "♠" "[spades]" "[spades]" "♠") - ("hearts" "\\heartsuit" t "♥" "[hearts]" "[hearts]" "♥") - ("heartsuit" "\\heartsuit" t "♥" "[hearts]" "[hearts]" "♥") - ("diams" "\\diamondsuit" t "♦" "[diamonds]" "[diamonds]" "◆") - ("diamondsuit" "\\diamondsuit" t "♦" "[diamonds]" "[diamonds]" "◆") - ("diamond" "\\diamondsuit" t "⋄" "[diamond]" "[diamond]" "◆") - ("Diamond" "\\diamondsuit" t "⋄" "[diamond]" "[diamond]" "◆") - ("loz" "\\lozenge" t "◊" "[lozenge]" "[lozenge]" "⧫") - ) - "Default entities used in Org-mode to produce special characters. + (append + '("* Letters" + "** Latin" + ("Agrave" "\\`{A}" nil "À" "A" "À" "À") + ("agrave" "\\`{a}" nil "à" "a" "à" "à") + ("Aacute" "\\'{A}" nil "Á" "A" "Á" "Á") + ("aacute" "\\'{a}" nil "á" "a" "á" "á") + ("Acirc" "\\^{A}" nil "Â" "A" "Â" "Â") + ("acirc" "\\^{a}" nil "â" "a" "â" "â") + ("Amacr" "\\bar{A}" nil "Ā" "A" "Ã" "Ã") + ("amacr" "\\bar{a}" nil "ā" "a" "ã" "ã") + ("Atilde" "\\~{A}" nil "Ã" "A" "Ã" "Ã") + ("atilde" "\\~{a}" nil "ã" "a" "ã" "ã") + ("Auml" "\\\"{A}" nil "Ä" "Ae" "Ä" "Ä") + ("auml" "\\\"{a}" nil "ä" "ae" "ä" "ä") + ("Aring" "\\AA{}" nil "Å" "A" "Å" "Å") + ("AA" "\\AA{}" nil "Å" "A" "Å" "Å") + ("aring" "\\aa{}" nil "å" "a" "å" "å") + ("AElig" "\\AE{}" nil "Æ" "AE" "Æ" "Æ") + ("aelig" "\\ae{}" nil "æ" "ae" "æ" "æ") + ("Ccedil" "\\c{C}" nil "Ç" "C" "Ç" "Ç") + ("ccedil" "\\c{c}" nil "ç" "c" "ç" "ç") + ("Egrave" "\\`{E}" nil "È" "E" "È" "È") + ("egrave" "\\`{e}" nil "è" "e" "è" "è") + ("Eacute" "\\'{E}" nil "É" "E" "É" "É") + ("eacute" "\\'{e}" nil "é" "e" "é" "é") + ("Ecirc" "\\^{E}" nil "Ê" "E" "Ê" "Ê") + ("ecirc" "\\^{e}" nil "ê" "e" "ê" "ê") + ("Euml" "\\\"{E}" nil "Ë" "E" "Ë" "Ë") + ("euml" "\\\"{e}" nil "ë" "e" "ë" "ë") + ("Igrave" "\\`{I}" nil "Ì" "I" "Ì" "Ì") + ("igrave" "\\`{i}" nil "ì" "i" "ì" "ì") + ("Iacute" "\\'{I}" nil "Í" "I" "Í" "Í") + ("iacute" "\\'{i}" nil "í" "i" "í" "í") + ("Icirc" "\\^{I}" nil "Î" "I" "Î" "Î") + ("icirc" "\\^{i}" nil "î" "i" "î" "î") + ("Iuml" "\\\"{I}" nil "Ï" "I" "Ï" "Ï") + ("iuml" "\\\"{i}" nil "ï" "i" "ï" "ï") + ("Ntilde" "\\~{N}" nil "Ñ" "N" "Ñ" "Ñ") + ("ntilde" "\\~{n}" nil "ñ" "n" "ñ" "ñ") + ("Ograve" "\\`{O}" nil "Ò" "O" "Ò" "Ò") + ("ograve" "\\`{o}" nil "ò" "o" "ò" "ò") + ("Oacute" "\\'{O}" nil "Ó" "O" "Ó" "Ó") + ("oacute" "\\'{o}" nil "ó" "o" "ó" "ó") + ("Ocirc" "\\^{O}" nil "Ô" "O" "Ô" "Ô") + ("ocirc" "\\^{o}" nil "ô" "o" "ô" "ô") + ("Otilde" "\\~{O}" nil "Õ" "O" "Õ" "Õ") + ("otilde" "\\~{o}" nil "õ" "o" "õ" "õ") + ("Ouml" "\\\"{O}" nil "Ö" "Oe" "Ö" "Ö") + ("ouml" "\\\"{o}" nil "ö" "oe" "ö" "ö") + ("Oslash" "\\O" nil "Ø" "O" "Ø" "Ø") + ("oslash" "\\o{}" nil "ø" "o" "ø" "ø") + ("OElig" "\\OE{}" nil "Œ" "OE" "OE" "Œ") + ("oelig" "\\oe{}" nil "œ" "oe" "oe" "œ") + ("Scaron" "\\v{S}" nil "Š" "S" "S" "Š") + ("scaron" "\\v{s}" nil "š" "s" "s" "š") + ("szlig" "\\ss{}" nil "ß" "ss" "ß" "ß") + ("Ugrave" "\\`{U}" nil "Ù" "U" "Ù" "Ù") + ("ugrave" "\\`{u}" nil "ù" "u" "ù" "ù") + ("Uacute" "\\'{U}" nil "Ú" "U" "Ú" "Ú") + ("uacute" "\\'{u}" nil "ú" "u" "ú" "ú") + ("Ucirc" "\\^{U}" nil "Û" "U" "Û" "Û") + ("ucirc" "\\^{u}" nil "û" "u" "û" "û") + ("Uuml" "\\\"{U}" nil "Ü" "Ue" "Ü" "Ü") + ("uuml" "\\\"{u}" nil "ü" "ue" "ü" "ü") + ("Yacute" "\\'{Y}" nil "Ý" "Y" "Ý" "Ý") + ("yacute" "\\'{y}" nil "ý" "y" "ý" "ý") + ("Yuml" "\\\"{Y}" nil "Ÿ" "Y" "Y" "Ÿ") + ("yuml" "\\\"{y}" nil "ÿ" "y" "ÿ" "ÿ") + + "** Latin (special face)" + ("fnof" "\\textit{f}" nil "ƒ" "f" "f" "ƒ") + ("real" "\\Re" t "ℜ" "R" "R" "ℜ") + ("image" "\\Im" t "ℑ" "I" "I" "ℑ") + ("weierp" "\\wp" t "℘" "P" "P" "℘") + ("ell" "\\ell" t "ℓ" "ell" "ell" "ℓ") + ("imath" "\\imath" t "ı" "[dotless i]" "dotless i" "ı") + ("jmath" "\\jmath" t "ȷ" "[dotless j]" "dotless j" "ȷ") + + "** Greek" + ("Alpha" "A" nil "Α" "Alpha" "Alpha" "Α") + ("alpha" "\\alpha" t "α" "alpha" "alpha" "α") + ("Beta" "B" nil "Β" "Beta" "Beta" "Β") + ("beta" "\\beta" t "β" "beta" "beta" "β") + ("Gamma" "\\Gamma" t "Γ" "Gamma" "Gamma" "Γ") + ("gamma" "\\gamma" t "γ" "gamma" "gamma" "γ") + ("Delta" "\\Delta" t "Δ" "Delta" "Delta" "Δ") + ("delta" "\\delta" t "δ" "delta" "delta" "δ") + ("Epsilon" "E" nil "Ε" "Epsilon" "Epsilon" "Ε") + ("epsilon" "\\epsilon" t "ε" "epsilon" "epsilon" "ε") + ("varepsilon" "\\varepsilon" t "ε" "varepsilon" "varepsilon" "ε") + ("Zeta" "Z" nil "Ζ" "Zeta" "Zeta" "Ζ") + ("zeta" "\\zeta" t "ζ" "zeta" "zeta" "ζ") + ("Eta" "H" nil "Η" "Eta" "Eta" "Η") + ("eta" "\\eta" t "η" "eta" "eta" "η") + ("Theta" "\\Theta" t "Θ" "Theta" "Theta" "Θ") + ("theta" "\\theta" t "θ" "theta" "theta" "θ") + ("thetasym" "\\vartheta" t "ϑ" "theta" "theta" "ϑ") + ("vartheta" "\\vartheta" t "ϑ" "theta" "theta" "ϑ") + ("Iota" "I" nil "Ι" "Iota" "Iota" "Ι") + ("iota" "\\iota" t "ι" "iota" "iota" "ι") + ("Kappa" "K" nil "Κ" "Kappa" "Kappa" "Κ") + ("kappa" "\\kappa" t "κ" "kappa" "kappa" "κ") + ("Lambda" "\\Lambda" t "Λ" "Lambda" "Lambda" "Λ") + ("lambda" "\\lambda" t "λ" "lambda" "lambda" "λ") + ("Mu" "M" nil "Μ" "Mu" "Mu" "Μ") + ("mu" "\\mu" t "μ" "mu" "mu" "μ") + ("nu" "\\nu" t "ν" "nu" "nu" "ν") + ("Nu" "N" nil "Ν" "Nu" "Nu" "Ν") + ("Xi" "\\Xi" t "Ξ" "Xi" "Xi" "Ξ") + ("xi" "\\xi" t "ξ" "xi" "xi" "ξ") + ("Omicron" "O" nil "Ο" "Omicron" "Omicron" "Ο") + ("omicron" "\\textit{o}" nil "ο" "omicron" "omicron" "ο") + ("Pi" "\\Pi" t "Π" "Pi" "Pi" "Π") + ("pi" "\\pi" t "π" "pi" "pi" "π") + ("Rho" "P" nil "Ρ" "Rho" "Rho" "Ρ") + ("rho" "\\rho" t "ρ" "rho" "rho" "ρ") + ("Sigma" "\\Sigma" t "Σ" "Sigma" "Sigma" "Σ") + ("sigma" "\\sigma" t "σ" "sigma" "sigma" "σ") + ("sigmaf" "\\varsigma" t "ς" "sigmaf" "sigmaf" "ς") + ("varsigma" "\\varsigma" t "ς" "varsigma" "varsigma" "ς") + ("Tau" "T" nil "Τ" "Tau" "Tau" "Τ") + ("Upsilon" "\\Upsilon" t "Υ" "Upsilon" "Upsilon" "Υ") + ("upsih" "\\Upsilon" t "ϒ" "upsilon" "upsilon" "ϒ") + ("upsilon" "\\upsilon" t "υ" "upsilon" "upsilon" "υ") + ("Phi" "\\Phi" t "Φ" "Phi" "Phi" "Φ") + ("phi" "\\phi" t "φ" "phi" "phi" "ɸ") + ("varphi" "\\varphi" t "ϕ" "varphi" "varphi" "φ") + ("Chi" "X" nil "Χ" "Chi" "Chi" "Χ") + ("chi" "\\chi" t "χ" "chi" "chi" "χ") + ("acutex" "\\acute x" t "´x" "'x" "'x" "𝑥́") + ("Psi" "\\Psi" t "Ψ" "Psi" "Psi" "Ψ") + ("psi" "\\psi" t "ψ" "psi" "psi" "ψ") + ("tau" "\\tau" t "τ" "tau" "tau" "τ") + ("Omega" "\\Omega" t "Ω" "Omega" "Omega" "Ω") + ("omega" "\\omega" t "ω" "omega" "omega" "ω") + ("piv" "\\varpi" t "ϖ" "omega-pi" "omega-pi" "ϖ") + ("varpi" "\\varpi" t "ϖ" "omega-pi" "omega-pi" "ϖ") + ("partial" "\\partial" t "∂" "[partial differential]" "[partial differential]" "∂") + + "** Hebrew" + ("alefsym" "\\aleph" t "ℵ" "aleph" "aleph" "ℵ") + ("aleph" "\\aleph" t "ℵ" "aleph" "aleph" "ℵ") + ("gimel" "\\gimel" t "ℷ" "gimel" "gimel" "ℷ") + ("beth" "\\beth" t "ℶ" "beth" "beth" "ב") + ("dalet" "\\daleth" t "ℸ" "dalet" "dalet" "ד") + + "** Dead languages" + ("ETH" "\\DH{}" nil "Ð" "D" "Ð" "Ð") + ("eth" "\\dh{}" nil "ð" "dh" "ð" "ð") + ("THORN" "\\TH{}" nil "Þ" "TH" "Þ" "Þ") + ("thorn" "\\th{}" nil "þ" "th" "þ" "þ") + + "* Punctuation" + "** Dots and Marks" + ("dots" "\\dots{}" nil "…" "..." "..." "…") + ("cdots" "\\cdots{}" t "⋯" "..." "..." "⋯") + ("hellip" "\\dots{}" nil "…" "..." "..." "…") + ("middot" "\\textperiodcentered{}" nil "·" "." "·" "·") + ("iexcl" "!`" nil "¡" "!" "¡" "¡") + ("iquest" "?`" nil "¿" "?" "¿" "¿") + + "** Dash-like" + ("shy" "\\-" nil "­" "" "" "") + ("ndash" "--" nil "–" "-" "-" "–") + ("mdash" "---" nil "—" "--" "--" "—") + + "** Quotations" + ("quot" "\\textquotedbl{}" nil """ "\"" "\"" "\"") + ("acute" "\\textasciiacute{}" nil "´" "'" "´" "´") + ("ldquo" "\\textquotedblleft{}" nil "“" "\"" "\"" "“") + ("rdquo" "\\textquotedblright{}" nil "”" "\"" "\"" "”") + ("bdquo" "\\quotedblbase{}" nil "„" "\"" "\"" "„") + ("lsquo" "\\textquoteleft{}" nil "‘" "`" "`" "‘") + ("rsquo" "\\textquoteright{}" nil "’" "'" "'" "’") + ("sbquo" "\\quotesinglbase{}" nil "‚" "," "," "‚") + ("laquo" "\\guillemotleft{}" nil "«" "<<" "«" "«") + ("raquo" "\\guillemotright{}" nil "»" ">>" "»" "»") + ("lsaquo" "\\guilsinglleft{}" nil "‹" "<" "<" "‹") + ("rsaquo" "\\guilsinglright{}" nil "›" ">" ">" "›") + + "* Other" + "** Misc. (often used)" + ("circ" "\\^{}" nil "ˆ" "^" "^" "∘") + ("vert" "\\vert{}" t "|" "|" "|" "|") + ("vbar" "|" nil "|" "|" "|" "|") + ("brvbar" "\\textbrokenbar{}" nil "¦" "|" "¦" "¦") + ("S" "\\S" nil "§" "paragraph" "§" "§") + ("sect" "\\S" nil "§" "paragraph" "§" "§") + ("amp" "\\&" nil "&" "&" "&" "&") + ("lt" "\\textless{}" nil "<" "<" "<" "<") + ("gt" "\\textgreater{}" nil ">" ">" ">" ">") + ("tilde" "\\textasciitilde{}" nil "~" "~" "~" "~") + ("slash" "/" nil "/" "/" "/" "/") + ("plus" "+" nil "+" "+" "+" "+") + ("under" "\\_" nil "_" "_" "_" "_") + ("equal" "=" nil "=" "=" "=" "=") + ("asciicirc" "\\textasciicircum{}" nil "^" "^" "^" "^") + ("dagger" "\\textdagger{}" nil "†" "[dagger]" "[dagger]" "†") + ("dag" "\\dag{}" nil "†" "[dagger]" "[dagger]" "†") + ("Dagger" "\\textdaggerdbl{}" nil "‡" "[doubledagger]" "[doubledagger]" "‡") + ("ddag" "\\ddag{}" nil "‡" "[doubledagger]" "[doubledagger]" "‡") + + "** Whitespace" + ("nbsp" "~" nil " " " " "\x00A0" "\x00A0") + ("ensp" "\\hspace*{.5em}" nil " " " " " " " ") + ("emsp" "\\hspace*{1em}" nil " " " " " " " ") + ("thinsp" "\\hspace*{.2em}" nil " " " " " " " ") + + "** Currency" + ("curren" "\\textcurrency{}" nil "¤" "curr." "¤" "¤") + ("cent" "\\textcent{}" nil "¢" "cent" "¢" "¢") + ("pound" "\\pounds{}" nil "£" "pound" "£" "£") + ("yen" "\\textyen{}" nil "¥" "yen" "¥" "¥") + ("euro" "\\texteuro{}" nil "€" "EUR" "EUR" "€") + ("EUR" "\\texteuro{}" nil "€" "EUR" "EUR" "€") + + "** Property Marks" + ("copy" "\\textcopyright{}" nil "©" "(c)" "©" "©") + ("reg" "\\textregistered{}" nil "®" "(r)" "®" "®") + ("trade" "\\texttrademark{}" nil "™" "TM" "TM" "™") + + "** Science et al." + ("minus" "\\minus" t "−" "-" "-" "−") + ("pm" "\\textpm{}" nil "±" "+-" "±" "±") + ("plusmn" "\\textpm{}" nil "±" "+-" "±" "±") + ("times" "\\texttimes{}" nil "×" "*" "×" "×") + ("frasl" "/" nil "⁄" "/" "/" "⁄") + ("colon" "\\colon" t ":" ":" ":" ":") + ("div" "\\textdiv{}" nil "÷" "/" "÷" "÷") + ("frac12" "\\textonehalf{}" nil "½" "1/2" "½" "½") + ("frac14" "\\textonequarter{}" nil "¼" "1/4" "¼" "¼") + ("frac34" "\\textthreequarters{}" nil "¾" "3/4" "¾" "¾") + ("permil" "\\textperthousand{}" nil "‰" "per thousand" "per thousand" "‰") + ("sup1" "\\textonesuperior{}" nil "¹" "^1" "¹" "¹") + ("sup2" "\\texttwosuperior{}" nil "²" "^2" "²" "²") + ("sup3" "\\textthreesuperior{}" nil "³" "^3" "³" "³") + ("radic" "\\sqrt{\\,}" t "√" "[square root]" "[square root]" "√") + ("sum" "\\sum" t "∑" "[sum]" "[sum]" "∑") + ("prod" "\\prod" t "∏" "[product]" "[n-ary product]" "∏") + ("micro" "\\textmu{}" nil "µ" "micro" "µ" "µ") + ("macr" "\\textasciimacron{}" nil "¯" "[macron]" "¯" "¯") + ("deg" "\\textdegree{}" nil "°" "degree" "°" "°") + ("prime" "\\prime" t "′" "'" "'" "′") + ("Prime" "\\prime{}\\prime" t "″" "''" "''" "″") + ("infin" "\\infty" t "∞" "[infinity]" "[infinity]" "∞") + ("infty" "\\infty" t "∞" "[infinity]" "[infinity]" "∞") + ("prop" "\\propto" t "∝" "[proportional to]" "[proportional to]" "∝") + ("propto" "\\propto" t "∝" "[proportional to]" "[proportional to]" "∝") + ("not" "\\textlnot{}" nil "¬" "[angled dash]" "¬" "¬") + ("neg" "\\neg{}" t "¬" "[angled dash]" "¬" "¬") + ("land" "\\land" t "∧" "[logical and]" "[logical and]" "∧") + ("wedge" "\\wedge" t "∧" "[logical and]" "[logical and]" "∧") + ("lor" "\\lor" t "∨" "[logical or]" "[logical or]" "∨") + ("vee" "\\vee" t "∨" "[logical or]" "[logical or]" "∨") + ("cap" "\\cap" t "∩" "[intersection]" "[intersection]" "∩") + ("cup" "\\cup" t "∪" "[union]" "[union]" "∪") + ("smile" "\\smile" t "⌣" "[cup product]" "[cup product]" "⌣") + ("frown" "\\frown" t "⌢" "[Cap product]" "[cap product]" "⌢") + ("int" "\\int" t "∫" "[integral]" "[integral]" "∫") + ("therefore" "\\therefore" t "∴" "[therefore]" "[therefore]" "∴") + ("there4" "\\therefore" t "∴" "[therefore]" "[therefore]" "∴") + ("because" "\\because" t "∵" "[because]" "[because]" "∵") + ("sim" "\\sim" t "∼" "~" "~" "∼") + ("cong" "\\cong" t "≅" "[approx. equal to]" "[approx. equal to]" "≅") + ("simeq" "\\simeq" t "≅" "[approx. equal to]" "[approx. equal to]" "≅") + ("asymp" "\\asymp" t "≈" "[almost equal to]" "[almost equal to]" "≈") + ("approx" "\\approx" t "≈" "[almost equal to]" "[almost equal to]" "≈") + ("ne" "\\ne" t "≠" "[not equal to]" "[not equal to]" "≠") + ("neq" "\\neq" t "≠" "[not equal to]" "[not equal to]" "≠") + ("equiv" "\\equiv" t "≡" "[identical to]" "[identical to]" "≡") + + ("triangleq" "\\triangleq" t "≜" "[defined to]" "[defined to]" "≜") + ("le" "\\le" t "≤" "<=" "<=" "≤") + ("leq" "\\le" t "≤" "<=" "<=" "≤") + ("ge" "\\ge" t "≥" ">=" ">=" "≥") + ("geq" "\\ge" t "≥" ">=" ">=" "≥") + ("lessgtr" "\\lessgtr" t "≶" "[less than or greater than]" "[less than or greater than]" "≶") + ("lesseqgtr" "\\lesseqgtr" t "⋚" "[less than or equal or greater than or equal]" "[less than or equal or greater than or equal]" "⋚") + ("ll" "\\ll" t "≪" "<<" "<<" "≪") + ("Ll" "\\lll" t "⋘" "<<<" "<<<" "⋘") + ("lll" "\\lll" t "⋘" "<<<" "<<<" "⋘") + ("gg" "\\gg" t "≫" ">>" ">>" "≫") + ("Gg" "\\ggg" t "⋙" ">>>" ">>>" "⋙") + ("ggg" "\\ggg" t "⋙" ">>>" ">>>" "⋙") + ("prec" "\\prec" t "≺" "[precedes]" "[precedes]" "≺") + ("preceq" "\\preceq" t "≼" "[precedes or equal]" "[precedes or equal]" "≼") + ("preccurlyeq" "\\preccurlyeq" t "≼" "[precedes or equal]" "[precedes or equal]" "≼") + ("succ" "\\succ" t "≻" "[succeeds]" "[succeeds]" "≻") + ("succeq" "\\succeq" t "≽" "[succeeds or equal]" "[succeeds or equal]" "≽") + ("succcurlyeq" "\\succcurlyeq" t "≽" "[succeeds or equal]" "[succeeds or equal]" "≽") + ("sub" "\\subset" t "⊂" "[subset of]" "[subset of]" "⊂") + ("subset" "\\subset" t "⊂" "[subset of]" "[subset of]" "⊂") + ("sup" "\\supset" t "⊃" "[superset of]" "[superset of]" "⊃") + ("supset" "\\supset" t "⊃" "[superset of]" "[superset of]" "⊃") + ("nsub" "\\not\\subset" t "⊄" "[not a subset of]" "[not a subset of" "⊄") + ("sube" "\\subseteq" t "⊆" "[subset of or equal to]" "[subset of or equal to]" "⊆") + ("nsup" "\\not\\supset" t "⊅" "[not a superset of]" "[not a superset of]" "⊅") + ("supe" "\\supseteq" t "⊇" "[superset of or equal to]" "[superset of or equal to]" "⊇") + ("setminus" "\\setminus" t "∖" "\" "\" "⧵") + ("forall" "\\forall" t "∀" "[for all]" "[for all]" "∀") + ("exist" "\\exists" t "∃" "[there exists]" "[there exists]" "∃") + ("exists" "\\exists" t "∃" "[there exists]" "[there exists]" "∃") + ("nexist" "\\nexists" t "∃" "[there does not exists]" "[there does not exists]" "∄") + ("nexists" "\\nexists" t "∃" "[there does not exists]" "[there does not exists]" "∄") + ("empty" "\\empty" t "∅" "[empty set]" "[empty set]" "∅") + ("emptyset" "\\emptyset" t "∅" "[empty set]" "[empty set]" "∅") + ("isin" "\\in" t "∈" "[element of]" "[element of]" "∈") + ("in" "\\in" t "∈" "[element of]" "[element of]" "∈") + ("notin" "\\notin" t "∉" "[not an element of]" "[not an element of]" "∉") + ("ni" "\\ni" t "∋" "[contains as member]" "[contains as member]" "∋") + ("nabla" "\\nabla" t "∇" "[nabla]" "[nabla]" "∇") + ("ang" "\\angle" t "∠" "[angle]" "[angle]" "∠") + ("angle" "\\angle" t "∠" "[angle]" "[angle]" "∠") + ("perp" "\\perp" t "⊥" "[up tack]" "[up tack]" "⊥") + ("parallel" "\\parallel" t "∥" "||" "||" "∥") + ("sdot" "\\cdot" t "⋅" "[dot]" "[dot]" "⋅") + ("cdot" "\\cdot" t "⋅" "[dot]" "[dot]" "⋅") + ("lceil" "\\lceil" t "⌈" "[left ceiling]" "[left ceiling]" "⌈") + ("rceil" "\\rceil" t "⌉" "[right ceiling]" "[right ceiling]" "⌉") + ("lfloor" "\\lfloor" t "⌊" "[left floor]" "[left floor]" "⌊") + ("rfloor" "\\rfloor" t "⌋" "[right floor]" "[right floor]" "⌋") + ("lang" "\\langle" t "⟨" "<" "<" "⟨") + ("rang" "\\rangle" t "⟩" ">" ">" "⟩") + ("langle" "\\langle" t "⟨" "<" "<" "⟨") + ("rangle" "\\rangle" t "⟩" ">" ">" "⟩") + ("hbar" "\\hbar" t "ℏ" "hbar" "hbar" "ℏ") + ("mho" "\\mho" t "℧" "mho" "mho" "℧") + + "** Arrows" + ("larr" "\\leftarrow" t "←" "<-" "<-" "←") + ("leftarrow" "\\leftarrow" t "←" "<-" "<-" "←") + ("gets" "\\gets" t "←" "<-" "<-" "←") + ("lArr" "\\Leftarrow" t "⇐" "<=" "<=" "⇐") + ("Leftarrow" "\\Leftarrow" t "⇐" "<=" "<=" "⇐") + ("uarr" "\\uparrow" t "↑" "[uparrow]" "[uparrow]" "↑") + ("uparrow" "\\uparrow" t "↑" "[uparrow]" "[uparrow]" "↑") + ("uArr" "\\Uparrow" t "⇑" "[dbluparrow]" "[dbluparrow]" "⇑") + ("Uparrow" "\\Uparrow" t "⇑" "[dbluparrow]" "[dbluparrow]" "⇑") + ("rarr" "\\rightarrow" t "→" "->" "->" "→") + ("to" "\\to" t "→" "->" "->" "→") + ("rightarrow" "\\rightarrow" t "→" "->" "->" "→") + ("rArr" "\\Rightarrow" t "⇒" "=>" "=>" "⇒") + ("Rightarrow" "\\Rightarrow" t "⇒" "=>" "=>" "⇒") + ("darr" "\\downarrow" t "↓" "[downarrow]" "[downarrow]" "↓") + ("downarrow" "\\downarrow" t "↓" "[downarrow]" "[downarrow]" "↓") + ("dArr" "\\Downarrow" t "⇓" "[dbldownarrow]" "[dbldownarrow]" "⇓") + ("Downarrow" "\\Downarrow" t "⇓" "[dbldownarrow]" "[dbldownarrow]" "⇓") + ("harr" "\\leftrightarrow" t "↔" "<->" "<->" "↔") + ("leftrightarrow" "\\leftrightarrow" t "↔" "<->" "<->" "↔") + ("hArr" "\\Leftrightarrow" t "⇔" "<=>" "<=>" "⇔") + ("Leftrightarrow" "\\Leftrightarrow" t "⇔" "<=>" "<=>" "⇔") + ("crarr" "\\hookleftarrow" t "↵" "<-'" "<-'" "↵") + ("hookleftarrow" "\\hookleftarrow" t "↵" "<-'" "<-'" "↵") + + "** Function names" + ("arccos" "\\arccos" t "arccos" "arccos" "arccos" "arccos") + ("arcsin" "\\arcsin" t "arcsin" "arcsin" "arcsin" "arcsin") + ("arctan" "\\arctan" t "arctan" "arctan" "arctan" "arctan") + ("arg" "\\arg" t "arg" "arg" "arg" "arg") + ("cos" "\\cos" t "cos" "cos" "cos" "cos") + ("cosh" "\\cosh" t "cosh" "cosh" "cosh" "cosh") + ("cot" "\\cot" t "cot" "cot" "cot" "cot") + ("coth" "\\coth" t "coth" "coth" "coth" "coth") + ("csc" "\\csc" t "csc" "csc" "csc" "csc") + ("deg" "\\deg" t "°" "deg" "deg" "deg") + ("det" "\\det" t "det" "det" "det" "det") + ("dim" "\\dim" t "dim" "dim" "dim" "dim") + ("exp" "\\exp" t "exp" "exp" "exp" "exp") + ("gcd" "\\gcd" t "gcd" "gcd" "gcd" "gcd") + ("hom" "\\hom" t "hom" "hom" "hom" "hom") + ("inf" "\\inf" t "inf" "inf" "inf" "inf") + ("ker" "\\ker" t "ker" "ker" "ker" "ker") + ("lg" "\\lg" t "lg" "lg" "lg" "lg") + ("lim" "\\lim" t "lim" "lim" "lim" "lim") + ("liminf" "\\liminf" t "liminf" "liminf" "liminf" "liminf") + ("limsup" "\\limsup" t "limsup" "limsup" "limsup" "limsup") + ("ln" "\\ln" t "ln" "ln" "ln" "ln") + ("log" "\\log" t "log" "log" "log" "log") + ("max" "\\max" t "max" "max" "max" "max") + ("min" "\\min" t "min" "min" "min" "min") + ("Pr" "\\Pr" t "Pr" "Pr" "Pr" "Pr") + ("sec" "\\sec" t "sec" "sec" "sec" "sec") + ("sin" "\\sin" t "sin" "sin" "sin" "sin") + ("sinh" "\\sinh" t "sinh" "sinh" "sinh" "sinh") + ("sup" "\\sup" t "⊃" "sup" "sup" "sup") + ("tan" "\\tan" t "tan" "tan" "tan" "tan") + ("tanh" "\\tanh" t "tanh" "tanh" "tanh" "tanh") + + "** Signs & Symbols" + ("bull" "\\textbullet{}" nil "•" "*" "*" "•") + ("bullet" "\\textbullet{}" nil "•" "*" "*" "•") + ("star" "\\star" t "*" "*" "*" "⋆") + ("lowast" "\\ast" t "∗" "*" "*" "∗") + ("ast" "\\ast" t "∗" "*" "*" "*") + ("odot" "\\odot" t "o" "[circled dot]" "[circled dot]" "ʘ") + ("oplus" "\\oplus" t "⊕" "[circled plus]" "[circled plus]" "⊕") + ("otimes" "\\otimes" t "⊗" "[circled times]" "[circled times]" "⊗") + ("check" "\\checkmark" t "✓" "[checkmark]" "[checkmark]" "✓") + ("checkmark" "\\checkmark" t "✓" "[checkmark]" "[checkmark]" "✓") + + "** Miscellaneous (seldom used)" + ("para" "\\P{}" nil "¶" "[pilcrow]" "¶" "¶") + ("ordf" "\\textordfeminine{}" nil "ª" "_a_" "ª" "ª") + ("ordm" "\\textordmasculine{}" nil "º" "_o_" "º" "º") + ("cedil" "\\c{}" nil "¸" "[cedilla]" "¸" "¸") + ("oline" "\\overline{~}" t "‾" "[overline]" "¯" "‾") + ("uml" "\\textasciidieresis{}" nil "¨" "[diaeresis]" "¨" "¨") + ("zwnj" "\\/{}" nil "‌" "" "" "‌") + ("zwj" "" nil "‍" "" "" "‍") + ("lrm" "" nil "‎" "" "" "‎") + ("rlm" "" nil "‏" "" "" "‏") + + "** Smilies" + ("smiley" "\\ddot\\smile" t "☺" ":-)" ":-)" "☺") + ("blacksmile" "\\ddot\\smile" t "☻" ":-)" ":-)" "☻") + ("sad" "\\ddot\\frown" t "☹" ":-(" ":-(" "☹") + ("frowny" "\\ddot\\frown" t "☹" ":-(" ":-(" "☹") + + "** Suits" + ("clubs" "\\clubsuit" t "♣" "[clubs]" "[clubs]" "♣") + ("clubsuit" "\\clubsuit" t "♣" "[clubs]" "[clubs]" "♣") + ("spades" "\\spadesuit" t "♠" "[spades]" "[spades]" "♠") + ("spadesuit" "\\spadesuit" t "♠" "[spades]" "[spades]" "♠") + ("hearts" "\\heartsuit" t "♥" "[hearts]" "[hearts]" "♥") + ("heartsuit" "\\heartsuit" t "♥" "[hearts]" "[hearts]" "♥") + ("diams" "\\diamondsuit" t "♦" "[diamonds]" "[diamonds]" "◆") + ("diamondsuit" "\\diamondsuit" t "♦" "[diamonds]" "[diamonds]" "◆") + ("diamond" "\\diamondsuit" t "⋄" "[diamond]" "[diamond]" "◆") + ("Diamond" "\\diamondsuit" t "⋄" "[diamond]" "[diamond]" "◆") + ("loz" "\\lozenge" t "◊" "[lozenge]" "[lozenge]" "⧫")) + ;; Add "\_ "-entity family for spaces. + (let (space-entities html-spaces (entity "_")) + (dolist (n (number-sequence 1 20) (nreverse space-entities)) + (let ((spaces (make-string n ?\s))) + (push (list (setq entity (concat entity " ")) + (format "\\hspace*{%sem}" (* n .5)) + nil + (setq html-spaces (concat " " html-spaces)) + spaces + spaces + (make-string n ?\x2002)) + space-entities))))) + "Default entities used in Org mode to produce special characters. For details see `org-entities-user'.") (defsubst org-entity-get (name) @@ -518,52 +531,27 @@ This first checks the user list, then the built-in list." (or (assoc name org-entities-user) (assoc name org-entities))) -(defun org-entity-get-representation (name kind) - "Get the correct representation of entity NAME for export type KIND. -Kind can be any of `latex', `html', `ascii', `latin1', or `utf8'." - (let* ((e (org-entity-get name)) - (n (cdr (assq kind '((latex . 1) (html . 3) (ascii . 4) - (latin1 . 5) (utf8 . 6))))) - (r (and e n (nth n e)))) - (if (and e r - (not org-entities-ascii-explanatory) - (memq kind '(ascii latin1 utf8)) - (= (string-to-char r) ?\[)) - (concat "\\" name) - r))) - -(defsubst org-entity-latex-math-p (name) - "Does entity NAME require math mode in LaTeX?" - (nth 2 (org-entity-get name))) - ;; Helpfunctions to create a table for orgmode.org/worg/org-symbols.org (defun org-entities-create-table () "Create an Org mode table with all entities." (interactive) - (let ((pos (point)) e latex mathp html latin utf8 name ascii) + (let ((pos (point))) (insert "|Name|LaTeX code|LaTeX|HTML code |HTML|ASCII|Latin1|UTF-8\n|-\n") - (mapc (lambda (e) (when (listp e) - (setq name (car e) - latex (nth 1 e) - mathp (nth 2 e) - html (nth 3 e) - ascii (nth 4 e) - latin (nth 5 e) - utf8 (nth 6 e)) - (if (equal ascii "|") (setq ascii "\\vert")) - (if (equal latin "|") (setq latin "\\vert")) - (if (equal utf8 "|") (setq utf8 "\\vert")) - (if (equal ascii "=>") (setq ascii "= >")) - (if (equal latin "=>") (setq latin "= >")) - (insert "|" name - "|" (format "=%s=" latex) - "|" (format (if mathp "$%s$" "$\\mbox{%s}$") - latex) - "|" (format "=%s=" html) "|" html - "|" ascii "|" latin "|" utf8 - "|\n"))) - org-entities) + (dolist (e org-entities) + (pcase e + (`(,name ,latex ,mathp ,html ,ascii ,latin ,utf8) + (if (equal ascii "|") (setq ascii "\\vert")) + (if (equal latin "|") (setq latin "\\vert")) + (if (equal utf8 "|") (setq utf8 "\\vert")) + (if (equal ascii "=>") (setq ascii "= >")) + (if (equal latin "=>") (setq latin "= >")) + (insert "|" name + "|" (format "=%s=" latex) + "|" (format (if mathp "$%s$" "$\\mbox{%s}$") latex) + "|" (format "=%s=" html) "|" html + "|" ascii "|" latin "|" utf8 + "|\n")))) (goto-char pos) (org-table-align))) @@ -572,31 +560,27 @@ Kind can be any of `latex', `html', `ascii', `latin1', or `utf8'." "Create a Help buffer with all available entities." (interactive) (with-output-to-temp-buffer "*Org Entity Help*" - (princ "Org-mode entities\n=================\n\n") + (princ "Org mode entities\n=================\n\n") (let ((ll (append '("* User-defined additions (variable org-entities-user)") org-entities-user org-entities)) - e latex mathp html latin utf8 name ascii (lastwasstring t) (head (concat "\n" " Symbol Org entity LaTeX code HTML code\n" " -----------------------------------------------------------\n"))) - (while ll - (setq e (pop ll)) - (if (stringp e) - (progn - (princ e) - (princ "\n") - (setq lastwasstring t)) - (if lastwasstring (princ head)) - (setq lastwasstring nil) - (setq name (car e) - latex (nth 1 e) - html (nth 3 e) - utf8 (nth 6 e)) - (princ (format " %-8s \\%-16s %-22s %-13s\n" - utf8 name latex html)))))) + (dolist (e ll) + (pcase e + (`(,name ,latex ,_ ,html ,_ ,_ ,utf8) + (when lastwasstring + (princ head) + (setq lastwasstring nil)) + (princ (format " %-8s \\%-16s %-22s %-13s\n" + utf8 name latex html))) + ((pred stringp) + (princ e) + (princ "\n") + (setq lastwasstring t)))))) (with-current-buffer "*Org Entity Help*" (org-mode) (when org-pretty-entities @@ -604,12 +588,6 @@ Kind can be any of `latex', `html', `ascii', `latin1', or `utf8'." (select-window (get-buffer-window "*Org Entity Help*"))) -(defun replace-amp () - "Postprocess HTML file to unescape the ampersand." - (interactive) - (while (re-search-forward "&\\([^<;]+;\\)" nil t) - (replace-match (concat "&" (match-string 1)) t t))) - (provide 'org-entities) ;; Local variables: diff --git a/lisp/org/org-eshell.el b/lisp/org/org-eshell.el index 9eddd3fcf4e..34cc4ffbb8d 100644 --- a/lisp/org/org-eshell.el +++ b/lisp/org/org-eshell.el @@ -1,4 +1,4 @@ -;;; org-eshell.el - Support for links to working directories in eshell +;;; org-eshell.el - Support for Links to Working Directories in Eshell -*- lexical-binding: t; -*- ;; Copyright (C) 2011-2017 Free Software Foundation, Inc. @@ -27,8 +27,9 @@ (require 'eshell) (require 'esh-mode) -(org-add-link-type "eshell" 'org-eshell-open) -(add-hook 'org-store-link-functions 'org-eshell-store-link) +(org-link-set-parameters "eshell" + :follow #'org-eshell-open + :store #'org-eshell-store-link) (defun org-eshell-open (link) "Switch to am eshell buffer and execute a command line. @@ -43,7 +44,7 @@ (eshell-buffer-name (car buffer-and-command)) (command (cadr buffer-and-command))) (if (get-buffer eshell-buffer-name) - (org-pop-to-buffer-same-window eshell-buffer-name) + (pop-to-buffer-same-window eshell-buffer-name) (eshell)) (goto-char (point-max)) (eshell-kill-input) diff --git a/lisp/org/org-eww.el b/lisp/org/org-eww.el new file mode 100644 index 00000000000..c14ae115afb --- /dev/null +++ b/lisp/org/org-eww.el @@ -0,0 +1,175 @@ +;;; org-eww.el --- Store url and kill from Eww mode for Org -*- lexical-binding: t -*- + +;; Copyright (C) 2014-2017 Free Software Foundation, Inc. + +;; Author: Marco Wahl a +;; Keywords: link, eww +;; Homepage: http://orgmode.org + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + + +;;; Commentary: + +;; When this module is active `org-store-link' (often on key C-c l) in +;; a eww buffer stores a link to the current url of the eww buffer. + +;; In an eww buffer function `org-eww-copy-for-org-mode' kills either +;; a region or the whole buffer if no region is set and transforms the +;; text on the fly so that it can be pasted into an Org buffer with +;; hot links. + +;; C-c C-x C-w (and also C-c C-x M-w) trigger +;; `org-eww-copy-for-org-mode'. + +;; Hint: A lot of code of this module comes from module org-w3m which +;; has been written by Andy Steward based on the idea of Richard +;; Riley. Thanks! + +;; Potential: Since the code for w3m and eww is so similar one could +;; try to refactor. + + +;;; Code: +(require 'org) +(require 'cl-lib) + +(defvar eww-current-title) +(defvar eww-current-url) +(defvar eww-data) +(defvar eww-mode-map) + +(declare-function eww-current-url "eww") + + +;; Store Org-link in eww-mode buffer +(org-link-set-parameters "eww" :follow #'eww :store #'org-eww-store-link) +(defun org-eww-store-link () + "Store a link to the url of a Eww buffer." + (when (eq major-mode 'eww-mode) + (org-store-link-props + :type "eww" + :link (if (< emacs-major-version 25) + eww-current-url + (eww-current-url)) + :url (url-view-url t) + :description (if (< emacs-major-version 25) + (or eww-current-title eww-current-url) + (or (plist-get eww-data :title) + (eww-current-url)))))) + + +;; Some auxiliary functions concerning links in eww buffers +(defun org-eww-goto-next-url-property-change () + "Move to the start of next link if exists. +Otherwise point is not moved. Return point." + (goto-char + (or (next-single-property-change (point) 'shr-url) + (point)))) + +(defun org-eww-has-further-url-property-change-p () + "Non-nil if there is a next url property change." + (save-excursion + (not (eq (point) (org-eww-goto-next-url-property-change))))) + +(defun org-eww-url-below-point () + "Return the url below point if there is an url; otherwise, return nil." + (get-text-property (point) 'shr-url)) + + +(defun org-eww-copy-for-org-mode () + "Copy current buffer content or active region with `org-mode' style links. +This will encode `link-title' and `link-location' with +`org-make-link-string', and insert the transformed test into the kill ring, +so that it can be yanked into an Org mode buffer with links working correctly. + +Further lines starting with a star get quoted with a comma to keep +the structure of the Org file." + (interactive) + (let* ((regionp (org-region-active-p)) + (transform-start (point-min)) + (transform-end (point-max)) + return-content + link-location link-title + temp-position out-bound) + (when regionp + (setq transform-start (region-beginning)) + (setq transform-end (region-end)) + ;; Deactivate mark if current mark is activate. + (when (fboundp 'deactivate-mark) (deactivate-mark))) + (message "Transforming links...") + (save-excursion + (goto-char transform-start) + (while (and (not out-bound) ; still inside region to copy + (org-eww-has-further-url-property-change-p)) ; there is a next link + ;; Store current point before jump next anchor. + (setq temp-position (point)) + ;; Move to next anchor when current point is not at anchor. + (or (org-eww-url-below-point) + (org-eww-goto-next-url-property-change)) + (cl-assert + (org-eww-url-below-point) t + "program logic error: point must have an url below but it hasn't") + (if (<= (point) transform-end) ; if point is inside transform bound + (progn + ;; Get content between two links. + (when (< temp-position (point)) + (setq return-content (concat return-content + (buffer-substring + temp-position (point))))) + ;; Get link location at current point. + (setq link-location (org-eww-url-below-point)) + ;; Get link title at current point. + (setq link-title + (buffer-substring + (point) + (org-eww-goto-next-url-property-change))) + ;; concat `org-mode' style url to `return-content'. + (setq return-content + (concat return-content + (if (stringp link-location) + ;; hint: link-location is different for form-elements. + (org-make-link-string link-location link-title) + link-title)))) + (goto-char temp-position) ; reset point before jump next anchor + (setq out-bound t) ; for break out `while' loop + )) + ;; Add the rest until end of the region to be copied. + (when (< (point) transform-end) + (setq return-content + (concat return-content + (buffer-substring (point) transform-end)))) + ;; Quote lines starting with *. + (org-kill-new (replace-regexp-in-string "^\\*" ",*" return-content)) + (message "Transforming links...done, use C-y to insert text into Org mode file")))) + + +;; Additional keys for eww-mode + +(defun org-eww-extend-eww-keymap () + (define-key eww-mode-map "\C-c\C-x\M-w" 'org-eww-copy-for-org-mode) + (define-key eww-mode-map "\C-c\C-x\C-w" 'org-eww-copy-for-org-mode)) + +(when (and (boundp 'eww-mode-map) + (keymapp eww-mode-map)) ; eww is already up. + (org-eww-extend-eww-keymap)) + +(add-hook 'eww-mode-hook #'org-eww-extend-eww-keymap) + + +(provide 'org-eww) + +;;; org-eww.el ends here diff --git a/lisp/org/org-faces.el b/lisp/org/org-faces.el index c340aca73a5..cd43d37178b 100644 --- a/lisp/org/org-faces.el +++ b/lisp/org/org-faces.el @@ -1,4 +1,4 @@ -;;; org-faces.el --- Face definitions for Org-mode. +;;; org-faces.el --- Face definitions -*- lexical-binding: t; -*- ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. @@ -28,32 +28,12 @@ ;;; Code: -(require 'org-macs) -(require 'org-compat) - -(defun org-copy-face (old-face new-face docstring &rest attributes) - (unless (facep new-face) - (if (fboundp 'set-face-attribute) - (progn - (make-face new-face) - (set-face-attribute new-face nil :inherit old-face) - (apply 'set-face-attribute new-face nil attributes) - (set-face-doc-string new-face docstring)) - (copy-face old-face new-face) - (if (fboundp 'set-face-doc-string) - (set-face-doc-string new-face docstring))))) -(put 'org-copy-face 'lisp-indent-function 2) - -(when (featurep 'xemacs) - (put 'mode-line 'face-alias 'modeline)) - (defgroup org-faces nil - "Faces in Org-mode." + "Faces in Org mode." :tag "Org Faces" :group 'org-appearance) -(defface org-default - (org-compatible-face 'default nil) +(defface org-default '((t :inherit default)) "Face used for default text." :group 'org-faces) @@ -65,99 +45,49 @@ The foreground color of this face should be equal to the background color of the frame." :group 'org-faces) -(defface org-level-1 ;; originally copied from font-lock-function-name-face - (org-compatible-face 'outline-1 - '((((class color) (min-colors 88) (background light)) (:foreground "Blue1")) - (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue")) - (((class color) (min-colors 16) (background light)) (:foreground "Blue")) - (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue")) - (((class color) (min-colors 8)) (:foreground "blue" :bold t)) - (t (:bold t)))) +(defface org-level-1 '((t :inherit outline-1)) "Face used for level 1 headlines." :group 'org-faces) -(defface org-level-2 ;; originally copied from font-lock-variable-name-face - (org-compatible-face 'outline-2 - '((((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod")) - (((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod")) - (((class color) (min-colors 8) (background light)) (:foreground "yellow")) - (((class color) (min-colors 8) (background dark)) (:foreground "yellow" :bold t)) - (t (:bold t)))) +(defface org-level-2 '((t :inherit outline-2)) "Face used for level 2 headlines." :group 'org-faces) -(defface org-level-3 ;; originally copied from font-lock-keyword-face - (org-compatible-face 'outline-3 - '((((class color) (min-colors 88) (background light)) (:foreground "Purple")) - (((class color) (min-colors 88) (background dark)) (:foreground "Cyan1")) - (((class color) (min-colors 16) (background light)) (:foreground "Purple")) - (((class color) (min-colors 16) (background dark)) (:foreground "Cyan")) - (((class color) (min-colors 8) (background light)) (:foreground "purple" :bold t)) - (((class color) (min-colors 8) (background dark)) (:foreground "cyan" :bold t)) - (t (:bold t)))) +(defface org-level-3 '((t :inherit outline-3)) "Face used for level 3 headlines." :group 'org-faces) -(defface org-level-4 ;; originally copied from font-lock-comment-face - (org-compatible-face 'outline-4 - '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick")) - (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1")) - (((class color) (min-colors 16) (background light)) (:foreground "red")) - (((class color) (min-colors 16) (background dark)) (:foreground "red1")) - (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t)) - (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t)) - (t (:bold t)))) +(defface org-level-4 '((t :inherit outline-4)) "Face used for level 4 headlines." :group 'org-faces) -(defface org-level-5 ;; originally copied from font-lock-type-face - (org-compatible-face 'outline-5 - '((((class color) (min-colors 16) (background light)) (:foreground "ForestGreen")) - (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen")) - (((class color) (min-colors 8)) (:foreground "green")))) +(defface org-level-5 '((t :inherit outline-5)) "Face used for level 5 headlines." :group 'org-faces) -(defface org-level-6 ;; originally copied from font-lock-constant-face - (org-compatible-face 'outline-6 - '((((class color) (min-colors 16) (background light)) (:foreground "CadetBlue")) - (((class color) (min-colors 16) (background dark)) (:foreground "Aquamarine")) - (((class color) (min-colors 8)) (:foreground "magenta")))) +(defface org-level-6 '((t :inherit outline-6)) "Face used for level 6 headlines." :group 'org-faces) -(defface org-level-7 ;; originally copied from font-lock-builtin-face - (org-compatible-face 'outline-7 - '((((class color) (min-colors 16) (background light)) (:foreground "Orchid")) - (((class color) (min-colors 16) (background dark)) (:foreground "LightSteelBlue")) - (((class color) (min-colors 8)) (:foreground "blue")))) +(defface org-level-7 '((t :inherit outline-7)) "Face used for level 7 headlines." :group 'org-faces) -(defface org-level-8 ;; originally copied from font-lock-string-face - (org-compatible-face 'outline-8 - '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown")) - (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon")) - (((class color) (min-colors 8)) (:foreground "green")))) +(defface org-level-8 '((t :inherit outline-8)) "Face used for level 8 headlines." :group 'org-faces) -(defface org-special-keyword ;; originally copied from font-lock-string-face - (org-compatible-face 'font-lock-keyword-face - '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown")) - (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon")) - (t (:italic t)))) +(defface org-special-keyword '((t :inherit font-lock-keyword-face)) "Face used for special keywords." :group 'org-faces) -(defface org-drawer ;; originally copied from font-lock-function-name-face - (org-compatible-face nil - '((((class color) (min-colors 88) (background light)) (:foreground "Blue1")) - (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue")) - (((class color) (min-colors 16) (background light)) (:foreground "Blue")) - (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue")) - (((class color) (min-colors 8)) (:foreground "blue" :bold t)) - (t (:bold t)))) +(defface org-drawer ;Copied from `font-lock-function-name-face' + '((((class color) (min-colors 88) (background light)) (:foreground "Blue1")) + (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue")) + (((class color) (min-colors 16) (background light)) (:foreground "Blue")) + (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue")) + (((class color) (min-colors 8)) (:foreground "blue" :bold t)) + (t (:bold t))) "Face used for drawers." :group 'org-faces) @@ -166,18 +96,17 @@ color of the frame." :group 'org-faces) (defface org-column - (org-compatible-face nil - '((((class color) (min-colors 16) (background light)) - (:background "grey90" :weight normal :slant normal :strike-through nil - :underline nil)) - (((class color) (min-colors 16) (background dark)) - (:background "grey30" :weight normal :slant normal :strike-through nil - :underline nil)) - (((class color) (min-colors 8)) - (:background "cyan" :foreground "black" - :weight normal :slant normal :strike-through nil - :underline nil)) - (t (:inverse-video t)))) + '((((class color) (min-colors 16) (background light)) + (:background "grey90" :weight normal :slant normal :strike-through nil + :underline nil)) + (((class color) (min-colors 16) (background dark)) + (:background "grey30" :weight normal :slant normal :strike-through nil + :underline nil)) + (((class color) (min-colors 8)) + (:background "cyan" :foreground "black" + :weight normal :slant normal :strike-through nil + :underline nil)) + (t (:inverse-video t))) "Face for column display of entry properties. This is actually only part of the face definition for the text in column view. The following faces apply, with this priority. @@ -198,59 +127,33 @@ character (this might for example be the a TODO keyword) might still shine through in some properties. So when your column view looks funny, with \"random\" colors, weight, strike-through, try to explicitly set the properties in the `org-column' face. For example, set -:underline to nil, or the :slant to `normal'. - -Under XEmacs, the rules are simpler, because the XEmacs version of -column view defines special faces for each outline level. See the file -`org-colview-xemacs.el' in Org's contrib/ directory for details." +:underline to nil, or the :slant to `normal'." :group 'org-faces) (defface org-column-title - (org-compatible-face nil - '((((class color) (min-colors 16) (background light)) - (:background "grey90" :underline t :weight bold)) - (((class color) (min-colors 16) (background dark)) - (:background "grey30" :underline t :weight bold)) - (((class color) (min-colors 8)) - (:background "cyan" :foreground "black" :underline t :weight bold)) - (t (:inverse-video t)))) + '((((class color) (min-colors 16) (background light)) + (:background "grey90" :underline t :weight bold)) + (((class color) (min-colors 16) (background dark)) + (:background "grey30" :underline t :weight bold)) + (((class color) (min-colors 8)) + (:background "cyan" :foreground "black" :underline t :weight bold)) + (t (:inverse-video t))) "Face for column display of entry properties." :group 'org-faces) -(defface org-agenda-column-dateline - (org-compatible-face 'org-column - '((t nil))) +(defface org-agenda-column-dateline '((t :inherit org-column)) "Face used in agenda column view for datelines with summaries." :group 'org-faces) -(defface org-warning - (org-compatible-face 'font-lock-warning-face - '((((class color) (min-colors 16) (background light)) (:foreground "Red1" :bold t)) - (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :bold t)) - (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t)) - (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t)) - (t (:bold t)))) +(defface org-warning '((t :inherit font-lock-warning-face)) "Face for deadlines and TODO keywords." :group 'org-faces) -(defface org-archived ; similar to shadow - (org-compatible-face 'shadow - '((((class color grayscale) (min-colors 88) (background light)) - (:foreground "grey50")) - (((class color grayscale) (min-colors 88) (background dark)) - (:foreground "grey70")) - (((class color) (min-colors 8) (background light)) - (:foreground "green")) - (((class color) (min-colors 8) (background dark)) - (:foreground "yellow")))) +(defface org-archived '((t :inherit shadow)) "Face for headline with the ARCHIVE tag." :group 'org-faces) -(defface org-link - (org-compatible-face 'link - '((((class color) (background light)) (:foreground "Purple" :underline t)) - (((class color) (background dark)) (:foreground "Cyan" :underline t)) - (t (:underline t)))) +(defface org-link '((t :inherit link)) "Face for links." :group 'org-faces) @@ -283,12 +186,11 @@ column view defines special faces for each outline level. See the file :group 'org-faces) (defface org-date-selected - (org-compatible-face nil - '((((class color) (min-colors 16) (background light)) (:foreground "Red1" :inverse-video t)) - (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :inverse-video t)) - (((class color) (min-colors 8) (background light)) (:foreground "red" :inverse-video t)) - (((class color) (min-colors 8) (background dark)) (:foreground "red" :inverse-video t)) - (t (:inverse-video t)))) + '((((class color) (min-colors 16) (background light)) (:foreground "Red1" :inverse-video t)) + (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :inverse-video t)) + (((class color) (min-colors 8) (background light)) (:foreground "red" :inverse-video t)) + (((class color) (min-colors 8) (background dark)) (:foreground "red" :inverse-video t)) + (t (:inverse-video t))) "Face for highlighting the calendar day when using `org-read-date'. Using a bold face here might cause discrepancies while displaying the calendar." @@ -301,43 +203,38 @@ calendar." "Face for diary-like sexp date specifications." :group 'org-faces) -(defface org-tag - '((t (:bold t))) +(defface org-tag '((t (:bold t))) "Default face for tags. Note that the variable `org-tag-faces' can be used to overrule this face for specific tags." :group 'org-faces) -(defface org-list-dt - '((t (:bold t))) +(defface org-list-dt '((t (:bold t))) "Default face for definition terms in lists." :group 'org-faces) -(defface org-todo ; font-lock-warning-face - (org-compatible-face nil - '((((class color) (min-colors 16) (background light)) (:foreground "Red1" :bold t)) - (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :bold t)) - (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t)) - (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t)) - (t (:inverse-video t :bold t)))) +(defface org-todo ;Copied from `font-lock-warning-face' + '((((class color) (min-colors 16) (background light)) (:foreground "Red1" :bold t)) + (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :bold t)) + (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t)) + (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t)) + (t (:inverse-video t :bold t))) "Face for TODO keywords." :group 'org-faces) -(defface org-done ;; originally copied from font-lock-type-face - (org-compatible-face nil - '((((class color) (min-colors 16) (background light)) (:foreground "ForestGreen" :bold t)) - (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen" :bold t)) - (((class color) (min-colors 8)) (:foreground "green")) - (t (:bold t)))) +(defface org-done ;Copied from `font-lock-type-face' + '((((class color) (min-colors 16) (background light)) (:foreground "ForestGreen" :bold t)) + (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen" :bold t)) + (((class color) (min-colors 8)) (:foreground "green")) + (t (:bold t))) "Face used for todo keywords that indicate DONE items." :group 'org-faces) -(defface org-agenda-done ;; originally copied from font-lock-type-face - (org-compatible-face nil - '((((class color) (min-colors 16) (background light)) (:foreground "ForestGreen")) - (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen")) - (((class color) (min-colors 8)) (:foreground "green")) - (t (:bold nil)))) +(defface org-agenda-done ;Copied from `font-lock-type-face' + '((((class color) (min-colors 16) (background light)) (:foreground "ForestGreen")) + (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen")) + (((class color) (min-colors 8)) (:foreground "green")) + (t (:bold nil))) "Face used in agenda, to indicate lines switched to DONE. This face is used to de-emphasize items that where brightly colored in the agenda because they were things to do, or overdue. The DONE state itself @@ -346,11 +243,10 @@ is of course immediately visible, but for example a passed deadline is of the frame, for example." :group 'org-faces) -(defface org-headline-done ;; originally copied from font-lock-string-face - (org-compatible-face nil - '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown")) - (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon")) - (((class color) (min-colors 8) (background light)) (:bold nil)))) +(defface org-headline-done ;Copied from `font-lock-string-face' + '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown")) + (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon")) + (((class color) (min-colors 8) (background light)) (:bold nil))) "Face used to indicate that a headline is DONE. This face is only used if `org-fontify-done-headline' is set. If applies to the part of the headline after the DONE keyword." @@ -388,11 +284,7 @@ determines if it is a foreground or a background color." (string :tag "Color") (sexp :tag "Face"))))) -(defface org-priority ;; originally copied from font-lock-string-face - (org-compatible-face 'font-lock-keyword-face - '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown")) - (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon")) - (t (:italic t)))) +(defface org-priority '((t :inherit font-lock-keyword-face)) "Face used for priority cookies." :group 'org-faces) @@ -421,18 +313,17 @@ determines if it is a foreground or a background color." (setq org-tags-special-faces-re (concat ":\\(" (mapconcat 'car value "\\|") "\\):")))) -(defface org-checkbox - (org-compatible-face 'bold - '((t (:bold t)))) +(defface org-checkbox '((t :inherit bold)) "Face for checkboxes." :group 'org-faces) +(defface org-checkbox-statistics-todo '((t (:inherit org-todo))) + "Face used for unfinished checkbox statistics." + :group 'org-faces) -(org-copy-face 'org-todo 'org-checkbox-statistics-todo - "Face used for unfinished checkbox statistics.") - -(org-copy-face 'org-done 'org-checkbox-statistics-done - "Face used for finished checkbox statistics.") +(defface org-checkbox-statistics-done '((t (:inherit org-done))) + "Face used for finished checkbox statistics." + :group 'org-faces) (defcustom org-tag-faces nil "Faces for specific tags. @@ -454,44 +345,32 @@ changes." (string :tag "Foreground color") (sexp :tag "Face"))))) -(defface org-table ;; originally copied from font-lock-function-name-face - (org-compatible-face nil - '((((class color) (min-colors 88) (background light)) (:foreground "Blue1")) - (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue")) - (((class color) (min-colors 16) (background light)) (:foreground "Blue")) - (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue")) - (((class color) (min-colors 8) (background light)) (:foreground "blue")) - (((class color) (min-colors 8) (background dark))))) +(defface org-table ;Copied from `font-lock-function-name-face' + '((((class color) (min-colors 88) (background light)) (:foreground "Blue1")) + (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue")) + (((class color) (min-colors 16) (background light)) (:foreground "Blue")) + (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue")) + (((class color) (min-colors 8) (background light)) (:foreground "blue")) + (((class color) (min-colors 8) (background dark)))) "Face used for tables." :group 'org-faces) (defface org-formula - (org-compatible-face nil - '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick")) - (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1")) - (((class color) (min-colors 8) (background light)) (:foreground "red")) - (((class color) (min-colors 8) (background dark)) (:foreground "red")) - (t (:bold t :italic t)))) + '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick")) + (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1")) + (((class color) (min-colors 8) (background light)) (:foreground "red")) + (((class color) (min-colors 8) (background dark)) (:foreground "red")) + (t (:bold t :italic t))) "Face for formulas." :group 'org-faces) -(defface org-code - (org-compatible-face 'shadow - '((((class color grayscale) (min-colors 88) (background light)) - (:foreground "grey50")) - (((class color grayscale) (min-colors 88) (background dark)) - (:foreground "grey70")) - (((class color) (min-colors 8) (background light)) - (:foreground "green")) - (((class color) (min-colors 8) (background dark)) - (:foreground "yellow")))) +(defface org-code '((t :inherit shadow)) "Face for fixed-width text like code snippets." :group 'org-faces :version "22.1") -(defface org-meta-line - (org-compatible-face 'font-lock-comment-face nil) - "Face for meta lines startin with \"#+\"." +(defface org-meta-line '((t :inherit font-lock-comment-face)) + "Face for meta lines starting with \"#+\"." :group 'org-faces :version "22.1") @@ -510,60 +389,37 @@ changes." follows a #+DATE:, #+AUTHOR: or #+EMAIL: keyword." :group 'org-faces) -(defface org-document-info-keyword - (org-compatible-face 'shadow - '((((class color grayscale) (min-colors 88) (background light)) - (:foreground "grey50")) - (((class color grayscale) (min-colors 88) (background dark)) - (:foreground "grey70")) - (((class color) (min-colors 8) (background light)) - (:foreground "green")) - (((class color) (min-colors 8) (background dark)) - (:foreground "yellow")))) +(defface org-document-info-keyword '((t :inherit shadow)) "Face for #+TITLE:, #+AUTHOR:, #+EMAIL: and #+DATE: keywords." :group 'org-faces) -(defface org-block - (org-compatible-face 'shadow - '((((class color grayscale) (min-colors 88) (background light)) - (:foreground "grey50")) - (((class color grayscale) (min-colors 88) (background dark)) - (:foreground "grey70")) - (((class color) (min-colors 8) (background light)) - (:foreground "green")) - (((class color) (min-colors 8) (background dark)) - (:foreground "yellow")))) - "Face text in #+begin ... #+end blocks." +(defface org-block '((t :inherit shadow)) + "Face text in #+begin ... #+end blocks. +For source-blocks `org-src-block-faces' takes precedence. +See also `org-fontify-quote-and-verse-blocks'." :group 'org-faces - :version "22.1") + :version "26.1") -(defface org-block-background '((t ())) - "Face used for the source block background.") - -(org-copy-face 'org-meta-line 'org-block-begin-line - "Face used for the line delimiting the begin of source blocks.") - -(org-copy-face 'org-meta-line 'org-block-end-line - "Face used for the line delimiting the end of source blocks.") - -(defface org-verbatim - (org-compatible-face 'shadow - '((((class color grayscale) (min-colors 88) (background light)) - (:foreground "grey50" :underline t)) - (((class color grayscale) (min-colors 88) (background dark)) - (:foreground "grey70" :underline t)) - (((class color) (min-colors 8) (background light)) - (:foreground "green" :underline t)) - (((class color) (min-colors 8) (background dark)) - (:foreground "yellow" :underline t)))) - "Face for fixed-with text like code snippets." +(defface org-block-begin-line '((t (:inherit org-meta-line))) + "Face used for the line delimiting the begin of source blocks." + :group 'org-faces) + +(defface org-block-end-line '((t (:inherit org-block-begin-line))) + "Face used for the line delimiting the end of source blocks." + :group 'org-faces) + +(defface org-verbatim '((t (:inherit shadow))) + "Face for fixed-with text like code snippets" :group 'org-faces :version "22.1") -(org-copy-face 'org-block 'org-quote - "Face for #+BEGIN_QUOTE ... #+END_QUOTE blocks.") -(org-copy-face 'org-block 'org-verse - "Face for #+BEGIN_VERSE ... #+END_VERSE blocks.") +(defface org-quote '((t (:inherit org-block))) + "Face for #+BEGIN_QUOTE ... #+END_QUOTE blocks." + :group 'org-faces) + +(defface org-verse '((t (:inherit org-block))) + "Face for #+BEGIN_VERSE ... #+END_VERSE blocks." + :group 'org-faces) (defcustom org-fontify-quote-and-verse-blocks nil "Non-nil means, add a special face to #+begin_quote and #+begin_verse block. @@ -573,64 +429,64 @@ content of these blocks will still be treated as Org syntax." :version "24.1" :type 'boolean) -(defface org-clock-overlay ;; copied from secondary-selection - (org-compatible-face nil - '((((class color) (min-colors 88) (background light)) - (:background "yellow1")) - (((class color) (min-colors 88) (background dark)) - (:background "SkyBlue4")) - (((class color) (min-colors 16) (background light)) - (:background "yellow")) - (((class color) (min-colors 16) (background dark)) - (:background "SkyBlue4")) - (((class color) (min-colors 8)) - (:background "cyan" :foreground "black")) - (t (:inverse-video t)))) +(defface org-clock-overlay ;Copied from `secondary-selection' + '((((class color) (min-colors 88) (background light)) + (:background "LightGray" :foreground "black")) + (((class color) (min-colors 88) (background dark)) + (:background "SkyBlue4" :foreground "white")) + (((class color) (min-colors 16) (background light)) + (:background "gray" :foreground "black")) + (((class color) (min-colors 16) (background dark)) + (:background "SkyBlue4" :foreground "white")) + (((class color) (min-colors 8)) + (:background "cyan" :foreground "black")) + (t (:inverse-video t))) "Basic face for displaying the secondary selection." :group 'org-faces) -(defface org-agenda-structure ;; originally copied from font-lock-function-name-face - (org-compatible-face nil - '((((class color) (min-colors 88) (background light)) (:foreground "Blue1")) - (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue")) - (((class color) (min-colors 16) (background light)) (:foreground "Blue")) - (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue")) - (((class color) (min-colors 8)) (:foreground "blue" :bold t)) - (t (:bold t)))) +(defface org-agenda-structure ;Copied from `font-lock-function-name-face' + '((((class color) (min-colors 88) (background light)) (:foreground "Blue1")) + (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue")) + (((class color) (min-colors 16) (background light)) (:foreground "Blue")) + (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue")) + (((class color) (min-colors 8)) (:foreground "blue" :bold t)) + (t (:bold t))) "Face used in agenda for captions and dates." :group 'org-faces) -(org-copy-face 'org-agenda-structure 'org-agenda-date - "Face used in agenda for normal days.") +(defface org-agenda-date '((t (:inherit org-agenda-structure))) + "Face used in agenda for normal days." + :group 'org-faces) -(org-copy-face 'org-agenda-date 'org-agenda-date-today +(defface org-agenda-date-today + '((t (:inherit org-agenda-date :weight bold :italic t))) "Face used in agenda for today." - :weight 'bold :italic 't) + :group 'org-faces) -(org-copy-face 'secondary-selection 'org-agenda-clocking - "Face marking the current clock item in the agenda.") +(defface org-agenda-clocking '((t (:inherit secondary-selection))) + "Face marking the current clock item in the agenda." + :group 'org-faces) -(org-copy-face 'org-agenda-date 'org-agenda-date-weekend +(defface org-agenda-date-weekend '((t (:inherit org-agenda-date :weight bold))) "Face used in agenda for weekend days. -See the variable `org-agenda-weekend-days' for a definition of which days -belong to the weekend." - :weight 'bold) + +See the variable `org-agenda-weekend-days' for a definition of +which days belong to the weekend." + :group 'org-faces) (defface org-scheduled - (org-compatible-face nil - '((((class color) (min-colors 88) (background light)) (:foreground "DarkGreen")) - (((class color) (min-colors 88) (background dark)) (:foreground "PaleGreen")) - (((class color) (min-colors 8)) (:foreground "green")) - (t (:bold t :italic t)))) + '((((class color) (min-colors 88) (background light)) (:foreground "DarkGreen")) + (((class color) (min-colors 88) (background dark)) (:foreground "PaleGreen")) + (((class color) (min-colors 8)) (:foreground "green")) + (t (:bold t :italic t))) "Face for items scheduled for a certain day." :group 'org-faces) (defface org-scheduled-today - (org-compatible-face nil - '((((class color) (min-colors 88) (background light)) (:foreground "DarkGreen")) - (((class color) (min-colors 88) (background dark)) (:foreground "PaleGreen")) - (((class color) (min-colors 8)) (:foreground "green")) - (t (:bold t :italic t)))) + '((((class color) (min-colors 88) (background light)) (:foreground "DarkGreen")) + (((class color) (min-colors 88) (background dark)) (:foreground "PaleGreen")) + (((class color) (min-colors 8)) (:foreground "green")) + (t (:bold t :italic t))) "Face for items scheduled for a certain day." :group 'org-faces) @@ -641,22 +497,20 @@ belong to the weekend." :group 'org-faces) (defface org-scheduled-previously - (org-compatible-face nil - '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick")) - (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1")) - (((class color) (min-colors 8) (background light)) (:foreground "red")) - (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t)) - (t (:bold t)))) + '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick")) + (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1")) + (((class color) (min-colors 8) (background light)) (:foreground "red")) + (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t)) + (t (:bold t))) "Face for items scheduled previously, and not yet done." :group 'org-faces) (defface org-upcoming-deadline - (org-compatible-face nil - '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick")) - (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1")) - (((class color) (min-colors 8) (background light)) (:foreground "red")) - (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t)) - (t (:bold t)))) + '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick")) + (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1")) + (((class color) (min-colors 8) (background light)) (:foreground "red")) + (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t)) + (t (:bold t))) "Face for items scheduled previously, and not yet done." :group 'org-faces) @@ -666,7 +520,7 @@ belong to the weekend." (0.0 . default)) "Faces for showing deadlines in the agenda. This is a list of cons cells. The cdr of each cell is a face to be used, -and it can also just be like (:foreground \"yellow\"). +and it can also just be like \\='(:foreground \"yellow\"). Each car is a fraction of the head-warning time that must have passed for this the face in the cdr to be used for display. The numbers must be given in descending order. The head-warning time is normally taken @@ -686,65 +540,61 @@ month and 365.24 days for a year)." (sexp :tag "Face")))) (defface org-agenda-restriction-lock - (org-compatible-face nil - '((((class color) (min-colors 88) (background light)) (:background "#eeeeee")) - (((class color) (min-colors 88) (background dark)) (:background "#1C1C1C")) - (((class color) (min-colors 16) (background light)) (:background "#eeeeee")) - (((class color) (min-colors 16) (background dark)) (:background "#1C1C1C")) - (((class color) (min-colors 8)) (:background "cyan" :foreground "black")) - (t (:inverse-video t)))) + '((((class color) (min-colors 88) (background light)) (:background "#eeeeee")) + (((class color) (min-colors 88) (background dark)) (:background "#1C1C1C")) + (((class color) (min-colors 16) (background light)) (:background "#eeeeee")) + (((class color) (min-colors 16) (background dark)) (:background "#1C1C1C")) + (((class color) (min-colors 8)) (:background "cyan" :foreground "black")) + (t (:inverse-video t))) "Face for showing the agenda restriction lock." :group 'org-faces) -(defface org-agenda-filter-tags - (org-compatible-face 'mode-line nil) +(defface org-agenda-filter-tags '((t :inherit mode-line)) "Face for tag(s) in the mode-line when filtering the agenda." :group 'org-faces) -(defface org-agenda-filter-regexp - (org-compatible-face 'mode-line nil) +(defface org-agenda-filter-regexp '((t :inherit mode-line)) "Face for regexp(s) in the mode-line when filtering the agenda." :group 'org-faces) -(defface org-agenda-filter-category - (org-compatible-face 'mode-line nil) - "Face for categories(s) in the mode-line when filtering the agenda." +(defface org-agenda-filter-category '((t :inherit mode-line)) + "Face for categories in the mode-line when filtering the agenda." :group 'org-faces) -(defface org-time-grid ;; originally copied from font-lock-variable-name-face - (org-compatible-face nil - '((((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod")) - (((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod")) - (((class color) (min-colors 8)) (:foreground "yellow" :weight light)))) +(defface org-agenda-filter-effort '((t :inherit mode-line)) + "Face for effort in the mode-line when filtering the agenda." + :group 'org-faces) + +(defface org-time-grid ;Copied from `font-lock-variable-name-face' + '((((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod")) + (((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod")) + (((class color) (min-colors 8)) (:foreground "yellow" :weight light))) "Face used for time grids." :group 'org-faces) -(org-copy-face 'org-time-grid 'org-agenda-current-time - "Face used to show the current time in the time grid.") +(defface org-agenda-current-time '((t (:inherit org-time-grid))) + "Face used to show the current time in the time grid." + :group 'org-faces) -(defface org-agenda-diary - (org-compatible-face 'default nil) +(defface org-agenda-diary '((t :inherit default)) "Face used for agenda entries that come from the Emacs diary." :group 'org-faces) -(defface org-agenda-calendar-event - (org-compatible-face 'default nil) +(defface org-agenda-calendar-event '((t :inherit default)) "Face used to show events and appointments in the agenda." :group 'org-faces) -(defface org-agenda-calendar-sexp - (org-compatible-face 'default nil) +(defface org-agenda-calendar-sexp '((t :inherit default)) "Face used to show events computed from a S-expression." :group 'org-faces) (defconst org-level-faces '(org-level-1 org-level-2 org-level-3 org-level-4 - org-level-5 org-level-6 org-level-7 org-level-8 - )) + org-level-5 org-level-6 org-level-7 org-level-8)) (defcustom org-n-level-faces (length org-level-faces) "The number of different faces to be used for headlines. -Org-mode defines 8 different headline faces, so this can be at most 8. +Org mode defines 8 different headline faces, so this can be at most 8. If it is less than 8, the level-1 face gets re-used for level N+1 etc." :type 'integer :group 'org-faces) @@ -777,25 +627,26 @@ level org-n-level-faces" :version "24.4" :package-version '(Org . "8.0")) -(defface org-macro - (org-compatible-face 'org-latex-and-related nil) +(defface org-macro '((t :inherit org-latex-and-related)) "Face for macros." :group 'org-faces :version "24.4" :package-version '(Org . "8.0")) -(defface org-tag-group - (org-compatible-face 'org-tag nil) +(defface org-tag-group '((t :inherit org-tag)) "Face for group tags." :group 'org-faces :version "24.4" :package-version '(Org . "8.0")) -(org-copy-face 'mode-line 'org-mode-line-clock - "Face used for clock display in mode line.") -(org-copy-face 'mode-line 'org-mode-line-clock-overrun +(defface org-mode-line-clock '((t (:inherit mode-line))) + "Face used for clock display in mode line." + :group 'org-faces) + +(defface org-mode-line-clock-overrun + '((t (:inherit mode-line :background "red"))) "Face used for clock display for overrun tasks in mode line." - :background "red") + :group 'org-faces) (provide 'org-faces) diff --git a/lisp/org/org-feed.el b/lisp/org/org-feed.el index cfb4b4f7e33..6ebe5ecf5dc 100644 --- a/lisp/org/org-feed.el +++ b/lisp/org/org-feed.el @@ -1,4 +1,4 @@ -;;; org-feed.el --- Add RSS feed items to Org files +;;; org-feed.el --- Add RSS feed items to Org files -*- lexical-binding: t; -*- ;; ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. ;; @@ -24,11 +24,11 @@ ;; ;;; Commentary: ;; -;; This module allows entries to be created and changed in an Org-mode -;; file triggered by items in an RSS feed. The basic functionality is -;; geared toward simply adding new items found in a feed as outline nodes -;; to an Org file. Using hooks, arbitrary actions can be triggered for -;; new or changed items. +;; This module allows entries to be created and changed in an Org mode +;; file triggered by items in an RSS feed. The basic functionality +;; is geared toward simply adding new items found in a feed as +;; outline nodes to an Org file. Using hooks, arbitrary actions can +;; be triggered for new or changed items. ;; ;; Selecting feeds and target locations ;; ------------------------------------ @@ -77,10 +77,8 @@ ;; org-feed.el needs to keep track of which feed items have been handled ;; before, so that they will not be handled again. For this, org-feed.el ;; stores information in a special drawer, FEEDSTATUS, under the heading -;; that received the input of the feed. You should add FEEDSTATUS -;; to your list of drawers in the files that receive feed input: +;; that received the input of the feed. ;; -;; #+DRAWERS: PROPERTIES CLOCK LOGBOOK RESULTS FEEDSTATUS ;; ;; Acknowledgments ;; --------------- @@ -102,8 +100,8 @@ (declare-function xml-substitute-special "xml" (string)) (declare-function org-capture-escaped-% "org-capture" ()) +(declare-function org-capture-expand-embedded-elisp "org-capture" (&optional mark)) (declare-function org-capture-inside-embedded-elisp-p "org-capture" ()) -(declare-function org-capture-expand-embedded-elisp "org-capture" ()) (defgroup org-feed nil "Options concerning RSS feeds as inputs for Org files." @@ -117,7 +115,9 @@ to create inbox items in Org. Each entry is a list with the following items: name a custom name for this feed URL the Feed URL -file the target Org file where entries should be listed +file the target Org file where entries should be listed, when + nil the target becomes the current buffer (may be an + indirect buffer) each time the feed update is invoked headline the headline under which entries should be listed Additional arguments can be given using keyword-value pairs. Many of these @@ -216,10 +216,7 @@ Here are the keyword-value pair allows in `org-feed-alist'. (defcustom org-feed-drawer "FEEDSTATUS" "The name of the drawer for feed status information. Each feed may also specify its own drawer name using the `:drawer' -parameter in `org-feed-alist'. -Note that in order to make these drawers behave like drawers, they must -be added to the variable `org-drawers' or configured with a #+DRAWERS -line." +parameter in `org-feed-alist'." :group 'org-feed :type '(string :tag "Drawer Name")) @@ -300,7 +297,8 @@ it can be a list structured like an entry in `org-feed-alist'." (catch 'exit (let ((name (car feed)) (url (nth 1 feed)) - (file (nth 2 feed)) + (file (or (nth 2 feed) (buffer-file-name (or (buffer-base-buffer) + (current-buffer))))) (headline (nth 3 feed)) (filter (nth 1 (memq :filter feed))) (formatter (nth 1 (memq :formatter feed))) @@ -315,7 +313,7 @@ it can be a list structured like an entry in `org-feed-alist'." (parse-entry (or (nth 1 (memq :parse-entry feed)) 'org-feed-parse-rss-entry)) feed-buffer inbox-pos new-formatted - entries old-status status new changed guid-alist e guid olds) + entries old-status status new changed guid-alist guid olds) (setq feed-buffer (org-feed-get-feed url)) (unless (and feed-buffer (bufferp (get-buffer feed-buffer))) (error "Cannot get feed %s" name)) @@ -407,8 +405,8 @@ it can be a list structured like an entry in `org-feed-alist'." ;; Normalize the visibility of the inbox tree (goto-char inbox-pos) - (hide-subtree) - (show-children) + (outline-hide-subtree) + (org-show-children) (org-cycle-hide-drawers 'children) ;; Hooks and messages @@ -442,7 +440,7 @@ it can be a list structured like an entry in `org-feed-alist'." (if (stringp feed) (setq feed (assoc feed org-feed-alist))) (unless feed (error "No such feed in `org-feed-alist")) - (org-pop-to-buffer-same-window + (pop-to-buffer-same-window (org-feed-update feed 'retrieve-only)) (goto-char (point-min))) @@ -477,8 +475,7 @@ This will find DRAWER and extract the alist." "Write the feed STATUS to DRAWER in entry at POS." (save-excursion (goto-char pos) - (let ((end (save-excursion (org-end-of-subtree t t))) - guid) + (let ((end (save-excursion (org-end-of-subtree t t)))) (if (re-search-forward (concat "^[ \t]*:" drawer ":[ \t]*\n") end t) (progn @@ -514,66 +511,77 @@ ENTRY is a property list. This function adds a `:formatted-for-org' property and returns the full property list. If that property is already present, nothing changes." (require 'org-capture) - (if formatter - (funcall formatter entry) - (let (dlines time escape name tmp - v-h v-t v-T v-u v-U v-a) - (setq dlines (org-split-string (or (plist-get entry :description) "???") - "\n") - v-h (or (plist-get entry :title) (car dlines) "???") - time (or (if (plist-get entry :pubDate) - (org-read-date t t (plist-get entry :pubDate))) - (current-time)) - v-t (format-time-string (org-time-stamp-format nil nil) time) - v-T (format-time-string (org-time-stamp-format t nil) time) - v-u (format-time-string (org-time-stamp-format nil t) time) - v-U (format-time-string (org-time-stamp-format t t) time) - v-a (if (setq tmp (or (and (plist-get entry :guid-permalink) - (plist-get entry :guid)) - (plist-get entry :link))) - (concat "[[" tmp "]]\n") - "")) + (if formatter (funcall formatter entry) + (let* ((dlines + (org-split-string (or (plist-get entry :description) "???") + "\n")) + (time (or (if (plist-get entry :pubDate) + (org-read-date t t (plist-get entry :pubDate))) + (current-time))) + (v-h (or (plist-get entry :title) (car dlines) "???")) + (v-t (format-time-string (org-time-stamp-format nil nil) time)) + (v-T (format-time-string (org-time-stamp-format t nil) time)) + (v-u (format-time-string (org-time-stamp-format nil t) time)) + (v-U (format-time-string (org-time-stamp-format t t) time)) + (v-a (let ((tmp (or (and (plist-get entry :guid-permalink) + (plist-get entry :guid)) + (plist-get entry :link)))) + (if tmp (format "[[%s]]\n" tmp ) "")))) (with-temp-buffer - (insert template) - - ;; Simple %-escapes - ;; before embedded elisp to support simple %-escapes as - ;; arguments for embedded elisp - (goto-char (point-min)) - (while (re-search-forward "%\\([a-zA-Z]+\\)" nil t) - (unless (org-capture-escaped-%) - (setq name (match-string 1) - escape (org-capture-inside-embedded-elisp-p)) - (cond - ((member name '("h" "t" "T" "u" "U" "a")) - (setq tmp (symbol-value (intern (concat "v-" name))))) - ((setq tmp (plist-get entry (intern (concat ":" name)))) - (save-excursion - (save-match-data - (beginning-of-line 1) - (when (looking-at - (concat "^\\([ \t]*\\)%" name "[ \t]*$")) - (setq tmp (org-feed-make-indented-block - tmp (org-get-indentation)))))))) - (when tmp - ;; escape string delimiters `"' when inside %() embedded lisp - (when escape - (setq tmp (replace-regexp-in-string "\"" "\\\\\"" tmp))) - (replace-match tmp t t)))) - - ;; %() embedded elisp - (org-capture-expand-embedded-elisp) - - (decode-coding-string - (buffer-string) (detect-coding-region (point-min) (point-max) t)))))) + (insert template) + (goto-char (point-min)) + + ;; Mark %() embedded elisp for later evaluation. + (org-capture-expand-embedded-elisp 'mark) + + ;; Simple %-escapes. `org-capture-escaped-%' may modify + ;; buffer and cripple match-data. Use markers instead. + (while (re-search-forward "%\\([a-zA-Z]+\\)" nil t) + (let ((key (match-string 1)) + (beg (copy-marker (match-beginning 0))) + (end (copy-marker (match-end 0)))) + (unless (org-capture-escaped-%) + (delete-region beg end) + (set-marker beg nil) + (set-marker end nil) + (let ((replacement + (pcase key + ("h" v-h) + ("t" v-t) + ("T" v-T) + ("u" v-u) + ("U" v-U) + ("a" v-a) + (name + (let ((v (plist-get entry (intern (concat ":" name))))) + (save-excursion + (save-match-data + (beginning-of-line) + (if (looking-at + (concat "^\\([ \t]*\\)%" name "[ \t]*$")) + (org-feed-make-indented-block + v (org-get-indentation)) + v)))))))) + (when replacement + (insert + ;; Escape string delimiters within embedded lisp. + (if (org-capture-inside-embedded-elisp-p) + (replace-regexp-in-string "\"" "\\\\\"" replacement) + replacement))))))) + + ;; %() embedded elisp + (org-capture-expand-embedded-elisp) + + (decode-coding-string + (buffer-string) (detect-coding-region (point-min) (point-max) t)))))) (defun org-feed-make-indented-block (s n) "Add indentation of N spaces to a multiline string S." (if (not (string-match "\n" s)) s (mapconcat 'identity - (org-split-string s "\n") - (concat "\n" (make-string n ?\ ))))) + (org-split-string s "\n") + (concat "\n" (make-string n ?\ ))))) (defun org-feed-skip-http-headers (buffer) "Remove HTTP headers from BUFFER, and return it. @@ -605,6 +613,7 @@ Assumes headers are indeed present!" "Parse BUFFER for RSS feed entries. Returns a list of entries, with each entry a property list, containing the properties `:guid' and `:item-full-text'." + (require 'xml) (let ((case-fold-search t) entries beg end item guid entry) (with-current-buffer buffer @@ -616,7 +625,7 @@ containing the properties `:guid' and `:item-full-text'." (match-beginning 0))) (setq item (buffer-substring beg end) guid (if (string-match ".*?>\\(.*?\\)" item) - (org-match-string-no-properties 1 item))) + (xml-substitute-special (match-string-no-properties 1 item)))) (setq entry (list :guid guid :item-full-text item)) (push entry entries) (widen) diff --git a/lisp/org/org-footnote.el b/lisp/org/org-footnote.el index 553f1240425..b9f23f144f7 100644 --- a/lisp/org/org-footnote.el +++ b/lisp/org/org-footnote.el @@ -1,4 +1,4 @@ -;;; org-footnote.el --- Footnote support in Org and elsewhere +;;; org-footnote.el --- Footnote support in Org -*- lexical-binding: t; -*- ;; ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. ;; @@ -24,72 +24,68 @@ ;; ;;; Commentary: -;; This file contains the code dealing with footnotes in Org-mode. -;; The code can also be used in arbitrary text modes to provide -;; footnotes. Compared to Steven L Baur's footnote.el it provides -;; better support for resuming editing. It is less configurable than -;; Steve's code, though. +;; This file contains the code dealing with footnotes in Org mode. ;;; Code: -(eval-when-compile - (require 'cl)) +;;;; Declarations + +(require 'cl-lib) (require 'org-macs) (require 'org-compat) -(declare-function message-point-in-header-p "message" ()) +(declare-function org-at-comment-p "org" ()) +(declare-function org-at-heading-p "org" (&optional ignored)) (declare-function org-back-over-empty-lines "org" ()) -(declare-function org-back-to-heading "org" (&optional invisible-ok)) -(declare-function org-combine-plists "org" (&rest plists)) +(declare-function org-edit-footnote-reference "org-src" ()) +(declare-function org-element-at-point "org-element" ()) +(declare-function org-element-class "org-element" (datum &optional parent)) +(declare-function org-element-context "org-element" (&optional element)) +(declare-function org-element-lineage "org-element" (blob &optional types with-self)) +(declare-function org-element-property "org-element" (property element)) +(declare-function org-element-type "org-element" (element)) (declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading)) (declare-function org-fill-paragraph "org" (&optional justify)) -(declare-function org-icompleting-read "org" (&rest args)) -(declare-function org-id-uuid "org-id" ()) (declare-function org-in-block-p "org" (names)) -(declare-function org-in-commented-line "org" ()) -(declare-function org-in-indented-comment-line "org" ()) (declare-function org-in-regexp "org" (re &optional nlines visually)) (declare-function org-in-verbatim-emphasis "org" ()) (declare-function org-inside-LaTeX-fragment-p "org" ()) (declare-function org-inside-latex-macro-p "org" ()) (declare-function org-mark-ring-push "org" (&optional pos buffer)) (declare-function org-show-context "org" (&optional key)) -(declare-function org-trim "org" (s)) -(declare-function org-skip-whitespace "org" ()) +(declare-function org-trim "org" (s &optional keep-lead)) (declare-function outline-next-heading "outline") -(declare-function org-skip-whitespace "org" ()) -(defvar org-outline-regexp-bol) ; defined in org.el -(defvar org-odd-levels-only) ; defined in org.el +(defvar electric-indent-mode) +(defvar org-blank-before-new-entry) ; defined in org.el (defvar org-bracket-link-regexp) ; defined in org.el -(defvar message-cite-prefix-regexp) ; defined in message.el -(defvar message-signature-separator) ; defined in message.el +(defvar org-complex-heading-regexp) ; defined in org.el +(defvar org-odd-levels-only) ; defined in org.el +(defvar org-outline-regexp) ; defined in org.el +(defvar org-outline-regexp-bol) ; defined in org.el + + +;;;; Constants (defconst org-footnote-re - ;; Only [1]-like footnotes are closed in this regexp, as footnotes - ;; from other types might contain square brackets (i.e. links) in - ;; their definition. - ;; - ;; `org-re' is used for regexp compatibility with XEmacs. - (concat "\\[\\(?:" - ;; Match inline footnotes. - (org-re "fn:\\([-_[:word:]]+\\)?:\\|") - ;; Match other footnotes. - "\\(?:\\([0-9]+\\)\\]\\)\\|" - (org-re "\\(fn:[-_[:word:]]+\\)") - "\\)") - "Regular expression for matching footnotes.") - -(defconst org-footnote-definition-re - (org-re "^\\[\\([0-9]+\\|fn:[-_[:word:]]+\\)\\]") - "Regular expression matching the definition of a footnote.") - -(defconst org-footnote-forbidden-blocks - '("ascii" "beamer" "comment" "example" "html" "latex" "odt" "src") + "\\[fn:\\(?:\\(?1:[-_[:word:]]+\\)?\\(:\\)\\|\\(?1:[-_[:word:]]+\\)\\]\\)" + "Regular expression for matching footnotes. +Match group 1 contains footnote's label. It is nil for anonymous +footnotes. Match group 2 is non-nil only when footnote is +inline, i.e., it contains its own definition.") + +(defconst org-footnote-definition-re "^\\[fn:\\([-_[:word:]]+\\)\\]" + "Regular expression matching the definition of a footnote. +Match group 1 contains definition's label.") + +(defconst org-footnote-forbidden-blocks '("comment" "example" "export" "src") "Names of blocks where footnotes are not allowed.") + +;;;; Customization + (defgroup org-footnote nil - "Footnotes in Org-mode." + "Footnotes in Org mode." :tag "Org Footnote" :group 'org) @@ -106,25 +102,21 @@ the notes. However, by hand you may place definitions *anywhere*. If this is a string, during export, all subtrees starting with -this heading will be ignored." - :group 'org-footnote - :type '(choice - (string :tag "Collect footnotes under heading") - (const :tag "Define footnotes locally" nil))) +this heading will be ignored. -(defcustom org-footnote-tag-for-non-org-mode-files "Footnotes:" - "Tag marking the beginning of footnote section. -The Org footnote engine can be used in arbitrary text files as well -as in Org-mode. Outside Org mode, new footnotes are always placed at -the end of the file. When you normalize the notes, any line containing -only this tag will be removed, a new one will be inserted at the end -of the file, followed by the collected and normalized footnotes. +If you don't use the customize interface to change this variable, +you will need to run the following command after the change: -If you don't want any tag in such buffers, set this variable to nil." + `\\[universal-argument] \\[org-element-cache-reset]'" :group 'org-footnote + :initialize 'custom-initialize-default + :set (lambda (var val) + (set var val) + (when (fboundp 'org-element-cache-reset) + (org-element-cache-reset 'all))) :type '(choice - (string :tag "Collect footnotes under tag") - (const :tag "Don't use a tag" nil))) + (string :tag "Collect footnotes under heading") + (const :tag "Define footnotes locally" nil))) (defcustom org-footnote-define-inline nil "Non-nil means define footnotes inline, at reference location. @@ -143,15 +135,13 @@ t Create unique labels of the form [fn:1], [fn:2], etc. confirm Like t, but let the user edit the created value. The label can be removed from the minibuffer to create an anonymous footnote. -random Automatically generate a unique, random label. -plain Automatically create plain number labels like [1]." +random Automatically generate a unique, random label." :group 'org-footnote :type '(choice (const :tag "Prompt for label" nil) (const :tag "Create automatic [fn:N]" t) (const :tag "Offer automatic [fn:N] for editing" confirm) - (const :tag "Create a random label" random) - (const :tag "Create automatic [N]" plain))) + (const :tag "Create a random label" random))) (defcustom org-footnote-auto-adjust nil "Non-nil means automatically adjust footnotes after insert/delete. @@ -179,23 +169,19 @@ extracted will be filled again." :group 'org-footnote :type 'boolean) + +;;;; Predicates + (defun org-footnote-in-valid-context-p () "Is point in a context where footnotes are allowed?" (save-match-data - (not (or (org-in-commented-line) - (org-in-indented-comment-line) + (not (or (org-at-comment-p) (org-inside-LaTeX-fragment-p) ;; Avoid literal example. (org-in-verbatim-emphasis) (save-excursion (beginning-of-line) (looking-at "[ \t]*:[ \t]+")) - ;; Avoid cited text and headers in message-mode. - (and (derived-mode-p 'message-mode) - (or (save-excursion - (beginning-of-line) - (looking-at message-cite-prefix-regexp)) - (message-point-in-header-p))) ;; Avoid forbidden blocks. (org-in-block-p org-footnote-forbidden-blocks))))) @@ -208,13 +194,9 @@ positions, and the definition, when inlined." (or (looking-at org-footnote-re) (org-in-regexp org-footnote-re) (save-excursion (re-search-backward org-footnote-re nil t))) - (/= (match-beginning 0) (point-at-bol))) + (/= (match-beginning 0) (line-beginning-position))) (let* ((beg (match-beginning 0)) - (label (or (org-match-string-no-properties 2) - (org-match-string-no-properties 3) - ;; Anonymous footnotes don't have labels - (and (match-string 1) - (concat "fn:" (org-match-string-no-properties 1))))) + (label (match-string-no-properties 1)) ;; Inline footnotes don't end at (match-end 0) as ;; `org-footnote-re' stops just after the second colon. ;; Find the real ending with `scan-sexps', so Org doesn't @@ -222,7 +204,8 @@ positions, and the definition, when inlined." (end (ignore-errors (scan-sexps beg 1)))) ;; Point is really at a reference if it's located before true ;; ending of the footnote. - (when (and end (< (point) end) + (when (and end + (< (point) end) ;; Verify match isn't a part of a link. (not (save-excursion (goto-char beg) @@ -234,16 +217,17 @@ positions, and the definition, when inlined." (not (org-inside-latex-macro-p))) (list label beg end ;; Definition: ensure this is an inline footnote first. - (and (or (not label) (match-string 1)) - (org-trim (buffer-substring-no-properties - (match-end 0) (1- end))))))))) + (and (match-end 2) + (org-trim + (buffer-substring-no-properties + (match-end 0) (1- end))))))))) (defun org-footnote-at-definition-p () "Is point within a footnote definition? This matches only pure definitions like [1] or [fn:name] at the beginning of a line. It does not match references like -[fn:name:definition], where the footnote text is included and +\[fn:name:definition], where the footnote text is included and defined locally. The return value will be nil if not at a footnote definition, and @@ -259,26 +243,224 @@ otherwise." (concat org-outline-regexp-bol "\\|^\\([ \t]*\n\\)\\{2,\\}") nil t)))) (when (re-search-backward org-footnote-definition-re lim t) - (let ((label (org-match-string-no-properties 1)) + (let ((label (match-string-no-properties 1)) (beg (match-beginning 0)) (beg-def (match-end 0)) - ;; In message-mode, do not search after signature. - (end (let ((bound (and (derived-mode-p 'message-mode) - (save-excursion - (goto-char (point-max)) - (re-search-backward - message-signature-separator nil t))))) - (if (progn - (end-of-line) - (re-search-forward - (concat org-outline-regexp-bol "\\|" - org-footnote-definition-re "\\|" - "^\\([ \t]*\n\\)\\{2,\\}") bound 'move)) - (match-beginning 0) - (point))))) + (end (if (progn + (end-of-line) + (re-search-forward + (concat org-outline-regexp-bol "\\|" + org-footnote-definition-re "\\|" + "^\\([ \t]*\n\\)\\{2,\\}") nil 'move)) + (match-beginning 0) + (point)))) (list label beg end (org-trim (buffer-substring-no-properties beg-def end))))))))) + +;;;; Internal functions + +(defun org-footnote--allow-reference-p () + "Non-nil when a footnote reference can be inserted at point." + ;; XXX: This is similar to `org-footnote-in-valid-context-p' but + ;; more accurate and usually faster, except in some corner cases. + ;; It may replace it after doing proper benchmarks as it would be + ;; used in fontification. + (unless (bolp) + (let* ((context (org-element-context)) + (type (org-element-type context))) + (cond + ;; No footnote reference in attributes. + ((let ((post (org-element-property :post-affiliated context))) + (and post (< (point) post))) + nil) + ;; Paragraphs and blank lines at top of document are fine. + ((memq type '(nil paragraph))) + ;; So are contents of verse blocks. + ((eq type 'verse-block) + (and (>= (point) (org-element-property :contents-begin context)) + (< (point) (org-element-property :contents-end context)))) + ;; In an headline or inlinetask, point must be either on the + ;; heading itself or on the blank lines below. + ((memq type '(headline inlinetask)) + (or (not (org-at-heading-p)) + (and (save-excursion + (beginning-of-line) + (and (let ((case-fold-search t)) + (not (looking-at-p "\\*+ END[ \t]*$"))) + (let ((case-fold-search nil)) + (looking-at org-complex-heading-regexp)))) + (match-beginning 4) + (>= (point) (match-beginning 4)) + (or (not (match-beginning 5)) + (< (point) (match-beginning 5)))))) + ;; White spaces after an object or blank lines after an element + ;; are OK. + ((>= (point) + (save-excursion (goto-char (org-element-property :end context)) + (skip-chars-backward " \r\t\n") + (if (eq (org-element-class context) 'object) (point) + (1+ (line-beginning-position 2)))))) + ;; Other elements are invalid. + ((eq (org-element-class context) 'element) nil) + ;; Just before object is fine. + ((= (point) (org-element-property :begin context))) + ;; Within recursive object too, but not in a link. + ((eq type 'link) nil) + ((let ((cbeg (org-element-property :contents-begin context)) + (cend (org-element-property :contents-end context))) + (and cbeg (>= (point) cbeg) (<= (point) cend)))))))) + +(defun org-footnote--clear-footnote-section () + "Remove all footnote sections in buffer and create a new one. +New section is created at the end of the buffer, before any file +local variable definition. Leave point within the new section." + (when org-footnote-section + (goto-char (point-min)) + (let ((regexp + (format "^\\*+ +%s[ \t]*$" + (regexp-quote org-footnote-section)))) + (while (re-search-forward regexp nil t) + (delete-region + (match-beginning 0) + (progn (org-end-of-subtree t t) + (if (not (eobp)) (point) + (org-footnote--goto-local-insertion-point) + (skip-chars-forward " \t\n") + (if (eobp) (point) (line-beginning-position))))))) + (goto-char (point-max)) + (org-footnote--goto-local-insertion-point) + (when (and (cdr (assq 'heading org-blank-before-new-entry)) + (zerop (save-excursion (org-back-over-empty-lines)))) + (insert "\n")) + (insert "* " org-footnote-section "\n"))) + +(defun org-footnote--set-label (label) + "Set label of footnote at point to string LABEL. +Assume point is at the beginning of the reference or definition +to rename." + (forward-char 4) + (cond ((eq (char-after) ?:) (insert label)) + ((looking-at "\\([-_[:word:]]+\\)") (replace-match label nil nil nil 1)) + (t nil))) + +(defun org-footnote--collect-references (&optional anonymous) + "Collect all labeled footnote references in current buffer. + +Return an alist where associations follow the pattern + + (LABEL MARKER TOP-LEVEL SIZE) + +with + + LABEL the label of the of the definition, + MARKER a marker pointing to its beginning, + TOP-LEVEL a boolean, nil when the footnote is contained within + another one, + SIZE the length of the inline definition, in characters, + or nil for non-inline references. + +When optional ANONYMOUS is non-nil, also collect anonymous +references. In such cases, LABEL is nil. + +References are sorted according to a deep-reading order." + (org-with-wide-buffer + (goto-char (point-min)) + (let ((regexp (if anonymous org-footnote-re "\\[fn:[-_[:word:]]+[]:]")) + references nested) + (save-excursion + (while (re-search-forward regexp nil t) + ;; Ignore definitions. + (unless (and (eq (char-before) ?\]) + (= (line-beginning-position) (match-beginning 0))) + ;; Ensure point is within the reference before parsing it. + (backward-char) + (let ((object (org-element-context))) + (when (eq (org-element-type object) 'footnote-reference) + (let* ((label (org-element-property :label object)) + (begin (org-element-property :begin object)) + (size + (and (eq (org-element-property :type object) 'inline) + (- (org-element-property :contents-end object) + (org-element-property :contents-begin object))))) + (let ((d (org-element-lineage object '(footnote-definition)))) + (push (list label (copy-marker begin) (not d) size) + references) + (when d + ;; Nested references are stored in alist NESTED. + ;; Associations there follow the pattern + ;; + ;; (DEFINITION-LABEL . REFERENCES) + (let* ((def-label (org-element-property :label d)) + (labels (assoc def-label nested))) + (if labels (push label (cdr labels)) + (push (list def-label label) nested))))))))))) + ;; Sort the list of references. Nested footnotes have priority + ;; over top-level ones. + (letrec ((ordered nil) + (add-reference + (lambda (ref allow-nested) + (when (or allow-nested (nth 2 ref)) + (push ref ordered) + (dolist (r (mapcar (lambda (l) (assoc l references)) + (reverse + (cdr (assoc (nth 0 ref) nested))))) + (funcall add-reference r t)))))) + (dolist (r (reverse references) (nreverse ordered)) + (funcall add-reference r nil)))))) + +(defun org-footnote--collect-definitions (&optional delete) + "Collect all footnote definitions in current buffer. + +Return an alist where associations follow the pattern + + (LABEL . DEFINITION) + +with LABEL and DEFINITION being, respectively, the label and the +definition of the footnote, as strings. + +When optional argument DELETE is non-nil, delete the definition +while collecting them." + (org-with-wide-buffer + (goto-char (point-min)) + (let (definitions seen) + (while (re-search-forward org-footnote-definition-re nil t) + (backward-char) + (let ((element (org-element-at-point))) + (let ((label (org-element-property :label element))) + (when (and (eq (org-element-type element) 'footnote-definition) + (not (member label seen))) + (push label seen) + (let* ((beg (progn + (goto-char (org-element-property :begin element)) + (skip-chars-backward " \r\t\n") + (if (bobp) (point) (line-beginning-position 2)))) + (end (progn + (goto-char (org-element-property :end element)) + (skip-chars-backward " \r\t\n") + (line-beginning-position 2))) + (def (org-trim (buffer-substring-no-properties beg end)))) + (push (cons label def) definitions) + (when delete (delete-region beg end))))))) + definitions))) + +(defun org-footnote--goto-local-insertion-point () + "Find insertion point for footnote, just before next outline heading. +Assume insertion point is within currently accessible part of the buffer." + (org-with-limited-levels (outline-next-heading)) + ;; Skip file local variables. See `modify-file-local-variable'. + (when (eobp) + (let ((case-fold-search t)) + (re-search-backward "^[ \t]*# +Local Variables:" + (max (- (point-max) 3000) (point-min)) + t))) + (skip-chars-backward " \t\n") + (forward-line) + (unless (bolp) (insert "\n"))) + + +;;;; Navigation + (defun org-footnote-get-next-reference (&optional label backward limit) "Return complete reference of the next footnote. @@ -289,7 +471,7 @@ the buffer position bounding the search. Return value is a list like those provided by `org-footnote-at-reference-p'. If no footnote is found, return nil." (save-excursion - (let* ((label-fmt (if label (format "\\[%s[]:]" label) org-footnote-re))) + (let* ((label-fmt (if label (format "\\[fn:%s[]:]" label) org-footnote-re))) (catch 'exit (while t (unless (funcall (if backward #'re-search-backward #'re-search-forward) @@ -313,59 +495,54 @@ If no footnote is found, return nil." (unless (re-search-forward org-footnote-re limit t) (goto-char origin) (throw 'exit nil)) - ;; Beware: with [1]-like footnotes point will be just after + ;; Beware: with non-inline footnotes point will be just after ;; the closing square bracket. (backward-char) (cond ((setq ref (org-footnote-at-reference-p)) (throw 'exit ref)) - ;; Definition: also grab the last square bracket, only - ;; matched in `org-footnote-re' for [1]-like footnotes. + ;; Definition: also grab the last square bracket, matched in + ;; `org-footnote-re' for non-inline footnotes. ((save-match-data (org-footnote-at-definition-p)) (let ((end (match-end 0))) (throw 'exit (list nil (match-beginning 0) - (if (eq (char-before end) 93) end (1+ end))))))))))) + (if (eq (char-before end) ?\]) end (1+ end))))))))))) -(defun org-footnote-get-definition (label) - "Return label, boundaries and definition of the footnote LABEL." - (let* ((label (regexp-quote (org-footnote-normalize-label label))) - (re (format "^\\[%s\\]\\|.\\[%s:" label label)) - pos) - (save-excursion - (save-restriction - (when (or (re-search-forward re nil t) - (and (goto-char (point-min)) - (re-search-forward re nil t)) - (and (progn (widen) t) - (goto-char (point-min)) - (re-search-forward re nil t))) - (let ((refp (org-footnote-at-reference-p))) - (cond - ((and (nth 3 refp) refp)) - ((org-footnote-at-definition-p))))))))) - -(defun org-footnote-goto-definition (label) +(defun org-footnote-goto-definition (label &optional location) "Move point to the definition of the footnote LABEL. -Return a non-nil value when a definition has been found." + +LOCATION, when non-nil specifies the buffer position of the +definition. + +Throw an error if there is no definition or if it cannot be +reached from current narrowed part of buffer. Return a non-nil +value if point was successfully moved." (interactive "sLabel: ") - (org-mark-ring-push) - (let ((def (org-footnote-get-definition label))) - (if (not def) - (error "Cannot find definition of footnote %s" label) - (goto-char (nth 1 def)) - (looking-at (format "\\[%s\\]\\|\\[%s:" label label)) - (goto-char (match-end 0)) - (org-show-context 'link-search) - (when (derived-mode-p 'org-mode) - (message "Edit definition and go back with `C-c &' or, if unique, with `C-c C-c'.")) - t))) + (let* ((label (org-footnote-normalize-label label)) + (def-start (or location (nth 1 (org-footnote-get-definition label))))) + (cond + ((not def-start) + (user-error "Cannot find definition of footnote %s" label)) + ((or (> def-start (point-max)) (< def-start (point-min))) + (user-error "Definition is outside narrowed part of buffer"))) + (org-mark-ring-push) + (goto-char def-start) + (looking-at (format "\\[fn:%s[]:] ?" (regexp-quote label))) + (goto-char (match-end 0)) + (org-show-context 'link-search) + (when (derived-mode-p 'org-mode) + (message "%s" (substitute-command-keys + "Edit definition and go back with \ +`\\[org-mark-ring-goto]' or, if unique, with `\\[org-ctrl-c-ctrl-c]'."))) + t)) (defun org-footnote-goto-previous-reference (label) "Find the first closest (to point) reference of footnote with label LABEL." (interactive "sLabel: ") (org-mark-ring-push) - (let* ((label (org-footnote-normalize-label label)) ref) + (let ((label (org-footnote-normalize-label label)) + ref) (save-excursion (setq ref (or (org-footnote-get-next-reference label t) (org-footnote-get-next-reference label) @@ -379,62 +556,74 @@ Return a non-nil value when a definition has been found." (goto-char (nth 1 ref)) (org-show-context 'link-search)))) + +;;;; Getters + (defun org-footnote-normalize-label (label) - "Return LABEL as an appropriate string." - (cond - ((numberp label) (number-to-string label)) - ((equal "" label) nil) - ((not (string-match "^[0-9]+$\\|^fn:" label)) - (concat "fn:" label)) - (t label))) - -(defun org-footnote-all-labels (&optional with-defs) - "Return list with all defined foot labels used in the buffer. - -If WITH-DEFS is non-nil, also associate the definition to each -label. The function will then return an alist whose key is label -and value definition." - (let* (rtn - (push-to-rtn - (function - ;; Depending on WITH-DEFS, store label or (label . def) of - ;; footnote reference/definition given as argument in RTN. - (lambda (el) - (let ((lbl (car el))) - (push (if with-defs (cons lbl (nth 3 el)) lbl) rtn)))))) - (save-excursion - (save-restriction - (widen) - ;; Find all labels found in definitions. - (goto-char (point-min)) - (let (def) - (while (re-search-forward org-footnote-definition-re nil t) - (when (setq def (org-footnote-at-definition-p)) - (funcall push-to-rtn def)))) - ;; Find all labels found in references. - (goto-char (point-min)) - (let (ref) - (while (setq ref (org-footnote-get-next-reference)) - (goto-char (nth 2 ref)) - (and (car ref) ; ignore anonymous footnotes - (not (funcall (if with-defs #'assoc #'member) (car ref) rtn)) - (funcall push-to-rtn ref)))))) - rtn)) + "Return LABEL without \"fn:\" prefix. +If LABEL is the empty string or constituted of white spaces only, +return nil instead." + (pcase (org-trim label) + ("" nil) + ((pred (string-prefix-p "fn:")) (substring label 3)) + (_ label))) + +(defun org-footnote-get-definition (label) + "Return label, boundaries and definition of the footnote LABEL." + (let* ((label (regexp-quote (org-footnote-normalize-label label))) + (re (format "^\\[fn:%s\\]\\|.\\[fn:%s:" label label))) + (org-with-wide-buffer + (goto-char (point-min)) + (catch 'found + (while (re-search-forward re nil t) + (let* ((datum (progn (backward-char) (org-element-context))) + (type (org-element-type datum))) + (when (memq type '(footnote-definition footnote-reference)) + (throw 'found + (list + label + (org-element-property :begin datum) + (org-element-property :end datum) + (let ((cbeg (org-element-property :contents-begin datum))) + (if (not cbeg) "" + (replace-regexp-in-string + "[ \t\n]*\\'" + "" + (buffer-substring-no-properties + cbeg + (org-element-property :contents-end datum)))))))))) + nil)))) + +(defun org-footnote-all-labels () + "List all defined footnote labels used throughout the buffer. +This function ignores narrowing, if any." + (org-with-wide-buffer + (goto-char (point-min)) + (let (all) + (while (re-search-forward org-footnote-re nil t) + (backward-char) + (let ((context (org-element-context))) + (when (memq (org-element-type context) + '(footnote-definition footnote-reference)) + (let ((label (org-element-property :label context))) + (when label (cl-pushnew label all :test #'equal)))))) + all))) (defun org-footnote-unique-label (&optional current) "Return a new unique footnote label. -The function returns the first \"fn:N\" or \"N\" label that is -currently not used. +The function returns the first numeric label currently unused. Optional argument CURRENT is the list of labels active in the buffer." - (unless current (setq current (org-footnote-all-labels))) - (let ((fmt (if (eq org-footnote-auto-label 'plain) "%d" "fn:%d")) - (cnt 1)) - (while (member (format fmt cnt) current) - (incf cnt)) - (format fmt cnt))) + (let ((current (or current (org-footnote-all-labels)))) + (let ((count 1)) + (while (member (number-to-string count) current) + (cl-incf count)) + (number-to-string count)))) + + +;;;; Adding, Deleting Footnotes (defun org-footnote-new () "Insert a new footnote. @@ -442,343 +631,66 @@ This command prompts for a label. If this is a label referencing an existing label, only insert the label. If the footnote label is empty or new, let the user edit the definition of the footnote." (interactive) - (unless (org-footnote-in-valid-context-p) - (error "Cannot insert a footnote here")) - (let* ((lbls (and (not (equal org-footnote-auto-label 'random)) - (org-footnote-all-labels))) - (propose (and (not (equal org-footnote-auto-label 'random)) - (org-footnote-unique-label lbls))) + (unless (org-footnote--allow-reference-p) + (user-error "Cannot insert a footnote here")) + (let* ((all (org-footnote-all-labels)) (label - (org-footnote-normalize-label - (cond - ((member org-footnote-auto-label '(t plain)) - propose) - ((equal org-footnote-auto-label 'random) - (require 'org-id) - (substring (org-id-uuid) 0 8)) - (t - (org-icompleting-read - "Label (leave empty for anonymous): " - (mapcar 'list lbls) nil nil - (if (eq org-footnote-auto-label 'confirm) propose nil))))))) - (cond - ((bolp) (error "Cannot create a footnote reference at left margin")) - ((not label) - (insert "[fn:: ]") - (backward-char 1)) - ((member label lbls) - (insert "[" label "]") - (message "New reference to existing note")) - (org-footnote-define-inline - (insert "[" label ": ]") - (backward-char 1) - (org-footnote-auto-adjust-maybe)) - (t - (insert "[" label "]") - (org-footnote-create-definition label) - (org-footnote-auto-adjust-maybe))))) - -(defvar org-blank-before-new-entry) ; silence byte-compiler + (if (eq org-footnote-auto-label 'random) + (format "%x" (random most-positive-fixnum)) + (org-footnote-normalize-label + (let ((propose (org-footnote-unique-label all))) + (if (eq org-footnote-auto-label t) propose + (completing-read + "Label (leave empty for anonymous): " + (mapcar #'list all) nil nil + (and (eq org-footnote-auto-label 'confirm) propose)))))))) + (cond ((not label) + (insert "[fn::]") + (backward-char 1)) + ((member label all) + (insert "[fn:" label "]") + (message "New reference to existing note")) + (org-footnote-define-inline + (insert "[fn:" label ":]") + (backward-char 1) + (org-footnote-auto-adjust-maybe)) + (t + (insert "[fn:" label "]") + (let ((p (org-footnote-create-definition label))) + ;; `org-footnote-goto-definition' needs to be called + ;; after `org-footnote-auto-adjust-maybe'. Otherwise + ;; both label and location of the definition are lost. + ;; On the contrary, it needs to be called before + ;; `org-edit-footnote-reference' so that the remote + ;; editing buffer can display the correct label. + (if (ignore-errors (org-footnote-goto-definition label p)) + (org-footnote-auto-adjust-maybe) + ;; Definition was created outside current scope: edit + ;; it remotely. + (org-footnote-auto-adjust-maybe) + (org-edit-footnote-reference))))))) + (defun org-footnote-create-definition (label) - "Start the definition of a footnote with label LABEL." - (interactive "sLabel: ") + "Start the definition of a footnote with label LABEL. +Return buffer position at the beginning of the definition. This +function doesn't move point." (let ((label (org-footnote-normalize-label label)) - electric-indent-mode) ;; Prevent wrong indentation - (cond - ;; In an Org file. - ((derived-mode-p 'org-mode) - ;; If `org-footnote-section' is defined, find it, or create it - ;; at the end of the buffer. - (when org-footnote-section - (goto-char (point-min)) - (let ((re (concat "^\\*+[ \t]+" org-footnote-section "[ \t]*$"))) - (unless (or (re-search-forward re nil t) - (and (progn (widen) t) - (re-search-forward re nil t))) - (goto-char (point-max)) - (skip-chars-backward " \t\r\n") - (unless (bolp) (newline)) - ;; Insert new section. Separate it from the previous one - ;; with a blank line, unless `org-blank-before-new-entry' - ;; explicitly says no. - (when (and (cdr (assq 'heading org-blank-before-new-entry)) - (zerop (save-excursion (org-back-over-empty-lines)))) - (insert "\n")) - (insert "* " org-footnote-section "\n")))) - ;; Move to the end of this entry (which may be - ;; `org-footnote-section' or the current one). - (org-footnote-goto-local-insertion-point) - (org-show-context 'link-search)) - (t - ;; In a non-Org file. Search for footnote tag, or create it if - ;; specified (at the end of buffer, or before signature if in - ;; Message mode). Set point after any definition already there. - (let ((tag (and org-footnote-tag-for-non-org-mode-files - (concat "^" (regexp-quote - org-footnote-tag-for-non-org-mode-files) - "[ \t]*$"))) - (max (if (and (derived-mode-p 'message-mode) - (goto-char (point-max)) - (re-search-backward - message-signature-separator nil t)) - (progn - ;; Ensure one blank line separates last - ;; footnote from signature. - (beginning-of-line) - (open-line 2) - (point-marker)) - (point-max-marker)))) - (set-marker-insertion-type max t) - (goto-char max) - ;; Check if the footnote tag is defined but missing. In this - ;; case, insert it, before any footnote or one blank line - ;; after any previous text. - (when (and tag (not (re-search-backward tag nil t))) - (skip-chars-backward " \t\r\n") - (while (re-search-backward org-footnote-definition-re nil t)) - (unless (bolp) (newline 2)) - (insert org-footnote-tag-for-non-org-mode-files "\n\n")) - ;; Remove superfluous white space and clear marker. - (goto-char max) - (skip-chars-backward " \t\r\n") - (delete-region (point) max) - (unless (bolp) (newline)) - (set-marker max nil)))) - ;; Insert footnote label. - (when (zerop (org-back-over-empty-lines)) (newline)) - (insert "[" label "] \n") - (backward-char) - ;; Only notify user about next possible action when in an Org - ;; buffer, as the bindings may have different meanings otherwise. - (when (derived-mode-p 'org-mode) - (message - "Edit definition and go back with `C-c &' or, if unique, with `C-c C-c'.")))) - -;;;###autoload -(defun org-footnote-action (&optional special) - "Do the right thing for footnotes. - -When at a footnote reference, jump to the definition. - -When at a definition, jump to the references if they exist, offer -to create them otherwise. - -When neither at definition or reference, create a new footnote, -interactively. - -With prefix arg SPECIAL, offer additional commands in a menu." - (interactive "P") - (let (tmp c) - (cond - (special - (message "Footnotes: [s]ort | [r]enumber fn:N | [S]=r+s |->[n]umeric | [d]elete") - (setq c (read-char-exclusive)) - (cond - ((eq c ?s) (org-footnote-normalize 'sort)) - ((eq c ?r) (org-footnote-renumber-fn:N)) - ((eq c ?S) - (org-footnote-renumber-fn:N) - (org-footnote-normalize 'sort)) - ((eq c ?n) (org-footnote-normalize)) - ((eq c ?d) (org-footnote-delete)) - (t (error "No such footnote command %c" c)))) - ((setq tmp (org-footnote-at-reference-p)) - (cond - ;; Anonymous footnote: move point at the beginning of its - ;; definition. - ((not (car tmp)) - (goto-char (nth 1 tmp)) - (forward-char 5)) - ;; A definition exists: move to it. - ((ignore-errors (org-footnote-goto-definition (car tmp)))) - ;; No definition exists: offer to create it. - ((yes-or-no-p (format "No definition for %s. Create one? " (car tmp))) - (org-footnote-create-definition (car tmp))))) - ((setq tmp (org-footnote-at-definition-p)) - (org-footnote-goto-previous-reference (car tmp))) - (t (org-footnote-new))))) - -;;;###autoload -(defun org-footnote-normalize (&optional sort-only) - "Collect the footnotes in various formats and normalize them. - -This finds the different sorts of footnotes allowed in Org, and -normalizes them to the usual [N] format. - -When SORT-ONLY is set, only sort the footnote definitions into the -referenced sequence." - ;; This is based on Paul's function, but rewritten. - ;; - ;; Re-create `org-with-limited-levels', but not limited to Org - ;; buffers. - (let* ((limit-level - (and (boundp 'org-inlinetask-min-level) - org-inlinetask-min-level - (1- org-inlinetask-min-level))) - (nstars (and limit-level - (if org-odd-levels-only (1- (* limit-level 2)) - limit-level))) - (org-outline-regexp - (concat "\\*" (if nstars (format "\\{1,%d\\} " nstars) "+ "))) - (count 0) - ins-point ref ref-table) - (save-excursion - ;; 1. Find every footnote reference, extract the definition, and - ;; collect that data in REF-TABLE. If SORT-ONLY is nil, also - ;; normalize references. - (goto-char (point-min)) - (while (setq ref (org-footnote-get-next-reference)) - (let* ((lbl (car ref)) - (pos (nth 1 ref)) - ;; When footnote isn't anonymous, check if it's label - ;; (REF) is already stored in REF-TABLE. In that case, - ;; extract number used to identify it (MARKER). If - ;; footnote is unknown, increment the global counter - ;; (COUNT) to create an unused identifier. - (a (and lbl (assoc lbl ref-table))) - (marker (or (nth 1 a) (incf count))) - ;; Is the reference inline or pointing to an inline - ;; footnote? - (inlinep (or (stringp (nth 3 ref)) (nth 3 a)))) - ;; Replace footnote reference with [MARKER]. Maybe fill - ;; paragraph once done. If SORT-ONLY is non-nil, only move - ;; to the end of reference found to avoid matching it twice. - (if sort-only (goto-char (nth 2 ref)) - (delete-region (nth 1 ref) (nth 2 ref)) - (goto-char (nth 1 ref)) - (insert (format "[%d]" marker)) - (and inlinep - org-footnote-fill-after-inline-note-extraction - (org-fill-paragraph))) - ;; Add label (REF), identifier (MARKER), definition (DEF) - ;; type (INLINEP) and position (POS) to REF-TABLE if data - ;; was unknown. - (unless a - (let ((def (or (nth 3 ref) ; Inline definition. - (nth 3 (org-footnote-get-definition lbl))))) - (push (list lbl marker def - ;; Reference beginning position is a marker - ;; to preserve it during further buffer - ;; modifications. - inlinep (copy-marker pos)) ref-table))))) - ;; 2. Find and remove the footnote section, if any. Also - ;; determine where footnotes shall be inserted (INS-POINT). - (cond - ((and org-footnote-section (derived-mode-p 'org-mode)) - (goto-char (point-min)) - (if (re-search-forward - (concat "^\\*[ \t]+" (regexp-quote org-footnote-section) - "[ \t]*$") nil t) - (delete-region (match-beginning 0) (org-end-of-subtree t t))) - ;; A new footnote section is inserted by default at the end of - ;; the buffer. - (goto-char (point-max)) - (skip-chars-backward " \r\t\n") - (forward-line) - (unless (bolp) (newline))) - ;; No footnote section set: Footnotes will be added at the end - ;; of the section containing their first reference. - ((derived-mode-p 'org-mode)) - (t - ;; Remove any left-over tag in the buffer, if one is set up. - (when org-footnote-tag-for-non-org-mode-files - (let ((tag (concat "^" (regexp-quote - org-footnote-tag-for-non-org-mode-files) - "[ \t]*$"))) - (goto-char (point-min)) - (while (re-search-forward tag nil t) - (replace-match "") - (delete-region (point) (progn (forward-line) (point)))))) - ;; In Message mode, ensure footnotes are inserted before the - ;; signature. - (if (and (derived-mode-p 'message-mode) - (goto-char (point-max)) - (re-search-backward message-signature-separator nil t)) - (beginning-of-line) - (goto-char (point-max))))) - (setq ins-point (point-marker)) - ;; 3. Clean-up REF-TABLE. - (setq ref-table - (delq nil - (mapcar - (lambda (x) - (cond - ;; When only sorting, ignore inline footnotes. - ;; Also clear position marker. - ((and sort-only (nth 3 x)) - (set-marker (nth 4 x) nil) nil) - ;; No definition available: provide one. - ((not (nth 2 x)) - (append - (list (car x) (nth 1 x) - (format "DEFINITION NOT FOUND: %s" (car x))) - (nthcdr 3 x))) - (t x))) - ref-table))) - (setq ref-table (nreverse ref-table)) - ;; 4. Remove left-over definitions in the buffer. - (mapc (lambda (x) - (unless (nth 3 x) (org-footnote-delete-definitions (car x)))) - ref-table) - ;; 5. Insert the footnotes again in the buffer, at the - ;; appropriate spot. - (goto-char ins-point) - (cond - ;; No footnote: exit. - ((not ref-table)) - ;; Cases when footnotes should be inserted in one place. - ((or (not (derived-mode-p 'org-mode)) org-footnote-section) - ;; Insert again the section title, if any. Ensure that title, - ;; or the subsequent footnotes, will be separated by a blank - ;; lines from the rest of the document. In an Org buffer, - ;; separate section with a blank line, unless explicitly - ;; stated in `org-blank-before-new-entry'. - (if (not (derived-mode-p 'org-mode)) - (progn (skip-chars-backward " \t\n\r") - (delete-region (point) ins-point) - (unless (bolp) (newline)) - (when org-footnote-tag-for-non-org-mode-files - (insert "\n" org-footnote-tag-for-non-org-mode-files "\n"))) - (when (and (cdr (assq 'heading org-blank-before-new-entry)) - (zerop (save-excursion (org-back-over-empty-lines)))) - (insert "\n")) - (insert "* " org-footnote-section "\n")) - (set-marker ins-point nil) - ;; Insert the footnotes, separated by a blank line. - (insert - (mapconcat - (lambda (x) - ;; Clean markers. - (set-marker (nth 4 x) nil) - (format "\n[%s] %s" (nth (if sort-only 0 1) x) (nth 2 x))) - ref-table "\n")) - (unless (eobp) (insert "\n\n"))) - ;; Each footnote definition has to be inserted at the end of - ;; the section where its first reference belongs. - (t - (mapc - (lambda (x) - (let ((pos (nth 4 x))) - (goto-char pos) - ;; Clean marker. - (set-marker pos nil)) - (org-footnote-goto-local-insertion-point) - (insert (format "\n[%s] %s\n" - (if sort-only (car x) (nth 1 x)) - (nth 2 x)))) - ref-table)))))) - -(defun org-footnote-goto-local-insertion-point () - "Find insertion point for footnote, just before next outline heading." - (org-with-limited-levels (outline-next-heading)) - (or (bolp) (newline)) - (beginning-of-line 0) - (while (and (not (bobp)) (= (char-after) ?#)) - (beginning-of-line 0)) - (if (let ((case-fold-search t)) (looking-at "[ \t]*#\\+tblfm:")) (beginning-of-line 2)) - (end-of-line 1) - (skip-chars-backward "\n\r\t ") - (forward-line)) + electric-indent-mode) ; Prevent wrong indentation. + (org-with-wide-buffer + (cond + ((not org-footnote-section) (org-footnote--goto-local-insertion-point)) + ((save-excursion + (goto-char (point-min)) + (re-search-forward + (concat "^\\*+[ \t]+" (regexp-quote org-footnote-section) "[ \t]*$") + nil t)) + (goto-char (match-end 0)) + (forward-line) + (unless (bolp) (insert "\n"))) + (t (org-footnote--clear-footnote-section))) + (when (zerop (org-back-over-empty-lines)) (insert "\n")) + (insert "[fn:" label "] \n") + (line-beginning-position 0)))) (defun org-footnote-delete-references (label) "Delete every reference to footnote LABEL. @@ -789,7 +701,7 @@ Return the number of footnotes removed." (while (setq ref (org-footnote-get-next-reference label)) (goto-char (nth 1 ref)) (delete-region (nth 1 ref) (nth 2 ref)) - (incf nref)) + (cl-incf nref)) nref))) (defun org-footnote-delete-definitions (label) @@ -797,17 +709,21 @@ Return the number of footnotes removed." Return the number of footnotes removed." (save-excursion (goto-char (point-min)) - (let ((def-re (concat "^\\[" (regexp-quote label) "\\]")) + (let ((def-re (format "^\\[fn:%s\\]" (regexp-quote label))) (ndef 0)) (while (re-search-forward def-re nil t) - (let ((full-def (org-footnote-at-definition-p))) - (when full-def - ;; Remove the footnote, and all blank lines before it. - (goto-char (nth 1 full-def)) - (skip-chars-backward " \r\t\n") - (unless (bolp) (forward-line)) - (delete-region (point) (nth 2 full-def)) - (incf ndef)))) + (pcase (org-footnote-at-definition-p) + (`(,_ ,start ,end ,_) + ;; Remove the footnote, and all blank lines before it. + (delete-region (progn + (goto-char start) + (skip-chars-backward " \r\t\n") + (if (bobp) (point) (line-beginning-position 2))) + (progn + (goto-char end) + (skip-chars-backward " \r\t\n") + (if (bobp) (point) (line-beginning-position 2)))) + (cl-incf ndef)))) ndef))) (defun org-footnote-delete (&optional label) @@ -843,24 +759,165 @@ If LABEL is non-nil, delete that footnote instead." (message "%d definition(s) of and %d reference(s) of footnote %s removed" ndef nref label)))) + +;;;; Sorting, Renumbering, Normalizing + (defun org-footnote-renumber-fn:N () - "Renumber the simple footnotes like fn:17 into a sequence in the document." + "Order numbered footnotes into a sequence in the document." (interactive) - (let (map (n 0)) - (org-with-wide-buffer - (goto-char (point-min)) - (while (re-search-forward "\\[fn:\\([0-9]+\\)[]:]" nil t) - (save-excursion - (goto-char (match-beginning 0)) - ;; Ensure match is a footnote reference or definition. - (when (save-match-data (if (bolp) - (org-footnote-at-definition-p) - (org-footnote-at-reference-p))) - (let ((new-val (or (cdr (assoc (match-string 1) map)) - (number-to-string (incf n))))) - (unless (assoc (match-string 1) map) - (push (cons (match-string 1) new-val) map)) - (replace-match new-val nil nil nil 1)))))))) + (let ((references (org-footnote--collect-references))) + (unwind-protect + (let* ((c 0) + (references (cl-remove-if-not + (lambda (r) (string-match-p "\\`[0-9]+\\'" (car r))) + references)) + (alist (mapcar (lambda (l) (cons l (number-to-string (cl-incf c)))) + (delete-dups (mapcar #'car references))))) + (org-with-wide-buffer + ;; Re-number references. + (dolist (ref references) + (goto-char (nth 1 ref)) + (org-footnote--set-label (cdr (assoc (nth 0 ref) alist)))) + ;; Re-number definitions. + (goto-char (point-min)) + (while (re-search-forward "^\\[fn:\\([0-9]+\\)\\]" nil t) + (replace-match (or (cdr (assoc (match-string 1) alist)) + ;; Un-referenced definitions get + ;; higher numbers. + (number-to-string (cl-incf c))) + nil nil nil 1)))) + (dolist (r references) (set-marker (nth 1 r) nil))))) + +(defun org-footnote-sort () + "Rearrange footnote definitions in the current buffer. +Sort footnote definitions so they match order of footnote +references. Also relocate definitions at the end of their +relative section or within a single footnote section, according +to `org-footnote-section'. Inline definitions are ignored." + (let ((references (org-footnote--collect-references))) + (unwind-protect + (let ((definitions (org-footnote--collect-definitions 'delete))) + (org-with-wide-buffer + (org-footnote--clear-footnote-section) + ;; Insert footnote definitions at the appropriate location, + ;; separated by a blank line. Each definition is inserted + ;; only once throughout the buffer. + (let (inserted) + (dolist (cell references) + (let ((label (car cell)) + (nested (not (nth 2 cell))) + (inline (nth 3 cell))) + (unless (or (member label inserted) inline) + (push label inserted) + (unless (or org-footnote-section nested) + ;; If `org-footnote-section' is non-nil, or + ;; reference is nested, point is already at the + ;; correct position. Otherwise, move at the + ;; appropriate location within the section + ;; containing the reference. + (goto-char (nth 1 cell)) + (org-footnote--goto-local-insertion-point)) + (insert "\n" + (or (cdr (assoc label definitions)) + (format "[fn:%s] DEFINITION NOT FOUND." label)) + "\n")))) + ;; Insert un-referenced footnote definitions at the end. + (let ((unreferenced + (cl-remove-if (lambda (d) (member (car d) inserted)) + definitions))) + (dolist (d unreferenced) (insert "\n" (cdr d) "\n")))))) + ;; Clear dangling markers in the buffer. + (dolist (r references) (set-marker (nth 1 r) nil))))) + +(defun org-footnote-normalize () + "Turn every footnote in buffer into a numbered one." + (interactive) + (let ((references (org-footnote--collect-references 'anonymous))) + (unwind-protect + (let ((n 0) + (translations nil) + (definitions nil)) + (org-with-wide-buffer + ;; Update label for reference. We need to do this before + ;; clearing definitions in order to rename nested footnotes + ;; before they are deleted. + (dolist (cell references) + (let* ((label (car cell)) + (anonymous (not label)) + (new + (cond + ;; In order to differentiate anonymous + ;; references from regular ones, set their + ;; labels to integers, not strings. + (anonymous (setcar cell (cl-incf n))) + ((cdr (assoc label translations))) + (t (let ((l (number-to-string (cl-incf n)))) + (push (cons label l) translations) + l))))) + (goto-char (nth 1 cell)) ; Move to reference's start. + (org-footnote--set-label + (if anonymous (number-to-string new) new)) + (let ((size (nth 3 cell))) + ;; Transform inline footnotes into regular references + ;; and retain their definition for later insertion as + ;; a regular footnote definition. + (when size + (let ((def (concat + (format "[fn:%s] " new) + (org-trim + (substring + (delete-and-extract-region + (point) (+ (point) size 1)) + 1))))) + (push (cons (if anonymous new label) def) definitions) + (when org-footnote-fill-after-inline-note-extraction + (org-fill-paragraph))))))) + ;; Collect definitions. Update labels according to ALIST. + (let ((definitions + (nconc definitions + (org-footnote--collect-definitions 'delete))) + (inserted)) + (org-footnote--clear-footnote-section) + (dolist (cell references) + (let* ((label (car cell)) + (anonymous (integerp label)) + (pos (nth 1 cell))) + ;; Move to appropriate location, if required. When + ;; there is a footnote section or reference is + ;; nested, point is already at the expected location. + (unless (or org-footnote-section (not (nth 2 cell))) + (goto-char pos) + (org-footnote--goto-local-insertion-point)) + ;; Insert new definition once label is updated. + (unless (member label inserted) + (push label inserted) + (let ((stored (cdr (assoc label definitions))) + ;; Anonymous footnotes' label is already + ;; up-to-date. + (new (if anonymous label + (cdr (assoc label translations))))) + (insert "\n" + (cond + ((not stored) + (format "[fn:%s] DEFINITION NOT FOUND." new)) + (anonymous stored) + (t + (replace-regexp-in-string + "\\`\\[fn:\\(.*?\\)\\]" new stored nil nil 1))) + "\n"))))) + ;; Insert un-referenced footnote definitions at the end. + (let ((unreferenced + (cl-remove-if (lambda (d) (member (car d) inserted)) + definitions))) + (dolist (d unreferenced) + (insert "\n" + (replace-regexp-in-string + org-footnote-definition-re + (format "[fn:%d]" (cl-incf n)) + (cdr d)) + "\n")))))) + ;; Clear dangling markers. + (dolist (r references) (set-marker (nth 1 r) nil))))) (defun org-footnote-auto-adjust-maybe () "Renumber and/or sort footnotes according to user settings." @@ -868,14 +925,77 @@ If LABEL is non-nil, delete that footnote instead." (org-footnote-renumber-fn:N)) (when (memq org-footnote-auto-adjust '(t sort)) (let ((label (car (org-footnote-at-definition-p)))) - (org-footnote-normalize 'sort) + (org-footnote-sort) (when label (goto-char (point-min)) - (and (re-search-forward (concat "^\\[" (regexp-quote label) "\\]") + (and (re-search-forward (format "^\\[fn:%s\\]" (regexp-quote label)) nil t) (progn (insert " ") (just-one-space))))))) + +;;;; End-user interface + +;;;###autoload +(defun org-footnote-action (&optional special) + "Do the right thing for footnotes. + +When at a footnote reference, jump to the definition. + +When at a definition, jump to the references if they exist, offer +to create them otherwise. + +When neither at definition or reference, create a new footnote, +interactively if possible. + +With prefix arg SPECIAL, or when no footnote can be created, +offer additional commands in a menu." + (interactive "P") + (let* ((context (and (not special) (org-element-context))) + (type (org-element-type context))) + (cond + ;; On white space after element, insert a new footnote. + ((and context + (> (point) + (save-excursion + (goto-char (org-element-property :end context)) + (skip-chars-backward " \t") + (point)))) + (org-footnote-new)) + ((eq type 'footnote-reference) + (let ((label (org-element-property :label context))) + (cond + ;; Anonymous footnote: move point at the beginning of its + ;; definition. + ((not label) + (goto-char (org-element-property :contents-begin context))) + ;; Check if a definition exists: then move to it. + ((let ((p (nth 1 (org-footnote-get-definition label)))) + (when p (org-footnote-goto-definition label p)))) + ;; No definition exists: offer to create it. + ((yes-or-no-p (format "No definition for %s. Create one? " label)) + (let ((p (org-footnote-create-definition label))) + (or (ignore-errors (org-footnote-goto-definition label p)) + ;; Since definition was created outside current scope, + ;; edit it remotely. + (org-edit-footnote-reference))))))) + ((eq type 'footnote-definition) + (org-footnote-goto-previous-reference + (org-element-property :label context))) + ((or special (not (org-footnote--allow-reference-p))) + (message "Footnotes: [s]ort | [r]enumber fn:N | [S]=r+s | [n]ormalize | \ +\[d]elete") + (pcase (read-char-exclusive) + (?s (org-footnote-sort)) + (?r (org-footnote-renumber-fn:N)) + (?S (org-footnote-renumber-fn:N) + (org-footnote-sort)) + (?n (org-footnote-normalize)) + (?d (org-footnote-delete)) + (char (error "No such footnote command %c" char)))) + (t (org-footnote-new))))) + + (provide 'org-footnote) ;; Local variables: diff --git a/lisp/org/org-gnus.el b/lisp/org/org-gnus.el index 1d287a740b5..b9d098957c8 100644 --- a/lisp/org/org-gnus.el +++ b/lisp/org/org-gnus.el @@ -1,4 +1,4 @@ -;;; org-gnus.el --- Support for links to Gnus groups and messages from within Org-mode +;;; org-gnus.el --- Support for Links to Gnus Groups and Messages -*- lexical-binding: t; -*- ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. @@ -25,8 +25,8 @@ ;; ;;; Commentary: -;; This file implements links to Gnus groups and messages from within Org-mode. -;; Org-mode loads this module by default - if this is not what you want, +;; This file implements links to Gnus groups and messages from within Org. +;; Org mode loads this module by default - if this is not what you want, ;; configure the variable `org-modules'. ;;; Code: @@ -36,18 +36,20 @@ (eval-when-compile (require 'gnus-sum)) ;; Declare external functions and variables + (declare-function message-fetch-field "message" (header &optional not-all)) (declare-function message-narrow-to-head-1 "message" nil) -;; The following line suppresses a compiler warning stemming from gnus-sum.el (declare-function gnus-summary-last-subject "gnus-sum" nil) +(declare-function nnvirtual-map-article "nnvirtual" (article)) + ;; Customization variables -(org-defvaralias 'org-usenet-links-prefer-google 'org-gnus-prefer-web-links) +(defvaralias 'org-usenet-links-prefer-google 'org-gnus-prefer-web-links) (defcustom org-gnus-prefer-web-links nil "If non-nil, `org-store-link' creates web links to Google groups or Gmane. -When nil, Gnus will be used for such links. -Using a prefix arg to the command \\[org-store-link] (`org-store-link') +\\When nil, Gnus will be used for such links. +Using a prefix argument to the command `\\[org-store-link]' (`org-store-link') negates this setting for the duration of the command." :group 'org-link-store :type 'boolean) @@ -72,20 +74,21 @@ this variable to t." :type 'boolean) ;; Install the link type -(org-add-link-type "gnus" 'org-gnus-open) -(add-hook 'org-store-link-functions 'org-gnus-store-link) +(org-link-set-parameters "gnus" :follow #'org-gnus-open :store #'org-gnus-store-link) ;; Implementation -;; FIXME: nnimap-group-overview-filename was removed from Gnus in -;; September 2010. Perhaps remove this function? (defun org-gnus-nnimap-cached-article-number (group server message-id) "Return cached article number (uid) of message in GROUP on SERVER. MESSAGE-ID is the message-id header field that identifies the message. If the uid is not cached, return nil." (with-temp-buffer - (let ((nov (nnimap-group-overview-filename group server))) - (when (file-exists-p nov) + (let ((nov (and (fboundp 'nnimap-group-overview-filename) + ;; nnimap-group-overview-filename was removed from + ;; Gnus in September 2010, and therefore should + ;; only be present in Emacs 23.1. + (nnimap-group-overview-filename group server)))) + (when (and nov (file-exists-p nov)) (mm-insert-file-contents nov) (set-buffer-modified-p nil) (goto-char (point-min)) @@ -104,7 +107,7 @@ Otherwise create a link to the group inside Gnus. If `org-store-link' was called with a prefix arg the meaning of `org-gnus-prefer-web-links' is reversed." (let ((unprefixed-group (replace-regexp-in-string "^[^:]+:" "" group))) - (if (and (string-match "^nntp" group) ;; Only for nntp groups + (if (and (string-prefix-p "nntp" group) ;; Only for nntp groups (org-xor current-prefix-arg org-gnus-prefer-web-links)) (concat (if (string-match "gmane" unprefixed-group) @@ -156,21 +159,17 @@ If `org-store-link' was called with a prefix arg the meaning of (header (with-current-buffer gnus-summary-buffer (gnus-summary-article-header))) (from (mail-header-from header)) - (message-id (org-remove-angle-brackets (mail-header-id header))) + (message-id (org-unbracket-string "<" ">" (mail-header-id header))) (date (org-trim (mail-header-date header))) - (date-ts (and date - (ignore-errors - (format-time-string - (org-time-stamp-format t) - (date-to-time date))))) - (date-ts-ia (and date - (ignore-errors - (format-time-string - (org-time-stamp-format t t) - (date-to-time date))))) (subject (copy-sequence (mail-header-subject header))) (to (cdr (assq 'To (mail-header-extra header)))) newsgroups x-no-archive desc link) + (cl-case (car (gnus-find-method-for-group gnus-newsgroup-name)) + (nnvirtual + (setq group (car (nnvirtual-map-article + (gnus-summary-article-number))))) + (nnir + (setq group (nnir-article-group (gnus-summary-article-number))))) ;; Remove text properties of subject string to avoid Emacs bug ;; #3506 (set-text-properties 0 (length subject) nil subject) @@ -183,11 +182,8 @@ If `org-store-link' was called with a prefix arg the meaning of (setq to (or to (gnus-fetch-original-field "To")) newsgroups (gnus-fetch-original-field "Newsgroups") x-no-archive (gnus-fetch-original-field "x-no-archive"))) - (org-store-link-props :type "gnus" :from from :subject subject + (org-store-link-props :type "gnus" :from from :date date :subject subject :message-id message-id :group group :to to) - (when date - (org-add-link-props :date date :date-timestamp date-ts - :date-timestamp-inactive date-ts-ia)) (setq desc (org-email-link-description) link (org-gnus-article-link group newsgroups message-id x-no-archive)) @@ -206,7 +202,7 @@ If `org-store-link' was called with a prefix arg the meaning of (let ((gcc (car (last (message-unquote-tokens (message-tokenize-header (mail-fetch-field "gcc" nil t) " ,"))))) - (id (org-remove-angle-brackets (mail-fetch-field "Message-ID"))) + (id (org-unbracket-string "<" ">" (mail-fetch-field "Message-ID"))) (to (mail-fetch-field "To")) (from (mail-fetch-field "From")) (subject (mail-fetch-field "Subject")) @@ -250,10 +246,8 @@ If `org-store-link' was called with a prefix arg the meaning of (require 'gnus) (funcall (cdr (assq 'gnus org-link-frame-setup))) (if gnus-other-frame-object (select-frame gnus-other-frame-object)) - (when group - (setq group (org-no-properties group))) - (when article - (setq article (org-no-properties article))) + (setq group (org-no-properties group)) + (setq article (org-no-properties article)) (cond ((and group article) (gnus-activate-group group) (condition-case nil diff --git a/lisp/org/org-habit.el b/lisp/org/org-habit.el index bbbf845d148..1f61565719f 100644 --- a/lisp/org/org-habit.el +++ b/lisp/org/org-habit.el @@ -1,4 +1,4 @@ -;;; org-habit.el --- The habit tracking code for Org-mode +;;; org-habit.el --- The habit tracking code for Org -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -24,18 +24,16 @@ ;; ;;; Commentary: -;; This file contains the habit tracking code for Org-mode +;; This file contains the habit tracking code for Org mode ;;; Code: +(require 'cl-lib) (require 'org) (require 'org-agenda) -(eval-when-compile - (require 'cl)) - (defgroup org-habit nil - "Options concerning habit tracking in Org-mode." + "Options concerning habit tracking in Org mode." :tag "Org Habit" :group 'org-progress) @@ -165,16 +163,17 @@ Returns a list with the following elements: 2: Optional deadline (nil if not present) 3: If deadline, the repeater for the deadline, otherwise nil 4: A list of all the past dates this todo was mark closed + 5: Repeater type as a string This list represents a \"habit\" for the rest of this module." (save-excursion (if pom (goto-char pom)) - (assert (org-is-habit-p (point))) + (cl-assert (org-is-habit-p (point))) (let* ((scheduled (org-get-scheduled-time (point))) (scheduled-repeat (org-get-repeat org-scheduled-string)) (end (org-entry-end-position)) (habit-entry (org-no-properties (nth 4 (org-heading-components)))) - closed-dates deadline dr-days sr-days) + closed-dates deadline dr-days sr-days sr-type) (if scheduled (setq scheduled (time-to-days scheduled)) (error "Habit %s has no scheduled date" habit-entry)) @@ -182,7 +181,9 @@ This list represents a \"habit\" for the rest of this module." (error "Habit `%s' has no scheduled repeat period or has an incorrect one" habit-entry)) - (setq sr-days (org-habit-duration-to-days scheduled-repeat)) + (setq sr-days (org-habit-duration-to-days scheduled-repeat) + sr-type (progn (string-match "[\\.+]?\\+" scheduled-repeat) + (match-string-no-properties 0 scheduled-repeat))) (unless (> sr-days 0) (error "Habit %s scheduled repeat period is less than 1d" habit-entry)) (when (string-match "/\\([0-9]+[dwmy]\\)" scheduled-repeat) @@ -197,17 +198,33 @@ This list represents a \"habit\" for the rest of this module." (reversed org-log-states-order-reversed) (search (if reversed 're-search-forward 're-search-backward)) (limit (if reversed end (point))) - (count 0)) + (count 0) + (re (format + "^[ \t]*-[ \t]+\\(?:State \"%s\".*%s%s\\)" + (regexp-opt org-done-keywords) + org-ts-regexp-inactive + (let ((value (cdr (assq 'done org-log-note-headings)))) + (if (not value) "" + (concat "\\|" + (org-replace-escapes + (regexp-quote value) + `(("%d" . ,org-ts-regexp-inactive) + ("%D" . ,org-ts-regexp) + ("%s" . "\"\\S-+\"") + ("%S" . "\"\\S-+\"") + ("%t" . ,org-ts-regexp-inactive) + ("%T" . ,org-ts-regexp) + ("%u" . ".*?") + ("%U" . ".*?"))))))))) (unless reversed (goto-char end)) - (while (and (< count maxdays) - (funcall search (format "- State \"%s\".*\\[\\([^]]+\\)\\]" - (regexp-opt org-done-keywords)) - limit t)) + (while (and (< count maxdays) (funcall search re limit t)) (push (time-to-days - (org-time-string-to-time (match-string-no-properties 1))) + (org-time-string-to-time + (or (match-string-no-properties 1) + (match-string-no-properties 2)))) closed-dates) (setq count (1+ count)))) - (list scheduled sr-days deadline dr-days closed-dates)))) + (list scheduled sr-days deadline dr-days closed-dates sr-type)))) (defsubst org-habit-scheduled (habit) (nth 0 habit)) @@ -225,6 +242,8 @@ This list represents a \"habit\" for the rest of this module." (org-habit-scheduled-repeat habit))) (defsubst org-habit-done-dates (habit) (nth 4 habit)) +(defsubst org-habit-repeat-type (habit) + (nth 5 habit)) (defsubst org-habit-get-priority (habit &optional moment) "Determine the relative priority of a habit. @@ -265,7 +284,6 @@ Habits are assigned colors on the following basis: schedule's repeat period." (let* ((scheduled (or scheduled-days (org-habit-scheduled habit))) (s-repeat (org-habit-scheduled-repeat habit)) - (scheduled-end (+ scheduled (1- s-repeat))) (d-repeat (org-habit-deadline-repeat habit)) (deadline (if scheduled-days (+ scheduled-days (- d-repeat s-repeat)) @@ -289,13 +307,14 @@ Habits are assigned colors on the following basis: CURRENT gives the current time between STARTING and ENDING, for the purpose of drawing the graph. It need not be the actual current time." - (let* ((done-dates (sort (org-habit-done-dates habit) '<)) + (let* ((all-done-dates (sort (org-habit-done-dates habit) #'<)) + (done-dates all-done-dates) (scheduled (org-habit-scheduled habit)) (s-repeat (org-habit-scheduled-repeat habit)) (start (time-to-days starting)) (now (time-to-days current)) (end (time-to-days ending)) - (graph (make-string (1+ (- end start)) ?\ )) + (graph (make-string (1+ (- end start)) ?\s)) (index 0) last-done-date) (while (and done-dates (< (car done-dates) start)) @@ -304,18 +323,55 @@ current time." (while (< start end) (let* ((in-the-past-p (< start now)) (todayp (= start now)) - (donep (and done-dates - (= start (car done-dates)))) - (faces (if (and in-the-past-p - (not last-done-date) - (not (< scheduled now))) - '(org-habit-clear-face . org-habit-clear-future-face) - (org-habit-get-faces - habit start (and in-the-past-p - (if last-done-date - (+ last-done-date s-repeat) - scheduled)) - donep))) + (donep (and done-dates (= start (car done-dates)))) + (faces + (if (and in-the-past-p + (not last-done-date) + (not (< scheduled now))) + '(org-habit-clear-face . org-habit-clear-future-face) + (org-habit-get-faces + habit start + (and in-the-past-p + last-done-date + ;; Compute scheduled time for habit at the time + ;; START was current. + (let ((type (org-habit-repeat-type habit))) + (cond + ;; At the last done date, use current + ;; scheduling in all cases. + ((null done-dates) scheduled) + ((equal type ".+") (+ last-done-date s-repeat)) + ((equal type "+") + ;; Since LAST-DONE-DATE, each done mark + ;; shifted scheduled date by S-REPEAT. + (- scheduled (* (length done-dates) s-repeat))) + (t + ;; Compute the scheduled time after the + ;; first repeat. This is the closest time + ;; past FIRST-DONE which can reach SCHEDULED + ;; by a number of S-REPEAT hops. + ;; + ;; Then, play TODO state change history from + ;; the beginning in order to find current + ;; scheduled time. + (let* ((first-done (car all-done-dates)) + (s (let ((shift (mod (- scheduled first-done) + s-repeat))) + (+ (if (= shift 0) s-repeat shift) + first-done)))) + (if (= first-done last-done-date) s + (catch :exit + (dolist (done (cdr all-done-dates) s) + ;; Each repeat shifts S by any + ;; number of S-REPEAT hops it takes + ;; to get past DONE, with a minimum + ;; of one hop. + (cl-incf s (* (1+ (/ (max (- done s) 0) + s-repeat)) + s-repeat)) + (when (= done last-done-date) + (throw :exit s)))))))))) + donep))) markedp face) (if donep (let ((done-time (time-add @@ -348,7 +404,7 @@ current time." (defun org-habit-insert-consistency-graphs (&optional line) "Insert consistency graph for any habitual tasks." - (let ((inhibit-read-only t) l c + (let ((inhibit-read-only t) (buffer-invisibility-spec '(org-link)) (moment (time-subtract (current-time) (list 0 (* 3600 org-extend-today-until) 0)))) diff --git a/lisp/org/org-id.el b/lisp/org/org-id.el index 54fc733578d..f07d243b8cf 100644 --- a/lisp/org/org-id.el +++ b/lisp/org/org-id.el @@ -1,4 +1,4 @@ -;;; org-id.el --- Global identifiers for Org-mode entries +;;; org-id.el --- Global identifiers for Org entries -*- lexical-binding: t; -*- ;; ;; Copyright (C) 2008-2017 Free Software Foundation, Inc. ;; @@ -24,7 +24,7 @@ ;; ;;; Commentary: -;; This file implements globally unique identifiers for Org-mode entries. +;; This file implements globally unique identifiers for Org entries. ;; Identifiers are stored in the entry as an :ID: property. Functions ;; are provided that create and retrieve such identifiers, and that find ;; entries based on the identifier. @@ -73,20 +73,17 @@ (require 'org) (declare-function message-make-fqdn "message" ()) -(declare-function org-pop-to-buffer-same-window - "org-compat" (&optional buffer-or-name norecord label)) ;;; Customization (defgroup org-id nil - "Options concerning global entry identifiers in Org-mode." + "Options concerning global entry identifiers in Org mode." :tag "Org ID" :group 'org) -(define-obsolete-variable-alias - 'org-link-to-org-use-id 'org-id-link-to-org-use-id "24.3") (defcustom org-id-link-to-org-use-id nil "Non-nil means storing a link to an Org file will use entry IDs. +\\\ The variable can have the following values: @@ -101,7 +98,7 @@ create-if-interactive call `org-capture' that automatically and preemptively creates a link. If you do want to get an ID link in a capture template to an entry not having an ID, create it first by explicitly creating - a link to it, using `C-c C-l' first. + a link to it, using `\\[org-store-link]' first. create-if-interactive-and-no-custom-id Like create-if-interactive, but do not create an ID if there is @@ -203,7 +200,7 @@ This variable is only relevant when `org-id-track-globally' is set." When Org reparses files to remake the list of files and IDs it is tracking, it will normally scan the agenda files, the archives related to agenda files, any files that are listed as ID containing in the current register, and -any Org-mode files currently visited by Emacs. +any Org file currently visited by Emacs. You can list additional files here. This variable is only relevant when `org-id-track-globally' is set." :group 'org-id @@ -277,7 +274,7 @@ If necessary, the ID is created." (move-marker pom nil)))) ;;;###autoload -(defun org-id-get-with-outline-drilling (&optional targets) +(defun org-id-get-with-outline-drilling () "Use an outline-cycling interface to retrieve the ID of an entry. This only finds entries in the current buffer, using `org-get-location'. It returns the ID of the entry. If necessary, the ID is created." @@ -294,7 +291,7 @@ Move the cursor to that entry in that buffer." (let ((m (org-id-find id 'marker))) (unless m (error "Cannot find entry with ID \"%s\"" id)) - (org-pop-to-buffer-same-window (marker-buffer m)) + (pop-to-buffer-same-window (marker-buffer m)) (goto-char m) (move-marker m nil) (org-show-context))) @@ -447,8 +444,7 @@ and time is the usual three-integer representation of time." Store the relation between files and corresponding IDs. This will scan all agenda files, all associated archives, and all files currently mentioned in `org-id-locations'. -When FILES is given, scan these files instead. -When CHECK is given, prepare detailed information about duplicate IDs." +When FILES is given, scan these files instead." (interactive) (if (not org-id-track-globally) (error "Please turn on `org-id-track-globally' if you want to track IDs") @@ -466,7 +462,7 @@ When CHECK is given, prepare detailed information about duplicate IDs." (if (symbolp org-id-extra-files) (symbol-value org-id-extra-files) org-id-extra-files) - ;; Files associated with live org-mode buffers + ;; Files associated with live Org buffers (delq nil (mapcar (lambda (b) (with-current-buffer b @@ -494,7 +490,7 @@ When CHECK is given, prepare detailed information about duplicate IDs." (goto-char (point-min)) (while (re-search-forward "^[ \t]*:ID:[ \t]+\\(\\S-+\\)[ \t]*$" nil t) - (setq id (org-match-string-no-properties 1)) + (setq id (match-string-no-properties 1)) (if (member id found) (progn (message "Duplicate ID \"%s\", also in file %s" @@ -678,7 +674,7 @@ optional argument MARKERP, return the position as a new marker." (move-marker m nil) (org-show-context))) -(org-add-link-type "id" 'org-id-open) +(org-link-set-parameters "id" :follow #'org-id-open) (provide 'org-id) diff --git a/lisp/org/org-indent.el b/lisp/org/org-indent.el index baaff2ff7c8..10c96179b61 100644 --- a/lisp/org/org-indent.el +++ b/lisp/org/org-indent.el @@ -1,4 +1,5 @@ -;;; org-indent.el --- Dynamic indentation for Org-mode +;;; org-indent.el --- Dynamic indentation for Org -*- lexical-binding: t; -*- + ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. ;; ;; Author: Carsten Dominik @@ -39,8 +40,7 @@ (require 'org-compat) (require 'org) -(eval-when-compile - (require 'cl)) +(require 'cl-lib) (declare-function org-inlinetask-get-task-level "org-inlinetask" ()) (declare-function org-inlinetask-in-task-p "org-inlinetask" ()) @@ -52,20 +52,6 @@ :tag "Org Indent" :group 'org) -(defconst org-indent-max 40 - "Maximum indentation in characters.") -(defconst org-indent-max-levels 20 - "Maximum added level through virtual indentation, in characters. - -It is computed by multiplying `org-indent-indentation-per-level' -minus one by actual level of the headline minus one.") - -(defvar org-indent-strings nil - "Vector with all indentation strings. -It will be set in `org-indent-initialize'.") -(defvar org-indent-stars nil - "Vector with all indentation star strings. -It will be set in `org-indent-initialize'.") (defvar org-indent-inlinetask-first-star (org-add-props "*" '(face org-warning)) "First star of inline tasks, with correct face.") (defvar org-indent-agent-timer nil @@ -82,7 +68,7 @@ Delay used when the buffer to initialize is current.") Delay used when the buffer to initialize isn't current.") (defvar org-indent-agent-resume-delay '(0 0 100000) "Minimal time for other idle processes before switching back to agent.") -(defvar org-indent-initial-marker nil +(defvar org-indent--initial-marker nil "Position of initialization before interrupt. This is used locally in each buffer being initialized.") (defvar org-hide-leading-stars-before-indent-mode nil @@ -92,15 +78,12 @@ This is used locally in each buffer being initialized.") It is modified by `org-indent-notify-modified-headline'.") -(defcustom org-indent-boundary-char ?\ ; comment to protect space char +(defcustom org-indent-boundary-char ?\s "The end of the virtual indentation strings, a single-character string. The default is just a space, but if you wish, you can use \"|\" or so. This can be useful on a terminal window - under a windowing system, -it may be prettier to customize the org-indent face." +it may be prettier to customize the `org-indent' face." :group 'org-indent - :set (lambda (var val) - (set var val) - (and org-indent-strings (org-indent-initialize))) :type 'character) (defcustom org-indent-mode-turns-off-org-adapt-indentation t @@ -121,29 +104,56 @@ turn on `org-hide-leading-stars'." :group 'org-indent :type 'integer) -(defface org-indent - (org-compatible-face nil nil) +(defface org-indent '((t (:inherit org-hide))) "Face for outline indentation. The default is to make it look like whitespace. But you may find it useful to make it ever so slightly different." :group 'org-faces) -(defun org-indent-initialize () - "Initialize the indentation strings." - (setq org-indent-strings (make-vector (1+ org-indent-max) nil)) - (setq org-indent-stars (make-vector (1+ org-indent-max) nil)) - (aset org-indent-strings 0 nil) - (aset org-indent-stars 0 nil) - (loop for i from 1 to org-indent-max do - (aset org-indent-strings i - (org-add-props - (concat (make-string (1- i) ?\ ) - (char-to-string org-indent-boundary-char)) +(defvar org-indent--text-line-prefixes nil + "Vector containing line prefixes strings for regular text.") + +(defvar org-indent--heading-line-prefixes nil + "Vector containing line prefix strings for headlines.") + +(defvar org-indent--inlinetask-line-prefixes nil + "Vector containing line prefix strings for inline tasks.") + +(defconst org-indent--deepest-level 50 + "Maximum theoretical headline depth.") + +(defun org-indent--compute-prefixes () + "Compute prefix strings for regular text and headlines." + (setq org-indent--heading-line-prefixes + (make-vector org-indent--deepest-level nil)) + (setq org-indent--inlinetask-line-prefixes + (make-vector org-indent--deepest-level nil)) + (setq org-indent--text-line-prefixes + (make-vector org-indent--deepest-level nil)) + (dotimes (n org-indent--deepest-level) + (let ((indentation (if (<= n 1) 0 + (* (1- org-indent-indentation-per-level) + (1- n))))) + ;; Headlines line prefixes. + (let ((heading-prefix (make-string indentation ?*))) + (aset org-indent--heading-line-prefixes + n + (org-add-props heading-prefix nil 'face 'org-indent)) + ;; Inline tasks line prefixes + (aset org-indent--inlinetask-line-prefixes + n + (org-add-props (if (bound-and-true-p org-inlinetask-show-first-star) + (concat org-indent-inlinetask-first-star + (substring heading-prefix 1)) + heading-prefix) nil 'face 'org-indent))) - (loop for i from 1 to org-indent-max-levels do - (aset org-indent-stars i - (org-add-props (make-string i ?*) - nil 'face 'org-hide)))) + ;; Text line prefixes. + (aset org-indent--text-line-prefixes + n + (concat (org-add-props (make-string (+ n indentation) ?\s) + nil 'face 'org-indent) + (and (> n 0) + (char-to-string org-indent-boundary-char))))))) (defsubst org-indent-remove-properties (beg end) "Remove indentations between BEG and END." @@ -162,34 +172,25 @@ buffer, which can take a few seconds on large buffers, is done during idle time." nil " Ind" nil (cond - ((and org-indent-mode (featurep 'xemacs)) - (message "org-indent-mode does not work in XEmacs - refusing to turn it on") - (setq org-indent-mode nil)) - ((and org-indent-mode - (not (org-version-check "23.1.50" "Org Indent mode" :predicate))) - (message "org-indent-mode can crash Emacs 23.1 - refusing to turn it on!") - (ding) - (sit-for 1) - (setq org-indent-mode nil)) (org-indent-mode ;; mode was turned on. - (org-set-local 'indent-tabs-mode nil) - (or org-indent-strings (org-indent-initialize)) - (org-set-local 'org-indent-initial-marker (copy-marker 1)) + (setq-local indent-tabs-mode nil) + (setq-local org-indent--initial-marker (copy-marker 1)) (when org-indent-mode-turns-off-org-adapt-indentation - (org-set-local 'org-adapt-indentation nil)) + (setq-local org-adapt-indentation nil)) (when org-indent-mode-turns-on-hiding-stars - (org-set-local 'org-hide-leading-stars-before-indent-mode - org-hide-leading-stars) - (org-set-local 'org-hide-leading-stars t)) - (org-add-hook 'filter-buffer-substring-functions - (lambda (fun start end delete) - (org-indent-remove-properties-from-string - (funcall fun start end delete))) - nil t) - (org-add-hook 'after-change-functions 'org-indent-refresh-maybe nil 'local) - (org-add-hook 'before-change-functions - 'org-indent-notify-modified-headline nil 'local) + (setq-local org-hide-leading-stars-before-indent-mode + org-hide-leading-stars) + (setq-local org-hide-leading-stars t)) + (org-indent--compute-prefixes) + (add-hook 'filter-buffer-substring-functions + (lambda (fun start end delete) + (org-indent-remove-properties-from-string + (funcall fun start end delete))) + nil t) + (add-hook 'after-change-functions 'org-indent-refresh-maybe nil 'local) + (add-hook 'before-change-functions + 'org-indent-notify-modified-headline nil 'local) (and font-lock-mode (org-restart-font-lock)) (org-indent-remove-properties (point-min) (point-max)) ;; Submit current buffer to initialize agent. If it's the first @@ -205,11 +206,11 @@ during idle time." (kill-local-variable 'org-adapt-indentation) (setq org-indent-agentized-buffers (delq (current-buffer) org-indent-agentized-buffers)) - (when (markerp org-indent-initial-marker) - (set-marker org-indent-initial-marker nil)) + (when (markerp org-indent--initial-marker) + (set-marker org-indent--initial-marker nil)) (when (boundp 'org-hide-leading-stars-before-indent-mode) - (org-set-local 'org-hide-leading-stars - org-hide-leading-stars-before-indent-mode)) + (setq-local org-hide-leading-stars + org-hide-leading-stars-before-indent-mode)) (remove-hook 'filter-buffer-substring-functions (lambda (fun start end delete) (org-indent-remove-properties-from-string @@ -245,7 +246,7 @@ When no more buffer is being watched, the agent suppress itself." (when org-indent-agent-resume-timer (cancel-timer org-indent-agent-resume-timer)) (setq org-indent-agentized-buffers - (org-remove-if-not #'buffer-live-p org-indent-agentized-buffers)) + (cl-remove-if-not #'buffer-live-p org-indent-agentized-buffers)) (cond ;; Job done: kill agent. ((not org-indent-agentized-buffers) (cancel-timer org-indent-agent-timer)) @@ -269,46 +270,44 @@ a time value." (let ((interruptp ;; Always nil unless interrupted. (catch 'interrupt - (and org-indent-initial-marker - (marker-position org-indent-initial-marker) - (org-indent-add-properties org-indent-initial-marker + (and org-indent--initial-marker + (marker-position org-indent--initial-marker) + (equal (marker-buffer org-indent--initial-marker) + buffer) + (org-indent-add-properties org-indent--initial-marker (point-max) delay) nil)))) - (move-marker org-indent-initial-marker interruptp) + (move-marker org-indent--initial-marker interruptp) ;; Job is complete: un-agentize buffer. (unless interruptp (setq org-indent-agentized-buffers (delq buffer org-indent-agentized-buffers)))))))) -(defsubst org-indent-set-line-properties (l w h) +(defun org-indent-set-line-properties (level indentation &optional heading) "Set prefix properties on current line an move to next one. -Prefix properties `line-prefix' and `wrap-prefix' in current line -are set to, respectively, length L and W. - -If H is non-nil, `line-prefix' will be starred. If H is -`inline', the first star will have `org-warning' face. - -Assume point is at beginning of line." - (let ((line (cond - ((eq 'inline h) - (let ((stars (aref org-indent-stars - (min l org-indent-max-levels)))) - (and stars - (if (org-bound-and-true-p org-inlinetask-show-first-star) - (concat org-indent-inlinetask-first-star - (substring stars 1)) - stars)))) - (h (aref org-indent-stars - (min l org-indent-max-levels))) - (t (aref org-indent-strings - (min l org-indent-max))))) - (wrap (aref org-indent-strings (min w org-indent-max)))) +LEVEL is the current level of heading. INDENTATION is the +expected indentation when wrapping line. + +When optional argument HEADING is non-nil, assume line is at +a heading. Moreover, if is is `inlinetask', the first star will +have `org-warning' face." + (let* ((line (aref (pcase heading + (`nil org-indent--text-line-prefixes) + (`inlinetask org-indent--inlinetask-line-prefixes) + (_ org-indent--heading-line-prefixes)) + level)) + (wrap + (org-add-props + (concat line + (if heading (concat (make-string level ?*) " ") + (make-string indentation ?\s))) + nil 'face 'org-indent))) ;; Add properties down to the next line to indent empty lines. - (add-text-properties (point) (min (1+ (point-at-eol)) (point-max)) + (add-text-properties (line-beginning-position) (line-beginning-position 2) `(line-prefix ,line wrap-prefix ,wrap))) - (forward-line 1)) + (forward-line)) (defun org-indent-add-properties (beg end &optional delay) "Add indentation properties between BEG and END. @@ -322,26 +321,14 @@ stopped." (org-with-wide-buffer (goto-char beg) (beginning-of-line) - ;; 1. Initialize prefix at BEG. This is done by storing two - ;; variables: INLINE-PF and PF, representing respectively - ;; length of current `line-prefix' when line is inside an - ;; inline task or not. + ;; Initialize prefix at BEG, according to current entry's level. (let* ((case-fold-search t) (limited-re (org-get-limited-outline-regexp)) - (added-ind-per-lvl (abs (1- org-indent-indentation-per-level))) - (pf (save-excursion - (and (ignore-errors (let ((outline-regexp limited-re)) - (org-back-to-heading t))) - (+ (* org-indent-indentation-per-level - (- (match-end 0) (match-beginning 0) 2)) 2)))) - (pf-inline (and (featurep 'org-inlinetask) - (org-inlinetask-in-task-p) - (+ (* org-indent-indentation-per-level - (1- (org-inlinetask-get-task-level))) 2))) + (level (or (org-current-level) 0)) (time-limit (and delay (time-add (current-time) delay)))) - ;; 2. For each line, set `line-prefix' and `wrap-prefix' - ;; properties depending on the type of line (headline, - ;; inline task, item or other). + ;; For each line, set `line-prefix' and `wrap-prefix' + ;; properties depending on the type of line (headline, inline + ;; task, item or other). (org-with-silent-modifications (while (and (<= (point) end) (not (eobp))) (cond @@ -354,38 +341,23 @@ stopped." ((and delay (time-less-p time-limit (current-time))) (setq org-indent-agent-resume-timer (run-with-idle-timer - (time-add (current-idle-time) - org-indent-agent-resume-delay) + (time-add (current-idle-time) org-indent-agent-resume-delay) nil #'org-indent-initialize-agent)) (throw 'interrupt (point))) ;; Headline or inline task. ((looking-at org-outline-regexp) (let* ((nstars (- (match-end 0) (match-beginning 0) 1)) - (line (* added-ind-per-lvl (1- nstars))) - (wrap (+ line (1+ nstars)))) - (cond - ;; Headline: new value for PF. - ((looking-at limited-re) - (org-indent-set-line-properties line wrap t) - (setq pf wrap)) - ;; End of inline task: PF-INLINE is now nil. - ((looking-at "\\*+ end[ \t]*$") - (org-indent-set-line-properties line wrap 'inline) - (setq pf-inline nil)) - ;; Start of inline task. Determine if it contains - ;; text, or if it is only one line long. Set - ;; PF-INLINE accordingly. - (t (org-indent-set-line-properties line wrap 'inline) - (setq pf-inline (and (org-inlinetask-in-task-p) wrap)))))) + (type (or (looking-at-p limited-re) 'inlinetask))) + (org-indent-set-line-properties nstars 0 type) + ;; At an headline, define new value for LEVEL. + (unless (eq type 'inlinetask) (setq level nstars)))) ;; List item: `wrap-prefix' is set where body starts. ((org-at-item-p) - (let* ((line (or pf-inline pf 0)) - (wrap (+ (org-list-item-body-column (point)) line))) - (org-indent-set-line-properties line wrap nil))) - ;; Normal line: use PF-INLINE, PF or nil as prefixes. - (t (let* ((line (or pf-inline pf 0)) - (wrap (+ line (org-get-indentation)))) - (org-indent-set-line-properties line wrap nil)))))))))) + (org-indent-set-line-properties + level (org-list-item-body-column (point)))) + ;; Regular line. + (t + (org-indent-set-line-properties level (org-get-indentation)))))))))) (defun org-indent-notify-modified-headline (beg end) "Set `org-indent-modified-headline-flag' depending on context. @@ -398,13 +370,14 @@ Flag will be non-nil if command is going to modify or delete an headline." (when org-indent-mode (setq org-indent-modified-headline-flag - (save-excursion - (goto-char beg) - (save-match-data - (or (and (org-at-heading-p) (< beg (match-end 0))) - (re-search-forward org-outline-regexp-bol end t))))))) - -(defun org-indent-refresh-maybe (beg end dummy) + (org-with-wide-buffer + (goto-char beg) + (save-match-data + (or (and (org-at-heading-p) (< beg (match-end 0))) + (re-search-forward + (org-with-limited-levels org-outline-regexp-bol) end t))))))) + +(defun org-indent-refresh-maybe (beg end _) "Refresh indentation properties in an adequate portion of buffer. BEG and END are the positions of the beginning and end of the range of inserted text. DUMMY is an unused argument. @@ -414,19 +387,21 @@ This function is meant to be called by `after-change-functions'." (save-match-data ;; If a headline was modified or inserted, set properties until ;; next headline. - (if (or org-indent-modified-headline-flag - (save-excursion - (goto-char beg) - (beginning-of-line) - (re-search-forward org-outline-regexp-bol end t))) - (let ((end (save-excursion - (goto-char end) - (org-with-limited-levels (outline-next-heading)) - (point)))) - (setq org-indent-modified-headline-flag nil) - (org-indent-add-properties beg end)) - ;; Otherwise, only set properties on modified area. - (org-indent-add-properties beg end))))) + (org-with-wide-buffer + (if (or org-indent-modified-headline-flag + (save-excursion + (goto-char beg) + (beginning-of-line) + (re-search-forward + (org-with-limited-levels org-outline-regexp-bol) end t))) + (let ((end (save-excursion + (goto-char end) + (org-with-limited-levels (outline-next-heading)) + (point)))) + (setq org-indent-modified-headline-flag nil) + (org-indent-add-properties beg end)) + ;; Otherwise, only set properties on modified area. + (org-indent-add-properties beg end)))))) (provide 'org-indent) diff --git a/lisp/org/org-info.el b/lisp/org/org-info.el index c8f6f06de06..79b9bcc3d96 100644 --- a/lisp/org/org-info.el +++ b/lisp/org/org-info.el @@ -1,4 +1,4 @@ -;;; org-info.el --- Support for links to Info nodes from within Org-Mode +;;; org-info.el --- Support for Links to Info Nodes -*- lexical-binding: t; -*- ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. @@ -24,8 +24,8 @@ ;; ;;; Commentary: -;; This file implements links to Info nodes from within Org-mode. -;; Org-mode loads this module by default - if this is not what you want, +;; This file implements links to Info nodes from within Org mode. +;; Org mode loads this module by default - if this is not what you want, ;; configure the variable `org-modules'. ;;; Code: @@ -40,19 +40,20 @@ (defvar Info-current-node) ;; Install the link type -(org-add-link-type "info" 'org-info-open) -(add-hook 'org-store-link-functions 'org-info-store-link) +(org-link-set-parameters "info" + :follow #'org-info-open + :export #'org-info-export + :store #'org-info-store-link) ;; Implementation (defun org-info-store-link () "Store a link to an Info file and node." (when (eq major-mode 'Info-mode) - (let (link desc) - (setq link (concat "info:" - (file-name-nondirectory Info-current-file) - "#" Info-current-node)) - (setq desc (concat (file-name-nondirectory Info-current-file) - "#" Info-current-node)) + (let ((link (concat "info:" + (file-name-nondirectory Info-current-file) + "#" Info-current-node)) + (desc (concat (file-name-nondirectory Info-current-file) + "#" Info-current-node))) (org-store-link-props :type "info" :file Info-current-file :node Info-current-node :link link :desc desc) @@ -67,12 +68,76 @@ "Follow an Info file and node link specified by NAME." (if (or (string-match "\\(.*\\)[#:]:?\\(.*\\)" name) (string-match "\\(.*\\)" name)) - (progn + (let ((filename (match-string 1 name)) + (nodename-or-index (or (match-string 2 name) "Top"))) (require 'info) - (if (match-string 2 name) ; If there isn't a node, choose "Top" - (Info-find-node (match-string 1 name) (match-string 2 name)) - (Info-find-node (match-string 1 name) "Top"))) - (message "Could not open: %s" name))) + ;; If nodename-or-index is invalid node name, then look it up + ;; in the index. + (condition-case nil + (Info-find-node filename nodename-or-index) + (user-error (Info-find-node filename "Top") + (condition-case nil + (Info-index nodename-or-index) + (user-error "Could not find '%s' node or index entry" + nodename-or-index))))) + (user-error "Could not open: %s" name))) + +(defconst org-info-emacs-documents + '("ada-mode" "auth" "autotype" "bovine" "calc" "ccmode" "cl" "dbus" "dired-x" + "ebrowse" "ede" "ediff" "edt" "efaq-w32" "efaq" "eieio" "eintr" "elisp" + "emacs-gnutls" "emacs-mime" "emacs" "epa" "erc" "ert" "eshell" "eudc" "eww" + "flymake" "forms" "gnus" "htmlfontify" "idlwave" "ido" "info" "mairix-el" + "message" "mh-e" "newsticker" "nxml-mode" "octave-mode" "org" "pcl-cvs" + "pgg" "rcirc" "reftex" "remember" "sasl" "sc" "semantic" "ses" "sieve" + "smtpmail" "speedbar" "srecode" "todo-mode" "tramp" "url" "vip" "viper" + "widget" "wisent" "woman") + "List of emacs documents available. +Taken from ") + +(defconst org-info-other-documents + '(("libc" . "http://www.gnu.org/software/libc/manual/html_mono/libc.html") + ("make" . "http://www.gnu.org/software/make/manual/make.html")) + "Alist of documents generated from Texinfo source. +When converting info links to HTML, links to any one of these manuals are +converted to use these URL.") + +(defun org-info-map-html-url (filename) + "Return URL or HTML file associated to Info FILENAME. +If FILENAME refers to an official GNU document, return a URL pointing to +the official page for that document, e.g., use \"gnu.org\" for all Emacs +related documents. Otherwise, append \".html\" extension to FILENAME. +See `org-info-emacs-documents' and `org-info-other-documents' for details." + (cond ((member filename org-info-emacs-documents) + (format "http://www.gnu.org/software/emacs/manual/html_mono/%s.html" + filename)) + ((cdr (assoc filename org-info-other-documents))) + (t (concat filename ".html")))) + +(defun org-info--expand-node-name (node) + "Expand Info NODE to HTML cross reference." + ;; See (info "(texinfo) HTML Xref Node Name Expansion") for the + ;; expansion rule. + (let ((node (replace-regexp-in-string + "\\([ \t\n\r]+\\)\\|\\([^a-zA-Z0-9]\\)" + (lambda (m) + (if (match-end 1) "-" (format "_%04x" (string-to-char m)))) + (org-trim node)))) + (cond ((string= node "") "") + ((string-match-p "\\`[0-9]" node) (concat "g_t" node)) + (t node)))) + +(defun org-info-export (path desc format) + "Export an info link. +See `org-link-parameters' for details about PATH, DESC and FORMAT." + (when (eq format 'html) + (or (string-match "\\(.*\\)[#:]:?\\(.*\\)" path) + (string-match "\\(.*\\)" path)) + (let ((filename (match-string 1 path)) + (node (or (match-string 2 path) "Top"))) + (format "%s" + (org-info-map-html-url filename) + (org-info--expand-node-name node) + (or desc path))))) (provide 'org-info) diff --git a/lisp/org/org-inlinetask.el b/lisp/org/org-inlinetask.el index bf4ab205a4c..2918d4061dd 100644 --- a/lisp/org/org-inlinetask.el +++ b/lisp/org/org-inlinetask.el @@ -1,4 +1,4 @@ -;;; org-inlinetask.el --- Tasks independent of outline hierarchy +;;; org-inlinetask.el --- Tasks Independent of Outline Hierarchy -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. ;; @@ -26,7 +26,7 @@ ;; ;;; Commentary: ;; -;; This module implements inline tasks in Org-mode. Inline tasks are +;; This module implements inline tasks in Org mode. Inline tasks are ;; tasks that have all the properties of normal outline nodes, ;; including the ability to store meta data like scheduling dates, ;; TODO state, tags and properties. However, these nodes are treated @@ -108,7 +108,6 @@ When nil, the first star is not shown." (defvar org-odd-levels-only) (defvar org-keyword-time-regexp) -(defvar org-drawer-regexp) (defvar org-complex-heading-regexp) (defvar org-property-end-re) @@ -168,9 +167,9 @@ The number of levels is controlled by `org-inlinetask-min-level'." (stars-re (org-inlinetask-outline-regexp)) (task-beg-re (concat stars-re "\\(?:.*\\)")) (task-end-re (concat stars-re "END[ \t]*$"))) - (or (org-looking-at-p task-beg-re) + (or (looking-at-p task-beg-re) (and (re-search-forward "^\\*+[ \t]+" nil t) - (progn (beginning-of-line) (org-looking-at-p task-end-re))))))) + (progn (beginning-of-line) (looking-at-p task-end-re))))))) (defun org-inlinetask-goto-beginning () "Go to the beginning of the inline task at point." @@ -178,7 +177,7 @@ The number of levels is controlled by `org-inlinetask-min-level'." (let ((case-fold-search t) (inlinetask-re (org-inlinetask-outline-regexp))) (re-search-backward inlinetask-re nil t) - (when (org-looking-at-p (concat inlinetask-re "END[ \t]*$")) + (when (looking-at-p (concat inlinetask-re "END[ \t]*$")) (re-search-backward inlinetask-re nil t)))) (defun org-inlinetask-goto-end () @@ -190,17 +189,16 @@ Return point." (inlinetask-re (org-inlinetask-outline-regexp)) (task-end-re (concat inlinetask-re "END[ \t]*$"))) (cond - ((looking-at task-end-re) (forward-line)) + ((looking-at task-end-re)) ((looking-at inlinetask-re) (forward-line) (cond - ((looking-at task-end-re) (forward-line)) + ((looking-at task-end-re)) ((looking-at inlinetask-re)) ((org-inlinetask-in-task-p) - (re-search-forward inlinetask-re nil t) - (forward-line)))) - (t (re-search-forward inlinetask-re nil t) - (forward-line))) + (re-search-forward inlinetask-re nil t)))) + (t (re-search-forward inlinetask-re nil t))) + (end-of-line) (point)))) (defun org-inlinetask-get-task-level () @@ -273,8 +271,7 @@ If the task has an end part, also demote it." (defvar org-indent-indentation-per-level) ; defined in org-indent.el -(defface org-inlinetask - (org-compatible-face 'shadow '((t (:bold t)))) +(defface org-inlinetask '((t :inherit shadow)) "Face for inlinetask headlines." :group 'org-faces) @@ -288,7 +285,7 @@ If the task has an end part, also demote it." ",\\}\\)\\(\\*\\* .*\\)")) ;; Virtual indentation will add the warning face on the first ;; star. Thus, in that case, only hide it. - (start-face (if (and (org-bound-and-true-p org-indent-mode) + (start-face (if (and (bound-and-true-p org-indent-mode) (> org-indent-indentation-per-level 1)) 'org-hide 'org-warning))) @@ -315,19 +312,36 @@ If the task has an end part, also demote it." ;; Nothing to show/hide. ((= end start)) ;; Inlinetask was folded: expand it. - ((get-char-property (1+ start) 'invisible) + ((eq (get-char-property (1+ start) 'invisible) 'outline) (outline-flag-region start end nil) (org-cycle-hide-drawers 'children)) (t (outline-flag-region start end t))))) +(defun org-inlinetask-hide-tasks (state) + "Hide inline tasks in buffer when STATE is `contents' or `children'. +This function is meant to be used in `org-cycle-hook'." + (pcase state + (`contents + (let ((regexp (org-inlinetask-outline-regexp))) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward regexp nil t) + (org-inlinetask-toggle-visibility) + (org-inlinetask-goto-end))))) + (`children + (save-excursion + (while (and (outline-next-heading) (org-inlinetask-at-task-p)) + (org-inlinetask-toggle-visibility) + (org-inlinetask-goto-end)))))) + (defun org-inlinetask-remove-END-maybe () "Remove an END line when present." (when (looking-at (format "\\([ \t]*\n\\)*\\*\\{%d,\\}[ \t]+END[ \t]*$" org-inlinetask-min-level)) (replace-match ""))) -(eval-after-load "org" - '(add-hook 'org-font-lock-hook 'org-inlinetask-fontify)) +(add-hook 'org-font-lock-hook 'org-inlinetask-fontify) +(add-hook 'org-cycle-hook 'org-inlinetask-hide-tasks) (provide 'org-inlinetask) diff --git a/lisp/org/org-irc.el b/lisp/org/org-irc.el index 1243587beb8..3a6a7f4db06 100644 --- a/lisp/org/org-irc.el +++ b/lisp/org/org-irc.el @@ -1,4 +1,4 @@ -;;; org-irc.el --- Store links to IRC sessions +;;; org-irc.el --- Store Links to IRC Sessions -*- lexical-binding: t; -*- ;; ;; Copyright (C) 2008-2017 Free Software Foundation, Inc. ;; @@ -22,8 +22,8 @@ ;;; Commentary: -;; This file implements links to an IRC session from within Org-mode. -;; Org-mode loads this module by default - if this is not what you want, +;; This file implements links to an IRC session from within Org mode. +;; Org mode loads this module by default - if this is not what you want, ;; configure the variable `org-modules'. ;; ;; Please customize the variable `org-modules' to select @@ -59,8 +59,6 @@ (declare-function erc-server-buffer "erc" ()) (declare-function erc-get-server-nickname-list "erc" ()) (declare-function erc-cmd-JOIN "erc" (channel &optional key)) -(declare-function org-pop-to-buffer-same-window - "org-compat" (&optional buffer-or-name norecord label)) (defvar org-irc-client 'erc "The IRC client to act on.") @@ -73,9 +71,7 @@ ;; Generic functions/config (extend these for other clients) -(add-to-list 'org-store-link-functions 'org-irc-store-link) - -(org-add-link-type "irc" 'org-irc-visit nil) +(org-link-set-parameters "irc" :follow #'org-irc-visit :store #'org-irc-store-link) (defun org-irc-visit (link) "Parse LINK and dispatch to the correct function based on the client found." @@ -114,11 +110,9 @@ chars that the value AFTER with `...'" (cons "[ \t]*$" "") (cons (concat "^\\(.\\{" after "\\}\\).*") "\\1...")))) - (mapc (lambda (x) - (when (string-match (car x) string) - (setq string (replace-match (cdr x) nil nil string)))) - replace-map) - string)) + (dolist (x replace-map string) + (when (string-match (car x) string) + (setq string (replace-match (cdr x) nil nil string)))))) ;; ERC specific functions @@ -233,7 +227,7 @@ default." (throw 'found x)))))) (if chan-buf (progn - (org-pop-to-buffer-same-window chan-buf) + (pop-to-buffer-same-window chan-buf) ;; if we got a nick, and they're in the chan, ;; then start a chat with them (let ((nick (pop link))) @@ -244,9 +238,9 @@ default." (insert (concat nick ": "))) (error "%s not found in %s" nick chan-name))))) (progn - (org-pop-to-buffer-same-window server-buffer) + (pop-to-buffer-same-window server-buffer) (erc-cmd-JOIN chan-name)))) - (org-pop-to-buffer-same-window server-buffer))) + (pop-to-buffer-same-window server-buffer))) ;; no server match, make new connection (erc-select :server server :port port)))) diff --git a/lisp/org/org-lint.el b/lisp/org/org-lint.el new file mode 100644 index 00000000000..5abda7c4a6b --- /dev/null +++ b/lisp/org/org-lint.el @@ -0,0 +1,1227 @@ +;;; org-lint.el --- Linting for Org documents -*- lexical-binding: t; -*- + +;; Copyright (C) 2015-2017 Free Software Foundation, Inc. + +;; Author: Nicolas Goaziou +;; Keywords: outlines, hypermedia, calendar, wp + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; This library implements linting for Org syntax. The sole public +;; function is `org-lint', which see. + +;; Internally, the library defines a new structure: +;; `org-lint-checker', with the following slots: + +;; - NAME: Unique check identifier, as a non-nil symbol that doesn't +;; start with an hyphen. +;; +;; The check is done calling the function `org-lint-NAME' with one +;; mandatory argument, the parse tree describing the current Org +;; buffer. Such function calls are wrapped within +;; a `save-excursion' and point is always at `point-min'. Its +;; return value has to be an alist (POSITION MESSAGE) when +;; POSITION refer to the buffer position of the error, as an +;; integer, and MESSAGE is a string describing the error. + +;; - DESCRIPTION: Summary about the check, as a string. + +;; - CATEGORIES: Categories relative to the check, as a list of +;; symbol. They are used for filtering when calling `org-lint'. +;; Checkers not explicitly associated to a category are collected +;; in the `default' one. + +;; - TRUST: The trust level one can have in the check. It is either +;; `low' or `high', depending on the heuristics implemented and +;; the nature of the check. This has an indicative value only and +;; is displayed along reports. + +;; All checks have to be listed in `org-lint--checkers'. + +;; Results are displayed in a special "*Org Lint*" buffer with +;; a dedicated major mode, derived from `tabulated-list-mode'. +;; +;; In addition to the usual key-bindings inherited from it, "C-j" and +;; "TAB" display problematic line reported under point whereas "RET" +;; jumps to it. Also, "h" hides all reports similar to the current +;; one. Additionally, "i" removes them from subsequent reports. + +;; Checks currently implemented are: + +;; - duplicate CUSTOM_ID properties +;; - duplicate NAME values +;; - duplicate targets +;; - duplicate footnote definitions +;; - orphaned affiliated keywords +;; - obsolete affiliated keywords +;; - missing language in src blocks +;; - missing back-end in export blocks +;; - invalid Babel call blocks +;; - NAME values with a colon +;; - deprecated export block syntax +;; - deprecated Babel header properties +;; - wrong header arguments in src blocks +;; - misuse of CATEGORY keyword +;; - "coderef" links with unknown destination +;; - "custom-id" links with unknown destination +;; - "fuzzy" links with unknown destination +;; - "id" links with unknown destination +;; - links to non-existent local files +;; - SETUPFILE keywords with non-existent file parameter +;; - INCLUDE keywords with wrong link parameter +;; - obsolete markup in INCLUDE keyword +;; - unknown items in OPTIONS keyword +;; - spurious macro arguments or invalid macro templates +;; - special properties in properties drawer +;; - obsolete syntax for PROPERTIES drawers +;; - missing definition for footnote references +;; - missing reference for footnote definitions +;; - non-footnote definitions in footnote section +;; - probable invalid keywords +;; - invalid blocks +;; - misplaced planning info line +;; - incomplete drawers +;; - indented diary-sexps +;; - obsolete QUOTE section +;; - obsolete "file+application" link +;; - blank headlines with tags + + +;;; Code: + +(require 'cl-lib) +(require 'org-element) +(require 'org-macro) +(require 'ox) +(require 'ob) + + +;;; Checkers + +(cl-defstruct (org-lint-checker (:copier nil)) + (name 'missing-checker-name) + (description "") + (categories '(default)) + (trust 'high)) ; `low' or `high' + +(defun org-lint-missing-checker-name (_) + (error + "`A checker has no `:name' property. Please verify `org-lint--checkers'")) + +(defconst org-lint--checkers + (list + (make-org-lint-checker + :name 'duplicate-custom-id + :description "Report duplicates CUSTOM_ID properties" + :categories '(link)) + (make-org-lint-checker + :name 'duplicate-name + :description "Report duplicate NAME values" + :categories '(babel link)) + (make-org-lint-checker + :name 'duplicate-target + :description "Report duplicate targets" + :categories '(link)) + (make-org-lint-checker + :name 'duplicate-footnote-definition + :description "Report duplicate footnote definitions" + :categories '(footnote)) + (make-org-lint-checker + :name 'orphaned-affiliated-keywords + :description "Report orphaned affiliated keywords" + :trust 'low) + (make-org-lint-checker + :name 'obsolete-affiliated-keywords + :description "Report obsolete affiliated keywords" + :categories '(obsolete)) + (make-org-lint-checker + :name 'deprecated-export-blocks + :description "Report deprecated export block syntax" + :categories '(obsolete export) + :trust 'low) + (make-org-lint-checker + :name 'deprecated-header-syntax + :description "Report deprecated Babel header syntax" + :categories '(obsolete babel) + :trust 'low) + (make-org-lint-checker + :name 'missing-language-in-src-block + :description "Report missing language in src blocks" + :categories '(babel)) + (make-org-lint-checker + :name 'missing-backend-in-export-block + :description "Report missing back-end in export blocks" + :categories '(export)) + (make-org-lint-checker + :name 'invalid-babel-call-block + :description "Report invalid Babel call blocks" + :categories '(babel)) + (make-org-lint-checker + :name 'colon-in-name + :description "Report NAME values with a colon" + :categories '(babel)) + (make-org-lint-checker + :name 'wrong-header-argument + :description "Report wrong babel headers" + :categories '(babel)) + (make-org-lint-checker + :name 'wrong-header-value + :description "Report invalid value in babel headers" + :categories '(babel) + :trust 'low) + (make-org-lint-checker + :name 'deprecated-category-setup + :description "Report misuse of CATEGORY keyword" + :categories '(obsolete)) + (make-org-lint-checker + :name 'invalid-coderef-link + :description "Report \"coderef\" links with unknown destination" + :categories '(link)) + (make-org-lint-checker + :name 'invalid-custom-id-link + :description "Report \"custom-id\" links with unknown destination" + :categories '(link)) + (make-org-lint-checker + :name 'invalid-fuzzy-link + :description "Report \"fuzzy\" links with unknown destination" + :categories '(link)) + (make-org-lint-checker + :name 'invalid-id-link + :description "Report \"id\" links with unknown destination" + :categories '(link)) + (make-org-lint-checker + :name 'link-to-local-file + :description "Report links to non-existent local files" + :categories '(link) + :trust 'low) + (make-org-lint-checker + :name 'non-existent-setupfile-parameter + :description "Report SETUPFILE keywords with non-existent file parameter" + :trust 'low) + (make-org-lint-checker + :name 'wrong-include-link-parameter + :description "Report INCLUDE keywords with misleading link parameter" + :categories '(export) + :trust 'low) + (make-org-lint-checker + :name 'obsolete-include-markup + :description "Report obsolete markup in INCLUDE keyword" + :categories '(obsolete export) + :trust 'low) + (make-org-lint-checker + :name 'unknown-options-item + :description "Report unknown items in OPTIONS keyword" + :categories '(export) + :trust 'low) + (make-org-lint-checker + :name 'invalid-macro-argument-and-template + :description "Report spurious macro arguments or invalid macro templates" + :categories '(export) + :trust 'low) + (make-org-lint-checker + :name 'special-property-in-properties-drawer + :description "Report special properties in properties drawers" + :categories '(properties)) + (make-org-lint-checker + :name 'obsolete-properties-drawer + :description "Report obsolete syntax for properties drawers" + :categories '(obsolete properties)) + (make-org-lint-checker + :name 'undefined-footnote-reference + :description "Report missing definition for footnote references" + :categories '(footnote)) + (make-org-lint-checker + :name 'unreferenced-footnote-definition + :description "Report missing reference for footnote definitions" + :categories '(footnote)) + (make-org-lint-checker + :name 'extraneous-element-in-footnote-section + :description "Report non-footnote definitions in footnote section" + :categories '(footnote)) + (make-org-lint-checker + :name 'invalid-keyword-syntax + :description "Report probable invalid keywords" + :trust 'low) + (make-org-lint-checker + :name 'invalid-block + :description "Report invalid blocks" + :trust 'low) + (make-org-lint-checker + :name 'misplaced-planning-info + :description "Report misplaced planning info line" + :trust 'low) + (make-org-lint-checker + :name 'incomplete-drawer + :description "Report probable incomplete drawers" + :trust 'low) + (make-org-lint-checker + :name 'indented-diary-sexp + :description "Report probable indented diary-sexps" + :trust 'low) + (make-org-lint-checker + :name 'quote-section + :description "Report obsolete QUOTE section" + :categories '(obsolete) + :trust 'low) + (make-org-lint-checker + :name 'file-application + :description "Report obsolete \"file+application\" link" + :categories '(link obsolete)) + (make-org-lint-checker + :name 'empty-headline-with-tags + :description "Report ambiguous empty headlines with tags" + :categories '(headline) + :trust 'low)) + "List of all available checkers.") + +(defun org-lint--collect-duplicates + (ast type extract-key extract-position build-message) + "Helper function to collect duplicates in parse tree AST. + +EXTRACT-KEY is a function extracting key. It is called with +a single argument: the element or object. Comparison is done +with `equal'. + +EXTRACT-POSITION is a function returning position for the report. +It is called with two arguments, the object or element, and the +key. + +BUILD-MESSAGE is a function creating the report message. It is +called with one argument, the key used for comparison." + (let* (keys + originals + reports + (make-report + (lambda (position value) + (push (list position (funcall build-message value)) reports)))) + (org-element-map ast type + (lambda (datum) + (let ((key (funcall extract-key datum))) + (cond + ((not key)) + ((assoc key keys) (cl-pushnew (assoc key keys) originals) + (funcall make-report (funcall extract-position datum key) key)) + (t (push (cons key (funcall extract-position datum key)) keys)))))) + (dolist (e originals reports) (funcall make-report (cdr e) (car e))))) + +(defun org-lint-duplicate-custom-id (ast) + (org-lint--collect-duplicates + ast + 'node-property + (lambda (property) + (and (eq (compare-strings "CUSTOM_ID" nil nil + (org-element-property :key property) nil nil + t) + t) + (org-element-property :value property))) + (lambda (property _) (org-element-property :begin property)) + (lambda (key) (format "Duplicate CUSTOM_ID property \"%s\"" key)))) + +(defun org-lint-duplicate-name (ast) + (org-lint--collect-duplicates + ast + org-element-all-elements + (lambda (datum) (org-element-property :name datum)) + (lambda (datum name) + (goto-char (org-element-property :begin datum)) + (re-search-forward + (format "^[ \t]*#\\+[A-Za-z]+: +%s *$" (regexp-quote name))) + (match-beginning 0)) + (lambda (key) (format "Duplicate NAME \"%s\"" key)))) + +(defun org-lint-duplicate-target (ast) + (org-lint--collect-duplicates + ast + 'target + (lambda (target) (org-split-string (org-element-property :value target))) + (lambda (target _) (org-element-property :begin target)) + (lambda (key) + (format "Duplicate target <<%s>>" (mapconcat #'identity key " "))))) + +(defun org-lint-duplicate-footnote-definition (ast) + (org-lint--collect-duplicates + ast + 'footnote-definition + (lambda (definition) (org-element-property :label definition)) + (lambda (definition _) (org-element-property :post-affiliated definition)) + (lambda (key) (format "Duplicate footnote definition \"%s\"" key)))) + +(defun org-lint-orphaned-affiliated-keywords (ast) + ;; Ignore orphan RESULTS keywords, which could be generated from + ;; a source block returning no value. + (let ((keywords (cl-set-difference org-element-affiliated-keywords + '("RESULT" "RESULTS") + :test #'equal))) + (org-element-map ast 'keyword + (lambda (k) + (let ((key (org-element-property :key k))) + (and (or (let ((case-fold-search t)) + (string-match-p "\\`ATTR_[-_A-Za-z0-9]+\\'" key)) + (member key keywords)) + (list (org-element-property :post-affiliated k) + (format "Orphaned affiliated keyword: \"%s\"" key)))))))) + +(defun org-lint-obsolete-affiliated-keywords (_) + (let ((regexp (format "^[ \t]*#\\+%s:" + (regexp-opt '("DATA" "LABEL" "RESNAME" "SOURCE" + "SRCNAME" "TBLNAME" "RESULT" "HEADERS") + t))) + reports) + (while (re-search-forward regexp nil t) + (let ((key (upcase (match-string-no-properties 1)))) + (when (< (point) + (org-element-property :post-affiliated (org-element-at-point))) + (push + (list (line-beginning-position) + (format + "Obsolete affiliated keyword: \"%s\". Use \"%s\" instead" + key + (pcase key + ("HEADERS" "HEADER") + ("RESULT" "RESULTS") + (_ "NAME")))) + reports)))) + reports)) + +(defun org-lint-deprecated-export-blocks (ast) + (let ((deprecated '("ASCII" "BEAMER" "HTML" "LATEX" "MAN" "MARKDOWN" "MD" + "ODT" "ORG" "TEXINFO"))) + (org-element-map ast 'special-block + (lambda (b) + (let ((type (org-element-property :type b))) + (when (member-ignore-case type deprecated) + (list + (org-element-property :post-affiliated b) + (format + "Deprecated syntax for export block. Use \"BEGIN_EXPORT %s\" \ +instead" + type)))))))) + +(defun org-lint-deprecated-header-syntax (ast) + (let* ((deprecated-babel-properties + (mapcar (lambda (arg) (symbol-name (car arg))) + org-babel-common-header-args-w-values)) + (deprecated-re + (format "\\`%s[ \t]" (regexp-opt deprecated-babel-properties t)))) + (org-element-map ast '(keyword node-property) + (lambda (datum) + (let ((key (org-element-property :key datum))) + (pcase (org-element-type datum) + (`keyword + (let ((value (org-element-property :value datum))) + (and (string= key "PROPERTY") + (string-match deprecated-re value) + (list (org-element-property :begin datum) + (format "Deprecated syntax for \"%s\". \ +Use header-args instead" + (match-string-no-properties 1 value)))))) + (`node-property + (and (member-ignore-case key deprecated-babel-properties) + (list + (org-element-property :begin datum) + (format "Deprecated syntax for \"%s\". \ +Use :header-args: instead" + key)))))))))) + +(defun org-lint-missing-language-in-src-block (ast) + (org-element-map ast 'src-block + (lambda (b) + (unless (org-element-property :language b) + (list (org-element-property :post-affiliated b) + "Missing language in source block"))))) + +(defun org-lint-missing-backend-in-export-block (ast) + (org-element-map ast 'export-block + (lambda (b) + (unless (org-element-property :type b) + (list (org-element-property :post-affiliated b) + "Missing back-end in export block"))))) + +(defun org-lint-invalid-babel-call-block (ast) + (org-element-map ast 'babel-call + (lambda (b) + (cond + ((not (org-element-property :call b)) + (list (org-element-property :post-affiliated b) + "Invalid syntax in babel call block")) + ((let ((h (org-element-property :end-header b))) + (and h (string-match-p "\\`\\[.*\\]\\'" h))) + (list + (org-element-property :post-affiliated b) + "Babel call's end header must not be wrapped within brackets")))))) + +(defun org-lint-deprecated-category-setup (ast) + (org-element-map ast 'keyword + (let (category-flag) + (lambda (k) + (cond + ((not (string= (org-element-property :key k) "CATEGORY")) nil) + (category-flag + (list (org-element-property :post-affiliated k) + "Spurious CATEGORY keyword. Set :CATEGORY: property instead")) + (t (setf category-flag t) nil)))))) + +(defun org-lint-invalid-coderef-link (ast) + (let ((info (list :parse-tree ast))) + (org-element-map ast 'link + (lambda (link) + (let ((ref (org-element-property :path link))) + (and (equal (org-element-property :type link) "coderef") + (not (ignore-errors (org-export-resolve-coderef ref info))) + (list (org-element-property :begin link) + (format "Unknown coderef \"%s\"" ref)))))))) + +(defun org-lint-invalid-custom-id-link (ast) + (let ((info (list :parse-tree ast))) + (org-element-map ast 'link + (lambda (link) + (and (equal (org-element-property :type link) "custom-id") + (not (ignore-errors (org-export-resolve-id-link link info))) + (list (org-element-property :begin link) + (format "Unknown custom ID \"%s\"" + (org-element-property :path link)))))))) + +(defun org-lint-invalid-fuzzy-link (ast) + (let ((info (list :parse-tree ast))) + (org-element-map ast 'link + (lambda (link) + (and (equal (org-element-property :type link) "fuzzy") + (not (ignore-errors (org-export-resolve-fuzzy-link link info))) + (list (org-element-property :begin link) + (format "Unknown fuzzy location \"%s\"" + (let ((path (org-element-property :path link))) + (if (string-prefix-p "*" path) + (substring path 1) + path))))))))) + +(defun org-lint-invalid-id-link (ast) + (org-element-map ast 'link + (lambda (link) + (let ((id (org-element-property :path link))) + (and (equal (org-element-property :type link) "id") + (not (org-id-find id)) + (list (org-element-property :begin link) + (format "Unknown ID \"%s\"" id))))))) + +(defun org-lint-special-property-in-properties-drawer (ast) + (org-element-map ast 'node-property + (lambda (p) + (let ((key (org-element-property :key p))) + (and (member-ignore-case key org-special-properties) + (list (org-element-property :begin p) + (format + "Special property \"%s\" found in a properties drawer" + key))))))) + +(defun org-lint-obsolete-properties-drawer (ast) + (org-element-map ast 'drawer + (lambda (d) + (when (equal (org-element-property :drawer-name d) "PROPERTIES") + (let ((section (org-element-lineage d '(section)))) + (unless (org-element-map section 'property-drawer #'identity nil t) + (list (org-element-property :post-affiliated d) + (if (save-excursion + (goto-char (org-element-property :post-affiliated d)) + (forward-line -1) + (or (org-at-heading-p) (org-at-planning-p))) + "Incorrect contents for PROPERTIES drawer" + "Incorrect location for PROPERTIES drawer")))))))) + +(defun org-lint-link-to-local-file (ast) + (org-element-map ast 'link + (lambda (l) + (when (equal (org-element-property :type l) "file") + (let ((file (org-link-unescape (org-element-property :path l)))) + (and (not (file-remote-p file)) + (not (file-exists-p file)) + (list (org-element-property :begin l) + (format (if (org-element-lineage l '(link)) + "Link to non-existent image file \"%s\"\ + in link description" + "Link to non-existent local file \"%s\"") + file)))))))) + +(defun org-lint-non-existent-setupfile-parameter (ast) + (org-element-map ast 'keyword + (lambda (k) + (when (equal (org-element-property :key k) "SETUPFILE") + (let ((file (org-unbracket-string + "\"" "\"" + (org-element-property :value k)))) + (and (not (file-remote-p file)) + (not (file-exists-p file)) + (list (org-element-property :begin k) + (format "Non-existent setup file \"%s\"" file)))))))) + +(defun org-lint-wrong-include-link-parameter (ast) + (org-element-map ast 'keyword + (lambda (k) + (when (equal (org-element-property :key k) "INCLUDE") + (let* ((value (org-element-property :value k)) + (path + (and (string-match "^\\(\".+\"\\|\\S-+\\)[ \t]*" value) + (save-match-data + (org-unbracket-string "\"" "\"" (match-string 1 value)))))) + (if (not path) + (list (org-element-property :post-affiliated k) + "Missing location argument in INCLUDE keyword") + (let* ((file (org-string-nw-p + (if (string-match "::\\(.*\\)\\'" path) + (substring path 0 (match-beginning 0)) + path))) + (search (and (not (equal file path)) + (org-string-nw-p (match-string 1 path))))) + (if (and file + (not (file-remote-p file)) + (not (file-exists-p file))) + (list (org-element-property :post-affiliated k) + "Non-existent file argument in INCLUDE keyword") + (let* ((visiting (if file (find-buffer-visiting file) + (current-buffer))) + (buffer (or visiting (find-file-noselect file)))) + (unwind-protect + (with-current-buffer buffer + (when (and search + (not + (ignore-errors + (let ((org-link-search-inhibit-query t)) + (org-link-search search nil t))))) + (list (org-element-property :post-affiliated k) + (format + "Invalid search part \"%s\" in INCLUDE keyword" + search)))) + (unless visiting (kill-buffer buffer)))))))))))) + +(defun org-lint-obsolete-include-markup (ast) + (let ((regexp (format "\\`\\(?:\".+\"\\|\\S-+\\)[ \t]+%s" + (regexp-opt + '("ASCII" "BEAMER" "HTML" "LATEX" "MAN" "MARKDOWN" "MD" + "ODT" "ORG" "TEXINFO") + t)))) + (org-element-map ast 'keyword + (lambda (k) + (when (equal (org-element-property :key k) "INCLUDE") + (let ((case-fold-search t) + (value (org-element-property :value k))) + (when (string-match regexp value) + (let ((markup (match-string-no-properties 1 value))) + (list (org-element-property :post-affiliated k) + (format "Obsolete markup \"%s\" in INCLUDE keyword. \ +Use \"export %s\" instead" + markup + markup)))))))))) + +(defun org-lint-unknown-options-item (ast) + (let ((allowed (delq nil + (append + (mapcar (lambda (o) (nth 2 o)) org-export-options-alist) + (cl-mapcan + (lambda (b) + (mapcar (lambda (o) (nth 2 o)) + (org-export-backend-options b))) + org-export-registered-backends)))) + reports) + (org-element-map ast 'keyword + (lambda (k) + (when (string= (org-element-property :key k) "OPTIONS") + (let ((value (org-element-property :value k)) + (start 0)) + (while (string-match "\\(.+?\\):\\((.*?)\\|\\S-*\\)[ \t]*" + value + start) + (setf start (match-end 0)) + (let ((item (match-string 1 value))) + (unless (member item allowed) + (push (list (org-element-property :post-affiliated k) + (format "Unknown OPTIONS item \"%s\"" item)) + reports)))))))) + reports)) + +(defun org-lint-invalid-macro-argument-and-template (ast) + (let ((extract-placeholders + (lambda (template) + (let ((start 0) + args) + (while (string-match "\\$\\([1-9][0-9]*\\)" template start) + (setf start (match-end 0)) + (push (string-to-number (match-string 1 template)) args)) + (sort (org-uniquify args) #'<)))) + reports) + ;; Check arguments for macro templates. + (org-element-map ast 'keyword + (lambda (k) + (when (string= (org-element-property :key k) "MACRO") + (let* ((value (org-element-property :value k)) + (name (and (string-match "^\\S-+" value) + (match-string 0 value))) + (template (and name + (org-trim (substring value (match-end 0)))))) + (cond + ((not name) + (push (list (org-element-property :post-affiliated k) + "Missing name in MACRO keyword") + reports)) + ((not (org-string-nw-p template)) + (push (list (org-element-property :post-affiliated k) + "Missing template in macro \"%s\"" name) + reports)) + (t + (unless (let ((args (funcall extract-placeholders template))) + (equal (number-sequence 1 (or (org-last args) 0)) args)) + (push (list (org-element-property :post-affiliated k) + (format "Unused placeholders in macro \"%s\"" + name)) + reports)))))))) + ;; Check arguments for macros. + (org-macro-initialize-templates) + (let ((templates (append + (mapcar (lambda (m) (cons m "$1")) + '("author" "date" "email" "title" "results")) + org-macro-templates))) + (org-element-map ast 'macro + (lambda (macro) + (let* ((name (org-element-property :key macro)) + (template (cdr (assoc-string name templates t)))) + (if (not template) + (push (list (org-element-property :begin macro) + (format "Undefined macro \"%s\"" name)) + reports) + (let ((arg-numbers (funcall extract-placeholders template))) + (when arg-numbers + (let ((spurious-args + (nthcdr (apply #'max arg-numbers) + (org-element-property :args macro)))) + (when spurious-args + (push + (list (org-element-property :begin macro) + (format "Unused argument%s in macro \"%s\": %s" + (if (> (length spurious-args) 1) "s" "") + name + (mapconcat (lambda (a) (format "\"%s\"" a)) + spurious-args + ", "))) + reports)))))))))) + reports)) + +(defun org-lint-undefined-footnote-reference (ast) + (let ((definitions (org-element-map ast 'footnote-definition + (lambda (f) (org-element-property :label f))))) + (org-element-map ast 'footnote-reference + (lambda (f) + (let ((label (org-element-property :label f))) + (and label + (not (member label definitions)) + (list (org-element-property :begin f) + (format "Missing definition for footnote [%s]" + label)))))))) + +(defun org-lint-unreferenced-footnote-definition (ast) + (let ((references (org-element-map ast 'footnote-reference + (lambda (f) (org-element-property :label f))))) + (org-element-map ast 'footnote-definition + (lambda (f) + (let ((label (org-element-property :label f))) + (and label + (not (member label references)) + (list (org-element-property :post-affiliated f) + (format "No reference for footnote definition [%s]" + label)))))))) + +(defun org-lint-colon-in-name (ast) + (org-element-map ast org-element-all-elements + (lambda (e) + (let ((name (org-element-property :name e))) + (and name + (string-match-p ":" name) + (list (progn + (goto-char (org-element-property :begin e)) + (re-search-forward + (format "^[ \t]*#\\+\\w+: +%s *$" (regexp-quote name))) + (match-beginning 0)) + (format + "Name \"%s\" contains a colon; Babel cannot use it as input" + name))))))) + +(defun org-lint-misplaced-planning-info (_) + (let ((case-fold-search t) + reports) + (while (re-search-forward org-planning-line-re nil t) + (unless (memq (org-element-type (org-element-at-point)) + '(comment-block example-block export-block planning + src-block verse-block)) + (push (list (line-beginning-position) "Misplaced planning info line") + reports))) + reports)) + +(defun org-lint-incomplete-drawer (_) + (let (reports) + (while (re-search-forward org-drawer-regexp nil t) + (let ((name (org-trim (match-string-no-properties 0))) + (element (org-element-at-point))) + (pcase (org-element-type element) + ((or `drawer `property-drawer) + (goto-char (org-element-property :end element)) + nil) + ((or `comment-block `example-block `export-block `src-block + `verse-block) + nil) + (_ + (push (list (line-beginning-position) + (format "Possible incomplete drawer \"%s\"" name)) + reports))))) + reports)) + +(defun org-lint-indented-diary-sexp (_) + (let (reports) + (while (re-search-forward "^[ \t]+%%(" nil t) + (unless (memq (org-element-type (org-element-at-point)) + '(comment-block diary-sexp example-block export-block + src-block verse-block)) + (push (list (line-beginning-position) "Possible indented diary-sexp") + reports))) + reports)) + +(defun org-lint-invalid-block (_) + (let ((case-fold-search t) + (regexp "^[ \t]*#\\+\\(BEGIN\\|END\\)\\(?::\\|_[^[:space:]]*\\)?[ \t]*") + reports) + (while (re-search-forward regexp nil t) + (let ((name (org-trim (buffer-substring-no-properties + (line-beginning-position) (line-end-position))))) + (cond + ((and (string-prefix-p "END" (match-string 1) t) + (not (eolp))) + (push (list (line-beginning-position) + (format "Invalid block closing line \"%s\"" name)) + reports)) + ((not (memq (org-element-type (org-element-at-point)) + '(center-block comment-block dynamic-block example-block + export-block quote-block special-block + src-block verse-block))) + (push (list (line-beginning-position) + (format "Possible incomplete block \"%s\"" + name)) + reports))))) + reports)) + +(defun org-lint-invalid-keyword-syntax (_) + (let ((regexp "^[ \t]*#\\+\\([^[:space:]:]*\\)\\(?: \\|$\\)") + (exception-re + (format "[ \t]*#\\+%s\\(\\[.*\\]\\)?:\\(?: \\|$\\)" + (regexp-opt org-element-dual-keywords))) + reports) + (while (re-search-forward regexp nil t) + (let ((name (match-string-no-properties 1))) + (unless (or (string-prefix-p "BEGIN" name t) + (string-prefix-p "END" name t) + (save-excursion + (beginning-of-line) + (let ((case-fold-search t)) (looking-at exception-re)))) + (push (list (match-beginning 0) + (format "Possible missing colon in keyword \"%s\"" name)) + reports)))) + reports)) + +(defun org-lint-extraneous-element-in-footnote-section (ast) + (org-element-map ast 'headline + (lambda (h) + (and (org-element-property :footnote-section-p h) + (org-element-map (org-element-contents h) + (cl-remove-if + (lambda (e) + (memq e '(comment comment-block footnote-definition + property-drawer section))) + org-element-all-elements) + (lambda (e) + (not (and (eq (org-element-type e) 'headline) + (org-element-property :commentedp e)))) + nil t '(footnote-definition property-drawer)) + (list (org-element-property :begin h) + "Extraneous elements in footnote section are not exported"))))) + +(defun org-lint-quote-section (ast) + (org-element-map ast '(headline inlinetask) + (lambda (h) + (let ((title (org-element-property :raw-value h))) + (and (or (string-prefix-p "QUOTE " title) + (string-prefix-p (concat org-comment-string " QUOTE ") title)) + (list (org-element-property :begin h) + "Deprecated QUOTE section")))))) + +(defun org-lint-file-application (ast) + (org-element-map ast 'link + (lambda (l) + (let ((app (org-element-property :application l))) + (and app + (list (org-element-property :begin l) + (format "Deprecated \"file+%s\" link type" app))))))) + +(defun org-lint-wrong-header-argument (ast) + (let* ((reports) + (verify + (lambda (datum language headers) + (let ((allowed + ;; If LANGUAGE is specified, restrict allowed + ;; headers to both LANGUAGE-specific and default + ;; ones. Otherwise, accept headers from any loaded + ;; language. + (append + org-babel-header-arg-names + (cl-mapcan + (lambda (l) + (let ((v (intern (format "org-babel-header-args:%s" l)))) + (and (boundp v) (mapcar #'car (symbol-value v))))) + (if language (list language) + (mapcar #'car org-babel-load-languages)))))) + (dolist (header headers) + (let ((h (symbol-name (car header))) + (p (or (org-element-property :post-affiliated datum) + (org-element-property :begin datum)))) + (cond + ((not (string-prefix-p ":" h)) + (push + (list p + (format "Missing colon in header argument \"%s\"" h)) + reports)) + ((assoc-string (substring h 1) allowed)) + (t (push (list p (format "Unknown header argument \"%s\"" h)) + reports))))))))) + (org-element-map ast '(babel-call inline-babel-call inline-src-block keyword + node-property src-block) + (lambda (datum) + (pcase (org-element-type datum) + ((or `babel-call `inline-babel-call) + (funcall verify + datum + nil + (cl-mapcan #'org-babel-parse-header-arguments + (list + (org-element-property :inside-header datum) + (org-element-property :end-header datum))))) + (`inline-src-block + (funcall verify + datum + (org-element-property :language datum) + (org-babel-parse-header-arguments + (org-element-property :parameters datum)))) + (`keyword + (when (string= (org-element-property :key datum) "PROPERTY") + (let ((value (org-element-property :value datum))) + (when (string-match "\\`header-args\\(?::\\(\\S-+\\)\\)?\\+? *" + value) + (funcall verify + datum + (match-string 1 value) + (org-babel-parse-header-arguments + (substring value (match-end 0)))))))) + (`node-property + (let ((key (org-element-property :key datum))) + (when (let ((case-fold-search t)) + (string-match "\\`HEADER-ARGS\\(?::\\(\\S-+\\)\\)?\\+?" + key)) + (funcall verify + datum + (match-string 1 key) + (org-babel-parse-header-arguments + (org-element-property :value datum)))))) + (`src-block + (funcall verify + datum + (org-element-property :language datum) + (cl-mapcan #'org-babel-parse-header-arguments + (cons (org-element-property :parameters datum) + (org-element-property :header datum)))))))) + reports)) + +(defun org-lint-wrong-header-value (ast) + (let (reports) + (org-element-map ast + '(babel-call inline-babel-call inline-src-block src-block) + (lambda (datum) + (let* ((type (org-element-type datum)) + (language (org-element-property :language datum)) + (allowed-header-values + (append (and language + (let ((v (intern (concat "org-babel-header-args:" + language)))) + (and (boundp v) (symbol-value v)))) + org-babel-common-header-args-w-values)) + (datum-header-values + (org-babel-parse-header-arguments + (org-trim + (pcase type + (`src-block + (mapconcat + #'identity + (cons (org-element-property :parameters datum) + (org-element-property :header datum)) + " ")) + (`inline-src-block + (or (org-element-property :parameters datum) "")) + (_ + (concat + (org-element-property :inside-header datum) + " " + (org-element-property :end-header datum)))))))) + (dolist (header datum-header-values) + (let ((allowed-values + (cdr (assoc-string (substring (symbol-name (car header)) 1) + allowed-header-values)))) + (unless (memq allowed-values '(:any nil)) + (let ((values (cdr header)) + groups-alist) + (dolist (v (if (stringp values) (org-split-string values) + (list values))) + (let ((valid-value nil)) + (catch 'exit + (dolist (group allowed-values) + (cond + ((not (funcall + (if (stringp v) #'assoc-string #'assoc) + v group)) + (when (memq :any group) + (setf valid-value t) + (push (cons group v) groups-alist))) + ((assq group groups-alist) + (push + (list + (or (org-element-property :post-affiliated datum) + (org-element-property :begin datum)) + (format + "Forbidden combination in header \"%s\": %s, %s" + (car header) + (cdr (assq group groups-alist)) + v)) + reports) + (throw 'exit nil)) + (t (push (cons group v) groups-alist) + (setf valid-value t)))) + (unless valid-value + (push + (list + (or (org-element-property :post-affiliated datum) + (org-element-property :begin datum)) + (format "Unknown value \"%s\" for header \"%s\"" + v + (car header))) + reports)))))))))))) + reports)) + +(defun org-lint-empty-headline-with-tags (ast) + (org-element-map ast '(headline inlinetask) + (lambda (h) + (let ((title (org-element-property :raw-value h))) + (and (string-match-p "\\`:[[:alnum:]_@#%:]+:\\'" title) + (list (org-element-property :begin h) + (format "Headline containing only tags is ambiguous: %S" + title))))))) + + +;;; Reports UI + +(defvar org-lint--report-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map tabulated-list-mode-map) + (define-key map (kbd "RET") 'org-lint--jump-to-source) + (define-key map (kbd "TAB") 'org-lint--show-source) + (define-key map (kbd "C-j") 'org-lint--show-source) + (define-key map (kbd "h") 'org-lint--hide-checker) + (define-key map (kbd "i") 'org-lint--ignore-checker) + map) + "Local keymap for `org-lint--report-mode' buffers.") + +(define-derived-mode org-lint--report-mode tabulated-list-mode "OrgLint" + "Major mode used to display reports emitted during linting. +\\{org-lint--report-mode-map}" + (setf tabulated-list-format + `[("Line" 6 + (lambda (a b) + (< (string-to-number (aref (cadr a) 0)) + (string-to-number (aref (cadr b) 0)))) + :right-align t) + ("Trust" 5 t) + ("Warning" 0 t)]) + (tabulated-list-init-header)) + +(defun org-lint--generate-reports (buffer checkers) + "Generate linting report for BUFFER. + +CHECKERS is the list of checkers used. + +Return an alist (ID [LINE TRUST DESCRIPTION CHECKER]), suitable +for `tabulated-list-printer'." + (with-current-buffer buffer + (save-excursion + (goto-char (point-min)) + (let ((ast (org-element-parse-buffer)) + (id 0) + (last-line 1) + (last-pos 1)) + ;; Insert unique ID for each report. Replace buffer positions + ;; with line numbers. + (mapcar + (lambda (report) + (list + (cl-incf id) + (apply #'vector + (cons + (progn + (goto-char (car report)) + (beginning-of-line) + (prog1 (number-to-string + (cl-incf last-line + (count-lines last-pos (point)))) + (setf last-pos (point)))) + (cdr report))))) + ;; Insert trust level in generated reports. Also sort them + ;; by buffer position in order to optimize lines computation. + (sort (cl-mapcan + (lambda (c) + (let ((trust (symbol-name (org-lint-checker-trust c)))) + (mapcar + (lambda (report) + (list (car report) trust (nth 1 report) c)) + (save-excursion + (funcall + (intern (format "org-lint-%s" + (org-lint-checker-name c))) + ast))))) + checkers) + #'car-less-than-car)))))) + +(defvar-local org-lint--source-buffer nil + "Source buffer associated to current report buffer.") + +(defvar-local org-lint--local-checkers nil + "List of checkers used to build current report.") + +(defun org-lint--refresh-reports () + (setq tabulated-list-entries + (org-lint--generate-reports org-lint--source-buffer + org-lint--local-checkers)) + (tabulated-list-print)) + +(defun org-lint--current-line () + "Return current report line, as a number." + (string-to-number (aref (tabulated-list-get-entry) 0))) + +(defun org-lint--current-checker (&optional entry) + "Return current report checker. +When optional argument ENTRY is non-nil, use this entry instead +of current one." + (aref (if entry (nth 1 entry) (tabulated-list-get-entry)) 3)) + +(defun org-lint--display-reports (source checkers) + "Display linting reports for buffer SOURCE. +CHECKERS is the list of checkers used." + (let ((buffer (get-buffer-create "*Org Lint*"))) + (with-current-buffer buffer + (org-lint--report-mode) + (setf org-lint--source-buffer source) + (setf org-lint--local-checkers checkers) + (org-lint--refresh-reports) + (tabulated-list-print) + (add-hook 'tabulated-list-revert-hook #'org-lint--refresh-reports nil t)) + (pop-to-buffer buffer))) + +(defun org-lint--jump-to-source () + "Move to source line that generated the report at point." + (interactive) + (let ((l (org-lint--current-line))) + (switch-to-buffer-other-window org-lint--source-buffer) + (org-goto-line l) + (org-show-set-visibility 'local) + (recenter))) + +(defun org-lint--show-source () + "Show source line that generated the report at point." + (interactive) + (let ((buffer (current-buffer))) + (org-lint--jump-to-source) + (switch-to-buffer-other-window buffer))) + +(defun org-lint--hide-checker () + "Hide all reports from checker that generated the report at point." + (interactive) + (let ((c (org-lint--current-checker))) + (setf tabulated-list-entries + (cl-remove-if (lambda (e) (equal c (org-lint--current-checker e))) + tabulated-list-entries)) + (tabulated-list-print))) + +(defun org-lint--ignore-checker () + "Ignore all reports from checker that generated the report at point. +Checker will also be ignored in all subsequent reports." + (interactive) + (setf org-lint--local-checkers + (remove (org-lint--current-checker) org-lint--local-checkers)) + (org-lint--hide-checker)) + + +;;; Public function + +;;;###autoload +(defun org-lint (&optional arg) + "Check current Org buffer for syntax mistakes. + +By default, run all checkers. With a `\\[universal-argument]' prefix ARG, \ +select one +category of checkers only. With a `\\[universal-argument] \ +\\[universal-argument]' prefix, run one precise +checker by its name. + +ARG can also be a list of checker names, as symbols, to run." + (interactive "P") + (unless (derived-mode-p 'org-mode) (user-error "Not in an Org buffer")) + (when (called-interactively-p 'any) + (message "Org linting process starting...")) + (let ((checkers + (pcase arg + (`nil org-lint--checkers) + (`(4) + (let ((category + (completing-read + "Checker category: " + (mapcar #'org-lint-checker-categories org-lint--checkers) + nil t))) + (cl-remove-if-not + (lambda (c) + (assoc-string (org-lint-checker-categories c) category)) + org-lint--checkers))) + (`(16) + (list + (let ((name (completing-read + "Checker name: " + (mapcar #'org-lint-checker-name org-lint--checkers) + nil t))) + (catch 'exit + (dolist (c org-lint--checkers) + (when (string= (org-lint-checker-name c) name) + (throw 'exit c))))))) + ((pred consp) + (cl-remove-if-not (lambda (c) (memq (org-lint-checker-name c) arg)) + org-lint--checkers)) + (_ (user-error "Invalid argument `%S' for `org-lint'" arg))))) + (if (not (called-interactively-p 'any)) + (org-lint--generate-reports (current-buffer) checkers) + (org-lint--display-reports (current-buffer) checkers) + (message "Org linting process completed")))) + + +(provide 'org-lint) +;;; org-lint.el ends here diff --git a/lisp/org/org-list.el b/lisp/org/org-list.el index 4a45fd9817a..a3e26256f9b 100644 --- a/lisp/org/org-list.el +++ b/lisp/org/org-list.el @@ -1,4 +1,4 @@ -;;; org-list.el --- Plain lists for Org-mode +;;; org-list.el --- Plain lists for Org -*- lexical-binding: t; -*- ;; ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. ;; @@ -25,7 +25,7 @@ ;; ;;; Commentary: -;; This file contains the code dealing with plain lists in Org-mode. +;; This file contains the code dealing with plain lists in Org mode. ;; The core concept behind lists is their structure. A structure is ;; a snapshot of the list, in the shape of a data tree (see @@ -76,8 +76,7 @@ ;;; Code: -(eval-when-compile - (require 'cl)) +(require 'cl-lib) (require 'org-macs) (require 'org-compat) @@ -88,59 +87,84 @@ (defvar org-closed-string) (defvar org-deadline-string) (defvar org-description-max-indent) -(defvar org-drawers) +(defvar org-done-keywords) +(defvar org-drawer-regexp) +(defvar org-element-all-objects) +(defvar org-inhibit-startup) (defvar org-odd-levels-only) +(defvar org-outline-regexp-bol) (defvar org-scheduled-string) +(defvar org-todo-line-regexp) (defvar org-ts-regexp) (defvar org-ts-regexp-both) -(declare-function outline-invisible-p "outline" (&optional pos)) -(declare-function outline-flag-region "outline" (from to flag)) -(declare-function outline-next-heading "outline" ()) -(declare-function outline-previous-heading "outline" ()) - -(declare-function org-at-heading-p "org" (&optional ignored)) -(declare-function org-before-first-heading-p "org" ()) +(declare-function org-at-heading-p "org" (&optional invisible-ok)) (declare-function org-back-to-heading "org" (&optional invisible-ok)) +(declare-function org-before-first-heading-p "org" ()) (declare-function org-combine-plists "org" (&rest plists)) -(declare-function org-count "org" (cl-item cl-seq)) (declare-function org-current-level "org" ()) +(declare-function org-element-at-point "org-element" ()) +(declare-function org-element-context "org-element" (&optional element)) +(declare-function org-element-interpret-data "org-element" (data)) +(declare-function + org-element-lineage "org-element" (blob &optional types with-self)) +(declare-function org-element-macro-interpreter "org-element" (macro ##)) +(declare-function + org-element-map "org-element" + (data types fun &optional info first-match no-recursion with-affiliated)) +(declare-function org-element-normalize-string "org-element" (s)) +(declare-function org-element-parse-buffer "org-element" + (&optional granularity visible-only)) +(declare-function org-element-property "org-element" (property element)) +(declare-function org-element-put-property "org-element" + (element property value)) +(declare-function org-element-set-element "org-element" (old new)) +(declare-function org-element-type "org-element" (element)) +(declare-function org-element-update-syntax "org-element" ()) (declare-function org-entry-get "org" (pom property &optional inherit literal-nil)) +(declare-function org-export-create-backend "ox" (&rest rest) t) +(declare-function org-export-data-with-backend "ox" (data backend info)) +(declare-function org-export-get-backend "ox" (name)) +(declare-function org-export-get-environment "ox" + (&optional backend subtreep ext-plist)) +(declare-function org-export-get-next-element "ox" + (blob info &optional n)) +(declare-function org-export-with-backend "ox" + (backend data &optional contents info)) (declare-function org-fix-tags-on-the-fly "org" ()) (declare-function org-get-indentation "org" (&optional line)) -(declare-function org-icompleting-read "org" (&rest args)) +(declare-function org-get-todo-state "org" ()) (declare-function org-in-block-p "org" (names)) (declare-function org-in-regexp "org" (re &optional nlines visually)) +(declare-function org-inlinetask-goto-beginning "org-inlinetask" ()) +(declare-function org-inlinetask-goto-end "org-inlinetask" ()) +(declare-function org-inlinetask-in-task-p "org-inlinetask" ()) +(declare-function org-inlinetask-outline-regexp "org-inlinetask" ()) (declare-function org-level-increment "org" ()) (declare-function org-narrow-to-subtree "org" ()) -(declare-function org-at-heading-p "org" (&optional invisible-ok)) -(declare-function org-previous-line-empty-p "org" (&optional next)) -(declare-function org-remove-if "org" (predicate seq)) +(declare-function org-outline-level "org" ()) +(declare-function org-previous-line-empty-p "org" ()) (declare-function org-reduced-level "org" (L)) +(declare-function org-remove-indentation "org" (code &optional n)) (declare-function org-show-subtree "org" ()) (declare-function org-sort-remove-invisible "org" (S)) (declare-function org-time-string-to-seconds "org" (s)) (declare-function org-timer-hms-to-secs "org-timer" (hms)) (declare-function org-timer-item "org-timer" (&optional arg)) -(declare-function org-trim "org" (s)) +(declare-function org-trim "org" (s &optional keep-lead)) (declare-function org-uniquify "org" (list)) - -(declare-function org-inlinetask-goto-beginning "org-inlinetask" ()) -(declare-function org-inlinetask-goto-end "org-inlinetask" ()) -(declare-function org-inlinetask-in-task-p "org-inlinetask" ()) -(declare-function org-inlinetask-outline-regexp "org-inlinetask" ()) - -(declare-function org-export-string-as "ox" - (string backend &optional body-only ext-plist)) - +(declare-function org-invisible-p "org" (&optional pos)) +(declare-function outline-flag-region "outline" (from to flag)) +(declare-function outline-next-heading "outline" ()) +(declare-function outline-previous-heading "outline" ()) ;;; Configuration variables (defgroup org-plain-lists nil - "Options concerning plain lists in Org-mode." + "Options concerning plain lists in Org mode." :tag "Org Plain lists" :group 'org-structure) @@ -211,14 +235,20 @@ into (defcustom org-plain-list-ordered-item-terminator t "The character that makes a line with leading number an ordered list item. -Valid values are ?. and ?\). To get both terminators, use t." +Valid values are ?. and ?\). To get both terminators, use t. + +This variable needs to be set before org.el is loaded. If you +need to make a change while Emacs is running, use the customize +interface or run the following code after updating it: + + `\\[org-element-update-syntax]'" :group 'org-plain-lists :type '(choice (const :tag "dot like in \"2.\"" ?.) (const :tag "paren like in \"2)\"" ?\)) - (const :tag "both" t))) + (const :tag "both" t)) + :set (lambda (var val) (set var val) + (when (featurep 'org-element) (org-element-update-syntax)))) -(define-obsolete-variable-alias 'org-alphabetical-lists - 'org-list-allow-alphabetical "24.4") ; Since 8.0 (defcustom org-list-allow-alphabetical nil "Non-nil means single character alphabetical bullets are allowed. @@ -230,13 +260,12 @@ This variable needs to be set before org.el is loaded. If you need to make a change while Emacs is running, use the customize interface or run the following code after updating it: - (when (featurep \\='org-element) (load \"org-element\" t t))" + `\\[org-element-update-syntax]'" :group 'org-plain-lists :version "24.1" :type 'boolean - :set (lambda (var val) - (when (featurep 'org-element) (load "org-element" t t)) - (set var val))) + :set (lambda (var val) (set var val) + (when (featurep 'org-element) (org-element-update-syntax)))) (defcustom org-list-two-spaces-after-bullet-regexp nil "A regular expression matching bullets that should have 2 spaces after them. @@ -250,23 +279,22 @@ spaces instead of one after the bullet in each item of the list." (const :tag "never" nil) (regexp))) -(define-obsolete-variable-alias 'org-empty-line-terminates-plain-lists - 'org-list-empty-line-terminates-plain-lists "24.4") ;; Since 8.0 -(defcustom org-list-empty-line-terminates-plain-lists nil - "Non-nil means an empty line ends all plain list levels. -Otherwise, two of them will be necessary." - :group 'org-plain-lists - :type 'boolean) - (defcustom org-list-automatic-rules '((checkbox . t) (indent . t)) "Non-nil means apply set of rules when acting on lists. +\\ By default, automatic actions are taken when using - \\[org-meta-return], \\[org-metaright], \\[org-metaleft], - \\[org-shiftmetaright], \\[org-shiftmetaleft], - \\[org-ctrl-c-minus], \\[org-toggle-checkbox] or - \\[org-insert-todo-heading]. You can disable individually these - rules by setting them to nil. Valid rules are: + `\\[org-meta-return]', + `\\[org-metaright]', + `\\[org-metaleft]', + `\\[org-shiftmetaright]', + `\\[org-shiftmetaleft]', + `\\[org-ctrl-c-minus]', + `\\[org-toggle-checkbox]', + `\\[org-insert-todo-heading]'. + +You can disable individually these rules by setting them to nil. +Valid rules are: checkbox when non-nil, checkbox statistics is updated each time you either insert a new checkbox or toggle a checkbox. @@ -286,13 +314,15 @@ indent when non-nil, indenting or outdenting list top-item (defcustom org-list-use-circular-motion nil "Non-nil means commands implying motion in lists should be cyclic. - +\\ In that case, the item following the last item is the first one, and the item preceding the first item is the last one. -This affects the behavior of \\[org-move-item-up], - \\[org-move-item-down], \\[org-next-item] and - \\[org-previous-item]." +This affects the behavior of + `\\[org-move-item-up]', + `\\[org-move-item-down]', + `\\[org-next-item]', + `\\[org-previous-item]'." :group 'org-plain-lists :version "24.1" :type 'boolean) @@ -304,8 +334,6 @@ This hook runs even if checkbox rule in implement alternative ways of collecting statistics information.") -(define-obsolete-variable-alias 'org-hierarchical-checkbox-statistics - 'org-checkbox-hierarchical-statistics "24.4") ;; Since 8.0 (defcustom org-checkbox-hierarchical-statistics t "Non-nil means checkbox statistics counts only the state of direct children. When nil, all boxes below the cookie are counted. @@ -314,8 +342,6 @@ with the word \"recursive\" in the value." :group 'org-plain-lists :type 'boolean) -(org-defvaralias 'org-description-max-indent - 'org-list-description-max-indent) ;; Since 8.0 (defcustom org-list-description-max-indent 20 "Maximum indentation for the second line of a description list. When the indentation would be larger than this, it will become @@ -358,8 +384,7 @@ list, obtained by prompting the user." (list (symbol :tag "Major mode") (string :tag "Format")))) -(defvar org-list-forbidden-blocks '("example" "verse" "src" "ascii" "beamer" - "html" "latex" "odt") +(defvar org-list-forbidden-blocks '("example" "verse" "src" "export") "Names of blocks where lists are not allowed. Names must be in lower case.") @@ -374,10 +399,8 @@ specifically, type `block' is determined by the variable ;;; Predicates and regexps -(defconst org-list-end-re (if org-list-empty-line-terminates-plain-lists "^[ \t]*\n" - "^[ \t]*\n[ \t]*\n") - "Regex corresponding to the end of a list. -It depends on `org-list-empty-line-terminates-plain-lists'.") +(defconst org-list-end-re "^[ \t]*\n[ \t]*\n" + "Regex matching the end of a plain list.") (defconst org-list-full-item-re (concat "^[ \t]*\\(\\(?:[-+*]\\|\\(?:[0-9]+\\|[A-Za-z]\\)[.)]\\)\\(?:[ \t]+\\|$\\)\\)" @@ -430,9 +453,6 @@ group 4: description tag") (let* ((case-fold-search t) (context (org-list-context)) (lim-up (car context)) - (drawers-re (concat "^[ \t]*:\\(" - (mapconcat #'regexp-quote org-drawers "\\|") - "\\):[ \t]*$")) (inlinetask-re (and (featurep 'org-inlinetask) (org-inlinetask-outline-regexp))) (item-re (org-item-re)) @@ -476,7 +496,7 @@ group 4: description tag") ((and (looking-at "^[ \t]*#\\+end_") (re-search-backward "^[ \t]*#\\+begin_" lim-up t))) ((and (looking-at "^[ \t]*:END:") - (re-search-backward drawers-re lim-up t)) + (re-search-backward org-drawer-regexp lim-up t)) (beginning-of-line)) ((and inlinetask-re (looking-at inlinetask-re)) (org-inlinetask-goto-beginning) @@ -547,11 +567,7 @@ Contexts `block' and `invalid' refer to `org-list-forbidden-blocks'." (lim-down (or (save-excursion (outline-next-heading)) (point-max)))) ;; Is point inside a drawer? (let ((end-re "^[ \t]*:END:") - ;; Can't use org-drawers-regexp as this function might - ;; be called in buffers not in Org mode. - (beg-re (concat "^[ \t]*:\\(" - (mapconcat #'regexp-quote org-drawers "\\|") - "\\):[ \t]*$"))) + (beg-re org-drawer-regexp)) (when (save-excursion (and (not (looking-at beg-re)) (not (looking-at end-re)) @@ -635,9 +651,6 @@ Assume point is at an item." (lim-down (nth 1 context)) (text-min-ind 10000) (item-re (org-item-re)) - (drawers-re (concat "^[ \t]*:\\(" - (mapconcat #'regexp-quote org-drawers "\\|") - "\\):[ \t]*$")) (inlinetask-re (and (featurep 'org-inlinetask) (org-inlinetask-outline-regexp))) (beg-cell (cons (point) (org-get-indentation))) @@ -654,7 +667,7 @@ Assume point is at an item." (match-string-no-properties 2) ; counter (match-string-no-properties 3) ; checkbox ;; Description tag. - (and (save-match-data (string-match "[-+*]" bullet)) + (and (string-match-p "[-+*]" bullet) (match-string-no-properties 4))))))) (end-before-blank (function @@ -700,7 +713,7 @@ Assume point is at an item." ((and (looking-at "^[ \t]*#\\+end_") (re-search-backward "^[ \t]*#\\+begin_" lim-up t))) ((and (looking-at "^[ \t]*:END:") - (re-search-backward drawers-re lim-up t)) + (re-search-backward org-drawer-regexp lim-up t)) (beginning-of-line)) ((and inlinetask-re (looking-at inlinetask-re)) (org-inlinetask-goto-beginning) @@ -766,7 +779,7 @@ Assume point is at an item." (cond ((and (looking-at "^[ \t]*#\\+begin_") (re-search-forward "^[ \t]*#\\+end_" lim-down t))) - ((and (looking-at drawers-re) + ((and (looking-at org-drawer-regexp) (re-search-forward "^[ \t]*:END:" lim-down t)))) (forward-line 1)))))) (setq struct (append itm-lst (cdr (nreverse itm-lst-2))) @@ -1021,7 +1034,7 @@ Possible types are `descriptive', `ordered' and `unordered'. The type is determined by the first item of the list." (let ((first (org-list-get-list-begin item struct prevs))) (cond - ((string-match "[[:alnum:]]" (org-list-get-bullet first struct)) 'ordered) + ((string-match-p "[[:alnum:]]" (org-list-get-bullet first struct)) 'ordered) ((org-list-get-tag first struct) 'descriptive) (t 'unordered)))) @@ -1043,7 +1056,7 @@ that value." (let ((seq 0) (pos item) counter) (while (and (not (setq counter (org-list-get-counter pos struct))) (setq pos (org-list-get-prev-item pos struct prevs))) - (incf seq)) + (cl-incf seq)) (if (not counter) (1+ seq) (cond ((string-match "[A-Za-z]" counter) @@ -1137,13 +1150,20 @@ This function modifies STRUCT." ;; Store overlays responsible for visibility status. We ;; also need to store their boundaries as they will be ;; removed from buffer. - (overlays (cons - (mapcar (lambda (ov) - (list ov (overlay-start ov) (overlay-end ov))) - (overlays-in beg-A end-A)) - (mapcar (lambda (ov) - (list ov (overlay-start ov) (overlay-end ov))) - (overlays-in beg-B end-B))))) + (overlays + (cons + (delq nil + (mapcar (lambda (o) + (and (>= (overlay-start o) beg-A) + (<= (overlay-end o) end-A) + (list o (overlay-start o) (overlay-end o)))) + (overlays-in beg-A end-A))) + (delq nil + (mapcar (lambda (o) + (and (>= (overlay-start o) beg-B) + (<= (overlay-end o) end-B) + (list o (overlay-start o) (overlay-end o)))) + (overlays-in beg-B end-B)))))) ;; 1. Move effectively items in buffer. (goto-char beg-A) (delete-region beg-A end-B-no-blank) @@ -1154,42 +1174,39 @@ This function modifies STRUCT." ;; as empty spaces are not moved there. In others words, ;; item BEG-A will end with whitespaces that were at the end ;; of BEG-B and the same applies to BEG-B. - (mapc (lambda (e) - (let ((pos (car e))) - (cond - ((< pos beg-A)) - ((memq pos sub-A) - (let ((end-e (nth 6 e))) - (setcar e (+ pos (- end-B-no-blank end-A-no-blank))) - (setcar (nthcdr 6 e) - (+ end-e (- end-B-no-blank end-A-no-blank))) - (when (= end-e end-A) (setcar (nthcdr 6 e) end-B)))) - ((memq pos sub-B) - (let ((end-e (nth 6 e))) - (setcar e (- (+ pos beg-A) beg-B)) - (setcar (nthcdr 6 e) (+ end-e (- beg-A beg-B))) - (when (= end-e end-B) - (setcar (nthcdr 6 e) - (+ beg-A size-B (- end-A end-A-no-blank)))))) - ((< pos beg-B) - (let ((end-e (nth 6 e))) - (setcar e (+ pos (- size-B size-A))) - (setcar (nthcdr 6 e) (+ end-e (- size-B size-A)))))))) - struct) - (setq struct (sort struct (lambda (e1 e2) (< (car e1) (car e2))))) + (dolist (e struct) + (let ((pos (car e))) + (cond + ((< pos beg-A)) + ((memq pos sub-A) + (let ((end-e (nth 6 e))) + (setcar e (+ pos (- end-B-no-blank end-A-no-blank))) + (setcar (nthcdr 6 e) + (+ end-e (- end-B-no-blank end-A-no-blank))) + (when (= end-e end-A) (setcar (nthcdr 6 e) end-B)))) + ((memq pos sub-B) + (let ((end-e (nth 6 e))) + (setcar e (- (+ pos beg-A) beg-B)) + (setcar (nthcdr 6 e) (+ end-e (- beg-A beg-B))) + (when (= end-e end-B) + (setcar (nthcdr 6 e) + (+ beg-A size-B (- end-A end-A-no-blank)))))) + ((< pos beg-B) + (let ((end-e (nth 6 e))) + (setcar e (+ pos (- size-B size-A))) + (setcar (nthcdr 6 e) (+ end-e (- size-B size-A)))))))) + (setq struct (sort struct #'car-less-than-car)) ;; Restore visibility status, by moving overlays to their new ;; position. - (mapc (lambda (ov) - (move-overlay - (car ov) - (+ (nth 1 ov) (- (+ beg-B (- size-B size-A)) beg-A)) - (+ (nth 2 ov) (- (+ beg-B (- size-B size-A)) beg-A)))) - (car overlays)) - (mapc (lambda (ov) - (move-overlay (car ov) - (+ (nth 1 ov) (- beg-A beg-B)) - (+ (nth 2 ov) (- beg-A beg-B)))) - (cdr overlays)) + (dolist (ov (car overlays)) + (move-overlay + (car ov) + (+ (nth 1 ov) (- (+ beg-B (- size-B size-A)) beg-A)) + (+ (nth 2 ov) (- (+ beg-B (- size-B size-A)) beg-A)))) + (dolist (ov (cdr overlays)) + (move-overlay (car ov) + (+ (nth 1 ov) (- beg-A beg-B)) + (+ (nth 2 ov) (- beg-A beg-B)))) ;; Return structure. struct))) @@ -1219,7 +1236,7 @@ some heuristics to guess the result." (point)))))))) (cond ;; Trivial cases where there should be none. - ((or org-list-empty-line-terminates-plain-lists (not insert-blank-p)) 0) + ((not insert-blank-p) 0) ;; When `org-blank-before-new-entry' says so, it is 1. ((eq insert-blank-p t) 1) ;; `plain-list-item' is 'auto. Count blank lines separating @@ -1272,12 +1289,16 @@ This function modifies STRUCT." (beforep (progn (looking-at org-list-full-item-re) - ;; Do not count tag in a non-descriptive list. - (<= pos (if (and (match-beginning 4) - (save-match-data - (string-match "[.)]" (match-string 1)))) - (match-beginning 4) - (match-end 0))))) + (<= pos + (cond + ((not (match-beginning 4)) (match-end 0)) + ;; Ignore tag in a non-descriptive list. + ((save-match-data (string-match "[.)]" (match-string 1))) + (match-beginning 4)) + (t (save-excursion + (goto-char (match-end 4)) + (skip-chars-forward " \t") + (point))))))) (split-line-p (org-get-alist-option org-M-RET-may-split-line 'item)) (blank-nb (org-list-separating-blank-lines-number pos struct prevs)) @@ -1317,7 +1338,7 @@ This function modifies STRUCT." (size-offset (- item-size (length text-cut)))) ;; 4. Insert effectively item into buffer. (goto-char item) - (org-indent-to-column ind) + (indent-to-column ind) (insert body item-sep) ;; 5. Add new item to STRUCT. (mapc (lambda (e) @@ -1459,7 +1480,7 @@ This function returns, destructively, the new list structure." (save-excursion (goto-char (org-list-get-last-item item struct prevs)) (point-at-eol))) - ((string-match "\\`[0-9]+\\'" dest) + ((string-match-p "\\`[0-9]+\\'" dest) (let* ((all (org-list-get-all-items item struct prevs)) (len (length all)) (index (mod (string-to-number dest) len))) @@ -1473,8 +1494,10 @@ This function returns, destructively, the new list structure." (point-at-eol))))) (t dest))) (org-M-RET-may-split-line nil) - ;; Store visibility. - (visibility (overlays-in item item-end))) + ;; Store inner overlays (to preserve visibility). + (overlays (cl-remove-if (lambda (o) (or (< (overlay-start o) item) + (> (overlay-end o) item))) + (overlays-in item item-end)))) (cond ((eq dest 'delete) (org-list-delete-item item struct)) ((eq dest 'kill) @@ -1509,13 +1532,12 @@ This function returns, destructively, the new list structure." new-end (+ end shift))))))) moved-items)) - (lambda (e1 e2) (< (car e1) (car e2)))))) - ;; 2. Restore visibility. - (mapc (lambda (ov) - (move-overlay ov - (+ (overlay-start ov) (- (point) item)) - (+ (overlay-end ov) (- (point) item)))) - visibility) + #'car-less-than-car))) + ;; 2. Restore inner overlays. + (dolist (o overlays) + (move-overlay o + (+ (overlay-start o) (- (point) item)) + (+ (overlay-end o) (- (point) item)))) ;; 3. Eventually delete extra copy of the item and clean marker. (prog1 (org-list-delete-item (marker-position item) struct) (move-marker item nil))) @@ -1632,7 +1654,7 @@ as returned by `org-list-prevs-alist'." (while item (let ((count (org-list-get-counter item struct))) ;; Virtually determine current bullet - (if (and count (string-match "[a-zA-Z]" count)) + (if (and count (string-match-p "[a-zA-Z]" count)) ;; Counters are not case-sensitive. (setq ascii (string-to-char (upcase count))) (setq ascii (1+ ascii))) @@ -1861,10 +1883,9 @@ Initial position of cursor is restored after the changes." (item-re (org-item-re)) (shift-body-ind (function - ;; Shift the indentation between END and BEG by DELTA. If - ;; MAX-IND is non-nil, ensure that no line will be indented - ;; more than that number. Start from the line before END. - (lambda (end beg delta max-ind) + ;; Shift the indentation between END and BEG by DELTA. + ;; Start from the line before END. + (lambda (end beg delta) (goto-char end) (skip-chars-backward " \r\t\n") (beginning-of-line) @@ -1876,10 +1897,8 @@ Initial position of cursor is restored after the changes." ((and inlinetask-re (looking-at inlinetask-re)) (org-inlinetask-goto-beginning)) ;; Shift only non-empty lines. - ((org-looking-at-p "^[ \t]*\\S-") - (let ((i (org-get-indentation))) - (org-indent-line-to - (if max-ind (min (+ i delta) max-ind) (+ i delta)))))) + ((looking-at-p "^[ \t]*\\S-") + (indent-line-to (+ (org-get-indentation) delta)))) (forward-line -1))))) (modify-item (function @@ -1934,37 +1953,53 @@ Initial position of cursor is restored after the changes." ;; belongs to: it is the last item (ITEM-UP), whose ;; ending is further than the position we're ;; interested in. - (let ((item-up (assoc-default end-pos acc-end '>))) + (let ((item-up (assoc-default end-pos acc-end #'>))) (push (cons end-pos item-up) end-list))) (push (cons end-pos pos) acc-end))) ;; 2. Slice the items into parts that should be shifted by the ;; same amount of indentation. Each slice follow the pattern - ;; (END BEG DELTA MAX-IND-OR-NIL). Slices are returned in - ;; reverse order. + ;; (END BEG DELTA). Slices are returned in reverse order. (setq all-ends (sort (append (mapcar #'car itm-shift) (org-uniquify (mapcar #'car end-list))) - '<)) + #'<) + acc-end (nreverse acc-end)) (while (cdr all-ends) (let* ((up (pop all-ends)) (down (car all-ends)) (itemp (assq up struct)) - (item (if itemp up (cdr (assq up end-list)))) - (ind (cdr (assq item itm-shift))) - ;; If we're not at an item, there's a child of the item - ;; point belongs to above. Make sure this slice isn't - ;; moved within that child by specifying a maximum - ;; indentation. - (max-ind (and (not itemp) - (+ (org-list-get-ind item struct) - (length (org-list-get-bullet item struct)) - org-list-indent-offset)))) - (push (list down up ind max-ind) sliced-struct))) + (delta + (if itemp (cdr (assq up itm-shift)) + ;; If we're not at an item, there's a child of the + ;; item point belongs to above. Make sure the less + ;; indented line in this slice has the same column + ;; as that child. + (let* ((child (cdr (assq up acc-end))) + (ind (org-list-get-ind child struct)) + (min-ind most-positive-fixnum)) + (save-excursion + (goto-char up) + (while (< (point) down) + ;; Ignore empty lines. Also ignore blocks and + ;; drawers contents. + (unless (looking-at-p "[ \t]*$") + (setq min-ind (min (org-get-indentation) min-ind)) + (cond + ((and (looking-at "#\\+BEGIN\\(:\\|_\\S-+\\)") + (re-search-forward + (format "^[ \t]*#\\+END%s[ \t]*$" + (match-string 1)) + down t))) + ((and (looking-at org-drawer-regexp) + (re-search-forward "^[ \t]*:END:[ \t]*$" + down t))))) + (forward-line))) + (- ind min-ind))))) + (push (list down up delta) sliced-struct))) ;; 3. Shift each slice in buffer, provided delta isn't 0, from ;; end to beginning. Take a special action when beginning is ;; at item bullet. (dolist (e sliced-struct) - (unless (and (zerop (nth 2 e)) (not (nth 3 e))) - (apply shift-body-ind e)) + (unless (zerop (nth 2 e)) (apply shift-body-ind e)) (let* ((beg (nth 1 e)) (cell (assq beg struct))) (unless (or (not cell) (equal cell (assq beg old-struct))) @@ -2060,16 +2095,27 @@ Possible values are: `folded', `children' or `subtree'. See (defun org-list-item-body-column (item) "Return column at which body of ITEM should start." - (let (bpos bcol tpos tcol) - (save-excursion - (goto-char item) - (looking-at "[ \t]*\\(\\S-+\\)\\(.*[ \t]+::\\)?\\([ \t]+\\|$\\)") - (setq bpos (match-beginning 1) tpos (match-end 0) - bcol (progn (goto-char bpos) (current-column)) - tcol (progn (goto-char tpos) (current-column))) - (when (> tcol (+ bcol org-description-max-indent)) - (setq tcol (+ bcol 5)))) - tcol)) + (save-excursion + (goto-char item) + (if (save-excursion + (end-of-line) + (re-search-backward + "[ \t]::\\([ \t]\\|$\\)" (line-beginning-position) t)) + ;; Descriptive list item. Body starts after item's tag, if + ;; possible. + (let ((start (1+ (- (match-beginning 1) (line-beginning-position)))) + (ind (org-get-indentation))) + (if (> start (+ ind org-list-description-max-indent)) + (+ ind 5) + start)) + ;; Regular item. Body starts after bullet. + (looking-at "[ \t]*\\(\\S-+\\)") + (+ (progn (goto-char (match-end 1)) (current-column)) + (if (and org-list-two-spaces-after-bullet-regexp + (string-match-p org-list-two-spaces-after-bullet-regexp + (match-string 1))) + 2 + 1))))) @@ -2210,7 +2256,7 @@ item is invisible." (unless (or (not itemp) (save-excursion (goto-char itemp) - (outline-invisible-p))) + (org-invisible-p))) (if (save-excursion (goto-char itemp) (org-at-item-timer-p)) @@ -2325,9 +2371,6 @@ in subtree, ignoring drawers." block-item lim-up lim-down - (drawer-re (concat "^[ \t]*:\\(" - (mapconcat #'regexp-quote org-drawers "\\|") - "\\):[ \t]*$")) (keyword-re (concat "^[ \t]*\\<\\(" org-scheduled-string "\\|" org-deadline-string "\\|" org-closed-string @@ -2349,7 +2392,8 @@ in subtree, ignoring drawers." ;; time-stamps (scheduled, etc.). (let ((limit (save-excursion (outline-next-heading) (point)))) (forward-line 1) - (while (or (looking-at drawer-re) (looking-at keyword-re)) + (while (or (looking-at org-drawer-regexp) + (looking-at keyword-re)) (if (looking-at keyword-re) (forward-line 1) (re-search-forward "^[ \t]*:END:" limit nil))) @@ -2388,7 +2432,7 @@ in subtree, ignoring drawers." (parents (org-list-parents-alist struct)) (prevs (org-list-prevs-alist struct)) (bottom (copy-marker (org-list-get-bottom-point struct))) - (items-to-toggle (org-remove-if + (items-to-toggle (cl-remove-if (lambda (e) (or (< e lim-up) (> e lim-down))) (mapcar #'car struct)))) (mapc (lambda (e) (org-list-set-checkbox @@ -2439,130 +2483,129 @@ in subtree, ignoring drawers." (defun org-update-checkbox-count (&optional all) "Update the checkbox statistics in the current section. + This will find all statistic cookies like [57%] and [6/12] and update them with the current numbers. With optional prefix argument ALL, do this for the whole buffer." (interactive "P") - (save-excursion - (let ((cookie-re "\\(\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)\\)") - (box-re "^[ \t]*\\([-+*]\\|\\([0-9]+\\|[A-Za-z]\\)[.)]\\)[ \t]+\\(?:\\[@\\(?:start:\\)?\\([0-9]+\\|[A-Za-z]\\)\\][ \t]*\\)?\\(\\[[- X]\\]\\)") + (org-with-wide-buffer + (let* ((cookie-re "\\(\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)\\)") + (box-re "^[ \t]*\\([-+*]\\|\\([0-9]+\\|[A-Za-z]\\)[.)]\\)[ \t]+\ +\\(?:\\[@\\(?:start:\\)?\\([0-9]+\\|[A-Za-z]\\)\\][ \t]*\\)?\\(\\[[- X]\\]\\)") (recursivep (or (not org-checkbox-hierarchical-statistics) (string-match "\\" (or (org-entry-get nil "COOKIE_DATA") "")))) - (bounds (if all - (cons (point-min) (point-max)) - (cons (or (ignore-errors (org-back-to-heading t) (point)) - (point-min)) - (save-excursion (outline-next-heading) (point))))) + (within-inlinetask (and (not all) + (featurep 'org-inlinetask) + (org-inlinetask-in-task-p))) + (end (cond (all (point-max)) + (within-inlinetask + (save-excursion (outline-next-heading) (point))) + (t (save-excursion + (org-with-limited-levels (outline-next-heading)) + (point))))) (count-boxes - (function - ;; Return number of checked boxes and boxes of all types - ;; in all structures in STRUCTS. If RECURSIVEP is - ;; non-nil, also count boxes in sub-lists. If ITEM is - ;; nil, count across the whole structure, else count only - ;; across subtree whose ancestor is ITEM. - (lambda (item structs recursivep) - (let ((c-on 0) (c-all 0)) - (mapc - (lambda (s) - (let* ((pre (org-list-prevs-alist s)) - (par (org-list-parents-alist s)) - (items - (cond - ((and recursivep item) (org-list-get-subtree item s)) - (recursivep (mapcar #'car s)) - (item (org-list-get-children item s par)) - (t (org-list-get-all-items - (org-list-get-top-point s) s pre)))) - (cookies (delq nil (mapcar - (lambda (e) - (org-list-get-checkbox e s)) - items)))) - (setq c-all (+ (length cookies) c-all) - c-on (+ (org-count "[X]" cookies) c-on)))) - structs) - (cons c-on c-all))))) - (backup-end 1) - cookies-list structs-bak) - (goto-char (car bounds)) - ;; 1. Build an alist for each cookie found within BOUNDS. The - ;; key will be position at beginning of cookie and values - ;; ending position, format of cookie, and a cell whose car is - ;; number of checked boxes to report, and cdr total number of - ;; boxes. - (while (re-search-forward cookie-re (cdr bounds) t) - (catch 'skip - (save-excursion - (push - (list - (match-beginning 1) ; cookie start - (match-end 1) ; cookie end - (match-string 2) ; percent? - (cond ; boxes count - ;; Cookie is at an heading, but specifically for todo, - ;; not for checkboxes: skip it. - ((and (org-at-heading-p) - (string-match "\\" - (downcase - (or (org-entry-get nil "COOKIE_DATA") "")))) - (throw 'skip nil)) - ;; Cookie is at an heading, but all lists before next - ;; heading already have been read. Use data collected - ;; in STRUCTS-BAK. This should only happen when - ;; heading has more than one cookie on it. - ((and (org-at-heading-p) - (<= (save-excursion (outline-next-heading) (point)) - backup-end)) - (funcall count-boxes nil structs-bak recursivep)) - ;; Cookie is at a fresh heading. Grab structure of - ;; every list containing a checkbox between point and - ;; next headline, and save them in STRUCTS-BAK. - ((org-at-heading-p) - (setq backup-end (save-excursion - (outline-next-heading) (point)) - structs-bak nil) - (while (org-list-search-forward box-re backup-end 'move) - (let* ((struct (org-list-struct)) - (bottom (org-list-get-bottom-point struct))) - (push struct structs-bak) - (goto-char bottom))) - (funcall count-boxes nil structs-bak recursivep)) - ;; Cookie is at an item, and we already have list - ;; structure stored in STRUCTS-BAK. - ((and (org-at-item-p) - (< (point-at-bol) backup-end) - ;; Only lists in no special context are stored. - (not (nth 2 (org-list-context)))) - (funcall count-boxes (point-at-bol) structs-bak recursivep)) - ;; Cookie is at an item, but we need to compute list - ;; structure. - ((org-at-item-p) - (let ((struct (org-list-struct))) - (setq backup-end (org-list-get-bottom-point struct) - structs-bak (list struct))) - (funcall count-boxes (point-at-bol) structs-bak recursivep)) - ;; Else, cookie found is at a wrong place. Skip it. - (t (throw 'skip nil)))) - cookies-list)))) - ;; 2. Apply alist to buffer, in reverse order so positions stay - ;; unchanged after cookie modifications. - (mapc (lambda (cookie) - (let* ((beg (car cookie)) - (end (nth 1 cookie)) - (percentp (nth 2 cookie)) - (checked (car (nth 3 cookie))) - (total (cdr (nth 3 cookie))) - (new (if percentp - (format "[%d%%]" (floor (* 100.0 checked) - (max 1 total))) - (format "[%d/%d]" checked total)))) - (goto-char beg) - (insert new) - (delete-region (point) (+ (point) (- end beg))) - (when org-auto-align-tags (org-fix-tags-on-the-fly)))) + (lambda (item structs recursivep) + ;; Return number of checked boxes and boxes of all types + ;; in all structures in STRUCTS. If RECURSIVEP is + ;; non-nil, also count boxes in sub-lists. If ITEM is + ;; nil, count across the whole structure, else count only + ;; across subtree whose ancestor is ITEM. + (let ((c-on 0) (c-all 0)) + (dolist (s structs (list c-on c-all)) + (let* ((pre (org-list-prevs-alist s)) + (par (org-list-parents-alist s)) + (items + (cond + ((and recursivep item) (org-list-get-subtree item s)) + (recursivep (mapcar #'car s)) + (item (org-list-get-children item s par)) + (t (org-list-get-all-items + (org-list-get-top-point s) s pre)))) + (cookies (delq nil (mapcar + (lambda (e) + (org-list-get-checkbox e s)) + items)))) + (cl-incf c-all (length cookies)) + (cl-incf c-on (cl-count "[X]" cookies :test #'equal))))))) + cookies-list cache) + ;; Move to start. + (cond (all (goto-char (point-min))) + (within-inlinetask (org-back-to-heading t)) + (t (org-with-limited-levels (outline-previous-heading)))) + ;; Build an alist for each cookie found. The key is the position + ;; at beginning of cookie and values ending position, format of + ;; cookie, number of checked boxes to report and total number of + ;; boxes. + (while (re-search-forward cookie-re end t) + (let ((context (save-excursion (backward-char) + (save-match-data (org-element-context))))) + (when (eq (org-element-type context) 'statistics-cookie) + (push + (append + (list (match-beginning 1) (match-end 1) (match-end 2)) + (let* ((container + (org-element-lineage + context + '(drawer center-block dynamic-block inlinetask item + quote-block special-block verse-block))) + (beg (if container + (org-element-property :contents-begin container) + (save-excursion + (org-with-limited-levels + (outline-previous-heading)) + (point))))) + (or (cdr (assq beg cache)) + (save-excursion + (goto-char beg) + (let ((end + (if container + (org-element-property :contents-end container) + (save-excursion + (org-with-limited-levels (outline-next-heading)) + (point)))) + structs) + (while (re-search-forward box-re end t) + (let ((element (org-element-at-point))) + (when (eq (org-element-type element) 'item) + (push (org-element-property :structure element) + structs) + ;; Skip whole list since we have its + ;; structure anyway. + (while (setq element (org-element-lineage + element '(plain-list))) + (goto-char + (min (org-element-property :end element) + end)))))) + ;; Cache count for cookies applying to the same + ;; area. Then return it. + (let ((count + (funcall count-boxes + (and (eq (org-element-type container) + 'item) + (org-element-property + :begin container)) + structs + recursivep))) + (push (cons beg count) cache) + count)))))) cookies-list)))) + ;; Apply alist to buffer. + (dolist (cookie cookies-list) + (let* ((beg (car cookie)) + (end (nth 1 cookie)) + (percent (nth 2 cookie)) + (checked (nth 3 cookie)) + (total (nth 4 cookie))) + (goto-char beg) + (insert + (if percent (format "[%d%%]" (floor (* 100.0 checked) + (max 1 total))) + (format "[%d/%d]" checked total))) + (delete-region (point) (+ (point) (- end beg))) + (when org-auto-align-tags (org-fix-tags-on-the-fly))))))) (defun org-get-checkbox-statistics-face () "Select the face for checkbox statistics. @@ -2664,7 +2707,7 @@ Return t if successful." ;; of the subtree mustn't have a child. (let ((last-item (caar (reverse - (org-remove-if + (cl-remove-if (lambda (e) (>= (car e) end)) struct))))) (org-list-has-child-p last-item struct)))) @@ -2781,7 +2824,7 @@ Return t at each successful move." ((and (= ind (car org-tab-ind-state)) (ignore-errors (org-list-indent-item-generic 1 t struct)))) (t (delete-region (point-at-bol) (point-at-eol)) - (org-indent-to-column (car org-tab-ind-state)) + (indent-to-column (car org-tab-ind-state)) (insert (cdr org-tab-ind-state) " ") ;; Break cycle (setq this-command 'identity))) @@ -2794,7 +2837,8 @@ Return t at each successful move." (t (user-error "Cannot move item")))) t)))) -(defun org-sort-list (&optional with-case sorting-type getkey-func compare-func) +(defun org-sort-list + (&optional with-case sorting-type getkey-func compare-func interactive?) "Sort list items. The cursor may be at any item of the list that should be sorted. Sublists are not sorted. Checkboxes, if any, are ignored. @@ -2820,13 +2864,15 @@ Capital letters will reverse the sort order. If the SORTING-TYPE is ?f or ?F, then GETKEY-FUNC specifies a function to be called with point at the beginning of the -record. It must return either a string or a number that should -serve as the sorting key for that record. It will then use -COMPARE-FUNC to compare entries. +record. It must return a value that is compatible with COMPARE-FUNC, +the function used to compare entries. Sorting is done against the visible part of the headlines, it -ignores hidden links." - (interactive "P") +ignores hidden links. + +A non-nil value for INTERACTIVE? is used to signal that this +function is being called interactively." + (interactive (list current-prefix-arg nil nil nil t)) (let* ((case-func (if with-case 'identity 'downcase)) (struct (org-list-struct)) (prevs (org-list-prevs-alist struct)) @@ -2838,23 +2884,31 @@ ignores hidden links." (message "Sort plain list: [a]lpha [n]umeric [t]ime [f]unc [x]checked A/N/T/F/X means reversed:") (read-char-exclusive)))) + (dcst (downcase sorting-type)) (getkey-func - (or getkey-func - (and (= (downcase sorting-type) ?f) - (intern (org-icompleting-read "Sort using function: " - obarray 'fboundp t nil nil)))))) + (and (= dcst ?f) + (or getkey-func + (and interactive? + (org-read-function "Function for extracting keys: ")) + (error "Missing key extractor")))) + (sort-func + (cond + ((= dcst ?a) #'string<) + ((= dcst ?f) + (or compare-func + (and interactive? + (org-read-function + (concat "Function for comparing keys " + "(empty for default `sort-subr' predicate): ") + 'allow-empty)))) + ((= dcst ?t) #'<) + ((= dcst ?x) #'string<)))) (message "Sorting items...") (save-restriction (narrow-to-region start end) (goto-char (point-min)) - (let* ((dcst (downcase sorting-type)) - (case-fold-search nil) + (let* ((case-fold-search nil) (now (current-time)) - (sort-func (cond - ((= dcst ?a) 'string<) - ((= dcst ?f) compare-func) - ((= dcst ?t) '<) - ((= dcst ?x) 'string<))) (next-record (lambda () (skip-chars-forward " \r\t\n") (or (eobp) (beginning-of-line)))) @@ -2908,134 +2962,255 @@ ignores hidden links." (run-hooks 'org-after-sorting-entries-or-items-hook) (message "Sorting items...done"))))) +(defun org-toggle-item (arg) + "Convert headings or normal lines to items, items to normal lines. +If there is no active region, only the current line is considered. + +If the first non blank line in the region is a headline, convert +all headlines to items, shifting text accordingly. + +If it is an item, convert all items to normal lines. + +If it is normal text, change region into a list of items. +With a prefix argument ARG, change the region in a single item." + (interactive "P") + (let ((shift-text + (lambda (ind end) + ;; Shift text in current section to IND, from point to END. + ;; The function leaves point to END line. + (let ((min-i 1000) (end (copy-marker end))) + ;; First determine the minimum indentation (MIN-I) of + ;; the text. + (save-excursion + (catch 'exit + (while (< (point) end) + (let ((i (org-get-indentation))) + (cond + ;; Skip blank lines and inline tasks. + ((looking-at "^[ \t]*$")) + ((looking-at org-outline-regexp-bol)) + ;; We can't find less than 0 indentation. + ((zerop i) (throw 'exit (setq min-i 0))) + ((< i min-i) (setq min-i i)))) + (forward-line)))) + ;; Then indent each line so that a line indented to + ;; MIN-I becomes indented to IND. Ignore blank lines + ;; and inline tasks in the process. + (let ((delta (- ind min-i))) + (while (< (point) end) + (unless (or (looking-at "^[ \t]*$") + (looking-at org-outline-regexp-bol)) + (indent-line-to (+ (org-get-indentation) delta))) + (forward-line)))))) + (skip-blanks + (lambda (pos) + ;; Return beginning of first non-blank line, starting from + ;; line at POS. + (save-excursion + (goto-char pos) + (skip-chars-forward " \r\t\n") + (point-at-bol)))) + beg end) + ;; Determine boundaries of changes. + (if (org-region-active-p) + (setq beg (funcall skip-blanks (region-beginning)) + end (copy-marker (region-end))) + (setq beg (funcall skip-blanks (point-at-bol)) + end (copy-marker (point-at-eol)))) + ;; Depending on the starting line, choose an action on the text + ;; between BEG and END. + (org-with-limited-levels + (save-excursion + (goto-char beg) + (cond + ;; Case 1. Start at an item: de-itemize. Note that it only + ;; happens when a region is active: `org-ctrl-c-minus' + ;; would call `org-cycle-list-bullet' otherwise. + ((org-at-item-p) + (while (< (point) end) + (when (org-at-item-p) + (skip-chars-forward " \t") + (delete-region (point) (match-end 0))) + (forward-line))) + ;; Case 2. Start at an heading: convert to items. + ((org-at-heading-p) + (let* ((bul (org-list-bullet-string "-")) + (bul-len (length bul)) + ;; Indentation of the first heading. It should be + ;; relative to the indentation of its parent, if any. + (start-ind (save-excursion + (cond + ((not org-adapt-indentation) 0) + ((not (outline-previous-heading)) 0) + (t (length (match-string 0)))))) + ;; Level of first heading. Further headings will be + ;; compared to it to determine hierarchy in the list. + (ref-level (org-reduced-level (org-outline-level)))) + (while (< (point) end) + (let* ((level (org-reduced-level (org-outline-level))) + (delta (max 0 (- level ref-level))) + (todo-state (org-get-todo-state))) + ;; If current headline is less indented than the first + ;; one, set it as reference, in order to preserve + ;; subtrees. + (when (< level ref-level) (setq ref-level level)) + ;; Remove stars and TODO keyword. + (let ((case-fold-search nil)) (looking-at org-todo-line-regexp)) + (delete-region (point) (or (match-beginning 3) + (line-end-position))) + (insert bul) + (indent-line-to (+ start-ind (* delta bul-len))) + ;; Turn TODO keyword into a check box. + (when todo-state + (let* ((struct (org-list-struct)) + (old (copy-tree struct))) + (org-list-set-checkbox + (line-beginning-position) + struct + (if (member todo-state org-done-keywords) + "[X]" + "[ ]")) + (org-list-write-struct struct + (org-list-parents-alist struct) + old))) + ;; Ensure all text down to END (or SECTION-END) belongs + ;; to the newly created item. + (let ((section-end (save-excursion + (or (outline-next-heading) (point))))) + (forward-line) + (funcall shift-text + (+ start-ind (* (1+ delta) bul-len)) + (min end section-end))))))) + ;; Case 3. Normal line with ARG: make the first line of region + ;; an item, and shift indentation of others lines to + ;; set them as item's body. + (arg (let* ((bul (org-list-bullet-string "-")) + (bul-len (length bul)) + (ref-ind (org-get-indentation))) + (skip-chars-forward " \t") + (insert bul) + (forward-line) + (while (< (point) end) + ;; Ensure that lines less indented than first one + ;; still get included in item body. + (funcall shift-text + (+ ref-ind bul-len) + (min end (save-excursion (or (outline-next-heading) + (point))))) + (forward-line)))) + ;; Case 4. Normal line without ARG: turn each non-item line + ;; into an item. + (t + (while (< (point) end) + (unless (or (org-at-heading-p) (org-at-item-p)) + (when (looking-at "\\([ \t]*\\)\\(\\S-\\)") + (replace-match + (concat "\\1" (org-list-bullet-string "-") "\\2")))) + (forward-line)))))))) ;;; Send and receive lists -(defun org-list-parse-list (&optional delete) +(defun org-list-to-lisp (&optional delete) "Parse the list at point and maybe DELETE it. Return a list whose car is a symbol of list type, among `ordered', `unordered' and `descriptive'. Then, each item is -a list whose car is counter, and cdr are strings and other -sub-lists. Inside strings, check-boxes are replaced by -\"[CBON]\", \"[CBOFF]\" and \"[CBTRANS]\". +a list of strings and other sub-lists. For example, the following list: -1. first item - + sub-item one - + [X] sub-item two - more text in first item -2. [@3] last item + 1. first item + + sub-item one + + [X] sub-item two + more text in first item + 2. [@3] last item -will be parsed as: +is parsed as (ordered - (nil \"first item\" - (unordered - (nil \"sub-item one\") - (nil \"[CBON] sub-item two\")) - \"more text in first item\") - (3 \"last item\")) - -Point is left at list end." - (defvar parse-item) ;FIXME: Or use `cl-labels' or `letrec'. - (let* ((struct (org-list-struct)) - (prevs (org-list-prevs-alist struct)) - (parents (org-list-parents-alist struct)) - (top (org-list-get-top-point struct)) - (bottom (org-list-get-bottom-point struct)) - out - (get-text - (function - ;; Return text between BEG and END, trimmed, with - ;; checkboxes replaced. - (lambda (beg end) - (let ((text (org-trim (buffer-substring beg end)))) - (if (string-match "\\`\\[\\([-X ]\\)\\]" text) - (replace-match - (let ((box (match-string 1 text))) - (cond - ((equal box " ") "CBOFF") - ((equal box "-") "CBTRANS") - (t "CBON"))) - t nil text 1) - text))))) - (parse-sublist - (function - ;; Return a list whose car is list type and cdr a list of - ;; items' body. - (lambda (e) - (cons (org-list-get-list-type (car e) struct prevs) - (mapcar parse-item e))))) - (parse-item - (function - ;; Return a list containing counter of item, if any, text - ;; and any sublist inside it. - (lambda (e) - (let ((start (save-excursion - (goto-char e) - (looking-at "[ \t]*\\S-+\\([ \t]+\\[@\\(start:\\)?\\([0-9]+\\|[a-zA-Z]\\)\\]\\)?[ \t]*") - (match-end 0))) - ;; Get counter number. For alphabetic counter, get - ;; its position in the alphabet. - (counter (let ((c (org-list-get-counter e struct))) - (cond - ((not c) nil) - ((string-match "[A-Za-z]" c) - (- (string-to-char (upcase (match-string 0 c))) - 64)) - ((string-match "[0-9]+" c) - (string-to-number (match-string 0 c)))))) - (childp (org-list-has-child-p e struct)) - (end (org-list-get-item-end e struct))) - ;; If item has a child, store text between bullet and - ;; next child, then recursively parse all sublists. At - ;; the end of each sublist, check for the presence of - ;; text belonging to the original item. - (if childp - (let* ((children (org-list-get-children e struct parents)) - (body (list (funcall get-text start childp)))) - (while children - (let* ((first (car children)) - (sub (org-list-get-all-items first struct prevs)) - (last-c (car (last sub))) - (last-end (org-list-get-item-end last-c struct))) - (push (funcall parse-sublist sub) body) - ;; Remove children from the list just parsed. - (setq children (cdr (member last-c children))) - ;; There is a chunk of text belonging to the - ;; item if last child doesn't end where next - ;; child starts or where item ends. - (unless (= (or (car children) end) last-end) - (push (funcall get-text - last-end (or (car children) end)) - body)))) - (cons counter (nreverse body))) - (list counter (funcall get-text start end)))))))) + (\"first item\" + (unordered + (\"sub-item one\") + (\"[X] sub-item two\")) + \"more text in first item\") + (\"[@3] last item\")) + +Point is left at list's end." + (letrec ((struct (org-list-struct)) + (prevs (org-list-prevs-alist struct)) + (parents (org-list-parents-alist struct)) + (top (org-list-get-top-point struct)) + (bottom (org-list-get-bottom-point struct)) + (trim + (lambda (text) + ;; Remove indentation and final newline from TEXT. + (org-remove-indentation + (if (string-match-p "\n\\'" text) + (substring text 0 -1) + text)))) + (parse-sublist + (lambda (e) + ;; Return a list whose car is list type and cdr a list + ;; of items' body. + (cons (org-list-get-list-type (car e) struct prevs) + (mapcar parse-item e)))) + (parse-item + (lambda (e) + ;; Return a list containing counter of item, if any, + ;; text and any sublist inside it. + (let* ((end (org-list-get-item-end e struct)) + (children (org-list-get-children e struct parents)) + (body + (save-excursion + (goto-char e) + (looking-at "[ \t]*\\S-+[ \t]*") + (list + (funcall + trim + (concat + (make-string (string-width (match-string 0)) ?\s) + (buffer-substring-no-properties + (match-end 0) (or (car children) end)))))))) + (while children + (let* ((child (car children)) + (sub (org-list-get-all-items child struct prevs)) + (last-in-sub (car (last sub)))) + (push (funcall parse-sublist sub) body) + ;; Remove whole sub-list from children. + (setq children (cdr (memq last-in-sub children))) + ;; There is a chunk of text belonging to the item + ;; if last child doesn't end where next child + ;; starts or where item ends. + (let ((sub-end (org-list-get-item-end last-in-sub struct)) + (next (or (car children) end))) + (when (/= sub-end next) + (push (funcall + trim + (buffer-substring-no-properties sub-end next)) + body))))) + (nreverse body))))) ;; Store output, take care of cursor position and deletion of ;; list, then return output. - (setq out (funcall parse-sublist (org-list-get-all-items top struct prevs))) - (goto-char top) - (when delete - (delete-region top bottom) - (when (and (not (looking-at "[ \t]*$")) (looking-at org-list-end-re)) - (replace-match ""))) - out)) + (prog1 (funcall parse-sublist (org-list-get-all-items top struct prevs)) + (goto-char top) + (when delete + (delete-region top bottom) + (when (and (not (looking-at "[ \t]*$")) (looking-at org-list-end-re)) + (replace-match "")))))) (defun org-list-make-subtree () "Convert the plain list at point into a subtree." (interactive) (if (not (ignore-errors (goto-char (org-in-item-p)))) (error "Not in a list") - (let ((list (save-excursion (org-list-parse-list t)))) + (let ((list (save-excursion (org-list-to-lisp t)))) (insert (org-list-to-subtree list))))) (defun org-list-insert-radio-list () "Insert a radio list template appropriate for this major mode." (interactive) - (let* ((e (assq major-mode org-list-radio-list-templates)) + (let* ((e (cl-assoc-if #'derived-mode-p org-list-radio-list-templates)) (txt (nth 1 e)) name pos) (unless e (error "No radio list setup defined for %s" major-mode)) @@ -3055,11 +3230,13 @@ for this list." (catch 'exit (unless (org-at-item-p) (error "Not at a list item")) (save-excursion - (re-search-backward "#\\+ORGLST" nil t) - (unless (looking-at "#\\+ORGLST:[ \t]+SEND[ \t]+\\(\\S-+\\)[ \t]+\\(\\S-+\\)") - (if maybe (throw 'exit nil) - (error "Don't know how to transform this list")))) - (let* ((name (match-string 1)) + (let ((case-fold-search t)) + (re-search-backward "^[ \t]*#\\+ORGLST:" nil t) + (unless (looking-at + "[ \t]*#\\+ORGLST:[ \t]+SEND[ \t]+\\(\\S-+\\)[ \t]+\\([^ \t\n]+\\)") + (if maybe (throw 'exit nil) + (error "Don't know how to transform this list"))))) + (let* ((name (regexp-quote (match-string 1))) (transform (intern (match-string 2))) (bottom-point (save-excursion @@ -3071,220 +3248,342 @@ for this list." (re-search-backward "#\\+ORGLST" nil t) (re-search-forward (org-item-beginning-re) bottom-point t) (match-beginning 0))) - (plain-list (buffer-substring-no-properties top-point bottom-point)) - beg) + (plain-list (save-excursion + (goto-char top-point) + (org-list-to-lisp)))) (unless (fboundp transform) (error "No such transformation function %s" transform)) (let ((txt (funcall transform plain-list))) - ;; Find the insertion place + ;; Find the insertion(s) place(s). (save-excursion (goto-char (point-min)) - (unless (re-search-forward - (concat "BEGIN RECEIVE ORGLST +" - name - "\\([ \t]\\|$\\)") - nil t) - (error "Don't know where to insert translated list")) - (goto-char (match-beginning 0)) - (beginning-of-line 2) - (setq beg (point)) - (unless (re-search-forward (concat "END RECEIVE ORGLST +" name) nil t) - (error "Cannot find end of insertion region")) - (delete-region beg (point-at-bol)) - (goto-char beg) - (insert txt "\n"))) - (message "List converted and installed at receiver location")))) - -(defsubst org-list-item-trim-br (item) - "Trim line breaks in a list ITEM." - (setq item (replace-regexp-in-string "\n +" " " item))) + (let ((receiver-count 0) + (begin-re (format "BEGIN +RECEIVE +ORGLST +%s\\([ \t]\\|$\\)" + name)) + (end-re (format "END +RECEIVE +ORGLST +%s\\([ \t]\\|$\\)" + name))) + (while (re-search-forward begin-re nil t) + (cl-incf receiver-count) + (let ((beg (line-beginning-position 2))) + (unless (re-search-forward end-re nil t) + (user-error "Cannot find end of receiver location at %d" beg)) + (beginning-of-line) + (delete-region beg (point)) + (insert txt "\n"))) + (cond + ((> receiver-count 1) + (message "List converted and installed at receiver locations")) + ((= receiver-count 1) + (message "List converted and installed at receiver location")) + (t (user-error "No valid receiver location found"))))))))) (defun org-list-to-generic (list params) - "Convert a LIST parsed through `org-list-parse-list' to other formats. -Valid parameters PARAMS are: - -:ustart String to start an unordered list -:uend String to end an unordered list - -:ostart String to start an ordered list -:oend String to end an ordered list - -:dstart String to start a descriptive list -:dend String to end a descriptive list -:dtstart String to start a descriptive term -:dtend String to end a descriptive term -:ddstart String to start a description -:ddend String to end a description - -:splice When set to t, return only list body lines, don't wrap - them into :[u/o]start and :[u/o]end. Default is nil. - -:istart String to start a list item. -:icount String to start an item with a counter. -:iend String to end a list item -:isep String to separate items -:lsep String to separate sublists -:csep String to separate text from a sub-list - -:cboff String to insert for an unchecked check-box -:cbon String to insert for a checked check-box -:cbtrans String to insert for a check-box in transitional state - -:nobr Non-nil means remove line breaks in lists items. - -Alternatively, each parameter can also be a form returning -a string. These sexp can use keywords `counter' and `depth', -representing respectively counter associated to the current -item, and depth of the current sub-list, starting at 0. -Obviously, `counter' is only available for parameters applying to -items." - (interactive) - (let* ((p params) - (splicep (plist-get p :splice)) - (ostart (plist-get p :ostart)) - (oend (plist-get p :oend)) - (ustart (plist-get p :ustart)) - (uend (plist-get p :uend)) - (dstart (plist-get p :dstart)) - (dend (plist-get p :dend)) - (dtstart (plist-get p :dtstart)) - (dtend (plist-get p :dtend)) - (ddstart (plist-get p :ddstart)) - (ddend (plist-get p :ddend)) - (istart (plist-get p :istart)) - (icount (plist-get p :icount)) - (iend (plist-get p :iend)) - (isep (plist-get p :isep)) - (lsep (plist-get p :lsep)) - (csep (plist-get p :csep)) - (cbon (plist-get p :cbon)) - (cboff (plist-get p :cboff)) - (cbtrans (plist-get p :cbtrans)) - (nobr (plist-get p :nobr)) - export-sublist ; for byte-compiler - (export-item - (function - ;; Export an item ITEM of type TYPE, at DEPTH. First - ;; string in item is treated in a special way as it can - ;; bring extra information that needs to be processed. - (lambda (item type depth) - (let* ((counter (pop item)) - (fmt (concat - (cond - ((eq type 'descriptive) - ;; Stick DTSTART to ISTART by - ;; left-trimming the latter. - (concat (let ((s (eval istart))) - (or (and (string-match "[ \t\n\r]+\\'" s) - (replace-match "" t t s)) - istart)) - "%s" (eval ddend))) - ((and counter (eq type 'ordered)) - (concat (eval icount) "%s")) - (t (concat (eval istart) "%s"))) - (eval iend))) - (first (car item))) - ;; Replace checkbox if any is found. - (cond - ((string-match "\\[CBON\\]" first) - (setq first (replace-match cbon t t first))) - ((string-match "\\[CBOFF\\]" first) - (setq first (replace-match cboff t t first))) - ((string-match "\\[CBTRANS\\]" first) - (setq first (replace-match cbtrans t t first)))) - ;; Replace line breaks if required - (when nobr (setq first (org-list-item-trim-br first))) - ;; Insert descriptive term if TYPE is `descriptive'. - (when (eq type 'descriptive) - (let* ((complete (string-match "^\\(.*\\)[ \t]+::" first)) - (term (if complete - (save-match-data - (org-trim (match-string 1 first))) - "???")) - (desc (if complete - (org-trim (substring first (match-end 0))) - first))) - (setq first (concat (eval dtstart) term (eval dtend) - (eval ddstart) desc)))) - (setcar item first) - (format fmt - (mapconcat (lambda (e) - (if (stringp e) e - (funcall export-sublist e (1+ depth)))) - item (or (eval csep) ""))))))) - (export-sublist - (function - ;; Export sublist SUB at DEPTH. - (lambda (sub depth) - (let* ((type (car sub)) - (items (cdr sub)) - (fmt (concat (cond - (splicep "%s") - ((eq type 'ordered) - (concat (eval ostart) "%s" (eval oend))) - ((eq type 'descriptive) - (concat (eval dstart) "%s" (eval dend))) - (t (concat (eval ustart) "%s" (eval uend)))) - (eval lsep)))) - (format fmt (mapconcat (lambda (e) - (funcall export-item e type depth)) - items (or (eval isep) "")))))))) - (concat (funcall export-sublist list 0) "\n"))) - -(defun org-list-to-latex (list &optional _params) + "Convert a LIST parsed through `org-list-to-lisp' to a custom format. + +LIST is a list as returned by `org-list-to-lisp', which see. +PARAMS is a property list of parameters used to tweak the output +format. + +Valid parameters are: + +:backend, :raw + + Export back-end used as a basis to transcode elements of the + list, when no specific parameter applies to it. It is also + used to translate its contents. You can prevent this by + setting :raw property to a non-nil value. + +:splice + + When non-nil, only export the contents of the top most plain + list, effectively ignoring its opening and closing lines. + +:ustart, :uend + + Strings to start and end an unordered list. They can also be + set to a function returning a string or nil, which will be + called with the depth of the list, counting from 1. + +:ostart, :oend + + Strings to start and end an ordered list. They can also be set + to a function returning a string or nil, which will be called + with the depth of the list, counting from 1. + +:dstart, :dend + + Strings to start and end a descriptive list. They can also be + set to a function returning a string or nil, which will be + called with the depth of the list, counting from 1. + +:dtstart, :dtend, :ddstart, :ddend + + Strings to start and end a descriptive term. + +:istart, :iend + + Strings to start or end a list item, and to start a list item + with a counter. They can also be set to a function returning + a string or nil, which will be called with the depth of the + item, counting from 1. + +:icount + + Strings to start a list item with a counter. It can also be + set to a function returning a string or nil, which will be + called with two arguments: the depth of the item, counting from + 1, and the counter. Its value, when non-nil, has precedence + over `:istart'. + +:isep + + String used to separate items. It can also be set to + a function returning a string or nil, which will be called with + the depth of the items, counting from 1. It always start on + a new line. + +:cbon, :cboff, :cbtrans + + String to insert, respectively, an un-checked check-box, + a checked check-box and a check-box in transitional state." + (require 'ox) + (let* ((backend (plist-get params :backend)) + (custom-backend + (org-export-create-backend + :parent (or backend 'org) + :transcoders + `((plain-list . ,(org-list--to-generic-plain-list params)) + (item . ,(org-list--to-generic-item params)) + (macro . (lambda (m c i) (org-element-macro-interpreter m nil)))))) + data info) + ;; Write LIST back into Org syntax and parse it. + (with-temp-buffer + (let ((org-inhibit-startup t)) (org-mode)) + (letrec ((insert-list + (lambda (l) + (dolist (i (cdr l)) + (funcall insert-item i (car l))))) + (insert-item + (lambda (i type) + (let ((start (point))) + (insert (if (eq type 'ordered) "1. " "- ")) + (dolist (e i) + (if (consp e) (funcall insert-list e) + (insert e) + (insert "\n"))) + (beginning-of-line) + (save-excursion + (let ((ind (if (eq type 'ordered) 3 2))) + (while (> (point) start) + (unless (looking-at-p "[ \t]*$") + (indent-to ind)) + (forward-line -1)))))))) + (funcall insert-list list)) + (setf data + (org-element-map (org-element-parse-buffer) 'plain-list + #'identity nil t)) + (setf info (org-export-get-environment backend nil params))) + (when (and backend (symbolp backend) (not (org-export-get-backend backend))) + (user-error "Unknown :backend value")) + (unless backend (require 'ox-org)) + ;; When`:raw' property has a non-nil value, turn all objects back + ;; into Org syntax. + (when (and backend (plist-get params :raw)) + (org-element-map data org-element-all-objects + (lambda (object) + (org-element-set-element + object (org-element-interpret-data object))))) + ;; We use a low-level mechanism to export DATA so as to skip all + ;; usual pre-processing and post-processing, i.e., hooks, filters, + ;; Babel code evaluation, include keywords and macro expansion, + ;; and filters. + (let ((output (org-export-data-with-backend data custom-backend info))) + ;; Remove final newline. + (if (org-string-nw-p output) (substring-no-properties output 0 -1) "")))) + +(defun org-list--depth (element) + "Return the level of ELEMENT within current plain list. +ELEMENT is either an item or a plain list." + (cl-count-if (lambda (ancestor) (eq (org-element-type ancestor) 'plain-list)) + (org-element-lineage element nil t))) + +(defun org-list--trailing-newlines (string) + "Return the number of trailing newlines in STRING." + (with-temp-buffer + (insert string) + (skip-chars-backward " \t\n") + (count-lines (line-beginning-position 2) (point-max)))) + +(defun org-list--generic-eval (value &rest args) + "Evaluate VALUE according to its type. +VALUE is either nil, a string or a function. In the latter case, +it is called with arguments ARGS." + (cond ((null value) nil) + ((stringp value) value) + ((functionp value) (apply value args)) + (t (error "Wrong value: %s" value)))) + +(defun org-list--to-generic-plain-list (params) + "Return a transcoder for `plain-list' elements. +PARAMS is a plist used to tweak the behavior of the transcoder." + (let ((ustart (plist-get params :ustart)) + (uend (plist-get params :uend)) + (ostart (plist-get params :ostart)) + (oend (plist-get params :oend)) + (dstart (plist-get params :dstart)) + (dend (plist-get params :dend)) + (splice (plist-get params :splice)) + (backend (plist-get params :backend))) + (lambda (plain-list contents info) + (let* ((type (org-element-property :type plain-list)) + (depth (org-list--depth plain-list)) + (start (and (not splice) + (org-list--generic-eval + (pcase type + (`ordered ostart) + (`unordered ustart) + (_ dstart)) + depth))) + (end (and (not splice) + (org-list--generic-eval + (pcase type + (`ordered oend) + (`unordered uend) + (_ dend)) + depth)))) + ;; Make sure trailing newlines in END appear in the output by + ;; setting `:post-blank' property to their number. + (when end + (org-element-put-property + plain-list :post-blank (org-list--trailing-newlines end))) + ;; Build output. + (concat (and start (concat start "\n")) + (if (or start end splice (not backend)) + contents + (org-export-with-backend backend plain-list contents info)) + end))))) + +(defun org-list--to-generic-item (params) + "Return a transcoder for `item' elements. +PARAMS is a plist used to tweak the behavior of the transcoder." + (let ((backend (plist-get params :backend)) + (istart (plist-get params :istart)) + (iend (plist-get params :iend)) + (isep (plist-get params :isep)) + (icount (plist-get params :icount)) + (cboff (plist-get params :cboff)) + (cbon (plist-get params :cbon)) + (cbtrans (plist-get params :cbtrans)) + (dtstart (plist-get params :dtstart)) + (dtend (plist-get params :dtend)) + (ddstart (plist-get params :ddstart)) + (ddend (plist-get params :ddend))) + (lambda (item contents info) + (let* ((type + (org-element-property :type (org-element-property :parent item))) + (tag (org-element-property :tag item)) + (depth (org-list--depth item)) + (separator (and (org-export-get-next-element item info) + (org-list--generic-eval isep depth))) + (closing (pcase (org-list--generic-eval iend depth) + ((or `nil `"") "\n") + ((and (guard separator) s) + (if (equal (substring s -1) "\n") s (concat s "\n"))) + (s s)))) + ;; When a closing line or a separator is provided, make sure + ;; its trailing newlines are taken into account when building + ;; output. This is done by setting `:post-blank' property to + ;; the number of such lines in the last line to be added. + (let ((last-string (or separator closing))) + (when last-string + (org-element-put-property + item + :post-blank + (max (1- (org-list--trailing-newlines last-string)) 0)))) + ;; Build output. + (concat + (let ((c (org-element-property :counter item))) + (if c (org-list--generic-eval icount depth c) + (org-list--generic-eval istart depth))) + (let ((body + (if (or istart iend icount cbon cboff cbtrans (not backend) + (and (eq type 'descriptive) + (or dtstart dtend ddstart ddend))) + (concat + (pcase (org-element-property :checkbox item) + (`on cbon) + (`off cboff) + (`trans cbtrans)) + (and tag + (concat dtstart + (if backend + (org-export-data-with-backend + tag backend info) + (org-element-interpret-data tag)) + dtend)) + (and tag ddstart) + (if (= (length contents) 0) "" (substring contents 0 -1)) + (and tag ddend)) + (org-export-with-backend backend item contents info)))) + ;; Remove final newline. + (if (equal body "") "" + (substring (org-element-normalize-string body) 0 -1))) + closing + separator))))) + +(defun org-list-to-latex (list &optional params) "Convert LIST into a LaTeX list. -LIST is as string representing the list to transform, as Org -syntax. Return converted list as a string." +LIST is a parsed plain list, as returned by `org-list-to-lisp'. +PARAMS is a property list with overruling parameters for +`org-list-to-generic'. Return converted list as a string." (require 'ox-latex) - (org-export-string-as list 'latex t)) + (org-list-to-generic list (org-combine-plists '(:backend latex) params))) -(defun org-list-to-html (list) +(defun org-list-to-html (list &optional params) "Convert LIST into a HTML list. -LIST is as string representing the list to transform, as Org -syntax. Return converted list as a string." +LIST is a parsed plain list, as returned by `org-list-to-lisp'. +PARAMS is a property list with overruling parameters for +`org-list-to-generic'. Return converted list as a string." (require 'ox-html) - (org-export-string-as list 'html t)) + (org-list-to-generic list (org-combine-plists '(:backend html) params))) -(defun org-list-to-texinfo (list &optional _params) +(defun org-list-to-texinfo (list &optional params) "Convert LIST into a Texinfo list. -LIST is as string representing the list to transform, as Org -syntax. Return converted list as a string." +LIST is a parsed plain list, as returned by `org-list-to-lisp'. +PARAMS is a property list with overruling parameters for +`org-list-to-generic'. Return converted list as a string." (require 'ox-texinfo) - (org-export-string-as list 'texinfo t)) + (org-list-to-generic list (org-combine-plists '(:backend texinfo) params))) (defun org-list-to-subtree (list &optional params) "Convert LIST into an Org subtree. -LIST is as returned by `org-list-parse-list'. PARAMS is a property list -with overruling parameters for `org-list-to-generic'." - (defvar get-stars) (defvar org--blankp) - (let* ((rule (cdr (assq 'heading org-blank-before-new-entry))) +LIST is as returned by `org-list-to-lisp'. PARAMS is a property +list with overruling parameters for `org-list-to-generic'." + (let* ((blank (pcase (cdr (assq 'heading org-blank-before-new-entry)) + (`t t) + (`auto (save-excursion + (org-with-limited-levels (outline-previous-heading)) + (org-previous-line-empty-p))))) (level (org-reduced-level (or (org-current-level) 0))) - (org--blankp (or (eq rule t) - (and (eq rule 'auto) - (save-excursion - (outline-previous-heading) - (org-previous-line-empty-p))))) - (get-stars ;FIXME: Can't rename without renaming it in org.el as well! - (function - ;; Return the string for the heading, depending on depth D - ;; of current sub-list. - (lambda (d) - (let ((oddeven-level (+ level d 1))) - (concat (make-string (if org-odd-levels-only - (1- (* 2 oddeven-level)) - oddeven-level) - ?*) - " ")))))) + (make-stars + (lambda (depth) + ;; Return the string for the heading, depending on DEPTH + ;; of current sub-list. + (let ((oddeven-level (+ level depth))) + (concat (make-string (if org-odd-levels-only + (1- (* 2 oddeven-level)) + oddeven-level) + ?*) + " "))))) (org-list-to-generic list (org-combine-plists - '(:splice t - :dtstart " " :dtend " " - :istart (funcall get-stars depth) - :icount (funcall get-stars depth) - :isep (if org--blankp "\n\n" "\n") - :csep (if org--blankp "\n\n" "\n") - :cbon "DONE" :cboff "TODO" :cbtrans "TODO") + (list :splice t + :istart make-stars + :icount make-stars + :dtstart " " :dtend " " + :isep (if blank "\n\n" "\n") + :cbon "DONE " :cboff "TODO " :cbtrans "TODO ") params)))) (provide 'org-list) diff --git a/lisp/org/org-macro.el b/lisp/org/org-macro.el index f4919d1385e..3dc9c5450ed 100644 --- a/lisp/org/org-macro.el +++ b/lisp/org/org-macro.el @@ -1,4 +1,4 @@ -;;; org-macro.el --- Macro Replacement Code for Org Mode +;;; org-macro.el --- Macro Replacement Code for Org -*- lexical-binding: t; -*- ;; Copyright (C) 2013-2017 Free Software Foundation, Inc. @@ -30,6 +30,10 @@ ;; `org-macro-initialize-templates', which recursively calls ;; `org-macro--collect-macros' in order to read setup files. +;; Argument in macros are separated with commas. Proper escaping rules +;; are implemented in `org-macro-escape-arguments' and arguments can +;; be extracted from a string with `org-macro-extract-arguments'. + ;; Along with macros defined through #+MACRO: keyword, default ;; templates include the following hard-coded macros: ;; {{{time(format-string)}}}, {{{property(node-property)}}}, @@ -39,19 +43,25 @@ ;; {{{email}}} and {{{title}}} macros. ;;; Code: +(require 'cl-lib) (require 'org-macs) +(require 'org-compat) -(declare-function org-element-at-point "org-element" (&optional keep-trail)) +(declare-function org-element-at-point "org-element" ()) (declare-function org-element-context "org-element" (&optional element)) +(declare-function org-element-macro-parser "org-element" ()) (declare-function org-element-property "org-element" (property element)) (declare-function org-element-type "org-element" (element)) -(declare-function org-remove-double-quotes "org" (s)) -(declare-function org-mode "org" ()) (declare-function org-file-contents "org" (file &optional noerror)) +(declare-function org-in-commented-heading-p "org" (&optional no-inheritance)) +(declare-function org-mode "org" ()) +(declare-function vc-backend "vc-hooks" (f)) +(declare-function vc-call "vc-hooks" (fun file &rest args) t) +(declare-function vc-exec-after "vc-dispatcher" (code)) ;;; Variables -(defvar org-macro-templates nil +(defvar-local org-macro-templates nil "Alist containing all macro templates in current buffer. Associations are in the shape of (NAME . TEMPLATE) where NAME stands for macro's name and template for its replacement value, @@ -59,48 +69,48 @@ both as strings. This is an internal variable. Do not set it directly, use instead: #+MACRO: name template") -(make-variable-buffer-local 'org-macro-templates) - ;;; Functions (defun org-macro--collect-macros () "Collect macro definitions in current buffer and setup files. Return an alist containing all macro templates found." - (let* (collect-macros ; For byte-compiler. - (collect-macros - (lambda (files templates) - ;; Return an alist of macro templates. FILES is a list of - ;; setup files names read so far, used to avoid circular - ;; dependencies. TEMPLATES is the alist collected so far. - (let ((case-fold-search t)) - (org-with-wide-buffer - (goto-char (point-min)) - (while (re-search-forward - "^[ \t]*#\\+\\(MACRO\\|SETUPFILE\\):" nil t) - (let ((element (org-element-at-point))) - (when (eq (org-element-type element) 'keyword) - (let ((val (org-element-property :value element))) - (if (equal (org-element-property :key element) "MACRO") - ;; Install macro in TEMPLATES. - (when (string-match - "^\\(.*?\\)\\(?:\\s-+\\(.*\\)\\)?\\s-*$" val) - (let* ((name (match-string 1 val)) - (template (or (match-string 2 val) "")) - (old-cell (assoc name templates))) - (if old-cell (setcdr old-cell template) - (push (cons name template) templates)))) - ;; Enter setup file. - (let ((file (expand-file-name - (org-remove-double-quotes val)))) - (unless (member file files) - (with-temp-buffer - (org-mode) - (insert (org-file-contents file 'noerror)) - (setq templates - (funcall collect-macros (cons file files) - templates))))))))))) - templates)))) + (letrec ((collect-macros + (lambda (files templates) + ;; Return an alist of macro templates. FILES is a list + ;; of setup files names read so far, used to avoid + ;; circular dependencies. TEMPLATES is the alist + ;; collected so far. + (let ((case-fold-search t)) + (org-with-wide-buffer + (goto-char (point-min)) + (while (re-search-forward + "^[ \t]*#\\+\\(MACRO\\|SETUPFILE\\):" nil t) + (let ((element (org-element-at-point))) + (when (eq (org-element-type element) 'keyword) + (let ((val (org-element-property :value element))) + (if (equal (org-element-property :key element) "MACRO") + ;; Install macro in TEMPLATES. + (when (string-match + "^\\(.*?\\)\\(?:\\s-+\\(.*\\)\\)?\\s-*$" val) + (let* ((name (match-string 1 val)) + (template (or (match-string 2 val) "")) + (old-cell (assoc name templates))) + (if old-cell (setcdr old-cell template) + (push (cons name template) templates)))) + ;; Enter setup file. + (let ((file (expand-file-name + (org-unbracket-string "\"" "\"" val)))) + (unless (member file files) + (with-temp-buffer + (setq default-directory + (file-name-directory file)) + (org-mode) + (insert (org-file-contents file 'noerror)) + (setq templates + (funcall collect-macros (cons file files) + templates))))))))))) + templates)))) (funcall collect-macros nil nil))) (defun org-macro-initialize-templates () @@ -117,15 +127,26 @@ function installs the following ones: \"property\", (if old-template (setcdr old-template (cdr cell)) (push cell templates)))))) ;; Install hard-coded macros. - (mapc (lambda (cell) (funcall update-templates cell)) - (list (cons "property" "(eval (org-entry-get nil \"$1\" 'selective))") + (mapc update-templates + (list (cons "property" + "(eval (save-excursion + (let ((l \"$2\")) + (when (org-string-nw-p l) + (condition-case _ + (let ((org-link-search-must-match-exact-headline t)) + (org-link-search l nil t)) + (error + (error \"Macro property failed: cannot find location %s\" + l))))) + (org-entry-get nil \"$1\" 'selective)))") (cons "time" "(eval (format-time-string \"$1\"))"))) (let ((visited-file (buffer-file-name (buffer-base-buffer)))) (when (and visited-file (file-exists-p visited-file)) - (mapc (lambda (cell) (funcall update-templates cell)) + (mapc update-templates (list (cons "input-file" (file-name-nondirectory visited-file)) (cons "modification-time" - (format "(eval (format-time-string \"$1\" '%s))" + (format "(eval (format-time-string \"$1\" (or (and (org-string-nw-p \"$2\") (org-macro--vc-modified-time %s)) '%s)))" + (prin1-to-string visited-file) (prin1-to-string (nth 5 (file-attributes visited-file))))))))) (setq org-macro-templates templates))) @@ -154,38 +175,132 @@ default value. Return nil if no template was found." ;; Return string. (format "%s" (or value "")))))) -(defun org-macro-replace-all (templates) +(defun org-macro-replace-all (templates &optional finalize keywords) "Replace all macros in current buffer by their expansion. + TEMPLATES is an alist of templates used for expansion. See -`org-macro-templates' for a buffer-local default value." +`org-macro-templates' for a buffer-local default value. + +If optional arg FINALIZE is non-nil, raise an error if a macro is +found in the buffer with no definition in TEMPLATES. + +Optional argument KEYWORDS, when non-nil is a list of keywords, +as strings, where macro expansion is allowed." (save-excursion (goto-char (point-min)) - (let (record) + (let ((properties-regexp + (format "\\`EXPORT_%s\\+?\\'" (regexp-opt keywords))) + record) (while (re-search-forward "{{{[-A-Za-z0-9_]" nil t) - (let ((object (org-element-context))) - (when (eq (org-element-type object) 'macro) - (let* ((value (org-macro-expand object templates)) - (begin (org-element-property :begin object)) - (signature (list begin - object - (org-element-property :args object)))) - ;; Avoid circular dependencies by checking if the same - ;; macro with the same arguments is expanded at the same - ;; position twice. - (if (member signature record) - (error "Circular macro expansion: %s" - (org-element-property :key object)) - (when value - (push signature record) - (delete-region - begin - ;; Preserve white spaces after the macro. - (progn (goto-char (org-element-property :end object)) - (skip-chars-backward " \t") - (point))) - ;; Leave point before replacement in case of recursive - ;; expansions. - (save-excursion (insert value))))))))))) + (unless (save-match-data (org-in-commented-heading-p)) + (let* ((datum (save-match-data (org-element-context))) + (type (org-element-type datum)) + (macro + (cond + ((eq type 'macro) datum) + ;; In parsed keywords and associated node + ;; properties, force macro recognition. + ((or (and (eq type 'keyword) + (member (org-element-property :key datum) + keywords)) + (and (eq type 'node-property) + (string-match-p properties-regexp + (org-element-property :key + datum)))) + (save-excursion + (goto-char (match-beginning 0)) + (org-element-macro-parser)))))) + (when macro + (let* ((value (org-macro-expand macro templates)) + (begin (org-element-property :begin macro)) + (signature (list begin + macro + (org-element-property :args macro)))) + ;; Avoid circular dependencies by checking if the same + ;; macro with the same arguments is expanded at the + ;; same position twice. + (cond ((member signature record) + (error "Circular macro expansion: %s" + (org-element-property :key macro))) + (value + (push signature record) + (delete-region + begin + ;; Preserve white spaces after the macro. + (progn (goto-char (org-element-property :end macro)) + (skip-chars-backward " \t") + (point))) + ;; Leave point before replacement in case of + ;; recursive expansions. + (save-excursion (insert value))) + (finalize + (error "Undefined Org macro: %s; aborting" + (org-element-property :key macro)))))))))))) + +(defun org-macro-escape-arguments (&rest args) + "Build macro's arguments string from ARGS. +ARGS are strings. Return value is a string with arguments +properly escaped and separated with commas. This is the opposite +of `org-macro-extract-arguments'." + (let ((s "")) + (dolist (arg (reverse args) (substring s 1)) + (setq s + (concat + "," + (replace-regexp-in-string + "\\(\\\\*\\)," + (lambda (m) + (concat (make-string (1+ (* 2 (length (match-string 1 m)))) ?\\) + ",")) + ;; If a non-terminal argument ends on backslashes, make + ;; sure to also escape them as they will be followed by + ;; a comma. + (concat arg (and (not (equal s "")) + (string-match "\\\\+\\'" arg) + (match-string 0 arg))) + nil t) + s))))) + +(defun org-macro-extract-arguments (s) + "Extract macro arguments from string S. +S is a string containing comma separated values properly escaped. +Return a list of arguments, as strings. This is the opposite of +`org-macro-escape-arguments'." + ;; Do not use `org-split-string' since empty strings are + ;; meaningful here. + (split-string + (replace-regexp-in-string + "\\(\\\\*\\)," + (lambda (str) + (let ((len (length (match-string 1 str)))) + (concat (make-string (/ len 2) ?\\) + (if (zerop (mod len 2)) "\000" ",")))) + s nil t) + "\000")) + +(defun org-macro--vc-modified-time (file) + (save-window-excursion + (when (vc-backend file) + (let ((buf (get-buffer-create " *org-vc*")) + (case-fold-search t) + date) + (unwind-protect + (progn + (vc-call print-log file buf nil nil 1) + (with-current-buffer buf + (vc-exec-after + (lambda () + (goto-char (point-min)) + (when (re-search-forward "Date:?[ \t]*" nil t) + (let ((time (parse-time-string + (buffer-substring + (point) (line-end-position))))) + (when (cl-some #'identity time) + (setq date (apply #'encode-time time)))))))) + (let ((proc (get-buffer-process buf))) + (while (and proc (accept-process-output proc .5 nil t))))) + (kill-buffer buf)) + date)))) (provide 'org-macro) diff --git a/lisp/org/org-macs.el b/lisp/org/org-macs.el index 64e28cee04c..ca47e5a5a33 100644 --- a/lisp/org/org-macs.el +++ b/lisp/org/org-macs.el @@ -1,4 +1,4 @@ -;;; org-macs.el --- Top-level definitions for Org-mode +;;; org-macs.el --- Top-level Definitions for Org -*- lexical-binding: t; -*- ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. @@ -25,29 +25,12 @@ ;;; Commentary: ;; This file contains macro definitions, defsubst definitions, other -;; stuff needed for compilation and top-level forms in Org-mode, as well -;; lots of small functions that are not org-mode specific but simply -;; generally useful stuff. +;; stuff needed for compilation and top-level forms in Org mode, as +;; well lots of small functions that are not Org mode specific but +;; simply generally useful stuff. ;;; Code: -(eval-and-compile - (unless (fboundp 'declare-function) - (defmacro declare-function (fn file &optional _arglist _fileonly) - `(autoload ',fn ,file))) - - (if (>= emacs-major-version 23) - (defsubst org-char-to-string(c) - "Defsubst to decode UTF-8 character values in emacs 23 and beyond." - (char-to-string c)) - (defsubst org-char-to-string (c) - "Defsubst to decode UTF-8 character values in emacs 22." - (string (decode-char 'ucs c))))) - -(declare-function org-add-props "org-compat" (string plist &rest props)) -(declare-function org-string-match-p "org-compat" - (regexp string &optional start)) - (defmacro org-with-gensyms (symbols &rest body) (declare (debug (sexp body)) (indent 1)) `(let ,(mapcar (lambda (s) @@ -55,26 +38,11 @@ symbols) ,@body)) -(defmacro org-called-interactively-p (&optional kind) - (declare (debug (&optional ("quote" symbolp)))) ;Why not just t? - (if (featurep 'xemacs) - `(interactive-p) - (if (or (> emacs-major-version 23) - (and (>= emacs-major-version 23) - (>= emacs-minor-version 2))) - ;; defined with no argument in <=23.1 - `(with-no-warnings (called-interactively-p ,kind)) - `(interactive-p)))) - -(defmacro org-bound-and-true-p (var) - "Return the value of symbol VAR if it is bound, else nil." - (declare (debug (symbolp))) - `(and (boundp (quote ,var)) ,var)) - (defun org-string-nw-p (s) - "Is S a string with a non-white character?" + "Return S if S is a string containing a non-blank character. +Otherwise, return nil." (and (stringp s) - (org-string-match-p "\\S-" s) + (string-match-p "[^ \r\t\n]" s) s)) (defun org-not-nil (v) @@ -82,25 +50,6 @@ Otherwise return nil." (and v (not (equal v "nil")) v)) -(defun org-substitute-posix-classes (re) - "Substitute posix classes in regular expression RE." - (let ((ss re)) - (save-match-data - (while (string-match "\\[:alnum:\\]" ss) - (setq ss (replace-match "a-zA-Z0-9" t t ss))) - (while (string-match "\\[:word:\\]" ss) - (setq ss (replace-match "a-zA-Z0-9" t t ss))) - (while (string-match "\\[:alpha:\\]" ss) - (setq ss (replace-match "a-zA-Z" t t ss))) - (while (string-match "\\[:punct:\\]" ss) - (setq ss (replace-match "\001-@[-`{-~" t t ss))) - ss))) - -(defmacro org-re (s) - "Replace posix classes in regular expression." - (declare (debug (form))) - (if (featurep 'xemacs) `(org-substitute-posix-classes ,s) s)) - (defmacro org-preserve-lc (&rest body) (declare (debug (body))) (org-with-gensyms (line col) @@ -136,19 +85,6 @@ Otherwise return nil." (partial-completion-mode 1)) ,@body)) -;; FIXME: Slated for removal. Current Org mode does not support Emacs < 22 -(defmacro org-maybe-intangible (props) - "Add (intangible t) to PROPS if Emacs version is earlier than Emacs 22. -In Emacs 21, invisible text is not avoided by the command loop, so the -intangible property is needed to make sure point skips this text. -In Emacs 22, this is not necessary. The intangible text property has -led to problems with flyspell. These problems are fixed in flyspell.el, -but we still avoid setting the property in Emacs 22 and later. -We use a macro so that the test can happen at compilation time." - (if (< emacs-major-version 22) - `(append '(intangible t) ,props) - props)) - (defmacro org-with-point-at (pom &rest body) "Move to buffer and point of point-or-marker POM for the duration of BODY." (declare (debug (form body)) (indent 1)) @@ -160,10 +96,6 @@ We use a macro so that the test can happen at compilation time." (goto-char (or ,mpom (point))) ,@body))))) -(defmacro org-no-warnings (&rest body) - (declare (debug (body))) - (cons (if (fboundp 'with-no-warnings) 'with-no-warnings 'progn) body)) - (defmacro org-with-remote-undo (buffer &rest body) "Execute BODY while recording undo information in two buffers." (declare (debug (form body)) (indent 1)) @@ -199,22 +131,12 @@ We use a macro so that the test can happen at compilation time." org-emphasis t) "Properties to remove when a string without properties is wanted.") -(defsubst org-match-string-no-properties (num &optional string) - (if (featurep 'xemacs) - (let ((s (match-string num string))) - (and s (remove-text-properties 0 (length s) org-rm-props s)) - s) - (match-string-no-properties num string))) - (defsubst org-no-properties (s &optional restricted) "Remove all text properties from string S. When RESTRICTED is non-nil, only remove the properties listed in `org-rm-props'." - (if (fboundp 'set-text-properties) - (set-text-properties 0 (length s) nil s) - (if restricted - (remove-text-properties 0 (length s) org-rm-props s) - (set-text-properties 0 (length s) nil s))) + (if restricted (remove-text-properties 0 (length s) org-rm-props s) + (set-text-properties 0 (length s) nil s)) s) (defsubst org-get-alist-option (option key) @@ -236,16 +158,6 @@ program is needed for, so that the error message can be more informative." (error "Can't find `%s'%s" cmd (if use (format " (%s)" use) ""))))) -(defsubst org-inhibit-invisibility () - "Modified `buffer-invisibility-spec' for Emacs 21. -Some ops with invisible text do not work correctly on Emacs 21. For these -we turn off invisibility temporarily. Use this in a `let' form." - (if (< emacs-major-version 22) nil buffer-invisibility-spec)) - -(defsubst org-set-local (var value) - "Make VAR local in current buffer and set it to VALUE." - (set (make-local-variable var) value)) - (defsubst org-last (list) "Return the last element of LIST." (car (last list))) @@ -282,11 +194,11 @@ we turn off invisibility temporarily. Use this in a `let' form." (<= (match-beginning n) pos) (>= (match-end n) pos))) -(defun org-match-line (re) - "Looking-at at the beginning of the current line." +(defun org-match-line (regexp) + "Match REGEXP at the beginning of the current line." (save-excursion - (goto-char (point-at-bol)) - (looking-at re))) + (beginning-of-line) + (looking-at regexp))) (defun org-plist-delete (plist property) "Delete PROPERTY from PLIST. @@ -298,13 +210,6 @@ This is in contrast to merely setting it to 0." (setq plist (cddr plist))) p)) -(defun org-replace-match-keep-properties (newtext &optional fixedcase - literal string) - "Like `replace-match', but add the text properties found original text." - (setq newtext (org-add-props newtext (text-properties-at - (match-beginning 0) string))) - (replace-match newtext fixedcase literal string)) - (defmacro org-save-outline-visibility (use-markers &rest body) "Save and restore outline visibility around BODY. If USE-MARKERS is non-nil, use markers for the positions. @@ -313,19 +218,15 @@ but it also means that the buffer should stay alive during the operation, because otherwise all these markers will point nowhere." (declare (debug (form body)) (indent 1)) - (org-with-gensyms (data rtn) - `(let ((,data (org-outline-overlay-data ,use-markers)) - ,rtn) + (org-with-gensyms (data) + `(let ((,data (org-outline-overlay-data ,use-markers))) (unwind-protect - (progn - (setq ,rtn (progn ,@body)) + (prog1 (progn ,@body) (org-set-outline-overlay-data ,data)) (when ,use-markers - (mapc (lambda (c) - (and (markerp (car c)) (move-marker (car c) nil)) - (and (markerp (cdr c)) (move-marker (cdr c) nil))) - ,data))) - ,rtn))) + (dolist (c ,data) + (when (markerp (car c)) (move-marker (car c) nil)) + (when (markerp (cdr c)) (move-marker (cdr c) nil)))))))) (defmacro org-with-wide-buffer (&rest body) "Execute body while temporarily widening the buffer." @@ -355,17 +256,16 @@ point nowhere." (defun org-get-limited-outline-regexp () "Return outline-regexp with limited number of levels. The number of levels is controlled by `org-inlinetask-min-level'" - (if (or (not (derived-mode-p 'org-mode)) (not (featurep 'org-inlinetask))) - org-outline-regexp - (let* ((limit-level (1- org-inlinetask-min-level)) - (nstars (if org-odd-levels-only (1- (* limit-level 2)) limit-level))) - (format "\\*\\{1,%d\\} " nstars)))) - -(defun org-format-seconds (string seconds) - "Compatibility function replacing format-seconds." - (if (fboundp 'format-seconds) - (format-seconds string seconds) - (format-time-string string (seconds-to-time seconds)))) + (cond ((not (derived-mode-p 'org-mode)) + outline-regexp) + ((not (featurep 'org-inlinetask)) + org-outline-regexp) + (t + (let* ((limit-level (1- org-inlinetask-min-level)) + (nstars (if org-odd-levels-only + (1- (* limit-level 2)) + limit-level))) + (format "\\*\\{1,%d\\} " nstars))))) (defmacro org-eval-in-environment (environment form) (declare (debug (form form)) (indent 1)) @@ -382,10 +282,27 @@ the value in cdr." ;;;###autoload (defmacro org-load-noerror-mustsuffix (file) - "Load FILE with optional arguments NOERROR and MUSTSUFFIX. Drop the MUSTSUFFIX argument for XEmacs, which doesn't recognize it." - (if (featurep 'xemacs) - `(load ,file 'noerror) - `(load ,file 'noerror nil nil 'mustsuffix))) + "Load FILE with optional arguments NOERROR and MUSTSUFFIX." + `(load ,file 'noerror nil nil 'mustsuffix)) + +(defun org-unbracket-string (pre post string) + "Remove PRE/POST from the beginning/end of STRING. +Both PRE and POST must be pre-/suffixes of STRING, or neither is +removed." + (if (and (string-prefix-p pre string) + (string-suffix-p post string)) + (substring string (length pre) (- (length post))) + string)) + +(defun org-read-function (prompt &optional allow-empty?) + "Prompt for a function. +If ALLOW-EMPTY? is non-nil, return nil rather than raising an +error when the user input is empty." + (let ((func (completing-read prompt obarray #'fboundp t))) + (cond ((not (string= func "")) + (intern func)) + (allow-empty? nil) + (t (user-error "Empty input is not valid"))))) (provide 'org-macs) diff --git a/lisp/org/org-mhe.el b/lisp/org/org-mhe.el index 72c2eeec22e..4142ae45b2b 100644 --- a/lisp/org/org-mhe.el +++ b/lisp/org/org-mhe.el @@ -1,4 +1,4 @@ -;;; org-mhe.el --- Support for links to MH-E messages from within Org-mode +;;; org-mhe.el --- Support for Links to MH-E Messages -*- lexical-binding: t; -*- ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. @@ -24,8 +24,8 @@ ;; ;;; Commentary: -;; This file implements links to MH-E messages from within Org-mode. -;; Org-mode loads this module by default - if this is not what you want, +;; This file implements links to MH-E messages from within Org. +;; Org mode loads this module by default - if this is not what you want, ;; configure the variable `org-modules'. ;;; Code: @@ -74,34 +74,25 @@ supported by MH-E." (defvar mh-search-regexp-builder) ;; Install the link type -(org-add-link-type "mhe" 'org-mhe-open) -(add-hook 'org-store-link-functions 'org-mhe-store-link) +(org-link-set-parameters "mhe" :follow #'org-mhe-open :store #'org-mhe-store-link) ;; Implementation (defun org-mhe-store-link () "Store a link to an MH-E folder or message." - (when (or (equal major-mode 'mh-folder-mode) - (equal major-mode 'mh-show-mode)) + (when (or (eq major-mode 'mh-folder-mode) + (eq major-mode 'mh-show-mode)) (save-window-excursion (let* ((from (org-mhe-get-header "From:")) (to (org-mhe-get-header "To:")) (message-id (org-mhe-get-header "Message-Id:")) (subject (org-mhe-get-header "Subject:")) (date (org-mhe-get-header "Date:")) - (date-ts (and date (format-time-string - (org-time-stamp-format t) (date-to-time date)))) - (date-ts-ia (and date (format-time-string - (org-time-stamp-format t t) - (date-to-time date)))) link desc) - (org-store-link-props :type "mh" :from from :to to + (org-store-link-props :type "mh" :from from :to to :date date :subject subject :message-id message-id) - (when date - (org-add-link-props :date date :date-timestamp date-ts - :date-timestamp-inactive date-ts-ia)) (setq desc (org-email-link-description)) (setq link (concat "mhe:" (org-mhe-get-message-real-folder) "#" - (org-remove-angle-brackets message-id))) + (org-unbracket-string "<" ">" message-id))) (org-add-link-props :link link :description desc) link)))) @@ -120,7 +111,7 @@ supported by MH-E." So if you use sequences, it will now work." (save-excursion (let* ((folder - (if (equal major-mode 'mh-folder-mode) + (if (eq major-mode 'mh-folder-mode) mh-current-folder ;; Refer to the show buffer mh-show-folder-buffer)) @@ -132,7 +123,7 @@ So if you use sequences, it will now work." ;; mh-index-data is always nil in a show buffer. (if (and (boundp 'mh-index-folder) (string= mh-index-folder (substring folder 0 end-index))) - (if (equal major-mode 'mh-show-mode) + (if (eq major-mode 'mh-show-mode) (save-window-excursion (let (pop-up-frames) (when (buffer-live-p (get-buffer folder)) @@ -158,7 +149,7 @@ So if you use sequences, it will now work." "Return the name of the current message folder. Be careful if you use sequences." (save-excursion - (if (equal major-mode 'mh-folder-mode) + (if (eq major-mode 'mh-folder-mode) mh-current-folder ;; Refer to the show buffer mh-show-folder-buffer))) @@ -167,7 +158,7 @@ Be careful if you use sequences." "Return the number of the current message. Be careful if you use sequences." (save-excursion - (if (equal major-mode 'mh-folder-mode) + (if (eq major-mode 'mh-folder-mode) (mh-get-msg-num nil) ;; Refer to the show buffer (mh-show-buffer-message-number)))) @@ -182,12 +173,12 @@ you have a better idea of how to do this then please let us know." (header-field)) (with-current-buffer buffer (mh-display-msg num folder) - (if (equal major-mode 'mh-folder-mode) + (if (eq major-mode 'mh-folder-mode) (mh-header-display) (mh-show-header-display)) (set-buffer buffer) (setq header-field (mh-get-header-field header)) - (if (equal major-mode 'mh-folder-mode) + (if (eq major-mode 'mh-folder-mode) (mh-show) (mh-show-show)) (org-trim header-field)))) @@ -206,13 +197,13 @@ folders." (if (not article) (mh-visit-folder (mh-normalize-folder-name folder)) (mh-search-choose) - (if (equal mh-searcher 'pick) + (if (eq mh-searcher 'pick) (progn (setq article (org-add-angle-brackets article)) (mh-search folder (list "--message-id" article)) (when (and org-mhe-search-all-folders (not (org-mhe-get-message-real-folder))) - (kill-this-buffer) + (kill-buffer) (mh-search "+" (list "--message-id" article)))) (if mh-search-regexp-builder (mh-search "+" (funcall mh-search-regexp-builder @@ -220,7 +211,7 @@ folders." (mh-search "+" article))) (if (org-mhe-get-message-real-folder) (mh-show-msg 1) - (kill-this-buffer) + (kill-buffer) (error "Message not found")))) (provide 'org-mhe) diff --git a/lisp/org/org-mobile.el b/lisp/org/org-mobile.el index 34e6af10d81..12e6c84b3ce 100644 --- a/lisp/org/org-mobile.el +++ b/lisp/org/org-mobile.el @@ -1,4 +1,4 @@ -;;; org-mobile.el --- Code for asymmetric sync with a mobile device +;;; org-mobile.el --- Code for Asymmetric Sync With a Mobile Device -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2017 Free Software Foundation, Inc. ;; ;; Author: Carsten Dominik @@ -24,21 +24,20 @@ ;; ;;; Commentary: ;; -;; This file contains the code to interact with Richard Moreland's iPhone -;; application MobileOrg, as well as with the Android version by Matthew Jones. -;; This code is documented in Appendix B of the Org-mode manual. The code is -;; not specific for the iPhone and Android - any external -;; viewer/flagging/editing application that uses the same conventions could -;; be used. +;; This file contains the code to interact with Richard Moreland's +;; iPhone application MobileOrg, as well as with the Android version +;; by Matthew Jones. This code is documented in Appendix B of the Org +;; manual. The code is not specific for the iPhone and Android - any +;; external viewer/flagging/editing application that uses the same +;; conventions could be used. (require 'org) (require 'org-agenda) -;;; Code: +(require 'cl-lib) -(eval-when-compile (require 'cl)) +(defvar org-agenda-keep-restricted-file-list) -(declare-function org-pop-to-buffer-same-window - "org-compat" (&optional buffer-or-name norecord label)) +;;; Code: (defgroup org-mobile nil "Options concerning support for a viewer/editor on a mobile device." @@ -192,27 +191,6 @@ the editing types for which the mobile version should always dominate." (const heading) (const body)))) -(defcustom org-mobile-action-alist - '(("edit" . (org-mobile-edit data old new))) - "Alist with flags and actions for mobile sync. -When flagging an entry, MobileOrg will create entries that look like - - * F(action:data) [[id:entry-id][entry title]] - -This alist defines that the ACTION in the parentheses of F() should mean, -i.e. what action should be taken. The :data part in the parenthesis is -optional. If present, the string after the colon will be passed to the -action form as the `data' variable. -The car of each elements of the alist is an actions string. The cdr is -an Emacs Lisp form that will be evaluated with the cursor on the headline -of that entry. - -For now, it is not recommended to change this variable." - :group 'org-mobile - :type '(repeat - (cons (string :tag "Action flag") - (sexp :tag "Action form")))) - (defcustom org-mobile-checksum-binary (or (executable-find "shasum") (executable-find "sha1sum") (executable-find "md5sum") @@ -249,6 +227,23 @@ by the mobile device, this hook should be used to copy the emptied capture file `mobileorg.org' back to the WebDAV directory, for example using `rsync' or `scp'.") +(defconst org-mobile-action-alist '(("edit" . org-mobile-edit)) + "Alist with flags and actions for mobile sync. +When flagging an entry, MobileOrg will create entries that look like + + * F(action:data) [[id:entry-id][entry title]] + +This alist defines that the ACTION in the parentheses of F() +should mean, i.e. what action should be taken. The :data part in +the parenthesis is optional. If present, the string after the +colon will be passed to the action function as the first argument +variable. + +The car of each elements of the alist is an actions string. The +cdr is a function that is called with the cursor on the headline +of that entry. It should accept three arguments, the :data part, +the old and new values for the entry.") + (defvar org-mobile-last-flagged-files nil "List of files containing entries flagged in the latest pull.") @@ -313,40 +308,29 @@ Also exclude files matching `org-mobile-files-exclude-regexp'." This will create the index file, copy all agenda files there, and also create all custom agenda views, for upload to the mobile phone." (interactive) - (let ((a-buffer (get-buffer org-agenda-buffer-name))) - (let ((org-agenda-curbuf-name org-agenda-buffer-name) - (org-agenda-buffer-name "*SUMO*") - (org-agenda-tag-filter org-agenda-tag-filter) - (org-agenda-redo-command org-agenda-redo-command)) - (save-excursion - (save-restriction - (save-window-excursion - (run-hooks 'org-mobile-pre-push-hook) - (org-mobile-check-setup) - (org-mobile-prepare-file-lists) - (message "Creating agendas...") - (let ((inhibit-redisplay t) - (org-agenda-files (mapcar 'car org-mobile-files-alist))) - (org-mobile-create-sumo-agenda)) - (message "Creating agendas...done") - (org-save-all-org-buffers) ; to save any IDs created by this process - (message "Copying files...") - (org-mobile-copy-agenda-files) - (message "Writing index file...") - (org-mobile-create-index-file) - (message "Writing checksums...") - (org-mobile-write-checksums) - (run-hooks 'org-mobile-post-push-hook)))) - (setq org-agenda-buffer-name org-agenda-curbuf-name - org-agenda-this-buffer-name org-agenda-curbuf-name)) - (redraw-display) - (when (buffer-live-p a-buffer) - (if (not (get-buffer-window a-buffer)) - (kill-buffer a-buffer) - (let ((cw (selected-window))) - (select-window (get-buffer-window a-buffer)) - (org-agenda-redo) - (select-window cw))))) + (let ((org-agenda-buffer-name "*SUMO*") + (org-agenda-tag-filter org-agenda-tag-filter) + (org-agenda-redo-command org-agenda-redo-command)) + (save-excursion + (save-restriction + (save-window-excursion + (run-hooks 'org-mobile-pre-push-hook) + (org-mobile-check-setup) + (org-mobile-prepare-file-lists) + (message "Creating agendas...") + (let ((inhibit-redisplay t) + (org-agenda-files (mapcar 'car org-mobile-files-alist))) + (org-mobile-create-sumo-agenda)) + (message "Creating agendas...done") + (org-save-all-org-buffers) ; to save any IDs created by this process + (message "Copying files...") + (org-mobile-copy-agenda-files) + (message "Writing index file...") + (org-mobile-create-index-file) + (message "Writing checksums...") + (org-mobile-write-checksums) + (run-hooks 'org-mobile-post-push-hook))))) + (org-agenda-maybe-redo) (message "Files for mobile viewer staged")) (defvar org-mobile-before-process-capture-hook nil @@ -422,10 +406,10 @@ agenda view showing the flagged items." (let ((files-alist (sort (copy-sequence org-mobile-files-alist) (lambda (a b) (string< (cdr a) (cdr b))))) (def-todo (default-value 'org-todo-keywords)) - (def-tags (default-value 'org-tag-alist)) + (def-tags org-tag-alist) (target-file (expand-file-name org-mobile-index-file org-mobile-directory)) - file link-name todo-kwds done-kwds tags drawers entry kwds dwds twds) + todo-kwds done-kwds tags) (when (stringp (car def-todo)) (setq def-todo (list (cons 'sequence def-todo)))) (org-agenda-prepare-buffers (mapcar 'car files-alist)) @@ -433,52 +417,36 @@ agenda view showing the flagged items." (setq todo-kwds (org-delete-all done-kwds (org-uniquify org-todo-keywords-for-agenda))) - (setq drawers (org-uniquify org-drawers-for-agenda)) (setq tags (mapcar 'car (org-global-tags-completion-table (mapcar 'car files-alist)))) - (with-temp-file - (if org-mobile-use-encryption - org-mobile-encryption-tempfile - target-file) - (while (setq entry (pop def-todo)) - (insert "#+READONLY\n") - (setq kwds (mapcar (lambda (x) (if (string-match "(" x) - (substring x 0 (match-beginning 0)) - x)) - (cdr entry))) - (insert "#+TODO: " (mapconcat 'identity kwds " ") "\n") - (setq dwds (member "|" kwds) - twds (org-delete-all dwds kwds) - todo-kwds (org-delete-all twds todo-kwds) - done-kwds (org-delete-all dwds done-kwds))) + (with-temp-file (if org-mobile-use-encryption org-mobile-encryption-tempfile + target-file) + (insert "#+READONLY\n") + (dolist (entry def-todo) + (let ((kwds (mapcar (lambda (x) + (if (string-match "(" x) + (substring x 0 (match-beginning 0)) + x)) + (cdr entry)))) + (insert "#+TODO: " (mapconcat #'identity kwds " ") "\n") + (let* ((dwds (or (member "|" kwds) (last kwds))) + (twds (org-delete-all dwds kwds))) + (setq todo-kwds (org-delete-all twds todo-kwds)) + (setq done-kwds (org-delete-all dwds done-kwds))))) (when (or todo-kwds done-kwds) (insert "#+TODO: " (mapconcat 'identity todo-kwds " ") " | " (mapconcat 'identity done-kwds " ") "\n")) - (setq def-tags (mapcar - (lambda (x) - (cond ((null x) nil) - ((stringp x) x) - ((eq (car x) :startgroup) "{") - ((eq (car x) :endgroup) "}") - ((eq (car x) :grouptags) nil) - ((eq (car x) :newline) nil) - ((listp x) (car x)))) - def-tags)) - (setq def-tags (delq nil def-tags)) + (setq def-tags (split-string (org-tag-alist-to-string def-tags t))) (setq tags (org-delete-all def-tags tags)) (setq tags (sort tags (lambda (a b) (string< (downcase a) (downcase b))))) (setq tags (append def-tags tags nil)) (insert "#+TAGS: " (mapconcat 'identity tags " ") "\n") - (insert "#+DRAWERS: " (mapconcat 'identity drawers " ") "\n") (insert "#+ALLPRIORITIES: " org-mobile-allpriorities "\n") (when (file-exists-p (expand-file-name org-mobile-directory "agendas.org")) (insert "* [[file:agendas.org][Agenda Views]]\n")) - (while (setq entry (pop files-alist)) - (setq file (car entry) - link-name (cdr entry)) - (insert (format "* [[file:%s][%s]]\n" - link-name link-name))) + (pcase-dolist (`(,_ . ,link-name) files-alist) + (insert (format "* [[file:%s][%s]]\n" link-name link-name))) (push (cons org-mobile-index-file (md5 (buffer-string))) org-mobile-checksum-files)) (when org-mobile-use-encryption @@ -501,7 +469,8 @@ agenda view showing the flagged items." (org-mobile-encrypt-and-move file target-path) (copy-file file target-path 'ok-if-exists)) (setq check (shell-command-to-string - (concat org-mobile-checksum-binary " " + (concat (shell-quote-argument org-mobile-checksum-binary) + " " (shell-quote-argument (expand-file-name file))))) (when (string-match "[a-fA-F0-9]\\{30,40\\}" check) (push (cons link-name (match-string 0 check)) @@ -663,7 +632,7 @@ The table of checksums is written to the file mobile-checksums." m 10 " " 'planning) "\n") (when (setq id - (if (org-bound-and-true-p + (if (bound-and-true-p org-mobile-force-id-on-agenda-items) (org-id-get m 'create) (or (org-entry-get m "ID") @@ -679,7 +648,7 @@ The table of checksums is written to the file mobile-checksums." (org-with-point-at pom (concat "olp:" (org-mobile-escape-olp (file-name-nondirectory buffer-file-name)) - "/" + ":" (mapconcat 'org-mobile-escape-olp (org-get-outline-path) "/") @@ -823,14 +792,14 @@ If BEG and END are given, only do this in that region." (cnt-flag 0) (cnt-error 0) buf-list - id-pos org-mobile-error) + org-mobile-error) ;; Count the new captures (goto-char beg) (while (re-search-forward "^\\* \\(.*\\)" end t) (and (>= (- (match-end 1) (match-beginning 1)) 2) (not (equal (downcase (substring (match-string 1) 0 2)) "f(")) - (incf cnt-new))) + (cl-incf cnt-new))) ;; Find and apply the edits (goto-char beg) @@ -842,19 +811,21 @@ If BEG and END are given, only do this in that region." (id-pos (condition-case msg (org-mobile-locate-entry (match-string 4)) (error (nth 1 msg)))) - (bos (point-at-bol)) + (bos (line-beginning-position)) (eos (save-excursion (org-end-of-subtree t t))) (cmd (if (equal action "") - '(progn - (incf cnt-flag) - (org-toggle-tag "FLAGGED" 'on) - (and note - (org-entry-put nil "THEFLAGGINGNOTE" note))) - (incf cnt-edit) + (let ((note (buffer-substring-no-properties + (line-beginning-position 2) eos))) + (lambda (_data _old _new) + (cl-incf cnt-flag) + (org-toggle-tag "FLAGGED" 'on) + (org-entry-put + nil "THEFLAGGINGNOTE" + (replace-regexp-in-string "\n" "\\\\n" note)))) + (cl-incf cnt-edit) (cdr (assoc action org-mobile-action-alist)))) - (note (and (equal action "") - (buffer-substring (1+ (point-at-eol)) eos))) - (org-inhibit-logging 'note) ;; Do not take notes interactively + ;; Do not take notes interactively. + (org-inhibit-logging 'note) old new) (goto-char bos) @@ -867,11 +838,11 @@ If BEG and END are given, only do this in that region." (if (stringp id-pos) (insert id-pos " ") (insert "BAD REFERENCE ")) - (incf cnt-error) + (cl-incf cnt-error) (throw 'next t)) (unless cmd (insert "BAD FLAG ") - (incf cnt-error) + (cl-incf cnt-error) (throw 'next t)) (move-marker bos-marker (point)) (if (re-search-forward "^** Old value[ \t]*$" eos t) @@ -884,34 +855,28 @@ If BEG and END are given, only do this in that region." (progn (outline-next-heading) (if (eobp) (org-back-over-empty-lines)) (point))))) - (setq old (and old (if (string-match "\\S-" old) old nil))) - (setq new (and new (if (string-match "\\S-" new) new nil))) - (if (and note (> (length note) 0)) - ;; Make Note into a single line, to fit into a property - (setq note (mapconcat 'identity - (org-split-string (org-trim note) "\n") - "\\n"))) + (setq old (org-string-nw-p old)) + (setq new (org-string-nw-p new)) (unless (equal data "body") - (setq new (and new (org-trim new)) - old (and old (org-trim old)))) + (setq new (and new (org-trim new))) + (setq old (and old (org-trim old)))) (goto-char (+ 2 bos-marker)) ;; Remember this place so that we can return (move-marker marker (point)) (setq org-mobile-error nil) - (save-excursion - (condition-case msg - (org-with-point-at id-pos - (progn - (eval cmd) - (unless (member data (list "delete" "archive" "archive-sibling" "addheading")) - (if (member "FLAGGED" (org-get-tags)) - (add-to-list 'org-mobile-last-flagged-files - (buffer-file-name (current-buffer))))))) - (error (setq org-mobile-error msg)))) + (condition-case msg + (org-with-point-at id-pos + (funcall cmd data old new) + (unless (member data '("delete" "archive" "archive-sibling" + "addheading")) + (when (member "FLAGGED" (org-get-tags)) + (add-to-list 'org-mobile-last-flagged-files + (buffer-file-name))))) + (error (setq org-mobile-error msg))) (when org-mobile-error - (org-pop-to-buffer-same-window (marker-buffer marker)) + (pop-to-buffer-same-window (marker-buffer marker)) (goto-char marker) - (incf cnt-error) + (cl-incf cnt-error) (insert (if (stringp (nth 1 org-mobile-error)) (nth 1 org-mobile-error) "EXECUTION FAILED") @@ -924,8 +889,8 @@ If BEG and END are given, only do this in that region." (save-buffer) (move-marker marker nil) (move-marker end nil) - (message "%d new, %d edits, %d flags, %d errors" cnt-new - cnt-edit cnt-flag cnt-error) + (message "%d new, %d edits, %d flags, %d errors" + cnt-new cnt-edit cnt-flag cnt-error) (sit-for 1))) (defun org-mobile-timestamp-buffer (buf) @@ -1020,7 +985,7 @@ be returned that indicates what went wrong." ((equal new "DONEARCHIVE") (org-todo 'done) (org-archive-subtree-default)) - ((equal new current) t) ; nothing needs to be done + ((equal new current) t) ; nothing needs to be done ((or (equal current old) (eq org-mobile-force-mobile-change t) (memq 'todo org-mobile-force-mobile-change)) @@ -1042,33 +1007,35 @@ be returned that indicates what went wrong." (or old "") (or current ""))))) ((eq what 'priority) - (when (looking-at org-complex-heading-regexp) - (setq current (and (match-end 3) (substring (match-string 3) 2 3))) - (cond - ((equal current new) t) ; no action required - ((or (equal current old) - (eq org-mobile-force-mobile-change t) - (memq 'tags org-mobile-force-mobile-change)) - (org-priority (and new (string-to-char new)))) - (t (error "Priority was expected to be %s, but is %s" - old current))))) + (let ((case-fold-search nil)) + (when (looking-at org-complex-heading-regexp) + (let ((current (and (match-end 3) (substring (match-string 3) 2 3)))) + (cond + ((equal current new) t) ;no action required + ((or (equal current old) + (eq org-mobile-force-mobile-change t) + (memq 'tags org-mobile-force-mobile-change)) + (org-priority (and new (string-to-char new)))) + (t (error "Priority was expected to be %s, but is %s" + old current))))))) ((eq what 'heading) - (when (looking-at org-complex-heading-regexp) - (setq current (match-string 4)) - (cond - ((equal current new) t) ; no action required - ((or (equal current old) - (eq org-mobile-force-mobile-change t) - (memq 'heading org-mobile-force-mobile-change)) - (goto-char (match-beginning 4)) - (insert new) - (delete-region (point) (+ (point) (length current))) - (org-set-tags nil 'align)) - (t (error "Heading changed in MobileOrg and on the computer"))))) + (let ((case-fold-search nil)) + (when (looking-at org-complex-heading-regexp) + (let ((current (match-string 4))) + (cond + ((equal current new) t) ;no action required + ((or (equal current old) + (eq org-mobile-force-mobile-change t) + (memq 'heading org-mobile-force-mobile-change)) + (goto-char (match-beginning 4)) + (insert new) + (delete-region (point) (+ (point) (length current))) + (org-set-tags nil 'align)) + (t (error "Heading changed in MobileOrg and on the computer"))))))) ((eq what 'addheading) - (if (org-at-heading-p) ; if false we are in top-level of file + (if (org-at-heading-p) ; if false we are in top-level of file (progn ;; Workaround a `org-insert-heading-respect-content' bug ;; which prevents correct insertion when point is invisible @@ -1083,7 +1050,7 @@ be returned that indicates what went wrong." ((eq what 'refile) (org-copy-subtree) (org-with-point-at (org-mobile-locate-entry new) - (if (org-at-heading-p) ; if false we are in top-level of file + (if (org-at-heading-p) ; if false we are in top-level of file (progn (setq level (org-get-valid-level (funcall outline-level) 1)) (org-end-of-subtree t t) diff --git a/lisp/org/org-mouse.el b/lisp/org/org-mouse.el index 7eef5c6b8ba..d6a472787e1 100644 --- a/lisp/org/org-mouse.el +++ b/lisp/org/org-mouse.el @@ -1,4 +1,4 @@ -;;; org-mouse.el --- Better mouse support for org-mode +;;; org-mouse.el --- Better mouse support for Org -*- lexical-binding: t; -*- ;; Copyright (C) 2006-2017 Free Software Foundation, Inc. @@ -26,8 +26,8 @@ ;; ;; http://orgmode.org ;; -;; Org-mouse implements the following features: -;; * following links with the left mouse button (in Emacs 22) +;; Org mouse implements the following features: +;; * following links with the left mouse button ;; * subtree expansion/collapse (org-cycle) with the left mouse button ;; * several context menus on the right mouse button: ;; + general text @@ -66,12 +66,12 @@ ;; History: ;; -;; Since version 5.10: Changes are listed in the general org-mode docs. +;; Since version 5.10: Changes are listed in the general Org docs. ;; -;; Version 5.09;; + Version number synchronization with Org-mode. +;; Version 5.09;; + Version number synchronization with Org mode. ;; ;; Version 0.25 -;; + made compatible with org-mode 4.70 (thanks to Carsten for the patch) +;; + made compatible with Org 4.70 (thanks to Carsten for the patch) ;; ;; Version 0.24 ;; + minor changes to the table menu @@ -81,7 +81,7 @@ ;; + context menu support for org-agenda-undo & org-sort-entries ;; ;; Version 0.22 -;; + handles undo support for the agenda buffer (requires org-mode >=4.58) +;; + handles undo support for the agenda buffer (requires Org >=4.58) ;; ;; Version 0.21 ;; + selected text activates its context menu @@ -105,7 +105,7 @@ ;; + added support for checkboxes ;; ;; Version 0.15 -;; + org-mode now works with the Agenda buffer as well +;; + Org now works with the Agenda buffer as well ;; ;; Version 0.14 ;; + added a menu option that converts plain list items to outline items @@ -125,7 +125,7 @@ ;; ;; Version 0.10 ;; + added a menu option to remove highlights -;; + compatible with org-mode 4.21 now +;; + compatible with Org 4.21 now ;; ;; Version 0.08: ;; + trees can be moved/promoted/demoted by dragging with the right @@ -136,8 +136,8 @@ ;;; Code: -(eval-when-compile (require 'cl)) (require 'org) +(require 'cl-lib) (defvar org-agenda-allow-remote-undo) (defvar org-agenda-undo-list) @@ -149,6 +149,8 @@ (declare-function org-agenda-earlier "org-agenda" (arg)) (declare-function org-agenda-later "org-agenda" (arg)) +(defvar org-mouse-main-buffer nil + "Active buffer for mouse operations.") (defvar org-mouse-plain-list-regexp "\\([ \t]*\\)\\([-+*]\\|[0-9]+[.)]\\) " "Regular expression that matches a plain list.") (defvar org-mouse-direct t @@ -191,15 +193,14 @@ Changing this variable requires a restart of Emacs to get activated." (interactive) (end-of-line) (skip-chars-backward "\t ") - (when (org-looking-back ":[A-Za-z]+:" (line-beginning-position)) + (when (looking-back ":[A-Za-z]+:" (line-beginning-position)) (skip-chars-backward ":A-Za-z") (skip-chars-backward "\t "))) -(defvar org-mouse-context-menu-function nil +(defvar-local org-mouse-context-menu-function nil "Function to create the context menu. The value of this variable is the function invoked by `org-mouse-context-menu' as the context menu.") -(make-variable-buffer-local 'org-mouse-context-menu-function) (defun org-mouse-show-context-menu (event prefix) "Invoke the context menu. @@ -215,13 +216,12 @@ this function is called. Otherwise, the current major mode menu is used." (when (not (org-mouse-mark-active)) (goto-char (posn-point (event-start event))) (when (not (eolp)) (save-excursion (run-hooks 'post-command-hook))) - (let ((redisplay-dont-pause t)) - (sit-for 0))) + (sit-for 0)) (if (functionp org-mouse-context-menu-function) (funcall org-mouse-context-menu-function event) (if (fboundp 'mouse-menu-major-mode-map) (popup-menu (mouse-menu-major-mode-map) event prefix) - (org-no-warnings ; don't warn about fallback, obsolete since 23.1 + (with-no-warnings ; don't warn about fallback, obsolete since 23.1 (mouse-major-mode-menu event prefix))))) (setq this-command 'mouse-save-then-kill) (mouse-save-then-kill event))) @@ -258,7 +258,7 @@ If the point is at the :beginning (`org-mouse-line-position') of the line, insert the new heading before the current line. Otherwise, insert it after the current heading." (interactive) - (case (org-mouse-line-position) + (cl-case (org-mouse-line-position) (:beginning (beginning-of-line) (org-insert-heading)) (t (org-mouse-next-heading) @@ -314,10 +314,10 @@ nor a function, elements of KEYWORDS are used directly." (just-one-space)) (defvar org-mouse-rest) -(defun org-mouse-replace-match-and-surround (newtext &optional fixedcase - literal string subexp) +(defun org-mouse-replace-match-and-surround + (_newtext &optional _fixedcase _literal _string subexp) "The same as `replace-match', but surrounds the replacement with spaces." - (apply 'replace-match org-mouse-rest) + (apply #'replace-match org-mouse-rest) (save-excursion (goto-char (match-beginning (or subexp 0))) (just-one-space) @@ -407,8 +407,8 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:" (> (match-end 0) point)))))) (defun org-mouse-priority-list () - (loop for priority from ?A to org-lowest-priority - collect (char-to-string priority))) + (cl-loop for priority from ?A to org-lowest-priority + collect (char-to-string priority))) (defun org-mouse-todo-menu (state) "Create the menu with TODO keywords." @@ -460,33 +460,33 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:" (insert " [ ] ")))) (defun org-mouse-agenda-type (type) - (case type - ('tags "Tags: ") - ('todo "TODO: ") - ('tags-tree "Tags tree: ") - ('todo-tree "TODO tree: ") - ('occur-tree "Occur tree: ") - (t "Agenda command ???"))) + (pcase type + (`tags "Tags: ") + (`todo "TODO: ") + (`tags-tree "Tags tree: ") + (`todo-tree "TODO tree: ") + (`occur-tree "Occur tree: ") + (_ "Agenda command ???"))) (defun org-mouse-list-options-menu (alloptions &optional function) (let ((options (save-match-data (split-string (match-string-no-properties 1))))) (print options) - (loop for name in alloptions - collect - (vector name - `(progn - (replace-match - (mapconcat 'identity - (sort (if (member ',name ',options) - (delete ',name ',options) - (cons ',name ',options)) - 'string-lessp) - " ") - nil nil nil 1) - (when (functionp ',function) (funcall ',function))) - :style 'toggle - :selected (and (member name options) t))))) + (cl-loop for name in alloptions + collect + (vector name + `(progn + (replace-match + (mapconcat 'identity + (sort (if (member ',name ',options) + (delete ',name ',options) + (cons ',name ',options)) + 'string-lessp) + " ") + nil nil nil 1) + (when (functionp ',function) (funcall ',function))) + :style 'toggle + :selected (and (member name options) t))))) (defun org-mouse-clip-text (text maxlength) (if (> (length text) maxlength) @@ -498,7 +498,7 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:" `("Main Menu" ["Show Overview" org-mouse-show-overview t] ["Show Headlines" org-mouse-show-headlines t] - ["Show All" show-all t] + ["Show All" outline-show-all t] ["Remove Highlights" org-remove-occur-highlights :visible org-occur-highlights] "--" @@ -556,12 +556,12 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:" (let ((contextdata (assq context contextlist))) (when contextdata (save-excursion - (goto-char (second contextdata)) - (re-search-forward ".*" (third contextdata)))))) + (goto-char (nth 1 contextdata)) + (re-search-forward ".*" (nth 2 contextdata)))))) (defun org-mouse-for-each-item (funct) - ;; Functions called by `org-apply-on-list' need an argument - (let ((wrap-fun (lambda (c) (funcall funct)))) + ;; Functions called by `org-apply-on-list' need an argument. + (let ((wrap-fun (lambda (_) (funcall funct)))) (when (ignore-errors (goto-char (org-in-item-p))) (save-excursion (org-apply-on-list wrap-fun nil))))) @@ -572,14 +572,14 @@ This means, between the beginning of line and the point." (skip-chars-backward " \t*") (bolp))) (defun org-mouse-insert-item (text) - (case (org-mouse-line-position) - (:beginning ; insert before + (cl-case (org-mouse-line-position) + (:beginning ; insert before (beginning-of-line) (looking-at "[ \t]*") (open-line 1) - (org-indent-to-column (- (match-end 0) (match-beginning 0))) + (indent-to-column (- (match-end 0) (match-beginning 0))) (insert "+ ")) - (:middle ; insert after + (:middle ; insert after (end-of-line) (newline t) (indent-relative) @@ -587,7 +587,7 @@ This means, between the beginning of line and the point." (:end ; insert text here (skip-chars-backward " \t") (kill-region (point) (point-at-eol)) - (unless (org-looking-back org-mouse-punctuation) + (unless (looking-back org-mouse-punctuation (line-beginning-position)) (insert (concat org-mouse-punctuation " "))))) (insert text) (beginning-of-line)) @@ -638,14 +638,15 @@ This means, between the beginning of line and the point." (progn (save-excursion (goto-char (region-beginning)) (insert "[[")) (save-excursion (goto-char (region-end)) (insert "]]")))] ["Insert Link Here" (org-mouse-yank-link ',event)])))) - ((save-excursion (beginning-of-line) (looking-at "#\\+STARTUP: \\(.*\\)")) + ((save-excursion (beginning-of-line) (looking-at "[ \t]*#\\+STARTUP: \\(.*\\)")) (popup-menu `(nil ,@(org-mouse-list-options-menu (mapcar 'car org-startup-options) 'org-mode-restart)))) ((or (eolp) (and (looking-at "\\( \\|\t\\)\\(+:[0-9a-zA-Z_:]+\\)?\\( \\|\t\\)+$") - (org-looking-back " \\|\t" (- (point) 2)))) + (looking-back " \\|\t" (- (point) 2) + (line-beginning-position)))) (org-mouse-popup-global-menu)) ((funcall get-context :checkbox) (popup-menu @@ -737,13 +738,13 @@ This means, between the beginning of line and the point." ["- 1 Month" (org-timestamp-change -1 'month)]))) ((funcall get-context :table-special) (let ((mdata (match-data))) - (incf (car mdata) 2) + (cl-incf (car mdata) 2) (store-match-data mdata)) (message "match: %S" (match-string 0)) (popup-menu `(nil ,@(org-mouse-keyword-replace-menu '(" " "!" "^" "_" "$" "#" "*" "'") 0 (lambda (mark) - (case (string-to-char mark) + (cl-case (string-to-char mark) (? "( ) Nothing Special") (?! "(!) Column Names") (?^ "(^) Field Names Above") @@ -914,7 +915,7 @@ This means, between the beginning of line and the point." ((org-footnote-at-reference-p) nil) (t ad-do-it)))))) -(defun org-mouse-move-tree-start (event) +(defun org-mouse-move-tree-start (_event) (interactive "e") (message "Same line: promote/demote, (***):move before, (text): make a child")) @@ -993,7 +994,7 @@ This means, between the beginning of line and the point." (defvar org-mouse-cmd) ;dynamically scoped from `org-with-remote-undo'. (defun org-mouse-do-remotely (command) - ; (org-agenda-check-no-diary) + ;; (org-agenda-check-no-diary) (when (get-text-property (point) 'org-marker) (let* ((anticol (- (point-at-eol) (point))) (marker (get-text-property (point) 'org-marker)) @@ -1031,7 +1032,7 @@ This means, between the beginning of line and the point." (org-agenda-change-all-lines newhead hdmarker 'fixface)))) t)))) -(defun org-mouse-agenda-context-menu (&optional event) +(defun org-mouse-agenda-context-menu (&optional _event) (or (org-mouse-do-remotely 'org-mouse-context-menu) (popup-menu '("Agenda" @@ -1093,17 +1094,17 @@ This means, between the beginning of line and the point." ; (setq org-agenda-mode-hook nil) (defvar org-agenda-mode-map) (add-hook 'org-agenda-mode-hook - #'(lambda () - (setq org-mouse-context-menu-function 'org-mouse-agenda-context-menu) - (org-defkey org-agenda-mode-map [mouse-3] 'org-mouse-show-context-menu) - (org-defkey org-agenda-mode-map [down-mouse-3] 'org-mouse-move-tree-start) - (org-defkey org-agenda-mode-map [C-mouse-4] 'org-agenda-earlier) - (org-defkey org-agenda-mode-map [C-mouse-5] 'org-agenda-later) - (org-defkey org-agenda-mode-map [drag-mouse-3] - #'(lambda (event) (interactive "e") - (case (org-mouse-get-gesture event) - (:left (org-agenda-earlier 1)) - (:right (org-agenda-later 1))))))) + (lambda () + (setq org-mouse-context-menu-function 'org-mouse-agenda-context-menu) + (org-defkey org-agenda-mode-map [mouse-3] 'org-mouse-show-context-menu) + (org-defkey org-agenda-mode-map [down-mouse-3] 'org-mouse-move-tree-start) + (org-defkey org-agenda-mode-map [C-mouse-4] 'org-agenda-earlier) + (org-defkey org-agenda-mode-map [C-mouse-5] 'org-agenda-later) + (org-defkey org-agenda-mode-map [drag-mouse-3] + (lambda (event) (interactive "e") + (cl-case (org-mouse-get-gesture event) + (:left (org-agenda-earlier 1)) + (:right (org-agenda-later 1))))))) (provide 'org-mouse) diff --git a/lisp/org/org-pcomplete.el b/lisp/org/org-pcomplete.el index 034c20e3077..61ec5fad4c3 100644 --- a/lisp/org/org-pcomplete.el +++ b/lisp/org/org-pcomplete.el @@ -1,4 +1,4 @@ -;;; org-pcomplete.el --- In-buffer completion code +;;; org-pcomplete.el --- In-buffer Completion Code -*- lexical-binding: t; -*- ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. ;; @@ -27,21 +27,17 @@ ;;;; Require other packages -(eval-when-compile - (require 'cl)) - (require 'org-macs) (require 'org-compat) (require 'pcomplete) -(declare-function org-split-string "org" (string &optional separators)) -(declare-function org-make-org-heading-search-string "org" - (&optional string)) +(declare-function org-make-org-heading-search-string "org" (&optional string)) (declare-function org-get-buffer-tags "org" ()) (declare-function org-get-tags "org" ()) (declare-function org-buffer-property-keys "org" - (&optional include-specials include-defaults include-columns)) -(declare-function org-entry-properties "org" (&optional pom which specific)) + (&optional specials defaults columns ignore-malformed)) +(declare-function org-entry-properties "org" (&optional pom which)) +(declare-function org-tag-alist-to-string "org" (alist &optional skip-key)) ;;;; Customization variables @@ -52,12 +48,13 @@ (defvar org-drawer-regexp) (defvar org-property-re) +(defvar org-current-tag-alist) (defun org-thing-at-point () "Examine the thing at point and let the caller know what it is. The return value is a string naming the thing at point." (let ((beg1 (save-excursion - (skip-chars-backward (org-re "[:alnum:]-_@")) + (skip-chars-backward "[:alnum:]-_@") (point))) (beg (save-excursion (skip-chars-backward "a-zA-Z0-9-_:$") @@ -93,8 +90,10 @@ The return value is a string naming the thing at point." (skip-chars-backward "[ \t\n]") ;; org-drawer-regexp matches a whole line but while ;; looking-back, we just ignore trailing whitespaces - (or (org-looking-back (substring org-drawer-regexp 0 -1)) - (org-looking-back org-property-re)))) + (or (looking-back (substring org-drawer-regexp 0 -1) + (line-beginning-position)) + (looking-back org-property-re + (line-beginning-position))))) (cons "prop" nil)) ((and (equal (char-before beg1) ?:) (not (equal (char-after (point-at-bol)) ?*))) @@ -140,7 +139,6 @@ When completing for #+STARTUP, for example, this function returns pcomplete-default-completion-function)))) (defvar org-options-keywords) ; From org.el -(defvar org-element-block-name-alist) ; From org-element.el (defvar org-element-affiliated-keywords) ; From org-element.el (declare-function org-get-export-keywords "org" ()) (defun pcomplete/org-mode/file-option () @@ -153,16 +151,19 @@ When completing for #+STARTUP, for example, this function returns (mapcar (lambda (keyword) (concat keyword ": ")) org-element-affiliated-keywords) (let (block-names) - (dolist (block-info org-element-block-name-alist block-names) - (let ((name (car block-info))) - (push (format "END_%s" name) block-names) - (push (concat "BEGIN_" - name - ;; Since language is compulsory in - ;; source blocks, add a space. - (and (equal name "SRC") " ")) - block-names) - (push (format "ATTR_%s: " name) block-names)))) + (dolist (name + '("CENTER" "COMMENT" "EXAMPLE" "EXPORT" "QUOTE" "SRC" + "VERSE") + block-names) + (push (format "END_%s" name) block-names) + (push (concat "BEGIN_" + name + ;; Since language is compulsory in + ;; export blocks source blocks, add + ;; a space. + (and (member name '("EXPORT" "SRC")) " ")) + block-names) + (push (format "ATTR_%s: " name) block-names))) (mapcar (lambda (keyword) (concat keyword ": ")) (org-get-export-keywords)))) (substring pcomplete-stub 2))) @@ -233,20 +234,10 @@ When completing for #+STARTUP, for example, this function returns (setq opts (delete "showstars" opts))))) opts)))) -(defvar org-tag-alist) (defun pcomplete/org-mode/file-option/tags () "Complete arguments for the #+TAGS file option." (pcomplete-here - (list - (mapconcat (lambda (x) - (cond - ((eq :startgroup (car x)) "{") - ((eq :endgroup (car x)) "}") - ((eq :grouptags (car x)) ":") - ((eq :newline (car x)) "\\n") - ((cdr x) (format "%s(%c)" (car x) (cdr x))) - (t (car x)))) - org-tag-alist " ")))) + (list (org-tag-alist-to-string org-current-tag-alist)))) (defun pcomplete/org-mode/file-option/title () "Complete arguments for the #+TITLE file option." @@ -271,8 +262,8 @@ When completing for #+STARTUP, for example, this function returns "|:" "tags:" "tasks:" "<:" "todo:") ;; OPTION items from registered back-ends. (let (items) - (dolist (backend (org-bound-and-true-p - org-export--registered-backends)) + (dolist (backend (bound-and-true-p + org-export-registered-backends)) (dolist (option (org-export-backend-options backend)) (let ((item (nth 2 option))) (when item (push (concat item ":") items))))) @@ -283,7 +274,7 @@ When completing for #+STARTUP, for example, this function returns (while (pcomplete-here (pcomplete-uniqify-list (mapcar (lambda (item) (format "%s:" (car item))) - (org-bound-and-true-p org-html-infojs-opts-table)))))) + (bound-and-true-p org-html-infojs-opts-table)))))) (defun pcomplete/org-mode/file-option/bind () "Complete arguments for the #+BIND file option, which are variable names." @@ -324,26 +315,24 @@ This needs more work, to handle headings with lots of spaces in them." (save-excursion (goto-char (point-min)) (let (tbl) - (while (re-search-forward org-todo-line-regexp nil t) - (push (org-make-org-heading-search-string - (match-string-no-properties 3)) - tbl)) + (let ((case-fold-search nil)) + (while (re-search-forward org-todo-line-regexp nil t) + (push (org-make-org-heading-search-string + (match-string-no-properties 3)) + tbl))) (pcomplete-uniqify-list tbl))) (substring pcomplete-stub 1)))) -(defvar org-tag-alist) (defun pcomplete/org-mode/tag () "Complete a tag name. Omit tags already set." (while (pcomplete-here - (mapcar (lambda (x) - (concat x ":")) + (mapcar (lambda (x) (concat x ":")) (let ((lst (pcomplete-uniqify-list - (or (remove + (or (remq nil - (mapcar (lambda (x) - (and (stringp (car x)) (car x))) - org-tag-alist)) - (mapcar 'car (org-get-buffer-tags)))))) + (mapcar (lambda (x) (org-string-nw-p (car x))) + org-current-tag-alist)) + (mapcar #'car (org-get-buffer-tags)))))) (dolist (tag (org-get-tags)) (setq lst (delete tag lst))) lst)) @@ -357,31 +346,12 @@ This needs more work, to handle headings with lots of spaces in them." (concat x ": ")) (let ((lst (pcomplete-uniqify-list (copy-sequence - (org-buffer-property-keys nil t t))))) + (org-buffer-property-keys nil t t t))))) (dolist (prop (org-entry-properties)) (setq lst (delete (car prop) lst))) lst)) (substring pcomplete-stub 1))) -(defvar org-drawers) - -(defun pcomplete/org-mode/drawer () - "Complete a drawer name." - (let ((spc (save-excursion - (move-beginning-of-line 1) - (looking-at "^\\([ \t]*\\):") - (match-string 1))) - (cpllist (mapcar (lambda (x) (concat x ": ")) org-drawers))) - (pcomplete-here cpllist - (substring pcomplete-stub 1) - (unless (or (not (delq - nil - (mapcar (lambda(x) - (string-match (substring pcomplete-stub 1) x)) - cpllist))) - (looking-at "[ \t]*\n.*:END:")) - (save-excursion (insert "\n" spc ":END:")))))) - (defun pcomplete/org-mode/block-option/src () "Complete the arguments of a begin_src block. Complete a language in the first field, the header arguments and switches." diff --git a/lisp/org/org-plot.el b/lisp/org/org-plot.el index 5ccfbb1e662..449143a47af 100644 --- a/lisp/org/org-plot.el +++ b/lisp/org/org-plot.el @@ -1,4 +1,4 @@ -;;; org-plot.el --- Support for plotting from Org-mode +;;; org-plot.el --- Support for Plotting from Org -*- lexical-binding: t; -*- ;; Copyright (C) 2008-2017 Free Software Foundation, Inc. ;; @@ -25,14 +25,14 @@ ;; Borrows ideas and a couple of lines of code from org-exp.el. -;; Thanks to the org-mode mailing list for testing and implementation -;; and feature suggestions +;; Thanks to the Org mailing list for testing and implementation and +;; feature suggestions ;;; Code: + +(require 'cl-lib) (require 'org) (require 'org-table) -(eval-when-compile - (require 'cl)) (declare-function gnuplot-delchar-or-maybe-eof "ext:gnuplot" (arg)) (declare-function gnuplot-mode "ext:gnuplot" ()) @@ -49,41 +49,39 @@ (defun org-plot/add-options-to-plist (p options) "Parse an OPTIONS line and set values in the property list P. Returns the resulting property list." - (let (o) - (when options - (let ((op '(("type" . :plot-type) - ("script" . :script) - ("line" . :line) - ("set" . :set) - ("title" . :title) - ("ind" . :ind) - ("deps" . :deps) - ("with" . :with) - ("file" . :file) - ("labels" . :labels) - ("map" . :map) - ("timeind" . :timeind) - ("timefmt" . :timefmt))) - (multiples '("set" "line")) - (regexp ":\\([\"][^\"]+?[\"]\\|[(][^)]+?[)]\\|[^ \t\n\r;,.]*\\)") - (start 0) - o) - (while (setq o (pop op)) - (if (member (car o) multiples) ;; keys with multiple values - (while (string-match - (concat (regexp-quote (car o)) regexp) - options start) - (setq start (match-end 0)) - (setq p (plist-put p (cdr o) - (cons (car (read-from-string - (match-string 1 options))) - (plist-get p (cdr o))))) - p) - (if (string-match (concat (regexp-quote (car o)) regexp) - options) - (setq p (plist-put p (cdr o) - (car (read-from-string - (match-string 1 options))))))))))) + (when options + (let ((op '(("type" . :plot-type) + ("script" . :script) + ("line" . :line) + ("set" . :set) + ("title" . :title) + ("ind" . :ind) + ("deps" . :deps) + ("with" . :with) + ("file" . :file) + ("labels" . :labels) + ("map" . :map) + ("timeind" . :timeind) + ("timefmt" . :timefmt))) + (multiples '("set" "line")) + (regexp ":\\([\"][^\"]+?[\"]\\|[(][^)]+?[)]\\|[^ \t\n\r;,.]*\\)") + (start 0)) + (dolist (o op) + (if (member (car o) multiples) ;; keys with multiple values + (while (string-match + (concat (regexp-quote (car o)) regexp) + options start) + (setq start (match-end 0)) + (setq p (plist-put p (cdr o) + (cons (car (read-from-string + (match-string 1 options))) + (plist-get p (cdr o))))) + p) + (if (string-match (concat (regexp-quote (car o)) regexp) + options) + (setq p (plist-put p (cdr o) + (car (read-from-string + (match-string 1 options)))))))))) p) (defun org-plot/goto-nearest-table () @@ -119,10 +117,9 @@ will be added. Returns the resulting property list." Pass PARAMS through to `orgtbl-to-generic' when exporting TABLE." (with-temp-file data-file - (make-local-variable 'org-plot-timestamp-fmt) - (setq org-plot-timestamp-fmt (or - (plist-get params :timefmt) - "%Y-%m-%d-%H:%M:%S")) + (setq-local org-plot-timestamp-fmt (or + (plist-get params :timefmt) + "%Y-%m-%d-%H:%M:%S")) (insert (orgtbl-to-generic table (org-combine-plists @@ -140,7 +137,7 @@ and dependant variables." (deps (if (plist-member params :deps) (mapcar (lambda (val) (- val 1)) (plist-get params :deps)) (let (collector) - (dotimes (col (length (first table))) + (dotimes (col (length (nth 0 table))) (setf collector (cons col collector))) collector))) (counter 0) @@ -158,7 +155,7 @@ and dependant variables." table))) ;; write table to gnuplot grid datafile format (with-temp-file data-file - (let ((num-rows (length table)) (num-cols (length (first table))) + (let ((num-rows (length table)) (num-cols (length (nth 0 table))) (gnuplot-row (lambda (col row value) (setf col (+ 1 col)) (setf row (+ 1 row)) (format "%f %f %f\n%f %f %f\n" @@ -187,9 +184,7 @@ NUM-COLS controls the number of columns plotted in a 2-d plot. Optional argument PREFACE returns only option parameters in a manner suitable for prepending to a user-specified script." (let* ((type (plist-get params :plot-type)) - (with (if (equal type 'grid) - 'pm3d - (plist-get params :with))) + (with (if (eq type 'grid) 'pm3d (plist-get params :with))) (sets (plist-get params :set)) (lines (plist-get params :line)) (map (plist-get params :map)) @@ -204,68 +199,72 @@ manner suitable for prepending to a user-specified script." (x-labels (plist-get params :xlabels)) (y-labels (plist-get params :ylabels)) (plot-str "'%s' using %s%d%s with %s title '%s'") - (plot-cmd (case type - ('2d "plot") - ('3d "splot") - ('grid "splot"))) + (plot-cmd (pcase type + (`2d "plot") + (`3d "splot") + (`grid "splot"))) (script "reset") - ; ats = add-to-script - (ats (lambda (line) (setf script (format "%s\n%s" script line)))) + ;; ats = add-to-script + (ats (lambda (line) (setf script (concat script "\n" line)))) plot-lines) - (when file ;; output file + (when file ; output file (funcall ats (format "set term %s" (file-name-extension file))) (funcall ats (format "set output '%s'" file))) - (case type ;; type - ('2d ()) - ('3d (if map (funcall ats "set map"))) - ('grid (if map (funcall ats "set pm3d map") - (funcall ats "set pm3d")))) - (when title (funcall ats (format "set title '%s'" title))) ;; title - (when lines (mapc (lambda (el) (funcall ats el)) lines)) ;; line - (when sets ;; set - (mapc (lambda (el) (funcall ats (format "set %s" el))) sets)) - (when x-labels ;; x labels (xtics) + (pcase type ; type + (`2d ()) + (`3d (when map (funcall ats "set map"))) + (`grid (funcall ats (if map "set pm3d map" "set pm3d")))) + (when title (funcall ats (format "set title '%s'" title))) ; title + (mapc ats lines) ; line + (dolist (el sets) (funcall ats (format "set %s" el))) ; set + ;; Unless specified otherwise, values are TAB separated. + (unless (string-match-p "^set datafile separator" script) + (funcall ats "set datafile separator \"\\t\"")) + (when x-labels ; x labels (xtics) (funcall ats (format "set xtics (%s)" (mapconcat (lambda (pair) (format "\"%s\" %d" (cdr pair) (car pair))) x-labels ", ")))) - (when y-labels ;; y labels (ytics) + (when y-labels ; y labels (ytics) (funcall ats (format "set ytics (%s)" (mapconcat (lambda (pair) (format "\"%s\" %d" (cdr pair) (car pair))) y-labels ", ")))) - (when time-ind ;; timestamp index + (when time-ind ; timestamp index (funcall ats "set xdata time") (funcall ats (concat "set timefmt \"" - (or timefmt ;; timefmt passed to gnuplot + (or timefmt ; timefmt passed to gnuplot "%Y-%m-%d-%H:%M:%S") "\""))) (unless preface - (case type ;; plot command - ('2d (dotimes (col num-cols) - (unless (and (equal type '2d) - (or (and ind (equal (+ 1 col) ind)) - (and deps (not (member (+ 1 col) deps))))) + (pcase type ; plot command + (`2d (dotimes (col num-cols) + (unless (and (eq type '2d) + (or (and ind (equal (1+ col) ind)) + (and deps (not (member (1+ col) deps))))) (setf plot-lines (cons (format plot-str data-file (or (and ind (> ind 0) - (not text-ind) - (format "%d:" ind)) "") - (+ 1 col) + (not text-ind) + (format "%d:" ind)) "") + (1+ col) (if text-ind (format ":xticlabel(%d)" ind) "") with - (or (nth col col-labels) (format "%d" (+ 1 col)))) + (or (nth col col-labels) + (format "%d" (1+ col)))) plot-lines))))) - ('3d + (`3d (setq plot-lines (list (format "'%s' matrix with %s title ''" data-file with)))) - ('grid + (`grid (setq plot-lines (list (format "'%s' with %s title ''" data-file with))))) (funcall ats - (concat plot-cmd " " (mapconcat 'identity (reverse plot-lines) ",\\\n ")))) + (concat plot-cmd " " (mapconcat #'identity + (reverse plot-lines) + ",\\\n ")))) script)) ;;----------------------------------------------------------------------------- @@ -279,59 +278,59 @@ line directly before or after the table." (require 'gnuplot) (save-window-excursion (delete-other-windows) - (when (get-buffer "*gnuplot*") ;; reset *gnuplot* if it already running + (when (get-buffer "*gnuplot*") ; reset *gnuplot* if it already running (with-current-buffer "*gnuplot*" - (goto-char (point-max)) - (gnuplot-delchar-or-maybe-eof nil))) + (goto-char (point-max)))) (org-plot/goto-nearest-table) - ;; set default options - (mapc - (lambda (pair) - (unless (plist-member params (car pair)) - (setf params (plist-put params (car pair) (cdr pair))))) - org-plot/gnuplot-default-options) + ;; Set default options. + (dolist (pair org-plot/gnuplot-default-options) + (unless (plist-member params (car pair)) + (setf params (plist-put params (car pair) (cdr pair))))) ;; collect table and table information (let* ((data-file (make-temp-file "org-plot")) (table (org-table-to-lisp)) - (num-cols (length (if (eq (first table) 'hline) (second table) - (first table))))) - (while (equal 'hline (first table)) (setf table (cdr table))) - (when (equal (second table) 'hline) - (setf params (plist-put params :labels (first table))) ;; headers to labels - (setf table (delq 'hline (cdr table)))) ;; clean non-data from table - ;; collect options + (num-cols (length (if (eq (nth 0 table) 'hline) (nth 1 table) + (nth 0 table))))) + (run-with-idle-timer 0.1 nil #'delete-file data-file) + (while (eq 'hline (car table)) (setf table (cdr table))) + (when (eq (cadr table) 'hline) + (setf params + (plist-put params :labels (nth 0 table))) ; headers to labels + (setf table (delq 'hline (cdr table)))) ; clean non-data from table + ;; Collect options. (save-excursion (while (and (equal 0 (forward-line -1)) (looking-at "[[:space:]]*#\\+")) (setf params (org-plot/collect-options params)))) - ;; dump table to datafile (very different for grid) - (case (plist-get params :plot-type) - ('2d (org-plot/gnuplot-to-data table data-file params)) - ('3d (org-plot/gnuplot-to-data table data-file params)) - ('grid (let ((y-labels (org-plot/gnuplot-to-grid-data + ;; Dump table to datafile (very different for grid). + (pcase (plist-get params :plot-type) + (`2d (org-plot/gnuplot-to-data table data-file params)) + (`3d (org-plot/gnuplot-to-data table data-file params)) + (`grid (let ((y-labels (org-plot/gnuplot-to-grid-data table data-file params))) (when y-labels (plist-put params :ylabels y-labels))))) - ;; check for timestamp ind column - (let ((ind (- (plist-get params :ind) 1))) - (when (and (>= ind 0) (equal '2d (plist-get params :plot-type))) + ;; Check for timestamp ind column. + (let ((ind (1- (plist-get params :ind)))) + (when (and (>= ind 0) (eq '2d (plist-get params :plot-type))) (if (= (length (delq 0 (mapcar (lambda (el) - (if (string-match org-ts-regexp3 el) - 0 1)) - (mapcar (lambda (row) (nth ind row)) table)))) 0) + (if (string-match org-ts-regexp3 el) 0 1)) + (mapcar (lambda (row) (nth ind row)) table)))) + 0) (plist-put params :timeind t) - ;; check for text ind column + ;; Check for text ind column. (if (or (string= (plist-get params :with) "hist") (> (length (delq 0 (mapcar (lambda (el) (if (string-match org-table-number-regexp el) 0 1)) - (mapcar (lambda (row) (nth ind row)) table)))) 0)) + (mapcar (lambda (row) (nth ind row)) table)))) + 0)) (plist-put params :textind t))))) - ;; write script + ;; Write script. (with-temp-buffer - (if (plist-get params :script) ;; user script + (if (plist-get params :script) ; user script (progn (insert (org-plot/gnuplot-script data-file num-cols params t)) (insert "\n") @@ -339,14 +338,12 @@ line directly before or after the table." (goto-char (point-min)) (while (re-search-forward "$datafile" nil t) (replace-match data-file nil nil))) - (insert - (org-plot/gnuplot-script data-file num-cols params))) - ;; graph table + (insert (org-plot/gnuplot-script data-file num-cols params))) + ;; Graph table. (gnuplot-mode) (gnuplot-send-buffer-to-gnuplot)) - ;; cleanup - (bury-buffer (get-buffer "*gnuplot*")) - (run-with-idle-timer 0.1 nil (lambda () (delete-file data-file)))))) + ;; Cleanup. + (bury-buffer (get-buffer "*gnuplot*"))))) (provide 'org-plot) diff --git a/lisp/org/org-protocol.el b/lisp/org/org-protocol.el index 4bd83bea486..82543567456 100644 --- a/lisp/org/org-protocol.el +++ b/lisp/org/org-protocol.el @@ -1,4 +1,4 @@ -;;; org-protocol.el --- Intercept calls from emacsclient to trigger custom actions. +;;; org-protocol.el --- Intercept Calls from Emacsclient to Trigger Custom Actions -*- lexical-binding: t; -*- ;; ;; Copyright (C) 2008-2017 Free Software Foundation, Inc. ;; @@ -49,7 +49,7 @@ ;; 4.) Try this from the command line (adjust the URL as needed): ;; ;; $ emacsclient \ -;; org-protocol://store-link://http:%2F%2Flocalhost%2Findex.html/The%20title +;; org-protocol://store-link?url=http:%2F%2Flocalhost%2Findex.html&title=The%20title ;; ;; 5.) Optionally add custom sub-protocols and handlers: ;; @@ -60,7 +60,7 @@ ;; ;; A "sub-protocol" will be found in URLs like this: ;; -;; org-protocol://sub-protocol://data +;; org-protocol://sub-protocol?key=val&key2=val2 ;; ;; If it works, you can now setup other applications for using this feature. ;; @@ -81,12 +81,12 @@ ;; * `org-protocol-open-source' uses the sub-protocol \"open-source\" and maps ;; URLs to local filenames defined in `org-protocol-project-alist'. ;; -;; * `org-protocol-store-link' stores an Org-link (if Org-mode is present) and +;; * `org-protocol-store-link' stores an Org link (if Org is present) and ;; pushes the browsers URL to the `kill-ring' for yanking. This handler is ;; triggered through the sub-protocol \"store-link\". ;; ;; * Call `org-protocol-capture' by using the sub-protocol \"capture\". If -;; Org-mode is loaded, Emacs will pop-up a capture buffer and fill the +;; Org is loaded, Emacs will pop-up a capture buffer and fill the ;; template with the data provided. I.e. the browser's URL is inserted as an ;; Org-link of which the page title will be the description part. If text ;; was select in the browser, that text will be the body of the entry. @@ -94,20 +94,20 @@ ;; You may use the same bookmark URL for all those standard handlers and just ;; adjust the sub-protocol used: ;; -;; location.href='org-protocol://sub-protocol://'+ -;; encodeURIComponent(location.href)+'/'+ -;; encodeURIComponent(document.title)+'/'+ +;; location.href='org-protocol://sub-protocol?url='+ +;; encodeURIComponent(location.href)+'&title='+ +;; encodeURIComponent(document.title)+'&body='+ ;; encodeURIComponent(window.getSelection()) ;; ;; The handler for the sub-protocol \"capture\" detects an optional template ;; char that, if present, triggers the use of a special template. ;; Example: ;; -;; location.href='org-protocol://sub-protocol://x/'+ ... +;; location.href='org-protocol://capture?template=x'+ ... ;; -;; use template ?x. +;; uses template ?x. ;; -;; Note, that using double slashes is optional from org-protocol.el's point of +;; Note that using double slashes is optional from org-protocol.el's point of ;; view because emacsclient squashes the slashes to one. ;; ;; @@ -116,25 +116,12 @@ ;;; Code: (require 'org) -(eval-when-compile - (require 'cl)) (declare-function org-publish-get-project-from-filename "ox-publish" (filename &optional up)) (declare-function server-edit "server" (&optional arg)) -(define-obsolete-function-alias - 'org-protocol-unhex-compound 'org-link-unescape-compound - "2011-02-17") - -(define-obsolete-function-alias - 'org-protocol-unhex-string 'org-link-unescape - "2011-02-17") - -(define-obsolete-function-alias - 'org-protocol-unhex-single-byte-sequence - 'org-link-unescape-single-byte-sequence - "2011-02-17") +(defvar org-capture-link-is-already-stored) (defgroup org-protocol nil "Intercept calls from emacsclient to trigger custom actions. @@ -225,27 +212,36 @@ Each element of this list must be of the form: (module-name :protocol protocol :function func :kill-client nil) -protocol - protocol to detect in a filename without trailing colon and slashes. - See rfc1738 section 2.1 for more on this. - If you define a protocol \"my-protocol\", `org-protocol-check-filename-for-protocol' - will search filenames for \"org-protocol:/my-protocol:/\" - and trigger your action for every match. `org-protocol' is defined in - `org-protocol-the-protocol'. Double and triple slashes are compressed - to one by emacsclient. - -function - function that handles requests with protocol and takes exactly one - argument: the filename with all protocols stripped. If the function - returns nil, emacsclient and -server do nothing. Any non-nil return - value is considered a valid filename and thus passed to the server. - - `org-protocol.el provides some support for handling those filenames, - if you stay with the conventions used for the standard handlers in - `org-protocol-protocol-alist-default'. See `org-protocol-split-data'. +protocol - protocol to detect in a filename without trailing + colon and slashes. See rfc1738 section 2.1 for more + on this. If you define a protocol \"my-protocol\", + `org-protocol-check-filename-for-protocol' will search + filenames for \"org-protocol:/my-protocol\" and + trigger your action for every match. `org-protocol' + is defined in `org-protocol-the-protocol'. Double and + triple slashes are compressed to one by emacsclient. + +function - function that handles requests with protocol and takes + one argument. If a new-style link (key=val&key2=val2) + is given, the argument will be a property list with + the values from the link. If an old-style link is + given (val1/val2), the argument will be the filename + with all protocols stripped. + + If the function returns nil, emacsclient and -server + do nothing. Any non-nil return value is considered a + valid filename and thus passed to the server. + + `org-protocol.el' provides some support for handling + old-style filenames, if you follow the conventions + used for the standard handlers in + `org-protocol-protocol-alist-default'. See + `org-protocol-parse-parameters'. kill-client - If t, kill the client immediately, once the sub-protocol is detected. This is necessary for actions that can be interrupted by - `C-g' to avoid dangling emacsclients. Note, that all other command - line arguments but the this one will be discarded, greedy handlers + `C-g' to avoid dangling emacsclients. Note that all other command + line arguments but the this one will be discarded. Greedy handlers still receive the whole list of arguments though. Here is an example: @@ -269,7 +265,7 @@ string with two characters." (defcustom org-protocol-data-separator "/+\\|\\?" "The default data separator to use. - This should be a single regexp string." +This should be a single regexp string." :group 'org-protocol :version "24.4" :package-version '(Org . "8.0") @@ -278,21 +274,20 @@ string with two characters." ;;; Helper functions: (defun org-protocol-sanitize-uri (uri) - "emacsclient compresses double and triple slashes. -Slashes are sanitized to double slashes here." + "Sanitize slashes to double-slashes in URI. +Emacsclient compresses double and triple slashes." (when (string-match "^\\([a-z]+\\):/" uri) (let* ((splitparts (split-string uri "/+"))) (setq uri (concat (car splitparts) "//" (mapconcat 'identity (cdr splitparts) "/"))))) uri) (defun org-protocol-split-data (data &optional unhexify separator) - "Split what an org-protocol handler function gets as only argument. -DATA is that one argument. DATA is split at each occurrence of -SEPARATOR (regexp). If no SEPARATOR is specified or SEPARATOR is -nil, assume \"/+\". The results of that splitting are returned -as a list. If UNHEXIFY is non-nil, hex-decode each split part. -If UNHEXIFY is a function, use that function to decode each split -part." + "Split the DATA argument for an org-protocol handler function. +If UNHEXIFY is non-nil, hex-decode each split part. If UNHEXIFY +is a function, use that function to decode each split part. The +string is split at each occurrence of SEPARATOR (regexp). If no +SEPARATOR is specified or SEPARATOR is nil, assume \"/+\". The +results of that splitting are returned as a list." (let* ((sep (or separator "/+\\|\\?")) (split-parts (split-string data sep))) (if unhexify @@ -302,23 +297,25 @@ part." split-parts))) (defun org-protocol-flatten-greedy (param-list &optional strip-path replacement) - "Greedy handlers might receive a list like this from emacsclient: - ((\"/dir/org-protocol:/greedy:/~/path1\" (23 . 12)) (\"/dir/param\")) -where \"/dir/\" is the absolute path to emacsclients working directory. This + "Transform PARAM-LIST into a flat list for greedy handlers. + +Greedy handlers might receive a list like this from emacsclient: +\((\"/dir/org-protocol:/greedy:/~/path1\" (23 . 12)) (\"/dir/param\")) +where \"/dir/\" is the absolute path to emacsclient's working directory. This function transforms it into a flat list using `org-protocol-flatten' and transforms the elements of that list as follows: -If strip-path is non-nil, remove the \"/dir/\" prefix from all members of +If STRIP-PATH is non-nil, remove the \"/dir/\" prefix from all members of param-list. -If replacement is string, replace the \"/dir/\" prefix with it. +If REPLACEMENT is string, replace the \"/dir/\" prefix with it. The first parameter, the one that contains the protocols, is always changed. Everything up to the end of the protocols is stripped. Note, that this function will always behave as if `org-protocol-reverse-list-of-files' was set to t and the returned list will -reflect that. I.e. emacsclients first parameter will be the first one in the +reflect that. emacsclient's first parameter will be the first one in the returned list." (let* ((l (org-protocol-flatten (if org-protocol-reverse-list-of-files param-list @@ -345,50 +342,106 @@ returned list." ret) l))) -(defun org-protocol-flatten (l) - "Greedy handlers might receive a list like this from emacsclient: - ((\"/dir/org-protocol:/greedy:/~/path1\" (23 . 12)) (\"/dir/param\")) +(defun org-protocol-flatten (list) + "Transform LIST into a flat list. + +Greedy handlers might receive a list like this from emacsclient: +\((\"/dir/org-protocol:/greedy:/~/path1\" (23 . 12)) (\"/dir/param\")) where \"/dir/\" is the absolute path to emacsclients working directory. This function transforms it into a flat list." - (if (null l) () - (if (listp l) - (append (org-protocol-flatten (car l)) (org-protocol-flatten (cdr l))) - (list l)))) - + (if (null list) () + (if (listp list) + (append (org-protocol-flatten (car list)) (org-protocol-flatten (cdr list))) + (list list)))) + +(defun org-protocol-parse-parameters (info &optional new-style default-order) + "Return a property list of parameters from INFO. +If NEW-STYLE is non-nil, treat INFO as a query string (ex: +url=URL&title=TITLE). If old-style links are used (ex: +org-protocol://store-link/url/title), assign them to attributes +following DEFAULT-ORDER. + +If no DEFAULT-ORDER is specified, return the list of values. + +If INFO is already a property list, return it unchanged." + (if (listp info) + info + (if new-style + (let ((data (org-protocol-convert-query-to-plist info)) + result) + (while data + (setq result + (append + result + (list + (pop data) + (org-link-unescape (pop data)))))) + result) + (let ((data (org-protocol-split-data info t org-protocol-data-separator))) + (if default-order + (org-protocol-assign-parameters data default-order) + data))))) + +(defun org-protocol-assign-parameters (data default-order) + "Return a property list of parameters from DATA. +Key names are taken from DEFAULT-ORDER, which should be a list of +symbols. If DEFAULT-ORDER is shorter than the number of values +specified, the rest of the values are treated as :key value pairs." + (let (result) + (while default-order + (setq result + (append result + (list (pop default-order) + (pop data))))) + (while data + (setq result + (append result + (list (intern (concat ":" (pop data))) + (pop data))))) + result)) ;;; Standard protocol handlers: (defun org-protocol-store-link (fname) - "Process an org-protocol://store-link:// style url. + "Process an org-protocol://store-link style url. Additionally store a browser URL as an org link. Also pushes the link's URL to the `kill-ring'. +Parameters: url, title (optional), body (optional) + +Old-style links such as org-protocol://store-link://URL/TITLE are +also recognized. + The location for a browser's bookmark has to look like this: - javascript:location.href=\\='org-protocol://store-link://\\='+ \\ - encodeURIComponent(location.href) - encodeURIComponent(document.title)+\\='/\\='+ \\ + javascript:location.href = \\ + \\='org-protocol://store-link?url=\\=' + \\ + encodeURIComponent(location.href) + \\='&title=\\=' + \\ + encodeURIComponent(document.title); -Don't use `escape()'! Use `encodeURIComponent()' instead. The title of the page -could contain slashes and the location definitely will. +Don't use `escape()'! Use `encodeURIComponent()' instead. The +title of the page could contain slashes and the location +definitely will. The sub-protocol used to reach this function is set in -`org-protocol-protocol-alist'." - (let* ((splitparts (org-protocol-split-data fname t org-protocol-data-separator)) - (uri (org-protocol-sanitize-uri (car splitparts))) - (title (cadr splitparts)) - orglink) - (if (boundp 'org-stored-links) - (setq org-stored-links (cons (list uri title) org-stored-links))) +`org-protocol-protocol-alist'. + +FNAME should be a property list. If not, an old-style link of the +form URL/TITLE can also be used." + (let* ((splitparts (org-protocol-parse-parameters fname nil '(:url :title))) + (uri (org-protocol-sanitize-uri (plist-get splitparts :url))) + (title (plist-get splitparts :title))) + (when (boundp 'org-stored-links) + (push (list uri title) org-stored-links)) (kill-new uri) (message "`%s' to insert new org-link, `%s' to insert `%s'" - (substitute-command-keys"\\[org-insert-link]") - (substitute-command-keys"\\[yank]") + (substitute-command-keys "`\\[org-insert-link]'") + (substitute-command-keys "`\\[yank]'") uri)) nil) (defun org-protocol-capture (info) - "Process an org-protocol://capture:// style url. + "Process an org-protocol://capture style url with INFO. The sub-protocol used to reach this function is set in `org-protocol-protocol-alist'. @@ -396,16 +449,16 @@ The sub-protocol used to reach this function is set in This function detects an URL, title and optional text, separated by `/'. The location for a browser's bookmark looks like this: - javascript:location.href=\\='org-protocol://capture://\\='+ \\ - encodeURIComponent(location.href)+\\='/\\=' \\ - encodeURIComponent(document.title)+\\='/\\='+ \\ + javascript:location.href = \\='org-protocol://capture?url=\\='+ \\ + encodeURIComponent(location.href) + \\='&title=\\=' \\ + encodeURIComponent(document.title) + \\='&body=\\=' + \\ encodeURIComponent(window.getSelection()) By default, it uses the character `org-protocol-default-template-key', which should be associated with a template in `org-capture-templates'. -But you may prepend the encoded URL with a character and a slash like so: +You may specify the template with a template= query parameter, like this: - javascript:location.href=\\='org-protocol://capture://b/\\='+ ... + javascript:location.href = \\='org-protocol://capture?template=b\\='+ ... Now template ?b will be used." (if (and (boundp 'org-stored-links) @@ -414,7 +467,7 @@ Now template ?b will be used." nil) (defun org-protocol-convert-query-to-plist (query) - "Convert query string that is part of url to property list." + "Convert QUERY key=value pairs in the URL to a property list." (if query (apply 'append (mapcar (lambda (x) (let ((c (split-string x "="))) @@ -422,45 +475,52 @@ Now template ?b will be used." (split-string query "&"))))) (defun org-protocol-do-capture (info) - "Support `org-capture'." - (let* ((parts (org-protocol-split-data info t org-protocol-data-separator)) - (template (or (and (>= 2 (length (car parts))) (pop parts)) + "Perform the actual capture based on INFO." + (let* ((temp-parts (org-protocol-parse-parameters info)) + (parts + (cond + ((and (listp info) (symbolp (car info))) info) + ((= (length (car temp-parts)) 1) ;; First parameter is exactly one character long + (org-protocol-assign-parameters temp-parts '(:template :url :title :body))) + (t + (org-protocol-assign-parameters temp-parts '(:url :title :body))))) + (template (or (plist-get parts :template) org-protocol-default-template-key)) - (url (org-protocol-sanitize-uri (car parts))) - (type (if (string-match "^\\([a-z]+\\):" url) - (match-string 1 url))) - (title (or (cadr parts) "")) - (region (or (caddr parts) "")) - (orglink (org-make-link-string - url (if (string-match "[^[:space:]]" title) title url))) - (query (or (org-protocol-convert-query-to-plist (cadddr parts)) "")) + (url (and (plist-get parts :url) (org-protocol-sanitize-uri (plist-get parts :url)))) + (type (and url (if (string-match "^\\([a-z]+\\):" url) + (match-string 1 url)))) + (title (or (plist-get parts :title) "")) + (region (or (plist-get parts :body) "")) + (orglink (if url + (org-make-link-string + url (if (string-match "[^[:space:]]" title) title url)) + title)) (org-capture-link-is-already-stored t)) ;; avoid call to org-store-link (setq org-stored-links (cons (list url title) org-stored-links)) - (kill-new orglink) (org-store-link-props :type type :link url :description title :annotation orglink :initial region - :query query) + :query parts) (raise-frame) (funcall 'org-capture nil template))) (defun org-protocol-open-source (fname) - "Process an org-protocol://open-source:// style url. + "Process an org-protocol://open-source?url= style URL with FNAME. Change a filename by mapping URLs to local filenames as set in `org-protocol-project-alist'. The location for a browser's bookmark should look like this: - javascript:location.href=\\='org-protocol://open-source://\\='+ \\ + javascript:location.href = \\='org-protocol://open-source?url=\\=' + \\ encodeURIComponent(location.href)" ;; As we enter this function for a match on our protocol, the return value ;; defaults to nil. (let ((result nil) - (f (org-link-unescape fname))) + (f (plist-get (org-protocol-parse-parameters fname nil '(:url)) :url))) (catch 'result (dolist (prolist org-protocol-project-alist) (let* ((base-url (plist-get (cdr prolist) :base-url)) @@ -490,13 +550,12 @@ The location for a browser's bookmark should look like this: (let ((rewrites (plist-get (cdr prolist) :rewrites))) (when rewrites (message "Rewrites found: %S" rewrites) - (mapc - (lambda (rewrite) - "Try to match a rewritten URL and map it to a real file." - ;; Compare redirects without suffix: - (if (string-match (car rewrite) f2) - (throw 'result (concat wdir (cdr rewrite))))) - rewrites)))) + (dolist (rewrite rewrites) + ;; Try to match a rewritten URL and map it to + ;; a real file. Compare redirects without + ;; suffix. + (when (string-match-p (car rewrite) f2) + (throw 'result (concat wdir (cdr rewrite)))))))) ;; -- end of redirects -- (if (file-readable-p the-file) @@ -509,44 +568,63 @@ The location for a browser's bookmark should look like this: ;;; Core functions: -(defun org-protocol-check-filename-for-protocol (fname restoffiles client) - "Detect if `org-protocol-the-protocol' and a known sub-protocol is used in fname. +(defun org-protocol-check-filename-for-protocol (fname restoffiles _client) + "Check if `org-protocol-the-protocol' and a valid protocol are used in FNAME. Sub-protocols are registered in `org-protocol-protocol-alist' and -`org-protocol-protocol-alist-default'. -This is, how the matching is done: +`org-protocol-protocol-alist-default'. This is how the matching is done: - (string-match \"protocol:/+sub-protocol:/+\" ...) + (string-match \"protocol:/+sub-protocol\\\\(://\\\\|\\\\?\\\\)\" ...) protocol and sub-protocol are regexp-quoted. -If a matching protocol is found, the protocol is stripped from fname and the -result is passed to the protocols function as the only parameter. If the -function returns nil, the filename is removed from the list of filenames -passed from emacsclient to the server. -If the function returns a non nil value, that value is passed to the server -as filename." +Old-style links such as \"protocol://sub-protocol://param1/param2\" are +also recognized. + +If a matching protocol is found, the protocol is stripped from +fname and the result is passed to the protocol function as the +first parameter. The second parameter will be non-nil if FNAME +uses key=val&key2=val2-type arguments, or nil if FNAME uses +val/val2-type arguments. If the function returns nil, the +filename is removed from the list of filenames passed from +emacsclient to the server. If the function returns a non-nil +value, that value is passed to the server as filename. + +If the handler function is greedy, RESTOFFILES will also be passed to it. + +CLIENT is ignored." (let ((sub-protocols (append org-protocol-protocol-alist org-protocol-protocol-alist-default))) (catch 'fname - (let ((the-protocol (concat (regexp-quote org-protocol-the-protocol) ":/+"))) + (let ((the-protocol (concat (regexp-quote org-protocol-the-protocol) + ":/+"))) (when (string-match the-protocol fname) (dolist (prolist sub-protocols) - (let ((proto (concat the-protocol - (regexp-quote (plist-get (cdr prolist) :protocol)) ":/+"))) + (let ((proto + (concat the-protocol + (regexp-quote (plist-get (cdr prolist) :protocol)) + "\\(:/+\\|\\?\\)"))) (when (string-match proto fname) (let* ((func (plist-get (cdr prolist) :function)) (greedy (plist-get (cdr prolist) :greedy)) (split (split-string fname proto)) - (result (if greedy restoffiles (cadr split)))) + (result (if greedy restoffiles (cadr split))) + (new-style (string= (match-string 1 fname) "?"))) (when (plist-get (cdr prolist) :kill-client) (message "Greedy org-protocol handler. Killing client.") (server-edit)) (when (fboundp func) (unless greedy - (throw 'fname (funcall func result))) - (funcall func result) + (throw 'fname + (if new-style + (funcall func (org-protocol-parse-parameters + result new-style)) + (warn "Please update your Org Protocol handler \ +to deal with new-style links.") + (funcall func result)))) + ;; Greedy protocol handlers are responsible for + ;; parsing their own filenames. + (funcall func result) (throw 'fname t)))))))) - ;; (message "fname: %s" fname) fname))) (defadvice server-visit-files (before org-protocol-detect-protocol-server activate) @@ -572,16 +650,18 @@ as filename." ;;; Org specific functions: (defun org-protocol-create-for-org () - "Create a org-protocol project for the current file's Org-mode project. + "Create a Org protocol project for the current file's project. The visited file needs to be part of a publishing project in `org-publish-project-alist' for this to work. The function delegates most of the work to `org-protocol-create'." (interactive) - (require 'org-publish) + (require 'ox-publish) (let ((all (or (org-publish-get-project-from-filename buffer-file-name)))) (if all (org-protocol-create (cdr all)) - (message "Not in an org-project. Did mean %s?" - (substitute-command-keys"\\[org-protocol-create]"))))) + (message "%s" + (substitute-command-keys + "Not in an Org project. \ +Did you mean `\\[org-protocol-create]'?"))))) (defun org-protocol-create (&optional project-plist) "Create a new org-protocol project interactively. @@ -600,19 +680,18 @@ the cdr of an element in `org-publish-project-alist', reuse (working-suffix (if (plist-get project-plist :base-extension) (concat "." (plist-get project-plist :base-extension)) ".org")) - (worglet-buffer nil) (insert-default-directory t) (minibuffer-allow-text-properties nil)) (setq base-url (read-string "Base URL of published content: " base-url nil base-url t)) - (if (not (string-match "\\/$" base-url)) - (setq base-url (concat base-url "/"))) + (or (string-suffix-p "/" base-url) + (setq base-url (concat base-url "/"))) (setq working-dir (expand-file-name (read-directory-name "Local working directory: " working-dir working-dir t))) - (if (not (string-match "\\/$" working-dir)) - (setq working-dir (concat working-dir "/"))) + (or (string-suffix-p "/" working-dir) + (setq working-dir (concat working-dir "/"))) (setq strip-suffix (read-string diff --git a/lisp/org/org-rmail.el b/lisp/org/org-rmail.el index 80bfce920c5..31c59a13d89 100644 --- a/lisp/org/org-rmail.el +++ b/lisp/org/org-rmail.el @@ -1,4 +1,4 @@ -;;; org-rmail.el --- Support for links to Rmail messages from within Org-mode +;;; org-rmail.el --- Support for Links to Rmail Messages -*- lexical-binding: t; -*- ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. @@ -24,9 +24,9 @@ ;; ;;; Commentary: -;; This file implements links to Rmail messages from within Org-mode. -;; Org-mode loads this module by default - if this is not what you want, -;; configure the variable `org-modules'. +;; This file implements links to Rmail messages from within Org mode. +;; Org mode loads this module by default - if this is not what you +;; want, configure the variable `org-modules'. ;;; Code: @@ -36,13 +36,14 @@ (declare-function rmail-show-message "rmail" (&optional n no-summary)) (declare-function rmail-what-message "rmail" (&optional pos)) (declare-function rmail-toggle-header "rmail" (&optional arg)) +(declare-function rmail "rmail" (&optional file-name-arg)) (declare-function rmail-widen "rmail" ()) (defvar rmail-current-message) ; From rmail.el (defvar rmail-header-style) ; From rmail.el +(defvar rmail-file-name) ; From rmail.el ;; Install the link type -(org-add-link-type "rmail" 'org-rmail-open) -(add-hook 'org-store-link-functions 'org-rmail-store-link) +(org-link-set-parameters "rmail" :follow #'org-rmail-open :store #'org-rmail-store-link) ;; Implementation (defun org-rmail-store-link () @@ -63,20 +64,11 @@ (to (mail-fetch-field "to")) (subject (mail-fetch-field "subject")) (date (mail-fetch-field "date")) - (date-ts (and date (format-time-string - (org-time-stamp-format t) - (date-to-time date)))) - (date-ts-ia (and date (format-time-string - (org-time-stamp-format t t) - (date-to-time date)))) desc link) (org-store-link-props - :type "rmail" :from from :to to + :type "rmail" :from from :to to :date date :subject subject :message-id message-id) - (when date - (org-add-link-props :date date :date-timestamp date-ts - :date-timestamp-inactive date-ts-ia)) - (setq message-id (org-remove-angle-brackets message-id)) + (setq message-id (org-unbracket-string "<" ">" message-id)) (setq desc (org-email-link-description)) (setq link (concat "rmail:" folder "#" message-id)) (org-add-link-props :link link :description desc) diff --git a/lisp/org/org-src.el b/lisp/org/org-src.el index 0e82cfda7b8..0e04d4b5a89 100644 --- a/lisp/org/org-src.el +++ b/lisp/org/org-src.el @@ -1,4 +1,4 @@ -;;; org-src.el --- Source code examples in Org +;;; org-src.el --- Source code examples in Org -*- lexical-binding: t; -*- ;; ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. ;; @@ -26,43 +26,33 @@ ;; ;;; Commentary: -;; This file contains the code dealing with source code examples in Org-mode. +;; This file contains the code dealing with source code examples in +;; Org mode. ;;; Code: +(require 'cl-lib) (require 'org-macs) (require 'org-compat) (require 'ob-keys) (require 'ob-comint) -(eval-when-compile - (require 'cl)) +(declare-function org-base-buffer "org" (buffer)) (declare-function org-do-remove-indentation "org" (&optional n)) -(declare-function org-at-table.el-p "org" ()) -(declare-function org-in-src-block-p "org" (&optional inside)) -(declare-function org-in-block-p "org" (names)) +(declare-function org-element-at-point "org-element" ()) +(declare-function org-element-class "org-element" (datum &optional parent)) +(declare-function org-element-context "org-element" (&optional element)) +(declare-function org-element-lineage "org-element" + (blob &optional types with-self)) +(declare-function org-element-property "org-element" (property element)) +(declare-function org-element-type "org-element" (element)) +(declare-function org-footnote-goto-definition "org-footnote" + (label &optional location)) (declare-function org-get-indentation "org" (&optional line)) (declare-function org-switch-to-buffer-other-window "org" (&rest args)) -(declare-function org-pop-to-buffer-same-window - "org-compat" (&optional buffer-or-name norecord label)) -(declare-function org-base-buffer "org" (buffer)) +(declare-function org-trim "org" (s &optional keep-lead)) -(defcustom org-edit-src-region-extra nil - "Additional regexps to identify regions for editing with `org-edit-src-code'. -For examples see the function `org-edit-src-find-region-and-lang'. -The regular expression identifying the begin marker should end with a newline, -and the regexp marking the end line should start with a newline, to make sure -there are kept outside the narrowed region." - :group 'org-edit-structure - :type '(repeat - (list - (regexp :tag "begin regexp") - (regexp :tag "end regexp") - (choice :tag "language" - (string :tag "specify") - (integer :tag "from match group") - (const :tag "from `lang' element") - (const :tag "from `style' element"))))) +(defvar org-inhibit-startup) (defcustom org-edit-src-turn-on-auto-save nil "Non-nil means turn `auto-save-mode' on when editing a source block. @@ -117,28 +107,29 @@ These are the regions where each line starts with a colon." (defcustom org-src-preserve-indentation nil "If non-nil preserve leading whitespace characters on export. +\\ If non-nil leading whitespace characters in source code blocks are preserved on export, and when switching between the org -buffer and the language mode edit buffer. If this variable is nil -then, after editing with \\[org-edit-src-code], the -minimum (across-lines) number of leading whitespace characters -are removed from all lines, and the code block is uniformly -indented according to the value of `org-edit-src-content-indentation'." +buffer and the language mode edit buffer. + +When this variable is nil, after editing with `\\[org-edit-src-code]', +the minimum (across-lines) number of leading whitespace characters +are removed from all lines, and the code block is uniformly indented +according to the value of `org-edit-src-content-indentation'." :group 'org-edit-structure :type 'boolean) (defcustom org-edit-src-content-indentation 2 "Indentation for the content of a source code block. + This should be the number of spaces added to the indentation of the #+begin line in order to compute the indentation of the block content after -editing it with \\[org-edit-src-code]. Has no effect if -`org-src-preserve-indentation' is non-nil." +editing it with `\\[org-edit-src-code]'. + +It has no effect if `org-src-preserve-indentation' is non-nil." :group 'org-edit-structure :type 'integer) -(defvar org-src-strip-leading-and-trailing-blank-lines nil - "If non-nil, blank lines are removed when exiting the code edit buffer.") - (defcustom org-edit-src-persistent-message t "Non-nil means show persistent exit help message while editing src examples. The message is shown in the header-line, which will be created in the @@ -146,6 +137,17 @@ first line of the window showing the editing buffer." :group 'org-edit-structure :type 'boolean) +(defcustom org-src-ask-before-returning-to-edit-buffer t + "Non-nil means ask before switching to an existing edit buffer. +If nil, when `org-edit-src-code' is used on a block that already +has an active edit buffer, it will switch to that edit buffer +immediately; otherwise it will ask whether you want to return to +the existing edit buffer." + :group 'org-edit-structure + :version "24.4" + :package-version '(Org . "8.0") + :type 'boolean) + (defcustom org-src-window-setup 'reorganize-frame "How the source code edit buffer should be displayed. Possible values for this option are: @@ -167,10 +169,10 @@ other-frame Use `switch-to-buffer-other-frame' to display edit buffer. (defvar org-src-mode-hook nil "Hook run after Org switched a source code snippet to its Emacs mode. -This hook will run - -- when editing a source code snippet with `\\[org-src-mode-map]'. -- When formatting a source code snippet for export with htmlize. +\\ +This hook will run: +- when editing a source code snippet with `\\[org-edit-special]' +- when formatting a source code snippet for export with htmlize. You may want to use this hook for example to turn off `outline-minor-mode' or similar things which you want to have when editing a source code file, @@ -180,7 +182,7 @@ but which mess up the display of a snippet in Org exported files.") '(("ocaml" . tuareg) ("elisp" . emacs-lisp) ("ditaa" . artist) ("asymptote" . asy) ("dot" . fundamental) ("sqlite" . sql) ("calc" . fundamental) ("C" . c) ("cpp" . c++) ("C++" . c++) - ("screen" . shell-script)) + ("screen" . shell-script) ("shell" . sh) ("bash" . sh)) "Alist mapping languages to their major mode. The key is the language name, the value is the string that should be inserted as the name of the major mode. For many languages this is @@ -194,451 +196,383 @@ For example, there is no ocaml-mode in Emacs, but the mode to use is (string "Language name") (symbol "Major mode")))) -;;; Editing source examples +(defcustom org-src-block-faces nil + "Alist of faces to be used for source-block. +Each element is a cell of the format -(defvar org-src-mode-map (make-sparse-keymap)) -(define-key org-src-mode-map "\C-c'" 'org-edit-src-exit) -(define-key org-src-mode-map "\C-c\C-k" 'org-edit-src-abort) -(define-key org-src-mode-map "\C-x\C-s" 'org-edit-src-save) + (\"language\" FACE) -(defvar org-edit-src-force-single-line nil) -(defvar org-edit-src-from-org-mode nil) -(defvar org-edit-src-allow-write-back-p t) -(defvar org-edit-src-picture nil) -(defvar org-edit-src-beg-marker nil) -(defvar org-edit-src-end-marker nil) -(defvar org-edit-src-overlay nil) -(defvar org-edit-src-block-indentation nil) -(defvar org-edit-src-saved-temp-window-config nil) +Where FACE is either a defined face or an anonymous face. -(defcustom org-src-ask-before-returning-to-edit-buffer t - "If nil, when org-edit-src code is used on a block that already -has an active edit buffer, it will switch to that edit buffer -immediately; otherwise it will ask whether you want to return to -the existing edit buffer." - :group 'org-edit-structure - :version "24.4" - :package-version '(Org . "8.0") - :type 'boolean) - -(defvar org-src-babel-info nil) +For instance, the following value would color the background of +emacs-lisp source blocks and python source blocks in purple and +green, respectability. -(define-minor-mode org-src-mode - "Minor mode for language major mode buffers generated by org. -This minor mode is turned on in two situations: -- when editing a source code snippet with `\\[org-src-mode-map]'. -- When formatting a source code snippet for export with htmlize. -There is a mode hook, and keybindings for `org-edit-src-exit' and -`org-edit-src-save'") - -(defvar org-edit-src-code-timer nil) -(defvar org-inhibit-startup) + \\='((\"emacs-lisp\" (:background \"#EEE2FF\")) + (\"python\" (:background \"#e5ffb8\")))" + :group 'org-edit-structure + :type '(repeat (list (string :tag "language") + (choice + (face :tag "Face") + (sexp :tag "Anonymous face")))) + :version "26.1" + :package-version '(Org . "9.0")) -(defun org-edit-src-code (&optional context code edit-buffer-name) - "Edit the source CODE block at point. -The code is copied to a separate buffer and the appropriate mode -is turned on. When done, exit with \\[org-edit-src-exit]. This will -remove the original code in the Org buffer, and replace it with the -edited version. An optional argument CONTEXT is used by \\[org-edit-src-save] -when calling this function. See `org-src-window-setup' to configure -the display of windows containing the Org buffer and the code buffer." - (interactive) - (if (not (or (org-in-block-p '("src" "example" "latex" "html")) - (org-at-table.el-p))) - (user-error "Not in a source code or example block") - (unless (eq context 'save) - (setq org-edit-src-saved-temp-window-config (current-window-configuration))) - (let* ((mark (and (org-region-active-p) (mark))) - (case-fold-search t) - (info - ;; If the src region consists in no lines, we insert a blank - ;; line. - (let* ((temp (org-edit-src-find-region-and-lang)) - (beg (nth 0 temp)) - (end (nth 1 temp))) - (if (>= end beg) temp - (goto-char beg) - (insert "\n") - (org-edit-src-find-region-and-lang)))) - (full-info (org-babel-get-src-block-info 'light)) - (org-mode-p (derived-mode-p 'org-mode)) ;; derived-mode-p is reflexive - (beg (make-marker)) - ;; Move marker with inserted text for case when src block is - ;; just one empty line, i.e. beg == end. - (end (copy-marker (make-marker) t)) - (allow-write-back-p (null code)) - block-nindent total-nindent ovl lang lang-f single buffer msg - begline markline markcol line col transmitted-variables) - (setq beg (move-marker beg (nth 0 info)) - end (move-marker end (nth 1 info)) - msg (if allow-write-back-p - "Edit, then exit with C-c ' (C-c and single quote) -- C-c C-k to abort" - "Exit with C-c ' (C-c and single quote) -- C-c C-k to abort") - code (or code (buffer-substring-no-properties beg end)) - lang (or (cdr (assoc (nth 2 info) org-src-lang-modes)) - (nth 2 info)) - lang (if (symbolp lang) (symbol-name lang) lang) - single (nth 3 info) - block-nindent (nth 5 info) - lang-f (intern (concat lang "-mode")) - begline (save-excursion (goto-char beg) (org-current-line)) - transmitted-variables - `((org-edit-src-content-indentation - ,org-edit-src-content-indentation) - (org-edit-src-force-single-line ,single) - (org-edit-src-from-org-mode ,org-mode-p) - (org-edit-src-allow-write-back-p ,allow-write-back-p) - (org-src-preserve-indentation ,org-src-preserve-indentation) - (org-src-babel-info ,(org-babel-get-src-block-info 'light)) - (org-coderef-label-format - ,(or (nth 4 info) org-coderef-label-format)) - (org-edit-src-beg-marker ,beg) - (org-edit-src-end-marker ,end) - (org-edit-src-block-indentation ,block-nindent))) - (if (and mark (>= mark beg) (<= mark (1+ end))) - (save-excursion (goto-char (min mark end)) - (setq markline (org-current-line) - markcol (current-column)))) - (if (equal lang-f 'table.el-mode) - (setq lang-f (lambda () - (text-mode) - (if (org-bound-and-true-p flyspell-mode) - (flyspell-mode -1)) - (table-recognize) - (org-set-local 'org-edit-src-content-indentation 0)))) - (unless (functionp lang-f) - (error "No such language mode: %s" lang-f)) - (save-excursion - (if (> (point) end) (goto-char end)) - (setq line (org-current-line) - col (current-column))) - (if (and (setq buffer (org-edit-src-find-buffer beg end)) - (or (eq context 'save) - (if org-src-ask-before-returning-to-edit-buffer - (y-or-n-p "Return to existing edit buffer ([n] will revert changes)? ") t))) - (org-src-switch-to-buffer buffer 'return) - (when buffer - (with-current-buffer buffer - (if (boundp 'org-edit-src-overlay) - (delete-overlay org-edit-src-overlay))) - (kill-buffer buffer)) - (setq buffer (generate-new-buffer - (or edit-buffer-name - (org-src-construct-edit-buffer-name (buffer-name) lang)))) - (setq ovl (make-overlay beg end)) - (overlay-put ovl 'edit-buffer buffer) - (overlay-put ovl 'help-echo "Click with mouse-1 to switch to buffer editing this segment") - (overlay-put ovl 'face 'secondary-selection) - (overlay-put ovl - 'keymap - (let ((map (make-sparse-keymap))) - (define-key map [mouse-1] 'org-edit-src-continue) - map)) - (overlay-put ovl :read-only "Leave me alone") - (setq transmitted-variables - (append transmitted-variables `((org-edit-src-overlay ,ovl)))) - (org-src-switch-to-buffer buffer 'edit) - (if (eq single 'macro-definition) - (setq code (replace-regexp-in-string "\\\\n" "\n" code t t))) - (insert code) - (remove-text-properties (point-min) (point-max) - '(display nil invisible nil intangible nil)) - (unless (cadr (assq 'org-src-preserve-indentation transmitted-variables)) - (setq total-nindent (or (org-do-remove-indentation) 0))) - (let ((org-inhibit-startup t)) - (condition-case e - (funcall lang-f) - (error - (message "Language mode `%s' fails with: %S" lang-f (nth 1 e))))) - (dolist (pair transmitted-variables) - (org-set-local (car pair) (cadr pair))) - ;; Remove protecting commas from visible part of buffer. - (org-unescape-code-in-region (point-min) (point-max)) - (when markline - (org-goto-line (1+ (- markline begline))) - (org-move-to-column - (if org-src-preserve-indentation markcol - (max 0 (- markcol total-nindent)))) - (push-mark (point) 'no-message t) - (setq deactivate-mark nil)) - (org-goto-line (1+ (- line begline))) - (org-move-to-column - (if org-src-preserve-indentation col (max 0 (- col total-nindent)))) - (org-src-mode) - (set-buffer-modified-p nil) - (setq buffer-file-name nil) - (when org-edit-src-turn-on-auto-save - (setq buffer-auto-save-file-name - (concat (make-temp-name "org-src-") - (format-time-string "-%Y-%d-%m") ".txt"))) - (and org-edit-src-persistent-message - (org-set-local 'header-line-format msg)) - (let ((edit-prep-func (intern (concat "org-babel-edit-prep:" lang)))) - (when (fboundp edit-prep-func) - (funcall edit-prep-func full-info))) - (or org-edit-src-code-timer - (zerop org-edit-src-auto-save-idle-delay) - (setq org-edit-src-code-timer - (run-with-idle-timer - org-edit-src-auto-save-idle-delay t - (lambda () - (cond - ((org-string-match-p "\\`\\*Org Src" (buffer-name)) - (when (buffer-modified-p) (org-edit-src-save))) - ((not (org-some (lambda (b) - (org-string-match-p "\\`\\*Org Src" - (buffer-name b))) - (buffer-list))) - (cancel-timer org-edit-src-code-timer) - (setq org-edit-src-code-timer nil)))))))) - t))) +(defcustom org-src-tab-acts-natively nil + "If non-nil, the effect of TAB in a code block is as if it were +issued in the language major mode buffer." + :type 'boolean + :version "24.1" + :group 'org-babel) -(defun org-edit-src-continue (e) - "Continue editing source blocks." ;; Fixme: be more accurate - (interactive "e") - (mouse-set-point e) - (let ((buf (get-char-property (point) 'edit-buffer))) - (if buf (org-src-switch-to-buffer buf 'continue) - (error "Something is wrong here")))) -(defun org-src-switch-to-buffer (buffer context) - (case org-src-window-setup - ('current-window - (org-pop-to-buffer-same-window buffer)) - ('other-window - (switch-to-buffer-other-window buffer)) - ('other-frame - (case context - ('exit - (let ((frame (selected-frame))) - (switch-to-buffer-other-frame buffer) - (delete-frame frame))) - ('save - (kill-buffer (current-buffer)) - (org-pop-to-buffer-same-window buffer)) - (t - (switch-to-buffer-other-frame buffer)))) - ('reorganize-frame - (if (eq context 'edit) (delete-other-windows)) - (org-switch-to-buffer-other-window buffer) - (if (eq context 'exit) (delete-other-windows))) - ('switch-invisibly - (set-buffer buffer)) - (t - (message "Invalid value %s for org-src-window-setup" - (symbol-name org-src-window-setup)) - (org-pop-to-buffer-same-window buffer)))) - -(defun org-src-construct-edit-buffer-name (org-buffer-name lang) + +;;; Internal functions and variables + +(defvar org-src--allow-write-back t) +(defvar org-src--auto-save-timer nil) +(defvar org-src--babel-info nil) +(defvar org-src--beg-marker nil) +(defvar org-src--block-indentation nil) +(defvar org-src--end-marker nil) +(defvar org-src--from-org-mode nil) +(defvar org-src--overlay nil) +(defvar org-src--preserve-indentation nil) +(defvar org-src--remote nil) +(defvar org-src--saved-temp-window-config nil) +(defvar org-src--source-type nil + "Type of element being edited, as a symbol.") +(defvar org-src--tab-width nil + "Contains `tab-width' value from Org source buffer. +However, if `indent-tabs-mode' is nil in that buffer, its value +is 0.") + +(defun org-src--construct-edit-buffer-name (org-buffer-name lang) "Construct the buffer name for a source editing buffer." (concat "*Org Src " org-buffer-name "[ " lang " ]*")) -(defun org-src-edit-buffer-p (&optional buffer) - "Test whether BUFFER (or the current buffer if BUFFER is nil) -is a source block editing buffer." - (let ((buffer (org-base-buffer (or buffer (current-buffer))))) - (and (buffer-name buffer) - (string-match "\\`*Org Src " (buffer-name buffer)) - (local-variable-p 'org-edit-src-beg-marker buffer) - (local-variable-p 'org-edit-src-end-marker buffer)))) - -(defun org-edit-src-find-buffer (beg end) - "Find a source editing buffer that is already editing the region BEG to END." +(defun org-src--edit-buffer (beg end) + "Return buffer editing area between BEG and END. +Return nil if there is no such buffer." (catch 'exit - (mapc - (lambda (b) - (with-current-buffer b - (if (and (string-match "\\`*Org Src " (buffer-name)) - (local-variable-p 'org-edit-src-beg-marker (current-buffer)) - (local-variable-p 'org-edit-src-end-marker (current-buffer)) - (equal beg org-edit-src-beg-marker) - (equal end org-edit-src-end-marker)) - (throw 'exit (current-buffer))))) - (buffer-list)) - nil)) + (dolist (b (buffer-list)) + (with-current-buffer b + (and (org-src-edit-buffer-p) + (= beg org-src--beg-marker) + (eq (marker-buffer beg) (marker-buffer org-src--beg-marker)) + (= end org-src--end-marker) + (eq (marker-buffer end) (marker-buffer org-src--end-marker)) + (throw 'exit b)))))) + +(defun org-src--source-buffer () + "Return source buffer edited by current buffer." + (unless (org-src-edit-buffer-p) (error "Not in a source buffer")) + (or (marker-buffer org-src--beg-marker) + (error "No source buffer available for current editing session"))) + +(defun org-src--get-lang-mode (lang) + "Return major mode that should be used for LANG. +LANG is a string, and the returned major mode is a symbol." + (intern + (concat + (let ((l (or (cdr (assoc lang org-src-lang-modes)) lang))) + (if (symbolp l) (symbol-name l) l)) + "-mode"))) -(defun org-edit-fixed-width-region () - "Edit the fixed-width ascii drawing at point. -This must be a region where each line starts with a colon followed by -a space character. -An new buffer is created and the fixed-width region is copied into it, -and the buffer is switched into `artist-mode' for editing. When done, -exit with \\[org-edit-src-exit]. The edited text will then replace -the fragment in the Org-mode buffer." - (interactive) - (let ((line (org-current-line)) - (col (current-column)) - (case-fold-search t) - (msg "Edit, then exit with C-c ' (C-c and single quote) -- C-c C-k to abort") - (org-mode-p (derived-mode-p 'org-mode)) - (beg (make-marker)) - (end (make-marker)) - block-nindent ovl beg1 end1 code begline buffer) - (beginning-of-line 1) - (if (looking-at "[ \t]*[^:\n \t]") - nil - (if (looking-at "[ \t]*\\(\n\\|\\'\\)") - (setq beg1 (point) end1 beg1) - (save-excursion - (if (re-search-backward "^[ \t]*[^: \t]" nil 'move) - (setq beg1 (point-at-bol 2)) - (setq beg1 (point)))) - (save-excursion - (if (re-search-forward "^[ \t]*[^: \t]" nil 'move) - (setq end1 (1- (match-beginning 0))) - (setq end1 (point)))) - (org-goto-line line)) - (setq beg (move-marker beg beg1) - end (move-marker end end1) - code (buffer-substring-no-properties beg end) - begline (save-excursion (goto-char beg) (org-current-line))) - (if (and (setq buffer (org-edit-src-find-buffer beg end)) - (y-or-n-p "Return to existing edit buffer ([n] will revert changes)? ")) - (org-pop-to-buffer-same-window buffer) - (when buffer - (with-current-buffer buffer - (if (boundp 'org-edit-src-overlay) - (delete-overlay org-edit-src-overlay))) - (kill-buffer buffer)) - (setq buffer (generate-new-buffer - (org-src-construct-edit-buffer-name - (buffer-name) "Fixed Width"))) - (setq ovl (make-overlay beg end)) - (overlay-put ovl 'face 'secondary-selection) - (overlay-put ovl 'edit-buffer buffer) - (overlay-put ovl 'help-echo "Click with mouse-1 to switch to buffer editing this segment") - (overlay-put ovl 'face 'secondary-selection) - (overlay-put ovl - 'keymap - (let ((map (make-sparse-keymap))) - (define-key map [mouse-1] 'org-edit-src-continue) - map)) - (overlay-put ovl :read-only "Leave me alone") - (org-pop-to-buffer-same-window buffer) - (insert code) +(defun org-src--coordinates (pos beg end) + "Return coordinates of POS relatively to BEG and END. +POS, BEG and END are buffer positions. Return value is either +a cons cell (LINE . COLUMN) or symbol `end'. See also +`org-src--goto-coordinates'." + (if (>= pos end) 'end + (org-with-wide-buffer + (goto-char (max beg pos)) + (cons (count-lines beg (line-beginning-position)) + ;; Column is relative to the end of line to avoid problems of + ;; comma escaping or colons appended in front of the line. + (- (current-column) + (progn (end-of-line) (current-column))))))) + +(defun org-src--goto-coordinates (coord beg end) + "Move to coordinates COORD relatively to BEG and END. +COORD are coordinates, as returned by `org-src--coordinates', +which see. BEG and END are buffer positions." + (goto-char + (if (eq coord 'end) (max (1- end) beg) + ;; If BEG happens to be located outside of the narrowed part of + ;; the buffer, widen it first. + (org-with-wide-buffer + (goto-char beg) + (forward-line (car coord)) + (end-of-line) + (org-move-to-column (max (+ (current-column) (cdr coord)) 0)) + (point))))) + +(defun org-src--contents-area (datum) + "Return contents boundaries of DATUM. +DATUM is an element or object. Return a list (BEG END CONTENTS) +where BEG and END are buffer positions and CONTENTS is a string." + (let ((type (org-element-type datum))) + (org-with-wide-buffer + (cond + ((eq type 'footnote-definition) + (let* ((beg (progn + (goto-char (org-element-property :post-affiliated datum)) + (search-forward "]"))) + (end (or (org-element-property :contents-end datum) beg))) + (list beg end (buffer-substring-no-properties beg end)))) + ((eq type 'inline-src-block) + (let ((beg (progn (goto-char (org-element-property :begin datum)) + (search-forward "{" (line-end-position) t))) + (end (progn (goto-char (org-element-property :end datum)) + (search-backward "}" (line-beginning-position) t)))) + (list beg end (buffer-substring-no-properties beg end)))) + ((org-element-property :contents-begin datum) + (let ((beg (org-element-property :contents-begin datum)) + (end (org-element-property :contents-end datum))) + (list beg end (buffer-substring-no-properties beg end)))) + ((memq type '(example-block export-block src-block)) + (list (progn (goto-char (org-element-property :post-affiliated datum)) + (line-beginning-position 2)) + (progn (goto-char (org-element-property :end datum)) + (skip-chars-backward " \r\t\n") + (line-beginning-position 1)) + (org-element-property :value datum))) + ((memq type '(fixed-width table)) + (let ((beg (org-element-property :post-affiliated datum)) + (end (progn (goto-char (org-element-property :end datum)) + (skip-chars-backward " \r\t\n") + (line-beginning-position 2)))) + (list beg + end + (if (eq type 'fixed-width) (org-element-property :value datum) + (buffer-substring-no-properties beg end))))) + (t (error "Unsupported element or object: %s" type)))))) + +(defun org-src--make-source-overlay (beg end edit-buffer) + "Create overlay between BEG and END positions and return it. +EDIT-BUFFER is the buffer currently editing area between BEG and +END." + (let ((overlay (make-overlay beg end))) + (overlay-put overlay 'face 'secondary-selection) + (overlay-put overlay 'edit-buffer edit-buffer) + (overlay-put overlay 'help-echo + "Click with mouse-1 to switch to buffer editing this segment") + (overlay-put overlay 'face 'secondary-selection) + (overlay-put overlay 'keymap + (let ((map (make-sparse-keymap))) + (define-key map [mouse-1] 'org-edit-src-continue) + map)) + (let ((read-only + (list + (lambda (&rest _) + (user-error + "Cannot modify an area being edited in a dedicated buffer"))))) + (overlay-put overlay 'modification-hooks read-only) + (overlay-put overlay 'insert-in-front-hooks read-only) + (overlay-put overlay 'insert-behind-hooks read-only)) + overlay)) + +(defun org-src--remove-overlay () + "Remove overlay from current source buffer." + (when (overlayp org-src--overlay) (delete-overlay org-src--overlay))) + +(defun org-src--on-datum-p (datum) + "Non-nil when point is on DATUM. +DATUM is an element or an object. Consider blank lines or white +spaces after it as being outside." + (and (>= (point) (org-element-property :begin datum)) + (<= (point) + (org-with-wide-buffer + (goto-char (org-element-property :end datum)) + (skip-chars-backward " \r\t\n") + (if (eq (org-element-class datum) 'element) + (line-end-position) + (point)))))) + +(defun org-src--contents-for-write-back () + "Return buffer contents in a format appropriate for write back. +Assume point is in the corresponding edit buffer." + (let ((indentation-offset + (if org-src--preserve-indentation 0 + (+ (or org-src--block-indentation 0) + (if (memq org-src--source-type '(example-block src-block)) + org-edit-src-content-indentation + 0)))) + (use-tabs? (and (> org-src--tab-width 0) t)) + (source-tab-width org-src--tab-width) + (contents (org-with-wide-buffer (buffer-string))) + (write-back org-src--allow-write-back)) + (with-temp-buffer + ;; Reproduce indentation parameters from source buffer. + (setq-local indent-tabs-mode use-tabs?) + (when (> source-tab-width 0) (setq-local tab-width source-tab-width)) + ;; Apply WRITE-BACK function on edit buffer contents. + (insert (org-no-properties contents)) + (goto-char (point-min)) + (when (functionp write-back) (save-excursion (funcall write-back))) + ;; Add INDENTATION-OFFSET to every non-empty line in buffer, + ;; unless indentation is meant to be preserved. + (when (> indentation-offset 0) + (while (not (eobp)) + (skip-chars-forward " \t") + (unless (eolp) ;ignore blank lines + (let ((i (current-column))) + (delete-region (line-beginning-position) (point)) + (indent-to (+ i indentation-offset)))) + (forward-line))) + (buffer-string)))) + +(defun org-src--edit-element + (datum name &optional major write-back contents remote) + "Edit DATUM contents in a dedicated buffer NAME. + +MAJOR is the major mode used in the edit buffer. A nil value is +equivalent to `fundamental-mode'. + +When WRITE-BACK is non-nil, assume contents will replace original +region. Moreover, if it is a function, apply it in the edit +buffer, from point min, before returning the contents. + +When CONTENTS is non-nil, display them in the edit buffer. +Otherwise, show DATUM contents as specified by +`org-src--contents-area'. + +When REMOTE is non-nil, do not try to preserve point or mark when +moving from the edit area to the source. + +Leave point in edit buffer." + (setq org-src--saved-temp-window-config (current-window-configuration)) + (let* ((area (org-src--contents-area datum)) + (beg (copy-marker (nth 0 area))) + (end (copy-marker (nth 1 area) t)) + (old-edit-buffer (org-src--edit-buffer beg end)) + (contents (or contents (nth 2 area)))) + (if (and old-edit-buffer + (or (not org-src-ask-before-returning-to-edit-buffer) + (y-or-n-p "Return to existing edit buffer ([n] will revert changes)? "))) + ;; Move to existing buffer. + (org-src-switch-to-buffer old-edit-buffer 'return) + ;; Discard old edit buffer. + (when old-edit-buffer + (with-current-buffer old-edit-buffer (org-src--remove-overlay)) + (kill-buffer old-edit-buffer)) + (let* ((org-mode-p (derived-mode-p 'org-mode)) + (source-tab-width (if indent-tabs-mode tab-width 0)) + (type (org-element-type datum)) + (ind (org-with-wide-buffer + (goto-char (org-element-property :begin datum)) + (org-get-indentation))) + (preserve-ind + (and (memq type '(example-block src-block)) + (or (org-element-property :preserve-indent datum) + org-src-preserve-indentation))) + ;; Store relative positions of mark (if any) and point + ;; within the edited area. + (point-coordinates (and (not remote) + (org-src--coordinates (point) beg end))) + (mark-coordinates (and (not remote) + (org-region-active-p) + (let ((m (mark))) + (and (>= m beg) (>= end m) + (org-src--coordinates m beg end))))) + ;; Generate a new edit buffer. + (buffer (generate-new-buffer name)) + ;; Add an overlay on top of source. + (overlay (org-src--make-source-overlay beg end buffer))) + ;; Switch to edit buffer. + (org-src-switch-to-buffer buffer 'edit) + ;; Insert contents. + (insert contents) (remove-text-properties (point-min) (point-max) '(display nil invisible nil intangible nil)) - (setq block-nindent (or (org-do-remove-indentation) 0)) - (cond - ((eq org-edit-fixed-width-region-mode 'artist-mode) - (fundamental-mode) - (artist-mode 1)) - (t (funcall org-edit-fixed-width-region-mode))) - (set (make-local-variable 'org-edit-src-force-single-line) nil) - (set (make-local-variable 'org-edit-src-from-org-mode) org-mode-p) - (set (make-local-variable 'org-edit-src-picture) t) - (goto-char (point-min)) - (while (re-search-forward "^[ \t]*: ?" nil t) - (replace-match "")) - (org-goto-line (1+ (- line begline))) - (org-move-to-column (max 0 (- col block-nindent 2))) - (org-set-local 'org-edit-src-beg-marker beg) - (org-set-local 'org-edit-src-end-marker end) - (org-set-local 'org-edit-src-overlay ovl) - (org-set-local 'org-edit-src-block-indentation block-nindent) - (org-set-local 'org-edit-src-content-indentation 0) - (org-set-local 'org-src-preserve-indentation nil) - (org-src-mode) + (unless preserve-ind (org-do-remove-indentation)) (set-buffer-modified-p nil) - (and org-edit-src-persistent-message - (org-set-local 'header-line-format msg))) - (message "%s" msg) - t))) + (setq buffer-file-name nil) + ;; Start major mode. + (if (not major) (fundamental-mode) + (let ((org-inhibit-startup t)) + (condition-case e (funcall major) + (error (message "Language mode `%s' fails with: %S" + major (nth 1 e)))))) + ;; Transmit buffer-local variables for exit function. It must + ;; be done after initializing major mode, as this operation + ;; may reset them otherwise. + (setq-local org-src--tab-width source-tab-width) + (setq-local org-src--from-org-mode org-mode-p) + (setq-local org-src--beg-marker beg) + (setq-local org-src--end-marker end) + (setq-local org-src--remote remote) + (setq-local org-src--source-type type) + (setq-local org-src--block-indentation ind) + (setq-local org-src--preserve-indentation preserve-ind) + (setq-local org-src--overlay overlay) + (setq-local org-src--allow-write-back write-back) + ;; Start minor mode. + (org-src-mode) + ;; Move mark and point in edit buffer to the corresponding + ;; location. + (if remote + (progn + ;; Put point at first non read-only character after + ;; leading blank. + (goto-char + (or (text-property-any (point-min) (point-max) 'read-only nil) + (point-max))) + (skip-chars-forward " \r\t\n")) + ;; Set mark and point. + (when mark-coordinates + (org-src--goto-coordinates mark-coordinates (point-min) (point-max)) + (push-mark (point) 'no-message t) + (setq deactivate-mark nil)) + (org-src--goto-coordinates + point-coordinates (point-min) (point-max))))))) + + + +;;; Fontification of source blocks -(defun org-edit-src-find-region-and-lang () - "Find the region and language for a local edit. -Return a list with beginning and end of the region, a string representing -the language, a switch telling if the content should be in a single line." - (let ((re-list - (append - org-edit-src-region-extra - '( - ("[^<]*>[ \t]*\n?" "\n?[ \t]*" lang) - ("[^<]*>[ \t]*\n?" "\n?[ \t]*" style) - ("[ \t]*\n?" "\n?[ \t]*" "fundamental") - ("[ \t]*\n?" "\n?[ \t]*" "emacs-lisp") - ("[ \t]*\n?" "\n?[ \t]*" "perl") - ("[ \t]*\n?" "\n?[ \t]*" "python") - ("[ \t]*\n?" "\n?[ \t]*" "ruby") - ("^[ \t]*#\\+begin_src\\( \\([^ \t\n]+\\)\\)?.*\n" "\n[ \t]*#\\+end_src" 2) - ("^[ \t]*#\\+begin_example.*\n" "\n[ \t]*#\\+end_example" "fundamental") - ("^[ \t]*#\\+html:" "\n" "html" single-line) - ("^[ \t]*#\\+begin_html.*\n" "\n[ \t]*#\\+end_html" "html") - ("^[ \t]*#\\+latex:" "\n" "latex" single-line) - ("^[ \t]*#\\+begin_latex.*\n" "\n[ \t]*#\\+end_latex" "latex") - ("^[ \t]*#\\+ascii:" "\n" "fundamental" single-line) - ("^[ \t]*#\\+begin_ascii.*\n" "\n[ \t]*#\\+end_ascii" "fundamental") - ("^[ \t]*#\\+macro:[ \t]+\\S-+\\( \\|$\\)" - "\n" "fundamental" macro-definition) - ))) - (pos (point)) - re1 re2 single beg end lang lfmt match-re1 ind entry) - (catch 'exit - (while (setq entry (pop re-list)) - (setq re1 (car entry) re2 (nth 1 entry) lang (nth 2 entry) - single (nth 3 entry)) - (save-excursion - (if (or (looking-at re1) - (re-search-backward re1 nil t)) - (progn - (setq match-re1 (match-string 0)) - (setq beg (match-end 0) - lang (org-edit-src-get-lang lang) - lfmt (org-edit-src-get-label-format match-re1) - ind (org-edit-src-get-indentation (match-beginning 0))) - (if (and (re-search-forward re2 nil t) - (>= (match-end 0) pos)) - (throw 'exit (list beg (match-beginning 0) - lang single lfmt ind)))) - (if (or (looking-at re2) - (re-search-forward re2 nil t)) - (progn - (setq end (match-beginning 0)) - (if (and (re-search-backward re1 nil t) - (<= (match-beginning 0) pos)) - (progn - (setq lfmt (org-edit-src-get-label-format - (match-string 0)) - ind (org-edit-src-get-indentation - (match-beginning 0))) - (throw 'exit - (list (match-end 0) end - (org-edit-src-get-lang lang) - single lfmt ind))))))))) - (when (org-at-table.el-p) - (re-search-backward "^[\t]*[^ \t|\\+]" nil t) - (setq beg (1+ (point-at-eol))) - (goto-char beg) - (or (re-search-forward "^[\t]*[^ \t|\\+]" nil t) - (progn (goto-char (point-max)) (newline))) - (setq end (1- (point-at-bol))) - (throw 'exit (list beg end 'table.el nil nil 0)))))) - -(defun org-edit-src-get-lang (lang) - "Extract the src language." - (let ((m (match-string 0))) - (cond - ((stringp lang) lang) - ((integerp lang) (match-string lang)) - ((and (eq lang 'lang) - (string-match "\\ cnt 0)) - (goto-char (point-max)) (insert "\\n"))) - (goto-char (point-min)) - (if (looking-at "\\s-*") (replace-match " "))) - (when (and (org-bound-and-true-p org-edit-src-from-org-mode) - (not fixed-width-p)) - (org-escape-code-in-region (point-min) (point-max)) - (setq delta (+ delta - (save-excursion - (org-goto-line line) - (if (looking-at "[ \t]*\\(,,\\)?\\(\\*\\|#+\\)") 1 - 0))))) - (when (org-bound-and-true-p org-edit-src-picture) - (setq preserve-indentation nil) - (untabify (point-min) (point-max)) - (goto-char (point-min)) - (while (re-search-forward "^" nil t) - (replace-match ": "))) - (unless (or single preserve-indentation (= total-nindent 0)) - (setq indent (make-string total-nindent ?\ )) - (goto-char (point-min)) - (while (re-search-forward "\\(^\\).+" nil t) - (replace-match indent nil nil nil 1))) - (if (org-bound-and-true-p org-edit-src-picture) - (setq total-nindent (+ total-nindent 2))) - (setq code (buffer-string)) - (when (eq context 'save) - (erase-buffer) - (insert bufstr)) - (set-buffer-modified-p nil)) - (org-src-switch-to-buffer (marker-buffer beg) (or context 'exit)) - (if (eq context 'save) (save-buffer) - (with-current-buffer buffer - (set-buffer-modified-p nil)) - (kill-buffer buffer)) - (goto-char beg) - (when allow-write-back-p - (undo-boundary) - (delete-region beg (max beg end)) - (unless (string-match "\\`[ \t]*\\'" code) - (insert code)) - ;; Make sure the overlay stays in place - (when (eq context 'save) (move-overlay ovl beg (point))) - (goto-char beg) - (if single (just-one-space))) - (if (memq t (mapcar (lambda (overlay) - (eq (overlay-get overlay 'invisible) - 'org-hide-block)) - (overlays-at (point)))) - ;; Block is hidden; put point at start of block - (beginning-of-line 0) - ;; Block is visible, put point where it was in the code buffer - (when allow-write-back-p - (org-goto-line (1- (+ (org-current-line) line))) - (org-move-to-column (if preserve-indentation col (+ col total-nindent delta))))) - (unless (eq context 'save) - (move-marker beg nil) - (move-marker end nil))) - (unless (eq context 'save) - (when org-edit-src-saved-temp-window-config - (set-window-configuration org-edit-src-saved-temp-window-config) - (setq org-edit-src-saved-temp-window-config nil)))) - -(defun org-edit-src-abort () - "Abort editing of the src code and return to the Org buffer." - (interactive) - (let (org-edit-src-allow-write-back-p) - (org-edit-src-exit 'exit))) - -(defmacro org-src-in-org-buffer (&rest body) - `(let ((p (point)) (m (mark)) (ul buffer-undo-list) msg) - (save-window-excursion - (org-edit-src-exit 'save) - ,@body - (setq msg (current-message)) - (if (eq org-src-window-setup 'other-frame) - (let ((org-src-window-setup 'current-window)) - (org-edit-src-code 'save)) - (org-edit-src-code 'save))) - (setq buffer-undo-list ul) - (push-mark m 'nomessage) - (goto-char (min p (point-max))) - (message (or msg "")))) -(def-edebug-spec org-src-in-org-buffer (body)) -(defun org-edit-src-save () - "Save parent buffer with current state source-code buffer." - (interactive) - (if (string-match "Fixed Width" (buffer-name)) - (user-error "%s" "Use C-c ' to save and exit, C-c C-k to abort editing") - (org-src-in-org-buffer (save-buffer)))) + +;;; Org src minor mode -(declare-function org-babel-tangle "ob-tangle" (&optional arg target-file lang)) +(defvar org-src-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "\C-c'" 'org-edit-src-exit) + (define-key map "\C-c\C-k" 'org-edit-src-abort) + (define-key map "\C-x\C-s" 'org-edit-src-save) + map)) -(defun org-src-tangle (arg) - "Tangle the parent buffer." - (interactive) - (org-src-in-org-buffer (org-babel-tangle arg))) +(define-minor-mode org-src-mode + "Minor mode for language major mode buffers generated by Org. +\\ +This minor mode is turned on in two situations: + - when editing a source code snippet with `\\[org-edit-special]' + - when formatting a source code snippet for export with htmlize. + +\\{org-src-mode-map} + +See also `org-src-mode-hook'." + nil " OrgSrc" nil + (when org-edit-src-persistent-message + (setq-local + header-line-format + (substitute-command-keys + (if org-src--allow-write-back + "Edit, then exit with `\\[org-edit-src-exit]' or abort with \ +`\\[org-edit-src-abort]'" + "Exit with `\\[org-edit-src-exit]' or abort with \ +`\\[org-edit-src-abort]'")))) + ;; Possibly activate various auto-save features (for the edit buffer + ;; or the source buffer). + (when org-edit-src-turn-on-auto-save + (setq buffer-auto-save-file-name + (concat (make-temp-name "org-src-") + (format-time-string "-%Y-%d-%m") + ".txt"))) + (unless (or org-src--auto-save-timer (zerop org-edit-src-auto-save-idle-delay)) + (setq org-src--auto-save-timer + (run-with-idle-timer + org-edit-src-auto-save-idle-delay t + (lambda () + (save-excursion + (let (edit-flag) + (dolist (b (buffer-list)) + (with-current-buffer b + (when (org-src-edit-buffer-p) + (unless edit-flag (setq edit-flag t)) + (when (buffer-modified-p) (org-edit-src-save))))) + (unless edit-flag + (cancel-timer org-src--auto-save-timer) + (setq org-src--auto-save-timer nil))))))))) (defun org-src-mode-configure-edit-buffer () - (when (org-bound-and-true-p org-edit-src-from-org-mode) - (org-add-hook 'kill-buffer-hook - #'(lambda () (delete-overlay org-edit-src-overlay)) nil 'local) - (if (org-bound-and-true-p org-edit-src-allow-write-back-p) + (when (bound-and-true-p org-src--from-org-mode) + (add-hook 'kill-buffer-hook #'org-src--remove-overlay nil 'local) + (if (bound-and-true-p org-src--allow-write-back) (progn (setq buffer-offer-save t) (setq buffer-file-name - (concat (buffer-file-name (marker-buffer org-edit-src-beg-marker)) + (concat (buffer-file-name (marker-buffer org-src--beg-marker)) "[" (buffer-name) "]")) - (if (featurep 'xemacs) - (progn - (make-variable-buffer-local 'write-contents-hooks) ; needed only for 21.4 - (setq write-contents-hooks '(org-edit-src-save))) - (setq write-contents-functions '(org-edit-src-save)))) + (setq-local write-contents-functions '(org-edit-src-save))) (setq buffer-read-only t)))) -(org-add-hook 'org-src-mode-hook 'org-src-mode-configure-edit-buffer) +(add-hook 'org-src-mode-hook #'org-src-mode-configure-edit-buffer) + + +;;; Babel related functions (defun org-src-associate-babel-session (info) "Associate edit buffer with comint session." (interactive) - (let ((session (cdr (assoc :session (nth 2 info))))) + (let ((session (cdr (assq :session (nth 2 info))))) (and session (not (string= session "none")) (org-babel-comint-buffer-livep session) (let ((f (intern (format "org-babel-%s-associate-session" @@ -843,18 +690,22 @@ with \",*\", \",#+\", \",,*\" and \",,#+\"." (and (fboundp f) (funcall f session)))))) (defun org-src-babel-configure-edit-buffer () - (when org-src-babel-info - (org-src-associate-babel-session org-src-babel-info))) + (when org-src--babel-info + (org-src-associate-babel-session org-src--babel-info))) + +(add-hook 'org-src-mode-hook #'org-src-babel-configure-edit-buffer) + + +;;; Public API -(org-add-hook 'org-src-mode-hook 'org-src-babel-configure-edit-buffer) (defmacro org-src-do-at-code-block (&rest body) - "Execute a command from an edit buffer in the Org-mode buffer." - `(let ((beg-marker org-edit-src-beg-marker)) - (if beg-marker - (with-current-buffer (marker-buffer beg-marker) - (goto-char (marker-position beg-marker)) - ,@body)))) -(def-edebug-spec org-src-do-at-code-block (body)) + "Execute BODY from an edit buffer in the Org mode buffer." + (declare (debug (body))) + `(let ((beg-marker org-src--beg-marker)) + (when beg-marker + (with-current-buffer (marker-buffer beg-marker) + (goto-char beg-marker) + ,@body)))) (defun org-src-do-key-sequence-at-code-block (&optional key) "Execute key sequence at code block in the source Org buffer. @@ -878,81 +729,375 @@ Org-babel commands." (if (equal key (kbd "C-g")) (keyboard-quit) (org-edit-src-save) (org-src-do-at-code-block - (call-interactively - (lookup-key org-babel-map key))))) + (call-interactively (lookup-key org-babel-map key))))) -(defcustom org-src-tab-acts-natively nil - "If non-nil, the effect of TAB in a code block is as if it were -issued in the language major mode buffer." - :type 'boolean - :version "24.1" - :group 'org-babel) +(defun org-src-edit-buffer-p (&optional buffer) + "Non-nil when current buffer is a source editing buffer. +If BUFFER is non-nil, test it instead." + (let ((buffer (org-base-buffer (or buffer (current-buffer))))) + (and (buffer-live-p buffer) + (local-variable-p 'org-src--beg-marker buffer) + (local-variable-p 'org-src--end-marker buffer)))) + +(defun org-src-switch-to-buffer (buffer context) + (pcase org-src-window-setup + (`current-window (pop-to-buffer-same-window buffer)) + (`other-window + (switch-to-buffer-other-window buffer)) + (`other-frame + (pcase context + (`exit + (let ((frame (selected-frame))) + (switch-to-buffer-other-frame buffer) + (delete-frame frame))) + (`save + (kill-buffer (current-buffer)) + (pop-to-buffer-same-window buffer)) + (_ (switch-to-buffer-other-frame buffer)))) + (`reorganize-frame + (when (eq context 'edit) (delete-other-windows)) + (org-switch-to-buffer-other-window buffer) + (when (eq context 'exit) (delete-other-windows))) + (`switch-invisibly (set-buffer buffer)) + (_ + (message "Invalid value %s for `org-src-window-setup'" + org-src-window-setup) + (pop-to-buffer-same-window buffer)))) + +(defun org-src-coderef-format (&optional element) + "Return format string for block at point. + +When optional argument ELEMENT is provided, use that block. +Otherwise, assume point is either at a source block, at an +example block. + +If point is in an edit buffer, retrieve format string associated +to the remote source block." + (cond + ((and element (org-element-property :label-fmt element))) + ((org-src-edit-buffer-p) (org-src-do-at-code-block (org-src-coderef-format))) + ((org-element-property :label-fmt (org-element-at-point))) + (t org-coderef-label-format))) + +(defun org-src-coderef-regexp (fmt &optional label) + "Return regexp matching a coderef format string FMT. + +When optional argument LABEL is non-nil, match coderef for that +label only. + +Match group 1 contains the full coderef string with surrounding +white spaces. Match group 2 contains the same string without any +surrounding space. Match group 3 contains the label. + +A coderef format regexp can only match at the end of a line." + (format "\\([ \t]*\\(%s\\)[ \t]*\\)$" + (replace-regexp-in-string + "%s" + (if label (regexp-quote label) "\\([-a-zA-Z0-9_][-a-zA-Z0-9_ ]*\\)") + (regexp-quote fmt) + nil t))) + +(defun org-edit-footnote-reference () + "Edit definition of footnote reference at point." + (interactive) + (let* ((context (org-element-context)) + (label (org-element-property :label context))) + (unless (and (eq (org-element-type context) 'footnote-reference) + (org-src--on-datum-p context)) + (user-error "Not on a footnote reference")) + (unless label (user-error "Cannot edit remotely anonymous footnotes")) + (let* ((definition (org-with-wide-buffer + (org-footnote-goto-definition label) + (backward-char) + (org-element-context))) + (inline? (eq 'footnote-reference (org-element-type definition))) + (contents + (org-with-wide-buffer + (buffer-substring-no-properties + (or (org-element-property :post-affiliated definition) + (org-element-property :begin definition)) + (cond + (inline? (1+ (org-element-property :contents-end definition))) + ((org-element-property :contents-end definition)) + (t (goto-char (org-element-property :post-affiliated definition)) + (line-end-position))))))) + (add-text-properties + 0 + (progn (string-match (if inline? "\\`\\[fn:.*?:" "\\`.*?\\]") contents) + (match-end 0)) + '(read-only "Cannot edit footnote label" front-sticky t rear-nonsticky t) + contents) + (when inline? + (let ((l (length contents))) + (add-text-properties + (1- l) l + '(read-only "Cannot edit past footnote reference" + front-sticky nil rear-nonsticky nil) + contents))) + (org-src--edit-element + definition + (format "*Edit footnote [%s]*" label) + #'org-mode + (lambda () + (if (not inline?) (delete-region (point) (search-forward "]")) + (delete-region (point) (search-forward ":" nil t 2)) + (delete-region (1- (point-max)) (point-max)) + (when (re-search-forward "\n[ \t]*\n" nil t) + (user-error "Inline definitions cannot contain blank lines")) + ;; If footnote reference belongs to a table, make sure to + ;; remove any newline characters in order to preserve + ;; table's structure. + (when (org-element-lineage definition '(table-cell)) + (while (search-forward "\n" nil t) (replace-match ""))))) + contents + 'remote)) + ;; Report success. + t)) + +(defun org-edit-table.el () + "Edit \"table.el\" table at point. +\\ +A new buffer is created and the table is copied into it. Then +the table is recognized with `table-recognize'. When done +editing, exit with `\\[org-edit-src-exit]'. The edited text will \ +then replace +the area in the Org mode buffer. + +Throw an error when not at such a table." + (interactive) + (let ((element (org-element-at-point))) + (unless (and (eq (org-element-type element) 'table) + (eq (org-element-property :type element) 'table.el) + (org-src--on-datum-p element)) + (user-error "Not in a table.el table")) + (org-src--edit-element + element + (org-src--construct-edit-buffer-name (buffer-name) "Table") + #'text-mode t) + (when (bound-and-true-p flyspell-mode) (flyspell-mode -1)) + (table-recognize) + t)) + +(defun org-edit-export-block () + "Edit export block at point. +\\ +A new buffer is created and the block is copied into it, and the +buffer is switched into an appropriate major mode. See also +`org-src-lang-modes'. + +When done, exit with `\\[org-edit-src-exit]'. The edited text \ +will then replace +the area in the Org mode buffer. + +Throw an error when not at an export block." + (interactive) + (let ((element (org-element-at-point))) + (unless (and (eq (org-element-type element) 'export-block) + (org-src--on-datum-p element)) + (user-error "Not in an export block")) + (let* ((type (downcase (org-element-property :type element))) + (mode (org-src--get-lang-mode type))) + (unless (functionp mode) (error "No such language mode: %s" mode)) + (org-src--edit-element + element + (org-src--construct-edit-buffer-name (buffer-name) type) + mode + (lambda () (org-escape-code-in-region (point-min) (point-max))))) + t)) + +(defun org-edit-src-code (&optional code edit-buffer-name) + "Edit the source or example block at point. +\\ +The code is copied to a separate buffer and the appropriate mode +is turned on. When done, exit with `\\[org-edit-src-exit]'. This \ +will remove the +original code in the Org buffer, and replace it with the edited +version. See `org-src-window-setup' to configure the display of +windows containing the Org buffer and the code buffer. -(defun org-src-native-tab-command-maybe () - "Perform language-specific TAB action. -Alter code block according to what TAB does in the language major mode." - (and org-src-tab-acts-natively - (org-in-src-block-p) - (not (equal this-command 'org-shifttab)) - (let ((org-src-strip-leading-and-trailing-blank-lines nil)) - (org-babel-do-key-sequence-in-edit-buffer (kbd "TAB"))))) +When optional argument CODE is a string, edit it in a dedicated +buffer instead. -(add-hook 'org-tab-first-hook 'org-src-native-tab-command-maybe) +When optional argument EDIT-BUFFER-NAME is non-nil, use it as the +name of the sub-editing buffer." + (interactive) + (let* ((element (org-element-at-point)) + (type (org-element-type element))) + (unless (and (memq type '(example-block src-block)) + (org-src--on-datum-p element)) + (user-error "Not in a source or example block")) + (let* ((lang + (if (eq type 'src-block) (org-element-property :language element) + "example")) + (lang-f (and (eq type 'src-block) (org-src--get-lang-mode lang))) + (babel-info (and (eq type 'src-block) + (org-babel-get-src-block-info 'light))) + deactivate-mark) + (when (and (eq type 'src-block) (not (functionp lang-f))) + (error "No such language mode: %s" lang-f)) + (org-src--edit-element + element + (or edit-buffer-name + (org-src--construct-edit-buffer-name (buffer-name) lang)) + lang-f + (and (null code) + (lambda () (org-escape-code-in-region (point-min) (point-max)))) + (and code (org-unescape-code-in-string code))) + ;; Finalize buffer. + (setq-local org-coderef-label-format + (or (org-element-property :label-fmt element) + org-coderef-label-format)) + (when (eq type 'src-block) + (setq-local org-src--babel-info babel-info) + (let ((edit-prep-func (intern (concat "org-babel-edit-prep:" lang)))) + (when (fboundp edit-prep-func) + (funcall edit-prep-func babel-info)))) + t))) -(defun org-src-font-lock-fontify-block (lang start end) - "Fontify code block. -This function is called by emacs automatic fontification, as long -as `org-src-fontify-natively' is non-nil. For manual -fontification of code blocks see `org-src-fontify-block' and -`org-src-fontify-buffer'" - (let ((lang-mode (org-src-get-lang-mode lang))) - (if (fboundp lang-mode) - (let ((string (buffer-substring-no-properties start end)) - (modified (buffer-modified-p)) - (org-buffer (current-buffer)) pos next) - (remove-text-properties start end '(face nil)) - (with-current-buffer - (get-buffer-create - (concat " org-src-fontification:" (symbol-name lang-mode))) - (delete-region (point-min) (point-max)) - (insert string " ") ;; so there's a final property change - (unless (eq major-mode lang-mode) (funcall lang-mode)) - (org-font-lock-ensure) - (setq pos (point-min)) - (while (setq next (next-single-property-change pos 'face)) - (put-text-property - (+ start (1- pos)) (1- (+ start next)) 'face - (get-text-property pos 'face) org-buffer) - (setq pos next))) - (add-text-properties - start end - '(font-lock-fontified t fontified t font-lock-multiline t)) - (set-buffer-modified-p modified))))) +(defun org-edit-inline-src-code () + "Edit inline source code at point." + (interactive) + (let ((context (org-element-context))) + (unless (and (eq (org-element-type context) 'inline-src-block) + (org-src--on-datum-p context)) + (user-error "Not on inline source code")) + (let* ((lang (org-element-property :language context)) + (lang-f (org-src--get-lang-mode lang)) + (babel-info (org-babel-get-src-block-info 'light)) + deactivate-mark) + (unless (functionp lang-f) (error "No such language mode: %s" lang-f)) + (org-src--edit-element + context + (org-src--construct-edit-buffer-name (buffer-name) lang) + lang-f + (lambda () + ;; Inline src blocks are limited to one line. + (while (re-search-forward "\n[ \t]*" nil t) (replace-match " ")) + ;; Trim contents. + (goto-char (point-min)) + (skip-chars-forward " \t") + (delete-region (point-min) (point)) + (goto-char (point-max)) + (skip-chars-backward " \t") + (delete-region (point) (point-max)))) + ;; Finalize buffer. + (setq-local org-src--babel-info babel-info) + (setq-local org-src--preserve-indentation t) + (let ((edit-prep-func (intern (concat "org-babel-edit-prep:" lang)))) + (when (fboundp edit-prep-func) (funcall edit-prep-func babel-info))) + ;; Return success. + t))) -(defvar org-src-fontify-natively) +(defun org-edit-fixed-width-region () + "Edit the fixed-width ASCII drawing at point. +\\ +This must be a region where each line starts with a colon +followed by a space or a newline character. + +A new buffer is created and the fixed-width region is copied into +it, and the buffer is switched into the major mode defined in +`org-edit-fixed-width-region-mode', which see. + +When done, exit with `\\[org-edit-src-exit]'. The edited text \ +will then replace +the area in the Org mode buffer." + (interactive) + (let ((element (org-element-at-point))) + (unless (and (eq (org-element-type element) 'fixed-width) + (org-src--on-datum-p element)) + (user-error "Not in a fixed-width area")) + (org-src--edit-element + element + (org-src--construct-edit-buffer-name (buffer-name) "Fixed Width") + org-edit-fixed-width-region-mode + (lambda () (while (not (eobp)) (insert ": ") (forward-line)))) + ;; Return success. + t)) -(defun org-src-fontify-block () - "Fontify code block at point." +(defun org-edit-src-abort () + "Abort editing of the src code and return to the Org buffer." (interactive) - (save-excursion - (let ((org-src-fontify-natively t) - (info (org-edit-src-find-region-and-lang))) - (font-lock-fontify-region (nth 0 info) (nth 1 info))))) + (let (org-src--allow-write-back) (org-edit-src-exit))) -(defun org-src-fontify-buffer () - "Fontify all code blocks in the current buffer." +(defun org-edit-src-continue (e) + "Unconditionally return to buffer editing area under point. +Throw an error if there is no such buffer." + (interactive "e") + (mouse-set-point e) + (let ((buf (get-char-property (point) 'edit-buffer))) + (if buf (org-src-switch-to-buffer buf 'continue) + (user-error "No sub-editing buffer for area at point")))) + +(defun org-edit-src-save () + "Save parent buffer with current state source-code buffer." (interactive) - (org-babel-map-src-blocks nil - (org-src-fontify-block))) + (unless (org-src-edit-buffer-p) (user-error "Not in a sub-editing buffer")) + (set-buffer-modified-p nil) + (let ((edited-code (org-src--contents-for-write-back)) + (beg org-src--beg-marker) + (end org-src--end-marker) + (overlay org-src--overlay)) + (with-current-buffer (org-src--source-buffer) + (undo-boundary) + (goto-char beg) + ;; Temporarily disable read-only features of OVERLAY in order to + ;; insert new contents. + (delete-overlay overlay) + (delete-region beg end) + (let ((expecting-bol (bolp))) + (insert edited-code) + (when (and expecting-bol (not (bolp))) (insert "\n"))) + (save-buffer) + (move-overlay overlay beg (point)))) + ;; `write-contents-functions' requires the function to return + ;; a non-nil value so that other functions are not called. + t) + +(defun org-edit-src-exit () + "Kill current sub-editing buffer and return to source buffer." + (interactive) + (unless (org-src-edit-buffer-p) (error "Not in a sub-editing buffer")) + (let* ((beg org-src--beg-marker) + (end org-src--end-marker) + (write-back org-src--allow-write-back) + (remote org-src--remote) + (coordinates (and (not remote) + (org-src--coordinates (point) 1 (point-max)))) + (code (and write-back (org-src--contents-for-write-back)))) + (set-buffer-modified-p nil) + ;; Switch to source buffer. Kill sub-editing buffer. + (let ((edit-buffer (current-buffer)) + (source-buffer (marker-buffer beg))) + (unless source-buffer (error "Source buffer disappeared. Aborting")) + (org-src-switch-to-buffer source-buffer 'exit) + (kill-buffer edit-buffer)) + ;; Insert modified code. Ensure it ends with a newline character. + (org-with-wide-buffer + (when (and write-back (not (equal (buffer-substring beg end) code))) + (undo-boundary) + (goto-char beg) + (delete-region beg end) + (let ((expecting-bol (bolp))) + (insert code) + (when (and expecting-bol (not (bolp))) (insert "\n"))))) + ;; If we are to return to source buffer, put point at an + ;; appropriate location. In particular, if block is hidden, move + ;; to the beginning of the block opening line. + (unless remote + (goto-char beg) + (cond + ;; Block is hidden; move at start of block. + ((cl-some (lambda (o) (eq (overlay-get o 'invisible) 'org-hide-block)) + (overlays-at (point))) + (beginning-of-line 0)) + (write-back (org-src--goto-coordinates coordinates beg end)))) + ;; Clean up left-over markers and restore window configuration. + (set-marker beg nil) + (set-marker end nil) + (when org-src--saved-temp-window-config + (set-window-configuration org-src--saved-temp-window-config) + (setq org-src--saved-temp-window-config nil)))) -(defun org-src-get-lang-mode (lang) - "Return major mode that should be used for LANG. -LANG is a string, and the returned major mode is a symbol." - (intern - (concat - (let ((l (or (cdr (assoc lang org-src-lang-modes)) lang))) - (if (symbolp l) (symbol-name l) l)) - "-mode"))) (provide 'org-src) diff --git a/lisp/org/org-table.el b/lisp/org/org-table.el index 08bbf3277ba..357fdcfa441 100644 --- a/lisp/org/org-table.el +++ b/lisp/org/org-table.el @@ -1,4 +1,4 @@ -;;; org-table.el --- The table editor for Org-mode +;;; org-table.el --- The Table Editor for Org -*- lexical-binding: t; -*- ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. @@ -24,27 +24,53 @@ ;; ;;; Commentary: -;; This file contains the table editor and spreadsheet for Org-mode. +;; This file contains the table editor and spreadsheet for Org mode. ;; Watch out: Here we are talking about two different kind of tables. -;; Most of the code is for the tables created with the Org-mode table editor. +;; Most of the code is for the tables created with the Org mode table editor. ;; Sometimes, we talk about tables created and edited with the table.el ;; Emacs package. We call the former org-type tables, and the latter ;; table.el-type tables. ;;; Code: -(eval-when-compile - (require 'cl)) +(require 'cl-lib) (require 'org) -(declare-function org-export-string-as "ox" - (string backend &optional body-only ext-plist)) -(declare-function aa2u "ext:ascii-art-to-unicode" ()) +(declare-function org-element-at-point "org-element" ()) +(declare-function org-element-contents "org-element" (element)) +(declare-function org-element-extract-element "org-element" (element)) +(declare-function org-element-interpret-data "org-element" (data)) +(declare-function org-element-lineage "org-element" + (blob &optional types with-self)) +(declare-function org-element-map "org-element" + (data types fun + &optional info first-match no-recursion with-affiliated)) +(declare-function org-element-parse-buffer "org-element" + (&optional granularity visible-only)) +(declare-function org-element-property "org-element" (property element)) +(declare-function org-element-type "org-element" (element)) + +(declare-function org-export-create-backend "ox" (&rest rest) t) +(declare-function org-export-data-with-backend "ox" (data backend info)) +(declare-function org-export-filter-apply-functions "ox" + (filters value info)) +(declare-function org-export-first-sibling-p "ox" (blob info)) +(declare-function org-export-get-backend "ox" (name)) +(declare-function org-export-get-environment "ox" + (&optional backend subtreep ext-plist)) +(declare-function org-export-install-filters "ox" (info)) +(declare-function org-export-table-has-special-column-p "ox" (table)) +(declare-function org-export-table-row-is-special-p "ox" (table-row info)) + +(declare-function calc-eval "calc" (str &optional separator &rest args)) + (defvar orgtbl-mode) ; defined below (defvar orgtbl-mode-menu) ; defined when orgtbl mode get initialized (defvar constants-unit-system) +(defvar org-export-filters-alist) (defvar org-table-follow-field-mode) +(defvar sort-fold-case) (defvar orgtbl-after-send-table-hook nil "Hook for functions attaching to `C-c C-c', if the table is sent. @@ -52,7 +78,7 @@ This can be used to add additional functionality after the table is sent to the receiver position, otherwise, if table is not sent, the functions are not run.") -(defvar org-table-TBLFM-begin-regexp "|\n[ \t]*#\\+TBLFM: ") +(defvar org-table-TBLFM-begin-regexp "^[ \t]*|.*\n[ \t]*#\\+TBLFM: ") (defcustom orgtbl-optimized (eq org-enable-table-editor 'optimized) "Non-nil means use the optimized table editor version for `orgtbl-mode'. @@ -63,7 +89,7 @@ for empty fields). Outside tables, the correct binding of the keys is restored. The default for this option is t if the optimized version is also used in -Org-mode. See the variable `org-enable-table-editor' for details. Changing +Org mode. See the variable `org-enable-table-editor' for details. Changing this variable requires a restart of Emacs to become effective." :group 'org-table :type 'boolean) @@ -118,7 +144,7 @@ table, obtained by prompting the user." (string :tag "Format")))) (defgroup org-table-settings nil - "Settings for tables in Org-mode." + "Settings for tables in Org mode." :tag "Org Table Settings" :group 'org-table) @@ -167,13 +193,13 @@ alignment to the right border applies." :type 'number) (defgroup org-table-editing nil - "Behavior of tables during editing in Org-mode." + "Behavior of tables during editing in Org mode." :tag "Org Table Editing" :group 'org-table) (defcustom org-table-automatic-realign t "Non-nil means automatically re-align table when pressing TAB or RETURN. -When nil, aligning is only done with \\[org-table-align], or after column +When nil, aligning is only done with `\\[org-table-align]', or after column removal/insertion." :group 'org-table-editing :type 'boolean) @@ -219,12 +245,12 @@ this line." :type 'boolean) (defgroup org-table-calculation nil - "Options concerning tables in Org-mode." + "Options concerning tables in Org mode." :tag "Org Table Calculation" :group 'org-table) (defcustom org-table-use-standard-references 'from - "Should org-mode work with table references like B3 instead of @3$2? + "Non-nil means using table references like B3 instead of @3$2. Possible values are: nil never use them from accept as input, do not present for editing @@ -236,9 +262,15 @@ t accept as input and present for editing" (const :tag "Convert user input, don't offer during editing" from))) (defcustom org-table-copy-increment t - "Non-nil means increment when copying current field with \\[org-table-copy-down]." + "Non-nil means increment when copying current field with \ +`\\[org-table-copy-down]'." :group 'org-table-calculation - :type 'boolean) + :version "26.1" + :package-version '(Org . "8.3") + :type '(choice + (const :tag "Use the difference between the current and the above fields" t) + (integer :tag "Use a number" 1) + (const :tag "Don't increment the value when copying a field" nil))) (defcustom org-calc-default-modes '(calc-internal-prec 12 @@ -251,16 +283,16 @@ t accept as input and present for editing" ) "List with Calc mode settings for use in `calc-eval' for table formulas. The list must contain alternating symbols (Calc modes variables and values). -Don't remove any of the default settings, just change the values. Org-mode +Don't remove any of the default settings, just change the values. Org mode relies on the variables to be present in the list." :group 'org-table-calculation :type 'plist) (defcustom org-table-duration-custom-format 'hours "Format for the output of calc computations like $1+$2;t. -The default value is 'hours, and will output the results as a -number of hours. Other allowed values are 'seconds, 'minutes and -'days, and the output will be a fraction of seconds, minutes or +The default value is `hours', and will output the results as a +number of hours. Other allowed values are `seconds', `minutes' and +`days', and the output will be a fraction of seconds, minutes or days." :group 'org-table-calculation :version "24.1" @@ -285,7 +317,7 @@ which should be evaluated as described in the manual and in the documentation string of the command `org-table-eval-formula'. This feature requires the Emacs calc package. When this variable is nil, formula calculation is only available through -the command \\[org-table-eval-formula]." +the command `\\[org-table-eval-formula]'." :group 'org-table-calculation :type 'boolean) @@ -317,15 +349,12 @@ Constants can also be defined on a per-file basis using a line like (defcustom org-table-allow-automatic-line-recalculation t "Non-nil means lines marked with |#| or |*| will be recomputed automatically. -Automatically means when TAB or RET or C-c C-c are pressed in the line." +\\\ +Automatically means when `TAB' or `RET' or `\\[org-ctrl-c-ctrl-c]' \ +are pressed in the line." :group 'org-table-calculation :type 'boolean) -(defcustom org-table-error-on-row-ref-crossing-hline t - "OBSOLETE VARIABLE, please see `org-table-relative-ref-may-cross-hline'." - :group 'org-table - :type 'boolean) - (defcustom org-table-relative-ref-may-cross-hline t "Non-nil means relative formula references may cross hlines. Here are the allowed values: @@ -345,8 +374,20 @@ portability of tables." (const :tag "Stick to hline" nil) (const :tag "Error on attempt to cross" error))) +(defcustom org-table-formula-create-columns nil + "Non-nil means that evaluation of a field formula can add new +columns if an out-of-bounds field is being set." + :group 'org-table-calculation + :version "26.1" + :package-version '(Org . "8.3") + :type '(choice + (const :tag "Setting an out-of-bounds field generates an error (default)" nil) + (const :tag "Setting an out-of-bounds field silently adds columns as needed" t) + (const :tag "Setting an out-of-bounds field adds columns as needed, but issues a warning message" warn) + (const :tag "When setting an out-of-bounds field, the user is prompted" prompt))) + (defgroup org-table-import-export nil - "Options concerning table import and export in Org-mode." + "Options concerning table import and export in Org mode." :tag "Org Table Import Export" :group 'org-table) @@ -359,38 +400,73 @@ available parameters." :group 'org-table-import-export :type 'string) +(defcustom org-table-convert-region-max-lines 999 + "Max lines that `org-table-convert-region' will attempt to process. + +The function can be slow on larger regions; this safety feature +prevents it from hanging emacs." + :group 'org-table-import-export + :type 'integer + :version "26.1" + :package-version '(Org . "8.3")) + (defconst org-table-auto-recalculate-regexp "^[ \t]*| *# *\\(|\\|$\\)" - "Detects a table line marked for automatic recalculation.") + "Regexp matching a line marked for automatic recalculation.") + (defconst org-table-recalculate-regexp "^[ \t]*| *[#*] *\\(|\\|$\\)" - "Detects a table line marked for automatic recalculation.") + "Regexp matching a line marked for recalculation.") + (defconst org-table-calculate-mark-regexp "^[ \t]*| *[!$^_#*] *\\(|\\|$\\)" - "Detects a table line marked for automatic recalculation.") + "Regexp matching a line marked for calculation.") + (defconst org-table-border-regexp "^[ \t]*[^| \t]" - "Searching from within a table (any type) this finds the first line outside the table.") + "Regexp matching any line outside an Org table.") + (defvar org-table-last-highlighted-reference nil) + (defvar org-table-formula-history nil) (defvar org-table-column-names nil - "Alist with column names, derived from the `!' line.") + "Alist with column names, derived from the `!' line. +This variable is initialized with `org-table-analyze'.") + (defvar org-table-column-name-regexp nil - "Regular expression matching the current column names.") + "Regular expression matching the current column names. +This variable is initialized with `org-table-analyze'.") + (defvar org-table-local-parameters nil - "Alist with parameter names, derived from the `$' line.") + "Alist with parameter names, derived from the `$' line. +This variable is initialized with `org-table-analyze'.") + (defvar org-table-named-field-locations nil - "Alist with locations of named fields.") + "Alist with locations of named fields. +Associations follow the pattern (NAME LINE COLUMN) where + NAME is the name of the field as a string, + LINE is the number of lines from the beginning of the table, + COLUMN is the column of the field, as an integer. +This variable is initialized with `org-table-analyze'.") (defvar org-table-current-line-types nil - "Table row types, non-nil only for the duration of a command.") -(defvar org-table-current-begin-line nil - "Table begin line, non-nil only for the duration of a command.") + "Table row types in current table. +This variable is initialized with `org-table-analyze'.") + (defvar org-table-current-begin-pos nil - "Table begin position, non-nil only for the duration of a command.") + "Current table begin position, as a marker. +This variable is initialized with `org-table-analyze'.") + (defvar org-table-current-ncol nil - "Number of columns in table, non-nil only for the duration of a command.") + "Number of columns in current table. +This variable is initialized with `org-table-analyze'.") + (defvar org-table-dlines nil - "Vector of data line line numbers in the current table.") + "Vector of data line line numbers in the current table. +Line numbers are counted from the beginning of the table. This +variable is initialized with `org-table-analyze'.") + (defvar org-table-hlines nil - "Vector of hline line numbers in the current table.") + "Vector of hline line numbers in the current table. +Line numbers are counted from the beginning of the table. This +variable is initialized with `org-table-analyze'.") (defconst org-table-range-regexp "@\\([-+]?I*[-+]?[0-9]*\\)?\\(\\$[-+]?[0-9]+\\)?\\(\\.\\.@?\\([-+]?I*[-+]?[0-9]*\\)?\\(\\$[-+]?[0-9]+\\)?\\)?" @@ -404,85 +480,33 @@ available parameters." "\\(" "@?[-0-9I$&]+" "\\|" "[a-zA-Z]\\{1,2\\}\\([0-9]+\\|&\\)" "\\|" "\\$[a-zA-Z0-9]+" "\\)") "Match a range for reference display.") -(defun org-table-colgroup-line-p (line) - "Is this a table line colgroup information?" - (save-match-data - (and (string-match "[<>]\\|&[lg]t;" line) - (string-match "\\`[ \t]*|[ \t]*/[ \t]*\\(|[ \t<>0-9|lgt&;]+\\)\\'" - line) - (not (delq - nil - (mapcar - (lambda (s) - (not (member s '("" "<" ">" "<>" "<" ">" "<>")))) - (org-split-string (match-string 1 line) "[ \t]*|[ \t]*"))))))) - -(defun org-table-cookie-line-p (line) - "Is this a table line with only alignment/width cookies?" - (save-match-data - (and (string-match "[<>]\\|&[lg]t;" line) - (or (string-match - "\\`[ \t]*|[ \t]*/[ \t]*\\(|[ \t<>0-9|lrcgt&;]+\\)\\'" line) - (string-match "\\(\\`[ \t<>lrc0-9|gt&;]+\\'\\)" line)) - (not (delq nil (mapcar - (lambda (s) - (not (or (equal s "") - (string-match - "\\`<\\([lrc]?[0-9]+\\|[lrc]\\)>\\'" s) - (string-match - "\\`<\\([lrc]?[0-9]+\\|[lrc]\\)>\\'" - s)))) - (org-split-string (match-string 1 line) - "[ \t]*|[ \t]*"))))))) - -(defvar org-table-clean-did-remove-column nil) ; dynamically scoped -(defun org-table-clean-before-export (lines &optional maybe-quoted) - "Check if the table has a marking column. -If yes remove the column and the special lines." - (let ((special (if maybe-quoted - "^[ \t]*| *\\\\?[#!$*_^/ ] *|" - "^[ \t]*| *[#!$*_^/ ] *|")) - (ignore (if maybe-quoted - "^[ \t]*| *\\\\?[!$_^/] *|" - "^[ \t]*| *[!$_^/] *|"))) - (setq org-table-clean-did-remove-column - (not (memq nil - (mapcar - (lambda (line) - (or (string-match org-table-hline-regexp line) - (string-match special line))) - lines)))) - (delq nil - (mapcar - (lambda (line) - (cond - ((or (org-table-colgroup-line-p line) ;; colgroup info - (org-table-cookie-line-p line) ;; formatting cookies - (and org-table-clean-did-remove-column - (string-match ignore line))) ;; non-exportable data - nil) - ((and org-table-clean-did-remove-column - (or (string-match "^\\([ \t]*\\)|-+\\+" line) - (string-match "^\\([ \t]*\\)|[^|]*|" line))) - ;; remove the first column - (replace-match "\\1|" t nil line)) - (t line))) - lines)))) - (defconst org-table-translate-regexp (concat "\\(" "@[-0-9I$]+" "\\|" "[a-zA-Z]\\{1,2\\}\\([0-9]+\\|&\\)" "\\)") "Match a reference that needs translation, for reference display.") +(defmacro org-table-save-field (&rest body) + "Save current field; execute BODY; restore field. +Field is restored even in case of abnormal exit." + (declare (debug (body))) + (org-with-gensyms (line column) + `(let ((,line (copy-marker (line-beginning-position))) + (,column (org-table-current-column))) + (unwind-protect + (progn ,@body) + (goto-char ,line) + (org-table-goto-column ,column) + (set-marker ,line nil))))) + ;;;###autoload (defun org-table-create-with-table.el () "Use the table.el package to insert a new table. -If there is already a table at point, convert between Org-mode tables +If there is already a table at point, convert between Org tables and table.el tables." (interactive) (require 'table) (cond ((org-at-table.el-p) - (if (y-or-n-p "Convert table to Org-mode table? ") + (if (y-or-n-p "Convert table to Org table? ") (org-table-convert))) ((org-at-table-p) (when (y-or-n-p "Convert table to table.el table? ") @@ -526,7 +550,7 @@ SIZE is a string Columns x Rows like for example \"3x2\"." (beginning-of-line 1) (newline)) ;; (mapcar (lambda (x) (insert line)) (make-list rows t)) - (dotimes (i rows) (insert line)) + (dotimes (_ rows) (insert line)) (goto-char pos) (if (> rows 1) ;; Insert a hline after the first row. @@ -539,15 +563,18 @@ SIZE is a string Columns x Rows like for example \"3x2\"." ;;;###autoload (defun org-table-convert-region (beg0 end0 &optional separator) "Convert region to a table. + The region goes from BEG0 to END0, but these borders will be moved slightly, to make sure a beginning of line in the first line is included. SEPARATOR specifies the field separator in the lines. It can have the following values: -(4) Use the comma as a field separator -(16) Use a TAB as field separator -integer When a number, use that many spaces as field separator +(4) Use the comma as a field separator +(16) Use a TAB as field separator +(64) Prompt for a regular expression as field separator +integer When a number, use that many spaces, or a TAB, as field separator +regexp When a regular expression, use it to match the separator nil When nil, the command tries to be smart and figure out the separator in the following way: - when each line contains a TAB, assume TAB-separated material @@ -557,45 +584,52 @@ nil When nil, the command tries to be smart and figure out the (let* ((beg (min beg0 end0)) (end (max beg0 end0)) re) - (goto-char beg) - (beginning-of-line 1) - (setq beg (point-marker)) - (goto-char end) - (if (bolp) (backward-char 1) (end-of-line 1)) - (setq end (point-marker)) - ;; Get the right field separator - (unless separator + (if (> (count-lines beg end) org-table-convert-region-max-lines) + (user-error "Region is longer than `org-table-convert-region-max-lines' (%s) lines; not converting" + org-table-convert-region-max-lines) + (if (equal separator '(64)) + (setq separator (read-regexp "Regexp for field separator"))) (goto-char beg) - (setq separator + (beginning-of-line 1) + (setq beg (point-marker)) + (goto-char end) + (if (bolp) (backward-char 1) (end-of-line 1)) + (setq end (point-marker)) + ;; Get the right field separator + (unless separator + (goto-char beg) + (setq separator + (cond + ((not (re-search-forward "^[^\n\t]+$" end t)) '(16)) + ((not (re-search-forward "^[^\n,]+$" end t)) '(4)) + (t 1)))) + (goto-char beg) + (if (equal separator '(4)) + (while (< (point) end) + ;; parse the csv stuff (cond - ((not (re-search-forward "^[^\n\t]+$" end t)) '(16)) - ((not (re-search-forward "^[^\n,]+$" end t)) '(4)) - (t 1)))) - (goto-char beg) - (if (equal separator '(4)) - (while (< (point) end) - ;; parse the csv stuff - (cond - ((looking-at "^") (insert "| ")) - ((looking-at "[ \t]*$") (replace-match " |") (beginning-of-line 2)) - ((looking-at "[ \t]*\"\\([^\"\n]*\\)\"") - (replace-match "\\1") - (if (looking-at "\"") (insert "\""))) - ((looking-at "[^,\n]+") (goto-char (match-end 0))) - ((looking-at "[ \t]*,") (replace-match " | ")) - (t (beginning-of-line 2)))) - (setq re (cond - ((equal separator '(4)) "^\\|\"?[ \t]*,[ \t]*\"?") - ((equal separator '(16)) "^\\|\t") - ((integerp separator) - (if (< separator 1) - (user-error "Number of spaces in separator must be >= 1") - (format "^ *\\| *\t *\\| \\{%d,\\}" separator))) - (t (error "This should not happen")))) - (while (re-search-forward re end t) - (replace-match "| " t t))) - (goto-char beg) - (org-table-align))) + ((looking-at "^") (insert "| ")) + ((looking-at "[ \t]*$") (replace-match " |") (beginning-of-line 2)) + ((looking-at "[ \t]*\"\\([^\"\n]*\\)\"") + (replace-match "\\1") + (if (looking-at "\"") (insert "\""))) + ((looking-at "[^,\n]+") (goto-char (match-end 0))) + ((looking-at "[ \t]*,") (replace-match " | ")) + (t (beginning-of-line 2)))) + (setq re (cond + ((equal separator '(4)) "^\\|\"?[ \t]*,[ \t]*\"?") + ((equal separator '(16)) "^\\|\t") + ((integerp separator) + (if (< separator 1) + (user-error "Number of spaces in separator must be >= 1") + (format "^ *\\| *\t *\\| \\{%d,\\}" separator))) + ((stringp separator) + (format "^ *\\|%s" separator)) + (t (error "This should not happen")))) + (while (re-search-forward re end t) + (replace-match "| " t t))) + (goto-char beg) + (org-table-align)))) ;;;###autoload (defun org-table-import (file arg) @@ -611,8 +645,6 @@ are found, lines will be split on whitespace into fields." (org-table-convert-region beg (+ (point) (- (point-max) pm)) arg))) -(defvar org-table-last-alignment) -(defvar org-table-last-column-widths) ;;;###autoload (defun org-table-export (&optional file format) "Export table to a file, with configurable format. @@ -630,77 +662,61 @@ extension of the given file name, and finally on the variable `org-table-export-default-format'." (interactive) (unless (org-at-table-p) (user-error "No table at point")) - (org-table-align) ;; make sure we have everything we need - (let* ((beg (org-table-begin)) - (end (org-table-end)) - (txt (buffer-substring-no-properties beg end)) - (file (or file (org-entry-get beg "TABLE_EXPORT_FILE" t))) - (formats '("orgtbl-to-tsv" "orgtbl-to-csv" - "orgtbl-to-latex" "orgtbl-to-html" - "orgtbl-to-generic" "orgtbl-to-texinfo" - "orgtbl-to-orgtbl")) - (format (or format - (org-entry-get beg "TABLE_EXPORT_FORMAT" t))) - buf deffmt-readable fileext) + (org-table-align) ; Make sure we have everything we need. + (let ((file (or file (org-entry-get (point) "TABLE_EXPORT_FILE" t)))) (unless file (setq file (read-file-name "Export table to: ")) (unless (or (not (file-exists-p file)) (y-or-n-p (format "Overwrite file %s? " file))) (user-error "File not written"))) - (if (file-directory-p file) - (user-error "This is a directory path, not a file")) - (if (and (buffer-file-name) - (equal (file-truename file) - (file-truename (buffer-file-name)))) - (user-error "Please specify a file name that is different from current")) - (setq fileext (concat (file-name-extension file) "$")) - (unless format - (setq deffmt-readable - (or (car (delq nil (mapcar (lambda(f) (if (string-match fileext f) f)) formats))) - org-table-export-default-format)) - (while (string-match "\t" deffmt-readable) - (setq deffmt-readable (replace-match "\\t" t t deffmt-readable))) - (while (string-match "\n" deffmt-readable) - (setq deffmt-readable (replace-match "\\n" t t deffmt-readable))) - (setq format (org-completing-read "Format: " formats nil nil deffmt-readable))) - (if (string-match "\\([^ \t\r\n]+\\)\\( +.*\\)?" format) - (let* ((transform (intern (match-string 1 format))) - (params (if (match-end 2) - (read (concat "(" (match-string 2 format) ")")))) - (skip (plist-get params :skip)) - (skipcols (plist-get params :skipcols)) - (lines (nthcdr (or skip 0) (org-split-string txt "[ \t]*\n[ \t]*"))) - (lines (org-table-clean-before-export lines)) - (i0 (if org-table-clean-did-remove-column 2 1)) - (table (mapcar - (lambda (x) - (if (string-match org-table-hline-regexp x) - 'hline - (org-remove-by-index - (org-split-string (org-trim x) "\\s-*|\\s-*") - skipcols i0))) - lines)) - (fun (if (= i0 2) 'cdr 'identity)) - (org-table-last-alignment - (org-remove-by-index (funcall fun org-table-last-alignment) - skipcols i0)) - (org-table-last-column-widths - (org-remove-by-index (funcall fun org-table-last-column-widths) - skipcols i0))) - - (unless (fboundp transform) - (user-error "No such transformation function %s" transform)) - (setq txt (funcall transform table params)) - - (with-current-buffer (find-file-noselect file) - (setq buf (current-buffer)) - (erase-buffer) - (fundamental-mode) - (insert txt "\n") - (save-buffer)) - (kill-buffer buf) - (message "Export done.")) - (user-error "TABLE_EXPORT_FORMAT invalid")))) + (when (file-directory-p file) + (user-error "This is a directory path, not a file")) + (when (and (buffer-file-name (buffer-base-buffer)) + (file-equal-p + (file-truename file) + (file-truename (buffer-file-name (buffer-base-buffer))))) + (user-error "Please specify a file name that is different from current")) + (let ((fileext (concat (file-name-extension file) "$")) + (format (or format (org-entry-get (point) "TABLE_EXPORT_FORMAT" t)))) + (unless format + (let* ((formats '("orgtbl-to-tsv" "orgtbl-to-csv" "orgtbl-to-latex" + "orgtbl-to-html" "orgtbl-to-generic" + "orgtbl-to-texinfo" "orgtbl-to-orgtbl" + "orgtbl-to-unicode")) + (deffmt-readable + (replace-regexp-in-string + "\t" "\\t" + (replace-regexp-in-string + "\n" "\\n" + (or (car (delq nil + (mapcar + (lambda (f) + (and (string-match-p fileext f) f)) + formats))) + org-table-export-default-format) + t t) t t))) + (setq format + (org-completing-read + "Format: " formats nil nil deffmt-readable)))) + (if (string-match "\\([^ \t\r\n]+\\)\\( +.*\\)?" format) + (let ((transform (intern (match-string 1 format))) + (params (and (match-end 2) + (read (concat "(" (match-string 2 format) ")")))) + (table (org-table-to-lisp + (buffer-substring-no-properties + (org-table-begin) (org-table-end))))) + (unless (fboundp transform) + (user-error "No such transformation function %s" transform)) + (let (buf) + (with-current-buffer (find-file-noselect file) + (setq buf (current-buffer)) + (erase-buffer) + (fundamental-mode) + (insert (funcall transform table params) "\n") + (save-buffer)) + (kill-buffer buf)) + (message "Export done.")) + (user-error "TABLE_EXPORT_FORMAT invalid"))))) (defvar org-table-aligned-begin-marker (make-marker) "Marker at the beginning of the table last aligned. @@ -714,13 +730,11 @@ This is being used to correctly align a single field after TAB or RET.") (defvar org-table-last-column-widths nil "List of max width of fields in each column. This is being used to correctly align a single field after TAB or RET.") -(defvar org-table-formula-debug nil +(defvar-local org-table-formula-debug nil "Non-nil means debug table formulas. When nil, simply write \"#ERROR\" in corrupted fields.") -(make-variable-buffer-local 'org-table-formula-debug) -(defvar org-table-overlay-coordinates nil +(defvar-local org-table-overlay-coordinates nil "Overlay coordinates after each align of a table.") -(make-variable-buffer-local 'org-table-overlay-coordinates) (defvar org-last-recalc-line nil) (defvar org-table-do-narrow t) ; for dynamic scoping @@ -731,216 +745,198 @@ When nil, simply write \"#ERROR\" in corrupted fields.") (defun org-table-align () "Align the table at point by aligning all vertical bars." (interactive) - (let* ( - ;; Limits of table - (beg (org-table-begin)) - (end (org-table-end)) - ;; Current cursor position - (linepos (org-current-line)) - (colpos (org-table-current-column)) - (winstart (window-start)) - (winstartline (org-current-line (min winstart (1- (point-max))))) - lines (new "") lengths l typenums ty fields maxfields i - column - (indent "") cnt frac - rfmt hfmt - (spaces '(1 . 1)) - (sp1 (car spaces)) - (sp2 (cdr spaces)) - (rfmt1 (concat - (make-string sp2 ?\ ) "%%%s%ds" (make-string sp1 ?\ ) "|")) - (hfmt1 (concat - (make-string sp2 ?-) "%s" (make-string sp1 ?-) "+")) - emptystrings links dates emph raise narrow - falign falign1 fmax f1 len c e space) - (untabify beg end) - (remove-text-properties beg end '(org-cwidth t org-dwidth t display t)) - ;; Check if we have links or dates - (goto-char beg) - (setq links (re-search-forward org-bracket-link-regexp end t)) - (goto-char beg) - (setq emph (and org-hide-emphasis-markers - (re-search-forward org-emph-re end t))) - (goto-char beg) - (setq raise (and org-use-sub-superscripts - (re-search-forward org-match-substring-regexp end t))) - (goto-char beg) - (setq dates (and org-display-custom-times - (re-search-forward org-ts-regexp-both end t))) - ;; Make sure the link properties are right - (when links (goto-char beg) (while (org-activate-bracket-links end))) - ;; Make sure the date properties are right - (when dates (goto-char beg) (while (org-activate-dates end))) - (when emph (goto-char beg) (while (org-do-emphasis-faces end))) - (when raise (goto-char beg) (while (org-raise-scripts end))) - - ;; Check if we are narrowing any columns - (goto-char beg) - (setq narrow (and org-table-do-narrow - org-format-transports-properties-p - (re-search-forward "<[lrc]?[0-9]+>" end t))) - (goto-char beg) - (setq falign (re-search-forward "<[lrc][0-9]*>" end t)) - (goto-char beg) - ;; Get the rows - (setq lines (org-split-string - (buffer-substring beg end) "\n")) - ;; Store the indentation of the first line - (if (string-match "^ *" (car lines)) - (setq indent (make-string (- (match-end 0) (match-beginning 0)) ?\ ))) - ;; Mark the hlines by setting the corresponding element to nil - ;; At the same time, we remove trailing space. - (setq lines (mapcar (lambda (l) - (if (string-match "^ *|-" l) - nil - (if (string-match "[ \t]+$" l) - (substring l 0 (match-beginning 0)) - l))) - lines)) - ;; Get the data fields by splitting the lines. - (setq fields (mapcar - (lambda (l) - (org-split-string l " *| *")) - (delq nil (copy-sequence lines)))) - ;; How many fields in the longest line? - (condition-case nil - (setq maxfields (apply 'max (mapcar 'length fields))) - (error - (kill-region beg end) - (org-table-create org-table-default-size) - (user-error "Empty table - created default table"))) - ;; A list of empty strings to fill any short rows on output - (setq emptystrings (make-list maxfields "")) - ;; Check for special formatting. - (setq i -1) - (while (< (setq i (1+ i)) maxfields) ;; Loop over all columns - (setq column (mapcar (lambda (x) (or (nth i x) "")) fields)) - ;; Check if there is an explicit width specified - (setq fmax nil) - (when (or narrow falign) - (setq c column fmax nil falign1 nil) - (while c - (setq e (pop c)) - (when (and (stringp e) (string-match "^<\\([lrc]\\)?\\([0-9]+\\)?>$" e)) - (if (match-end 1) (setq falign1 (match-string 1 e))) - (if (and org-table-do-narrow (match-end 2)) - (setq fmax (string-to-number (match-string 2 e)) c nil)))) - ;; Find fields that are wider than fmax, and shorten them - (when fmax - (loop for xx in column do - (when (and (stringp xx) - (> (org-string-width xx) fmax)) - (org-add-props xx nil - 'help-echo - (concat "Clipped table field, use C-c ` to edit. Full value is:\n" (org-no-properties (copy-sequence xx)))) - (setq f1 (min fmax (or (string-match org-bracket-link-regexp xx) fmax))) - (unless (> f1 1) - (user-error "Cannot narrow field starting with wide link \"%s\"" - (match-string 0 xx))) - (add-text-properties f1 (length xx) (list 'org-cwidth t) xx) - (add-text-properties (- f1 2) f1 - (list 'display org-narrow-column-arrow) - xx))))) - ;; Get the maximum width for each column - (push (apply 'max (or fmax 1) 1 (mapcar 'org-string-width column)) - lengths) - ;; Get the fraction of numbers, to decide about alignment of the column - (if falign1 - (push (equal (downcase falign1) "r") typenums) - (setq cnt 0 frac 0.0) - (loop for x in column do - (if (equal x "") - nil - (setq frac ( / (+ (* frac cnt) - (if (string-match org-table-number-regexp x) 1 0)) - (setq cnt (1+ cnt)))))) - (push (>= frac org-table-number-fraction) typenums))) - (setq lengths (nreverse lengths) typenums (nreverse typenums)) - - ;; Store the alignment of this table, for later editing of single fields - (setq org-table-last-alignment typenums - org-table-last-column-widths lengths) - - ;; With invisible characters, `format' does not get the field width right - ;; So we need to make these fields wide by hand. - (when (or links emph raise) - (loop for i from 0 upto (1- maxfields) do - (setq len (nth i lengths)) - (loop for j from 0 upto (1- (length fields)) do - (setq c (nthcdr i (car (nthcdr j fields)))) - (if (and (stringp (car c)) - (or (text-property-any 0 (length (car c)) - 'invisible 'org-link (car c)) - (text-property-any 0 (length (car c)) - 'org-dwidth t (car c))) - (< (org-string-width (car c)) len)) - (progn - (setq space (make-string (- len (org-string-width (car c))) ?\ )) - (setcar c (if (nth i typenums) - (concat space (car c)) - (concat (car c) space)))))))) - - ;; Compute the formats needed for output of the table - (setq rfmt (concat indent "|") hfmt (concat indent "|")) - (while (setq l (pop lengths)) - (setq ty (if (pop typenums) "" "-")) ; number types flushright - (setq rfmt (concat rfmt (format rfmt1 ty l)) - hfmt (concat hfmt (format hfmt1 (make-string l ?-))))) - (setq rfmt (concat rfmt "\n") - hfmt (concat (substring hfmt 0 -1) "|\n")) - - (setq new (mapconcat - (lambda (l) - (if l (apply 'format rfmt - (append (pop fields) emptystrings)) - hfmt)) - lines "")) - (move-marker org-table-aligned-begin-marker (point)) - (insert new) - ;; Replace the old one - (delete-region (point) end) - (move-marker end nil) - (move-marker org-table-aligned-end-marker (point)) - (when (and orgtbl-mode (not (derived-mode-p 'org-mode))) - (goto-char org-table-aligned-begin-marker) - (while (org-hide-wide-columns org-table-aligned-end-marker))) - ;; Try to move to the old location - (org-goto-line winstartline) - (setq winstart (point-at-bol)) - (org-goto-line linepos) - (when (eq (window-buffer (selected-window)) (current-buffer)) - (set-window-start (selected-window) winstart 'noforce)) - (org-table-goto-column colpos) - (and org-table-overlay-coordinates (org-table-overlay-coordinates)) - (setq org-table-may-need-update nil) - )) + (let* ((beg (org-table-begin)) + (end (copy-marker (org-table-end)))) + (org-table-save-field + ;; Make sure invisible characters in the table are at the right + ;; place since column widths take them into account. + (font-lock-fontify-region beg end) + (move-marker org-table-aligned-begin-marker beg) + (move-marker org-table-aligned-end-marker end) + (goto-char beg) + (let* ((indent (progn (looking-at "[ \t]*") (match-string 0))) + ;; Table's rows. Separators are replaced by nil. Trailing + ;; spaces are also removed. + (lines (mapcar (lambda (l) + (and (not (string-match-p "\\`[ \t]*|-" l)) + (let ((l (org-trim l))) + (remove-text-properties + 0 (length l) '(display t org-cwidth t) l) + l))) + (org-split-string (buffer-substring beg end) "\n"))) + ;; Get the data fields by splitting the lines. + (fields (mapcar (lambda (l) (org-split-string l " *| *")) + (remq nil lines))) + ;; Compute number of fields in the longest line. If the + ;; table contains no field, create a default table. + (maxfields (if fields (apply #'max (mapcar #'length fields)) + (kill-region beg end) + (org-table-create org-table-default-size) + (user-error "Empty table - created default table"))) + ;; A list of empty strings to fill any short rows on output. + (emptycells (make-list maxfields "")) + lengths typenums) + ;; Check for special formatting. + (dotimes (i maxfields) + (let ((column (mapcar (lambda (x) (or (nth i x) "")) fields)) + fmax falign) + ;; Look for an explicit width or alignment. + (when (save-excursion + (or (re-search-forward "| *<[lrc][0-9]*> *\\(|\\|$\\)" end t) + (and org-table-do-narrow + (re-search-forward + "| *<[lrc]?[0-9]+> *\\(|\\|$\\)" end t)))) + (catch :exit + (dolist (cell column) + (when (string-match "\\`<\\([lrc]\\)?\\([0-9]+\\)?>\\'" cell) + (when (match-end 1) (setq falign (match-string 1 cell))) + (when (and org-table-do-narrow (match-end 2)) + (setq fmax (string-to-number (match-string 2 cell)))) + (when (or falign fmax) (throw :exit nil))))) + ;; Find fields that are wider than FMAX, and shorten them. + (when fmax + (dolist (x column) + (when (> (org-string-width x) fmax) + (org-add-props x nil + 'help-echo + (concat + "Clipped table field, use `\\[org-table-edit-field]' to \ +edit. Full value is:\n" + (substring-no-properties x))) + (let ((l (length x)) + (f1 (min fmax + (or (string-match org-bracket-link-regexp x) + fmax))) + (f2 1)) + (unless (> f1 1) + (user-error + "Cannot narrow field starting with wide link \"%s\"" + (match-string 0 x))) + (if (= (org-string-width x) l) (setq f2 f1) + (setq f2 1) + (while (< (org-string-width (substring x 0 f2)) f1) + (cl-incf f2))) + (add-text-properties f2 l (list 'org-cwidth t) x) + (add-text-properties + (if (>= (string-width (substring x (1- f2) f2)) 2) (1- f2) + (- f2 2)) + f2 + (list 'display org-narrow-column-arrow) + x)))))) + ;; Get the maximum width for each column + (push (apply #'max (or fmax 1) 1 (mapcar #'org-string-width column)) + lengths) + ;; Get the fraction of numbers among non-empty cells to + ;; decide about alignment of the column. + (if falign (push (equal (downcase falign) "r") typenums) + (let ((cnt 0) + (frac 0.0)) + (dolist (x column) + (unless (equal x "") + (setq frac + (/ (+ (* frac cnt) + (if (string-match-p org-table-number-regexp x) + 1 + 0)) + (cl-incf cnt))))) + (push (>= frac org-table-number-fraction) typenums))))) + (setq lengths (nreverse lengths)) + (setq typenums (nreverse typenums)) + ;; Store alignment of this table, for later editing of single + ;; fields. + (setq org-table-last-alignment typenums) + (setq org-table-last-column-widths lengths) + ;; With invisible characters, `format' does not get the field + ;; width right So we need to make these fields wide by hand. + ;; Invisible characters may be introduced by fontified links, + ;; emphasis, macros or sub/superscripts. + (when (or (text-property-any beg end 'invisible 'org-link) + (text-property-any beg end 'invisible t)) + (dotimes (i maxfields) + (let ((len (nth i lengths))) + (dotimes (j (length fields)) + (let* ((c (nthcdr i (nth j fields))) + (cell (car c))) + (when (and + (stringp cell) + (let ((l (length cell))) + (or (text-property-any 0 l 'invisible 'org-link cell) + (text-property-any beg end 'invisible t))) + (< (org-string-width cell) len)) + (let ((s (make-string (- len (org-string-width cell)) ?\s))) + (setcar c (if (nth i typenums) (concat s cell) + (concat cell s)))))))))) + + ;; Compute the formats needed for output of the table. + (let ((hfmt (concat indent "|")) + (rfmt (concat indent "|")) + (rfmt1 " %%%s%ds |") + (hfmt1 "-%s-+")) + (dolist (l lengths (setq hfmt (concat (substring hfmt 0 -1) "|"))) + (let ((ty (if (pop typenums) "" "-"))) ; Flush numbers right. + (setq rfmt (concat rfmt (format rfmt1 ty l))) + (setq hfmt (concat hfmt (format hfmt1 (make-string l ?-)))))) + ;; Replace modified lines only. Check not only contents, but + ;; also columns' width. + (dolist (l lines) + (let ((line + (if l (apply #'format rfmt (append (pop fields) emptycells)) + hfmt)) + (previous (buffer-substring (point) (line-end-position)))) + (if (and (equal previous line) + (let ((a 0) + (b 0)) + (while (and (progn + (setq a (next-single-property-change + a 'org-cwidth previous)) + (setq b (next-single-property-change + b 'org-cwidth line))) + (eq a b))) + (eq a b))) + (forward-line) + (insert line "\n") + (delete-region (point) (line-beginning-position 2)))))) + (when (and orgtbl-mode (not (derived-mode-p 'org-mode))) + (goto-char org-table-aligned-begin-marker) + (while (org-hide-wide-columns org-table-aligned-end-marker))) + (set-marker end nil) + (when org-table-overlay-coordinates (org-table-overlay-coordinates)) + (setq org-table-may-need-update nil))))) ;;;###autoload (defun org-table-begin (&optional table-type) "Find the beginning of the table and return its position. -With argument TABLE-TYPE, go to the beginning of a table.el-type table." - (save-excursion - (if (not (re-search-backward - (if table-type org-table-any-border-regexp - org-table-border-regexp) - nil t)) - (progn (goto-char (point-min)) (point)) - (goto-char (match-beginning 0)) - (beginning-of-line 2) - (point)))) +With a non-nil optional argument TABLE-TYPE, return the beginning +of a table.el-type table. This function assumes point is on +a table." + (cond (table-type + (org-element-property :post-affiliated (org-element-at-point))) + ((save-excursion + (and (re-search-backward org-table-border-regexp nil t) + (line-beginning-position 2)))) + (t (point-min)))) ;;;###autoload (defun org-table-end (&optional table-type) "Find the end of the table and return its position. -With argument TABLE-TYPE, go to the end of a table.el-type table." +With a non-nil optional argument TABLE-TYPE, return the end of +a table.el-type table. This function assumes point is on +a table." (save-excursion - (if (not (re-search-forward - (if table-type org-table-any-border-regexp - org-table-border-regexp) - nil t)) - (goto-char (point-max)) - (goto-char (match-beginning 0))) - (point-marker))) + (cond (table-type + (goto-char (org-element-property :end (org-element-at-point))) + (skip-chars-backward " \t\n") + (line-beginning-position 2)) + ((re-search-forward org-table-border-regexp nil t) + (match-beginning 0)) + ;; When the line right after the table is the last line in + ;; the buffer with trailing spaces but no final newline + ;; character, be sure to catch the correct ending at its + ;; beginning. In any other case, ending is expected to be + ;; at point max. + (t (goto-char (point-max)) + (skip-chars-backward " \t") + (if (bolp) (point) (line-end-position)))))) ;;;###autoload (defun org-table-justify-field-maybe (&optional new) @@ -950,38 +946,40 @@ Optional argument NEW may specify text to replace the current field content." ((and (not new) org-table-may-need-update)) ; Realignment will happen anyway ((org-at-table-hline-p)) ((and (not new) - (or (not (equal (marker-buffer org-table-aligned-begin-marker) - (current-buffer))) + (or (not (eq (marker-buffer org-table-aligned-begin-marker) + (current-buffer))) (< (point) org-table-aligned-begin-marker) (>= (point) org-table-aligned-end-marker))) - ;; This is not the same table, force a full re-align + ;; This is not the same table, force a full re-align. (setq org-table-may-need-update t)) - (t ;; realign the current field, based on previous full realign - (let* ((pos (point)) s - (col (org-table-current-column)) - (num (if (> col 0) (nth (1- col) org-table-last-alignment))) - l f n o e) + (t + ;; Realign the current field, based on previous full realign. + (let ((pos (point)) + (col (org-table-current-column))) (when (> col 0) - (skip-chars-backward "^|\n") - (if (looking-at " *\\([^|\n]*?\\) *\\(|\\|$\\)") - (progn - (setq s (match-string 1) - o (match-string 0) - l (max 1 (- (match-end 0) (match-beginning 0) 3)) - e (not (= (match-beginning 2) (match-end 2)))) - (setq f (format (if num " %%%ds %s" " %%-%ds %s") - l (if e "|" (setq org-table-may-need-update t) "")) - n (format f s)) - (if new - (if (<= (length new) l) ;; FIXME: length -> str-width? - (setq n (format f new)) - (setq n (concat new "|") org-table-may-need-update t))) - (if (equal (string-to-char n) ?-) (setq n (concat " " n))) - (or (equal n o) - (let (org-table-may-need-update) - (replace-match n t t)))) - (setq org-table-may-need-update t)) - (goto-char pos)))))) + (skip-chars-backward "^|") + (if (not (looking-at " *\\([^|\n]*?\\) *\\(|\\|$\\)")) + (setq org-table-may-need-update t) + (let* ((numbers? (nth (1- col) org-table-last-alignment)) + (cell (match-string 0)) + (field (match-string 1)) + (len (max 1 (- (org-string-width cell) 3))) + (properly-closed? (/= (match-beginning 2) (match-end 2))) + (fmt (format (if numbers? " %%%ds %s" " %%-%ds %s") + len + (if properly-closed? "|" + (setq org-table-may-need-update t) + ""))) + (new-cell + (cond ((not new) (format fmt field)) + ((<= (org-string-width new) len) (format fmt new)) + (t + (setq org-table-may-need-update t) + (format " %s |" new))))) + (unless (equal new-cell cell) + (let (org-table-may-need-update) + (replace-match new-cell t t))) + (goto-char pos)))))))) ;;;###autoload (defun org-table-next-field () @@ -1036,9 +1034,10 @@ Before doing so, re-align the table if necessary." (goto-char (match-end 0)))) (defun org-table-beginning-of-field (&optional n) - "Move to the end of the current table field. -If already at or after the end, move to the end of the next table field. -With numeric argument N, move N-1 fields forward first." + "Move to the beginning of the current table field. +If already at or before the beginning, move to the beginning of the +previous field. +With numeric argument N, move N-1 fields backward first." (interactive "p") (let ((pos (point))) (while (> n 1) @@ -1051,10 +1050,9 @@ With numeric argument N, move N-1 fields forward first." (if (>= (point) pos) (org-table-beginning-of-field 2)))) (defun org-table-end-of-field (&optional n) - "Move to the beginning of the current table field. -If already at or before the beginning, move to the beginning of the -previous field. -With numeric argument N, move N-1 fields backward first." + "Move to the end of the current table field. +If already at or after the end, move to the end of the next table field. +With numeric argument N, move N-1 fields forward first." (interactive "p") (let ((pos (point))) (while (> n 1) @@ -1093,30 +1091,36 @@ Before doing so, re-align the table if necessary." ;;;###autoload (defun org-table-copy-down (n) - "Copy a field down in the current column. -If the field at the cursor is empty, copy into it the content of -the nearest non-empty field above. With argument N, use the Nth -non-empty field. If the current field is not empty, it is copied -down to the next row, and the cursor is moved with it. -Therefore, repeating this command causes the column to be filled -row-by-row. + "Copy the value of the current field one row below. + +If the field at the cursor is empty, copy the content of the +nearest non-empty field above. With argument N, use the Nth +non-empty field. + +If the current field is not empty, it is copied down to the next +row, and the cursor is moved with it. Therefore, repeating this +command causes the column to be filled row-by-row. + If the variable `org-table-copy-increment' is non-nil and the field is an integer or a timestamp, it will be incremented while -copying. In the case of a timestamp, increment by one day." +copying. By default, increment by the difference between the +value in the current field and the one in the field above. To +increment using a fixed integer, set `org-table-copy-increment' +to a number. In the case of a timestamp, increment by days." (interactive "p") (let* ((colpos (org-table-current-column)) (col (current-column)) (field (save-excursion (org-table-get-field))) + (field-up (or (save-excursion + (org-table-get (1- (org-table-current-line)) + (org-table-current-column))) "")) (non-empty (string-match "[^ \t]" field)) + (non-empty-up (string-match "[^ \t]" field-up)) (beg (org-table-begin)) (orig-n n) - txt) + txt txt-up inc) (org-table-check-inside-data-field) - (if non-empty - (progn - (setq txt (org-trim field)) - (org-table-next-row) - (org-table-blank-field)) + (if (not non-empty) (save-excursion (setq txt (catch 'exit @@ -1127,35 +1131,60 @@ copying. In the case of a timestamp, increment by one day." (if (and (looking-at "|[ \t]*\\([^| \t][^|]*?\\)[ \t]*|") (<= (setq n (1- n)) 0)) - (throw 'exit (match-string 1)))))))) - (if txt - (progn - (if (and org-table-copy-increment - (not (equal orig-n 0)) - (string-match "^[0-9]+$" txt) - (< (string-to-number txt) 100000000)) - (setq txt (format "%d" (+ (string-to-number txt) 1)))) - (insert txt) - (org-move-to-column col) - (if (and org-table-copy-increment (org-at-timestamp-p t)) - (org-timestamp-up-day) - (org-table-maybe-recalculate-line)) - (org-table-align) - (org-move-to-column col)) - (user-error "No non-empty field found")))) + (throw 'exit (match-string 1)))))) + (setq field-up + (catch 'exit + (while (progn (beginning-of-line 1) + (re-search-backward org-table-dataline-regexp + beg t)) + (org-table-goto-column colpos t) + (if (and (looking-at + "|[ \t]*\\([^| \t][^|]*?\\)[ \t]*|") + (<= (setq n (1- n)) 0)) + (throw 'exit (match-string 1)))))) + (setq non-empty-up (and field-up (string-match "[^ \t]" field-up)))) + ;; Above field was not empty, go down to the next row + (setq txt (org-trim field)) + (org-table-next-row) + (org-table-blank-field)) + (if non-empty-up (setq txt-up (org-trim field-up))) + (setq inc (cond + ((numberp org-table-copy-increment) org-table-copy-increment) + (txt-up (cond ((and (string-match org-ts-regexp3 txt-up) + (string-match org-ts-regexp3 txt)) + (- (org-time-string-to-absolute txt) + (org-time-string-to-absolute txt-up))) + ((string-match org-ts-regexp3 txt) 1) + ((string-match "\\([-+]\\)?[0-9]+\\(?:\.[0-9]+\\)?" txt-up) + (- (string-to-number txt) + (string-to-number (match-string 0 txt-up)))) + (t 1))) + (t 1))) + (if (not txt) + (user-error "No non-empty field found") + (if (and org-table-copy-increment + (not (equal orig-n 0)) + (string-match-p "^[-+^/*0-9eE.]+$" txt) + (< (string-to-number txt) 100000000)) + (setq txt (calc-eval (concat txt "+" (number-to-string inc))))) + (insert txt) + (org-move-to-column col) + (if (and org-table-copy-increment (org-at-timestamp-p t)) + (org-timestamp-up-day inc) + (org-table-maybe-recalculate-line)) + (org-table-align) + (org-move-to-column col)))) (defun org-table-check-inside-data-field (&optional noerror) "Is point inside a table data field? I.e. not on a hline or before the first or after the last column? This actually throws an error, so it aborts the current command." - (if (or (not (org-at-table-p)) - (= (org-table-current-column) 0) - (org-at-table-hline-p) - (looking-at "[ \t]*$")) - (if noerror - nil - (user-error "Not in table data field")) - t)) + (cond ((and (org-at-table-p) + (not (save-excursion (skip-chars-backward " \t") (bolp))) + (not (org-at-table-hline-p)) + (not (looking-at "[ \t]*$")))) + (noerror nil) + (t (user-error "Not in table data field")))) (defvar org-table-clip nil "Clipboard for table regions.") @@ -1166,7 +1195,7 @@ If LINE is larger than the number of data lines in the table, the function returns nil. However, if COLUMN is too large, we will simply return an empty string. If LINE is nil, use the current line. -If column is nil, use the current column." +If COLUMN is nil, use the current column." (setq column (or column (org-table-current-column))) (save-excursion (and (or (not line) (org-table-goto-line line)) @@ -1206,7 +1235,7 @@ Return t when the line exists, nil if it does not exist." "Blank the current table field or active region." (interactive) (org-table-check-inside-data-field) - (if (and (org-called-interactively-p 'any) (org-region-active-p)) + (if (and (called-interactively-p 'any) (org-region-active-p)) (let (org-table-clip) (org-table-cut-region (region-beginning) (region-end))) (skip-chars-backward "^|") @@ -1221,52 +1250,53 @@ Return t when the line exists, nil if it does not exist." (defun org-table-get-field (&optional n replace) "Return the value of the field in column N of current row. -N defaults to current field. -If REPLACE is a string, replace field with this value. The return value -is always the old value." - (and n (org-table-goto-column n)) +N defaults to current column. If REPLACE is a string, replace +field with this value. The return value is always the old +value." + (when n (org-table-goto-column n)) (skip-chars-backward "^|\n") - (backward-char 1) - (if (looking-at "|[^|\r\n]*") - (let* ((pos (match-beginning 0)) - (val (buffer-substring (1+ pos) (match-end 0)))) - (if replace - (replace-match (concat "|" (if (equal replace "") " " replace)) - t t)) - (goto-char (min (point-at-eol) (+ 2 pos))) - val) - (forward-char 1) "")) + (if (or (bolp) (looking-at-p "[ \t]*$")) + ;; Before first column or after last one. + "" + (looking-at "[^|\r\n]*") + (let* ((pos (match-beginning 0)) + (val (buffer-substring pos (match-end 0)))) + (when replace + (replace-match (if (equal replace "") " " replace) t t)) + (goto-char (min (line-end-position) (1+ pos))) + val))) ;;;###autoload -(defun org-table-field-info (arg) +(defun org-table-field-info (_arg) "Show info about the current field, and highlight any reference at point." (interactive "P") (unless (org-at-table-p) (user-error "Not at a table")) - (org-table-get-specials) + (org-table-analyze) (save-excursion (let* ((pos (point)) (col (org-table-current-column)) (cname (car (rassoc (int-to-string col) org-table-column-names))) - (name (car (rassoc (list (org-current-line) col) + (name (car (rassoc (list (count-lines org-table-current-begin-pos + (line-beginning-position)) + col) org-table-named-field-locations))) (eql (org-table-expand-lhs-ranges (mapcar (lambda (e) - (cons (org-table-formula-handle-first/last-rc - (car e)) (cdr e))) + (cons (org-table-formula-handle-first/last-rc (car e)) + (cdr e))) (org-table-get-stored-formulas)))) (dline (org-table-current-dline)) (ref (format "@%d$%d" dline col)) (ref1 (org-table-convert-refs-to-an ref)) + ;; Prioritize field formulas over column formulas. (fequation (or (assoc name eql) (assoc ref eql))) - (cequation (assoc (int-to-string col) eql)) + (cequation (assoc (format "$%d" col) eql)) (eqn (or fequation cequation))) - (if (and eqn (get-text-property 0 :orig-eqn (car eqn))) - (setq eqn (get-text-property 0 :orig-eqn (car eqn)))) + (let ((p (and eqn (get-text-property 0 :orig-eqn (car eqn))))) + (when p (setq eqn p))) (goto-char pos) - (condition-case nil - (org-table-show-reference 'local) - (error nil)) + (ignore-errors (org-table-show-reference 'local)) (message "line @%d, col $%s%s, ref @%d$%d or %s%s%s" dline col (if cname (concat " or $" cname) "") @@ -1277,39 +1307,42 @@ is always the old value." (concat ", formula: " (org-table-formula-to-user (concat - (if (string-match "^[$@]"(car eqn)) "" "$") + (if (or (string-prefix-p "$" (car eqn)) + (string-prefix-p "@" (car eqn))) + "" + "$") (car eqn) "=" (cdr eqn)))) ""))))) (defun org-table-current-column () "Find out which column we are in." (interactive) - (if (org-called-interactively-p 'any) (org-table-check-inside-data-field)) + (when (called-interactively-p 'any) (org-table-check-inside-data-field)) (save-excursion - (let ((cnt 0) (pos (point))) - (beginning-of-line 1) - (while (search-forward "|" pos t) - (setq cnt (1+ cnt))) - (when (org-called-interactively-p 'interactive) - (message "In table column %d" cnt)) - cnt))) + (let ((column 0) (pos (point))) + (beginning-of-line) + (while (search-forward "|" pos t) (cl-incf column)) + (when (called-interactively-p 'interactive) + (message "In table column %d" column)) + column))) ;;;###autoload (defun org-table-current-dline () "Find out what table data line we are in. Only data lines count for this." (interactive) - (when (org-called-interactively-p 'any) + (when (called-interactively-p 'any) (org-table-check-inside-data-field)) (save-excursion - (let ((cnt 0) (pos (point))) + (let ((c 0) + (pos (point))) (goto-char (org-table-begin)) (while (<= (point) pos) - (if (looking-at org-table-dataline-regexp) (setq cnt (1+ cnt))) - (beginning-of-line 2)) - (when (org-called-interactively-p 'any) - (message "This is table line %d" cnt)) - cnt))) + (when (looking-at org-table-dataline-regexp) (cl-incf c)) + (forward-line)) + (when (called-interactively-p 'any) + (message "This is table line %d" c)) + c))) ;;;###autoload (defun org-table-goto-column (n &optional on-delim force) @@ -1338,25 +1371,19 @@ However, when FORCE is non-nil, create new columns if necessary." (defun org-table-insert-column () "Insert a new column into the table." (interactive) - (if (not (org-at-table-p)) - (user-error "Not at a table")) + (unless (org-at-table-p) (user-error "Not at a table")) (org-table-find-dataline) (let* ((col (max 1 (org-table-current-column))) (beg (org-table-begin)) - (end (org-table-end)) - ;; Current cursor position - (linepos (org-current-line)) - (colpos col)) - (goto-char beg) - (while (< (point) end) - (if (org-at-table-hline-p) - nil - (org-table-goto-column col t) - (insert "| ")) - (beginning-of-line 2)) - (move-marker end nil) - (org-goto-line linepos) - (org-table-goto-column colpos) + (end (copy-marker (org-table-end)))) + (org-table-save-field + (goto-char beg) + (while (< (point) end) + (unless (org-at-table-hline-p) + (org-table-goto-column col t) + (insert "| ")) + (forward-line))) + (set-marker end nil) (org-table-align) (when (or (not org-table-fix-formulas-confirm) (funcall org-table-fix-formulas-confirm "Fix formulas? ")) @@ -1384,58 +1411,55 @@ However, when FORCE is non-nil, create new columns if necessary." (defun org-table-line-to-dline (line &optional above) "Turn a buffer line number into a data line number. + If there is no data line in this line, return nil. -If there is no matching dline (most likely te reference was a hline), the -first dline below it is used. When ABOVE is non-nil, the one above is used." - (catch 'exit - (let ((ll (length org-table-dlines)) - i) - (if above - (progn - (setq i (1- ll)) - (while (> i 0) - (if (<= (aref org-table-dlines i) line) - (throw 'exit i)) - (setq i (1- i)))) - (setq i 1) - (while (< i ll) - (if (>= (aref org-table-dlines i) line) - (throw 'exit i)) - (setq i (1+ i))))) - nil)) + +If there is no matching dline (most likely the reference was +a hline), the first dline below it is used. When ABOVE is +non-nil, the one above is used." + (let ((min 1) + (max (1- (length org-table-dlines)))) + (cond ((or (> (aref org-table-dlines min) line) + (< (aref org-table-dlines max) line)) + nil) + ((= (aref org-table-dlines max) line) max) + (t (catch 'exit + (while (> (- max min) 1) + (let* ((mean (/ (+ max min) 2)) + (v (aref org-table-dlines mean))) + (cond ((= v line) (throw 'exit mean)) + ((> v line) (setq max mean)) + (t (setq min mean))))) + (if above min max)))))) ;;;###autoload (defun org-table-delete-column () "Delete a column from the table." (interactive) - (if (not (org-at-table-p)) - (user-error "Not at a table")) + (unless (org-at-table-p) (user-error "Not at a table")) (org-table-find-dataline) (org-table-check-inside-data-field) - (let* ((col (org-table-current-column)) - (beg (org-table-begin)) - (end (org-table-end)) - ;; Current cursor position - (linepos (org-current-line)) - (colpos col)) - (goto-char beg) - (while (< (point) end) - (if (org-at-table-hline-p) - nil - (org-table-goto-column col t) - (and (looking-at "|[^|\n]+|") - (replace-match "|"))) - (beginning-of-line 2)) - (move-marker end nil) - (org-goto-line linepos) - (org-table-goto-column colpos) + (let ((col (org-table-current-column)) + (beg (org-table-begin)) + (end (copy-marker (org-table-end)))) + (org-table-save-field + (goto-char beg) + (while (< (point) end) + (if (org-at-table-hline-p) + nil + (org-table-goto-column col t) + (and (looking-at "|[^|\n]+|") + (replace-match "|"))) + (forward-line))) + (set-marker end nil) + (org-table-goto-column (max 1 (1- col))) (org-table-align) (when (or (not org-table-fix-formulas-confirm) (funcall org-table-fix-formulas-confirm "Fix formulas? ")) - (org-table-fix-formulas "$" (list (cons (number-to-string col) "INVALID")) - col -1 col) - (org-table-fix-formulas "$LR" (list (cons (number-to-string col) "INVALID")) - col -1 col)))) + (org-table-fix-formulas + "$" (list (cons (number-to-string col) "INVALID")) col -1 col) + (org-table-fix-formulas + "$LR" (list (cons (number-to-string col) "INVALID")) col -1 col)))) ;;;###autoload (defun org-table-move-column-right () @@ -1452,31 +1476,29 @@ first dline below it is used. When ABOVE is non-nil, the one above is used." (defun org-table-move-column (&optional left) "Move the current column to the right. With arg LEFT, move to the left." (interactive "P") - (if (not (org-at-table-p)) - (user-error "Not at a table")) + (unless (org-at-table-p) (user-error "Not at a table")) (org-table-find-dataline) (org-table-check-inside-data-field) (let* ((col (org-table-current-column)) (col1 (if left (1- col) col)) + (colpos (if left (1- col) (1+ col))) (beg (org-table-begin)) - (end (org-table-end)) - ;; Current cursor position - (linepos (org-current-line)) - (colpos (if left (1- col) (1+ col)))) - (if (and left (= col 1)) - (user-error "Cannot move column further left")) - (if (and (not left) (looking-at "[^|\n]*|[^|\n]*$")) - (user-error "Cannot move column further right")) - (goto-char beg) - (while (< (point) end) - (if (org-at-table-hline-p) - nil - (org-table-goto-column col1 t) - (and (looking-at "|\\([^|\n]+\\)|\\([^|\n]+\\)|") - (replace-match "|\\2|\\1|"))) - (beginning-of-line 2)) - (move-marker end nil) - (org-goto-line linepos) + (end (copy-marker (org-table-end)))) + (when (and left (= col 1)) + (user-error "Cannot move column further left")) + (when (and (not left) (looking-at "[^|\n]*|[^|\n]*$")) + (user-error "Cannot move column further right")) + (org-table-save-field + (goto-char beg) + (while (< (point) end) + (unless (org-at-table-hline-p) + (org-table-goto-column col1 t) + (when (looking-at "|\\([^|\n]+\\)|\\([^|\n]+\\)|") + (transpose-regions + (match-beginning 1) (match-end 1) + (match-beginning 2) (match-end 2)))) + (forward-line))) + (set-marker end nil) (org-table-goto-column colpos) (org-table-align) (when (or (not org-table-fix-formulas-confirm) @@ -1538,19 +1560,21 @@ first dline below it is used. When ABOVE is non-nil, the one above is used." "Insert a new row above the current line into the table. With prefix ARG, insert below the current line." (interactive "P") - (if (not (org-at-table-p)) - (user-error "Not at a table")) - (let* ((line (buffer-substring (point-at-bol) (point-at-eol))) + (unless (org-at-table-p) (user-error "Not at a table")) + (let* ((line (buffer-substring (line-beginning-position) (line-end-position))) (new (org-table-clean-line line))) ;; Fix the first field if necessary (if (string-match "^[ \t]*| *[#$] *|" line) (setq new (replace-match (match-string 0 line) t t new))) (beginning-of-line (if arg 2 1)) + ;; Buffer may not end of a newline character, so ensure + ;; (beginning-of-line 2) moves point to a new line. + (unless (bolp) (insert "\n")) (let (org-table-may-need-update) (insert-before-markers new "\n")) (beginning-of-line 0) - (re-search-forward "| ?" (point-at-eol) t) - (and (or org-table-may-need-update org-table-overlay-coordinates) - (org-table-align)) + (re-search-forward "| ?" (line-end-position) t) + (when (or org-table-may-need-update org-table-overlay-coordinates) + (org-table-align)) (when (or (not org-table-fix-formulas-confirm) (funcall org-table-fix-formulas-confirm "Fix formulas? ")) (org-table-fix-formulas "@" nil (1- (org-table-current-dline)) 1)))) @@ -1563,7 +1587,7 @@ With prefix ABOVE, insert above the current line." (if (not (org-at-table-p)) (user-error "Not at a table")) (when (eobp) (insert "\n") (backward-char 1)) - (if (not (string-match "|[ \t]*$" (org-current-line-string))) + (if (not (string-match-p "|[ \t]*$" (org-current-line-string))) (org-table-align)) (let ((line (org-table-clean-line (buffer-substring (point-at-bol) (point-at-eol)))) @@ -1623,7 +1647,8 @@ In particular, this does handle wide and invisible characters." dline -1 dline)))) ;;;###autoload -(defun org-table-sort-lines (with-case &optional sorting-type) +(defun org-table-sort-lines + (&optional with-case sorting-type getkey-func compare-func interactive?) "Sort table lines according to the column at point. The position of point indicates the column to be used for @@ -1636,76 +1661,112 @@ should be in the last line to be included into the sorting. The command then prompts for the sorting type which can be alphabetically, numerically, or by time (as given in a time stamp -in the field). Sorting in reverse order is also possible. +in the field, or as a HH:MM value). Sorting in reverse order is +also possible. With prefix argument WITH-CASE, alphabetic sorting will be case-sensitive. If SORTING-TYPE is specified when this function is called from a Lisp program, no prompting will take place. SORTING-TYPE must be a character, -any of (?a ?A ?n ?N ?t ?T) where the capital letter indicate that sorting -should be done in reverse order." - (interactive "P") - (let* ((thisline (org-current-line)) - (thiscol (org-table-current-column)) - (otc org-table-overlay-coordinates) - beg end bcol ecol tend tbeg column lns pos) - (when (equal thiscol 0) - (if (org-called-interactively-p 'any) - (setq thiscol - (string-to-number - (read-string "Use column N for sorting: "))) - (setq thiscol 1)) - (org-table-goto-column thiscol)) - (org-table-check-inside-data-field) - (if (org-region-active-p) - (progn - (setq beg (region-beginning) end (region-end)) - (goto-char beg) - (setq column (org-table-current-column) - beg (point-at-bol)) - (goto-char end) - (setq end (point-at-bol 2))) - (setq column (org-table-current-column) - pos (point) - tbeg (org-table-begin) - tend (org-table-end)) - (if (re-search-backward org-table-hline-regexp tbeg t) - (setq beg (point-at-bol 2)) - (goto-char tbeg) - (setq beg (point-at-bol 1))) - (goto-char pos) - (if (re-search-forward org-table-hline-regexp tend t) - (setq end (point-at-bol 1)) - (goto-char tend) - (setq end (point-at-bol)))) - (setq beg (move-marker (make-marker) beg) - end (move-marker (make-marker) end)) - (untabify beg end) - (goto-char beg) - (org-table-goto-column column) - (skip-chars-backward "^|") - (setq bcol (current-column)) - (org-table-goto-column (1+ column)) - (skip-chars-backward "^|") - (setq ecol (1- (current-column))) - (org-table-goto-column column) - (setq lns (mapcar (lambda(x) (cons - (org-sort-remove-invisible - (nth (1- column) - (org-split-string x "[ \t]*|[ \t]*"))) - x)) - (org-split-string (buffer-substring beg end) "\n"))) - (setq lns (org-do-sort lns "Table" with-case sorting-type)) - (when org-table-overlay-coordinates - (org-table-toggle-coordinate-overlays)) - (delete-region beg end) - (move-marker beg nil) - (move-marker end nil) - (insert (mapconcat 'cdr lns "\n") "\n") - (org-goto-line thisline) - (org-table-goto-column thiscol) - (when otc (org-table-toggle-coordinate-overlays)) - (message "%d lines sorted, based on column %d" (length lns) column))) +any of (?a ?A ?n ?N ?t ?T ?f ?F) where the capital letters indicate that +sorting should be done in reverse order. + +If the SORTING-TYPE is ?f or ?F, then GETKEY-FUNC specifies +a function to be called to extract the key. It must return a value +that is compatible with COMPARE-FUNC, the function used to compare +entries. + +A non-nil value for INTERACTIVE? is used to signal that this +function is being called interactively." + (interactive (list current-prefix-arg nil nil nil t)) + (when (org-region-active-p) (goto-char (region-beginning))) + ;; Point must be either within a field or before a data line. + (save-excursion + (skip-chars-backward " \t") + (when (bolp) (search-forward "|" (line-end-position) t)) + (org-table-check-inside-data-field)) + ;; Set appropriate case sensitivity and column used for sorting. + (let ((column (let ((c (org-table-current-column))) + (cond ((> c 0) c) + (interactive? + (read-number "Use column N for sorting: ")) + (t 1)))) + (sorting-type + (or sorting-type + (read-char-exclusive "Sort Table: [a]lphabetic, [n]umeric, \ +\[t]ime, [f]unc. A/N/T/F means reversed: ")))) + (save-restriction + ;; Narrow buffer to appropriate sorting area. + (if (org-region-active-p) + (progn (goto-char (region-beginning)) + (narrow-to-region + (point) + (save-excursion (goto-char (region-end)) + (line-beginning-position 2)))) + (let ((start (org-table-begin)) + (end (org-table-end))) + (narrow-to-region + (save-excursion + (if (re-search-backward org-table-hline-regexp start t) + (line-beginning-position 2) + start)) + (if (save-excursion (re-search-forward org-table-hline-regexp end t)) + (match-beginning 0) + end)))) + ;; Determine arguments for `sort-subr'. Also record original + ;; position. `org-table-save-field' cannot help here since + ;; sorting is too much destructive. + (let* ((sort-fold-case (not with-case)) + (coordinates + (cons (count-lines (point-min) (line-beginning-position)) + (current-column))) + (extract-key-from-field + ;; Function to be called on the contents of the field + ;; used for sorting in the current row. + (cl-case sorting-type + ((?n ?N) #'string-to-number) + ((?a ?A) #'org-sort-remove-invisible) + ((?t ?T) + (lambda (f) + (cond ((string-match org-ts-regexp-both f) + (float-time + (org-time-string-to-time (match-string 0 f)))) + ((string-match "[0-9]\\{1,2\\}:[0-9]\\{2\\}" f) + (org-hh:mm-string-to-minutes f)) + (t 0)))) + ((?f ?F) + (or getkey-func + (and interactive? + (org-read-function "Function for extracting keys: ")) + (error "Missing key extractor to sort rows"))) + (t (user-error "Invalid sorting type `%c'" sorting-type)))) + (predicate + (cl-case sorting-type + ((?n ?N ?t ?T) #'<) + ((?a ?A) #'string<) + ((?f ?F) + (or compare-func + (and interactive? + (org-read-function + (concat "Function for comparing keys " + "(empty for default `sort-subr' predicate): ") + 'allow-empty))))))) + (goto-char (point-min)) + (sort-subr (memq sorting-type '(?A ?N ?T ?F)) + (lambda () + (forward-line) + (while (and (not (eobp)) + (not (looking-at org-table-dataline-regexp))) + (forward-line))) + #'end-of-line + (lambda () + (funcall extract-key-from-field + (org-trim (org-table-get-field column)))) + nil + predicate) + ;; Move back to initial field. + (forward-line (car coordinates)) + (move-to-column (cdr coordinates)))))) ;;;###autoload (defun org-table-cut-region (beg end) @@ -1725,34 +1786,31 @@ with `org-table-paste-rectangle'." (if (org-region-active-p) (region-beginning) (point)) (if (org-region-active-p) (region-end) (point)) current-prefix-arg)) - (let* (l01 c01 l02 c02 l1 c1 l2 c2 ic1 ic2 - region cols - (rpl (if cut " " nil))) - (goto-char beg) - (org-table-check-inside-data-field) - (setq l01 (org-current-line) - c01 (org-table-current-column)) - (goto-char end) + (goto-char (min beg end)) + (org-table-check-inside-data-field) + (let ((beg (line-beginning-position)) + (c01 (org-table-current-column)) + region) + (goto-char (max beg end)) (org-table-check-inside-data-field) - (setq l02 (org-current-line) - c02 (org-table-current-column)) - (setq l1 (min l01 l02) l2 (max l01 l02) - c1 (min c01 c02) c2 (max c01 c02)) - (catch 'exit - (while t - (catch 'nextline - (if (> l1 l2) (throw 'exit t)) - (org-goto-line l1) - (if (org-at-table-hline-p) (throw 'nextline (setq l1 (1+ l1)))) - (setq cols nil ic1 c1 ic2 c2) - (while (< ic1 (1+ ic2)) - (push (org-table-get-field ic1 rpl) cols) - (setq ic1 (1+ ic1))) - (push (nreverse cols) region) - (setq l1 (1+ l1))))) - (setq org-table-clip (nreverse region)) - (if cut (org-table-align)) - org-table-clip)) + (let* ((end (copy-marker (line-end-position))) + (c02 (org-table-current-column)) + (column-start (min c01 c02)) + (column-end (max c01 c02)) + (column-number (1+ (- column-end column-start))) + (rpl (and cut " "))) + (goto-char beg) + (while (< (point) end) + (unless (org-at-table-hline-p) + ;; Collect every cell between COLUMN-START and COLUMN-END. + (let (cols) + (dotimes (c column-number) + (push (org-table-get-field (+ c column-start) rpl) cols)) + (push (nreverse cols) region))) + (forward-line)) + (set-marker end nil)) + (when cut (org-table-align)) + (setq org-table-clip (nreverse region)))) ;;;###autoload (defun org-table-paste-rectangle () @@ -1762,45 +1820,43 @@ will be overwritten. If the rectangle does not fit into the present table, the table is enlarged as needed. The process ignores horizontal separator lines." (interactive) - (unless (and org-table-clip (listp org-table-clip)) + (unless (consp org-table-clip) (user-error "First cut/copy a region to paste!")) (org-table-check-inside-data-field) - (let* ((clip org-table-clip) - (line (org-current-line)) - (col (org-table-current-column)) + (let* ((column (org-table-current-column)) (org-enable-table-editor t) - (org-table-automatic-realign nil) - c cols field) - (while (setq cols (pop clip)) - (while (org-at-table-hline-p) (beginning-of-line 2)) - (if (not (org-at-table-p)) - (progn (end-of-line 0) (org-table-next-field))) - (setq c col) - (while (setq field (pop cols)) - (org-table-goto-column c nil 'force) - (org-table-get-field nil field) - (setq c (1+ c))) - (beginning-of-line 2)) - (org-goto-line line) - (org-table-goto-column col) + (org-table-automatic-realign nil)) + (org-table-save-field + (dolist (row org-table-clip) + (while (org-at-table-hline-p) (forward-line)) + ;; If we left the table, create a new row. + (when (and (bolp) (not (looking-at "[ \t]*|"))) + (end-of-line 0) + (org-table-next-field)) + (let ((c column)) + (dolist (field row) + (org-table-goto-column c nil 'force) + (org-table-get-field nil field) + (cl-incf c))) + (forward-line))) (org-table-align))) ;;;###autoload (defun org-table-convert () "Convert from `org-mode' table to table.el and back. -Obviously, this only works within limits. When an Org-mode table is -converted to table.el, all horizontal separator lines get lost, because -table.el uses these as cell boundaries and has no notion of horizontal lines. -A table.el table can be converted to an Org-mode table only if it does not -do row or column spanning. Multiline cells will become multiple cells. -Beware, Org-mode does not test if the table can be successfully converted - it -blindly applies a recipe that works for simple tables." +Obviously, this only works within limits. When an Org table is converted +to table.el, all horizontal separator lines get lost, because table.el uses +these as cell boundaries and has no notion of horizontal lines. A table.el +table can be converted to an Org table only if it does not do row or column +spanning. Multiline cells will become multiple cells. Beware, Org mode +does not test if the table can be successfully converted - it blindly +applies a recipe that works for simple tables." (interactive) (require 'table) (if (org-at-table.el-p) - ;; convert to Org-mode table - (let ((beg (move-marker (make-marker) (org-table-begin t))) - (end (move-marker (make-marker) (org-table-end t)))) + ;; convert to Org table + (let ((beg (copy-marker (org-table-begin t))) + (end (copy-marker (org-table-end t)))) (table-unrecognize-region beg end) (goto-char beg) (while (re-search-forward "^\\([ \t]*\\)\\+-.*\n" end t) @@ -1808,8 +1864,8 @@ blindly applies a recipe that works for simple tables." (goto-char beg)) (if (org-at-table-p) ;; convert to table.el table - (let ((beg (move-marker (make-marker) (org-table-begin))) - (end (move-marker (make-marker) (org-table-end)))) + (let ((beg (copy-marker (org-table-begin))) + (end (copy-marker (org-table-end)))) ;; first, get rid of all horizontal lines (goto-char beg) (while (re-search-forward "^\\([ \t]*\\)|-.*\n" end t) @@ -1832,7 +1888,7 @@ blindly applies a recipe that works for simple tables." (goto-char beg))))) (defun org-table-transpose-table-at-point () - "Transpose orgmode table at point and eliminate hlines. + "Transpose Org table at point and eliminate hlines. So a table like | 1 | 2 | 4 | 5 | @@ -1847,22 +1903,31 @@ will be transposed as | 4 | c | g | | 5 | d | h | -Note that horizontal lines disappeared." +Note that horizontal lines disappear." (interactive) (let* ((table (delete 'hline (org-table-to-lisp))) - (contents (mapcar (lambda (p) + (dline_old (org-table-current-line)) + (col_old (org-table-current-column)) + (contents (mapcar (lambda (_) (let ((tp table)) (mapcar - (lambda (rown) + (lambda (_) (prog1 (pop (car tp)) (setq tp (cdr tp)))) table))) (car table)))) - (delete-region (org-table-begin) (org-table-end)) - (insert (mapconcat (lambda(x) (concat "| " (mapconcat 'identity x " | " ) " |\n" )) - contents "")) - (org-table-align))) + (goto-char (org-table-begin)) + (re-search-forward "|") + (backward-char) + (delete-region (point) (org-table-end)) + (insert (mapconcat + (lambda(x) + (concat "| " (mapconcat 'identity x " | " ) " |\n" )) + contents "")) + (org-table-goto-line col_old) + (org-table-goto-column dline_old)) + (org-table-align)) ;;;###autoload (defun org-table-wrap-region (arg) @@ -1873,7 +1938,8 @@ lines, in order to keep the table compact. If there is an active region, and both point and mark are in the same column, the text in the column is wrapped to minimum width for the given number of lines. Generally, this makes the table more compact. A prefix ARG may be -used to change the number of desired lines. For example, `C-2 \\[org-table-wrap]' +used to change the number of desired lines. For example, \ +`C-2 \\[org-table-wrap-region]' formats the selected text to two lines. If the region was longer than two lines, the remaining lines remain empty. A negative prefix argument reduces the current number of lines by that amount. The wrapped text is pasted back @@ -1890,57 +1956,53 @@ blank, and the content is appended to the field above." (interactive "P") (org-table-check-inside-data-field) (if (org-region-active-p) - ;; There is a region: fill as a paragraph - (let* ((beg (region-beginning)) - (cline (save-excursion (goto-char beg) (org-current-line))) - (ccol (save-excursion (goto-char beg) (org-table-current-column))) - nlines) + ;; There is a region: fill as a paragraph. + (let ((start (region-beginning))) (org-table-cut-region (region-beginning) (region-end)) - (if (> (length (car org-table-clip)) 1) - (user-error "Region must be limited to single column")) - (setq nlines (if arg - (if (< arg 1) - (+ (length org-table-clip) arg) - arg) - (length org-table-clip))) - (setq org-table-clip - (mapcar 'list (org-wrap (mapconcat 'car org-table-clip " ") - nil nlines))) - (org-goto-line cline) - (org-table-goto-column ccol) + (when (> (length (car org-table-clip)) 1) + (user-error "Region must be limited to single column")) + (let ((nlines (cond ((not arg) (length org-table-clip)) + ((< arg 1) (+ (length org-table-clip) arg)) + (t arg)))) + (setq org-table-clip + (mapcar #'list + (org-wrap (mapconcat #'car org-table-clip " ") + nil + nlines)))) + (goto-char start) (org-table-paste-rectangle)) - ;; No region, split the current field at point + ;; No region, split the current field at point. (unless (org-get-alist-option org-M-RET-may-split-line 'table) (skip-chars-forward "^\r\n|")) - (if arg - ;; combine with field above - (let ((s (org-table-blank-field)) - (col (org-table-current-column))) - (beginning-of-line 0) - (while (org-at-table-hline-p) (beginning-of-line 0)) - (org-table-goto-column col) - (skip-chars-forward "^|") - (skip-chars-backward " ") - (insert " " (org-trim s)) - (org-table-align)) - ;; split field - (if (looking-at "\\([^|]+\\)+|") - (let ((s (match-string 1))) - (replace-match " |") - (goto-char (match-beginning 0)) - (org-table-next-row) - (insert (org-trim s) " ") - (org-table-align)) - (org-table-next-row))))) + (cond + (arg ; Combine with field above. + (let ((s (org-table-blank-field)) + (col (org-table-current-column))) + (forward-line -1) + (while (org-at-table-hline-p) (forward-line -1)) + (org-table-goto-column col) + (skip-chars-forward "^|") + (skip-chars-backward " ") + (insert " " (org-trim s)) + (org-table-align))) + ((looking-at "\\([^|]+\\)+|") ; Split field. + (let ((s (match-string 1))) + (replace-match " |") + (goto-char (match-beginning 0)) + (org-table-next-row) + (insert (org-trim s) " ") + (org-table-align))) + (t (org-table-next-row))))) (defvar org-field-marker nil) ;;;###autoload (defun org-table-edit-field (arg) "Edit table field in a different window. -This is mainly useful for fields that contain hidden parts. -When called with a \\[universal-argument] prefix, just make the full field visible so that -it can be edited in place." +This is mainly useful for fields that contain hidden parts. When called +with a `\\[universal-argument]' prefix, just make the full field \ +visible so that it can be +edited in place." (interactive "P") (cond ((equal arg '(16)) @@ -1980,9 +2042,9 @@ it can be edited in place." '(invisible t org-cwidth t display t intangible t)) (goto-char p) - (org-set-local 'org-finish-function 'org-table-finish-edit-field) - (org-set-local 'org-window-configuration cw) - (org-set-local 'org-field-marker pos) + (setq-local org-finish-function 'org-table-finish-edit-field) + (setq-local org-window-configuration cw) + (setq-local org-field-marker pos) (message "Edit and finish with C-c C-c"))))) (defun org-table-finish-edit-field () @@ -2015,8 +2077,8 @@ current field. The mode exits automatically when the cursor leaves the table (but see `org-table-exit-follow-field-mode-when-leaving-table')." nil " TblFollow" nil (if org-table-follow-field-mode - (org-add-hook 'post-command-hook 'org-table-follow-fields-with-editor - 'append 'local) + (add-hook 'post-command-hook 'org-table-follow-fields-with-editor + 'append 'local) (remove-hook 'post-command-hook 'org-table-follow-fields-with-editor 'local) (let* ((buf (get-buffer "*Org Table Edit Field*")) (win (and buf (get-buffer-window buf)))) @@ -2091,11 +2153,10 @@ If NLAST is a number, only the NLAST fields will actually be summed." s diff) (format "%.0f:%02.0f:%02.0f" h m s)))) (kill-new sres) - (if (org-called-interactively-p 'interactive) - (message "%s" - (substitute-command-keys - (format "Sum of %d items: %-20s (\\[yank] will insert result into buffer)" - (length numbers) sres)))) + (when (called-interactively-p 'interactive) + (message "%s" (substitute-command-keys + (format "Sum of %d items: %-20s \ +\(\\[yank] will insert result into buffer)" (length numbers) sres)))) sres)))) (defun org-table-get-number-for-summing (s) @@ -2120,57 +2181,58 @@ If NLAST is a number, only the NLAST fields will actually be summed." (defun org-table-current-field-formula (&optional key noerror) "Return the formula active for the current field. -Assumes that specials are in place. -If KEY is given, return the key to this formula. -Otherwise return the formula preceded with \"=\" or \":=\"." - (let* ((name (car (rassoc (list (org-current-line) - (org-table-current-column)) - org-table-named-field-locations))) - (col (org-table-current-column)) - (scol (int-to-string col)) - (ref (format "@%d$%d" (org-table-current-dline) col)) - (stored-list (org-table-get-stored-formulas noerror)) - (ass (or (assoc name stored-list) - (assoc ref stored-list) - (assoc scol stored-list)))) - (if key - (car ass) - (if ass (concat (if (string-match "^[0-9]+$" (car ass)) "=" ":=") - (cdr ass)))))) + +Assumes that table is already analyzed. If KEY is given, return +the key to this formula. Otherwise return the formula preceded +with \"=\" or \":=\"." + (let* ((line (count-lines org-table-current-begin-pos + (line-beginning-position))) + (row (org-table-line-to-dline line))) + (cond + (row + (let* ((col (org-table-current-column)) + (name (car (rassoc (list line col) + org-table-named-field-locations))) + (scol (format "$%d" col)) + (ref (format "@%d$%d" (org-table-current-dline) col)) + (stored-list (org-table-get-stored-formulas noerror)) + (ass (or (assoc name stored-list) + (assoc ref stored-list) + (assoc scol stored-list)))) + (cond (key (car ass)) + (ass (concat (if (string-match-p "^[0-9]+$" (car ass)) "=" ":=") + (cdr ass)))))) + (noerror nil) + (t (error "No formula active for the current field"))))) (defun org-table-get-formula (&optional equation named) "Read a formula from the minibuffer, offer stored formula as default. When NAMED is non-nil, look for a named equation." (let* ((stored-list (org-table-get-stored-formulas)) - (name (car (rassoc (list (org-current-line) + (name (car (rassoc (list (count-lines org-table-current-begin-pos + (line-beginning-position)) (org-table-current-column)) org-table-named-field-locations))) - (ref (format "@%d$%d" (org-table-current-dline) + (ref (format "@%d$%d" + (org-table-current-dline) (org-table-current-column))) - (refass (assoc ref stored-list)) - (nameass (assoc name stored-list)) - (scol (if named - (if (and name (not (string-match "^LR[0-9]+$" name))) - name - ref) - (int-to-string (org-table-current-column)))) - (dummy (and (or nameass refass) (not named) - (not (y-or-n-p "Replace existing field formula with column formula? " )) - (message "Formula not replaced"))) + (scol (cond + ((not named) (format "$%d" (org-table-current-column))) + ((and name (not (string-match "\\`LR[0-9]+\\'" name))) name) + (t ref))) (name (or name ref)) (org-table-may-need-update nil) (stored (cdr (assoc scol stored-list))) (eq (cond - ((and stored equation (string-match "^ *=? *$" equation)) + ((and stored equation (string-match-p "^ *=? *$" equation)) stored) ((stringp equation) equation) (t (org-table-formula-from-user (read-string (org-table-formula-to-user - (format "%s formula %s%s=" + (format "%s formula %s=" (if named "Field" "Column") - (if (member (string-to-char scol) '(?$ ?@)) "" "$") scol)) (if stored (org-table-formula-to-user stored) "") 'org-table-formula-history @@ -2194,25 +2256,27 @@ When NAMED is non-nil, look for a named equation." (org-table-store-formulas stored-list)) eq)) -(defun org-table-store-formulas (alist) - "Store the list of formulas below the current table." - (setq alist (sort alist 'org-table-formula-less-p)) - (let ((case-fold-search t)) - (save-excursion - (goto-char (org-table-end)) - (if (looking-at "\\([ \t]*\n\\)*[ \t]*\\(#\\+tblfm:\\)\\(.*\n?\\)") +(defun org-table-store-formulas (alist &optional location) + "Store the list of formulas below the current table. +If optional argument LOCATION is a buffer position, insert it at +LOCATION instead." + (save-excursion + (if location + (progn (goto-char location) (beginning-of-line)) + (goto-char (org-table-end))) + (let ((case-fold-search t)) + (if (looking-at "\\([ \t]*\n\\)*[ \t]*\\(#\\+TBLFM:\\)\\(.*\n?\\)") (progn - ;; don't overwrite TBLFM, we might use text properties to store stuff + ;; Don't overwrite TBLFM, we might use text properties to + ;; store stuff. (goto-char (match-beginning 3)) (delete-region (match-beginning 3) (match-end 0))) (org-indent-line) (insert (or (match-string 2) "#+TBLFM:"))) (insert " " - (mapconcat (lambda (x) - (concat - (if (equal (string-to-char (car x)) ?@) "" "$") - (car x) "=" (cdr x))) - alist "::") + (mapconcat (lambda (x) (concat (car x) "=" (cdr x))) + (sort alist #'org-table-formula-less-p) + "::") "\n")))) (defsubst org-table-formula-make-cmp-string (a) @@ -2241,33 +2305,47 @@ When NAMED is non-nil, look for a named equation." (and as bs (string< as bs)))) ;;;###autoload -(defun org-table-get-stored-formulas (&optional noerror) - "Return an alist with the stored formulas directly after current table." - (interactive) ;; FIXME interactive? - (let ((case-fold-search t) scol eq eq-alist strings string seen) - (save-excursion - (goto-char (org-table-end)) - (when (looking-at "\\([ \t]*\n\\)*[ \t]*#\\+tblfm: *\\(.*\\)") - (setq strings (org-split-string (org-match-string-no-properties 2) - " *:: *")) - (while (setq string (pop strings)) - (when (string-match "\\`\\(@[-+I<>0-9.$@]+\\|@?[0-9]+\\|\\$\\([a-zA-Z0-9]+\\|[<>]+\\)\\) *= *\\(.*[^ \t]\\)" string) - (setq scol (if (match-end 2) - (match-string 2 string) - (match-string 1 string)) - scol (if (member (string-to-char scol) '(?< ?>)) - (concat "$" scol) scol) - eq (match-string 3 string) - eq-alist (cons (cons scol eq) eq-alist)) - (if (member scol seen) - (if noerror - (progn - (message "Double definition `$%s=' in TBLFM line, please fix by hand" scol) - (ding) - (sit-for 2)) - (user-error "Double definition `$%s=' in TBLFM line, please fix by hand" scol)) - (push scol seen)))))) - (nreverse eq-alist))) +(defun org-table-get-stored-formulas (&optional noerror location) + "Return an alist with the stored formulas directly after current table. +By default, only return active formulas, i.e., formulas located +on the first line after the table. However, if optional argument +LOCATION is a buffer position, consider the formulas there." + (save-excursion + (if location + (progn (goto-char location) (beginning-of-line)) + (goto-char (org-table-end))) + (let ((case-fold-search t)) + (when (looking-at "\\([ \t]*\n\\)*[ \t]*#\\+TBLFM: *\\(.*\\)") + (let ((strings (org-split-string (match-string-no-properties 2) + " *:: *")) + eq-alist seen) + (dolist (string strings (nreverse eq-alist)) + (when (string-match "\\`\\(@[-+I<>0-9.$@]+\\|\\$\\([_a-zA-Z0-9]+\\|\ +[<>]+\\)\\) *= *\\(.*[^ \t]\\)" + string) + (let ((lhs + (let ((m (match-string 1 string))) + (cond + ((not (match-end 2)) m) + ;; Is it a column reference? + ((string-match-p "\\`$\\([0-9]+\\|[<>]+\\)\\'" m) m) + ;; Since named columns are not possible in + ;; LHS, assume this is a named field. + (t (match-string 2 string))))) + (rhs (match-string 3 string))) + (push (cons lhs rhs) eq-alist) + (cond + ((not (member lhs seen)) (push lhs seen)) + (noerror + (message + "Double definition `%s=' in TBLFM line, please fix by hand" + lhs) + (ding) + (sit-for 2)) + (t + (user-error + "Double definition `%s=' in TBLFM line, please fix by hand" + lhs))))))))))) (defun org-table-fix-formulas (key replace &optional limit delta remove) "Modify the equations after the table structure has been edited. @@ -2305,83 +2383,6 @@ For all numbers larger than LIMIT, shift them by DELTA." (message msg)))))) (forward-line)))) -(defun org-table-get-specials () - "Get the column names and local parameters for this table." - (save-excursion - (let ((beg (org-table-begin)) (end (org-table-end)) - names name fields fields1 field cnt - c v l line col types dlines hlines last-dline) - (setq org-table-column-names nil - org-table-local-parameters nil - org-table-named-field-locations nil - org-table-current-begin-line nil - org-table-current-begin-pos nil - org-table-current-line-types nil - org-table-current-ncol 0) - (goto-char beg) - (when (re-search-forward "^[ \t]*| *! *\\(|.*\\)" end t) - (setq names (org-split-string (match-string 1) " *| *") - cnt 1) - (while (setq name (pop names)) - (setq cnt (1+ cnt)) - (if (string-match "^[a-zA-Z][_a-zA-Z0-9]*$" name) - (push (cons name (int-to-string cnt)) org-table-column-names)))) - (setq org-table-column-names (nreverse org-table-column-names)) - (setq org-table-column-name-regexp - (concat "\\$\\(" (mapconcat 'car org-table-column-names "\\|") "\\)\\>")) - (goto-char beg) - (while (re-search-forward "^[ \t]*| *\\$ *\\(|.*\\)" end t) - (setq fields (org-split-string (match-string 1) " *| *")) - (while (setq field (pop fields)) - (if (string-match "^\\([a-zA-Z][_a-zA-Z0-9]*\\|%\\) *= *\\(.*\\)" field) - (push (cons (match-string 1 field) (match-string 2 field)) - org-table-local-parameters)))) - (goto-char beg) - (while (re-search-forward "^[ \t]*| *\\([_^]\\) *\\(|.*\\)" end t) - (setq c (match-string 1) - fields (org-split-string (match-string 2) " *| *")) - (save-excursion - (beginning-of-line (if (equal c "_") 2 0)) - (setq line (org-current-line) col 1) - (and (looking-at "^[ \t]*|[^|]*\\(|.*\\)") - (setq fields1 (org-split-string (match-string 1) " *| *")))) - (while (and fields1 (setq field (pop fields))) - (setq v (pop fields1) col (1+ col)) - (when (and (stringp field) (stringp v) - (string-match "^[a-zA-Z][_a-zA-Z0-9]*$" field)) - (push (cons field v) org-table-local-parameters) - (push (list field line col) org-table-named-field-locations)))) - ;; Analyze the line types. - (goto-char beg) - (setq org-table-current-begin-line (org-current-line) - org-table-current-begin-pos (point) - l org-table-current-begin-line) - (while (looking-at "[ \t]*|\\(-\\)?") - (push (if (match-end 1) 'hline 'dline) types) - (if (match-end 1) (push l hlines) (push l dlines)) - (beginning-of-line 2) - (setq l (1+ l))) - (push 'hline types) ;; add an imaginary extra hline to the end - (setq org-table-current-line-types (apply 'vector (nreverse types)) - last-dline (car dlines) - org-table-dlines (apply 'vector (cons nil (nreverse dlines))) - org-table-hlines (apply 'vector (cons nil (nreverse hlines)))) - (org-goto-line last-dline) - (let* ((l last-dline) - (fields (org-split-string - (buffer-substring (point-at-bol) (point-at-eol)) - "[ \t]*|[ \t]*")) - (nfields (length fields)) - al al2) - (setq org-table-current-ncol nfields) - (loop for i from 1 to nfields do - (push (list (format "LR%d" i) l i) al) - (push (cons (format "LR%d" i) (nth (1- i) fields)) al2)) - (setq org-table-named-field-locations - (append org-table-named-field-locations al)) - (setq org-table-local-parameters - (append org-table-local-parameters al2)))))) - ;;;###autoload (defun org-table-maybe-eval-formula () "Check if the current field starts with \"=\" or \":=\". @@ -2394,11 +2395,8 @@ If yes, store the formula and apply it." (when (string-match "^:?=\\(.*[^=]\\)$" field) (setq named (equal (string-to-char field) ?:) eq (match-string 1 field)) - (if (or (fboundp 'calc-eval) - (equal (substring eq 0 (min 2 (length eq))) "'(")) - (org-table-eval-formula (if named '(4) nil) - (org-table-formula-from-user eq)) - (user-error "Calc does not seem to be installed, and is needed to evaluate the formula")))))) + (org-table-eval-formula (and named '(4)) + (org-table-formula-from-user eq)))))) (defvar org-recalc-commands nil "List of commands triggering the recalculation of a line. @@ -2424,56 +2422,199 @@ After each change, a message will be displayed indicating the meaning of the new mark." (interactive) (unless (org-at-table-p) (user-error "Not at a table")) - (let* ((marks (append (mapcar 'car org-recalc-marks) '(" "))) - (beg (org-table-begin)) - (end (org-table-end)) - (l (org-current-line)) - (l1 (if (org-region-active-p) (org-current-line (region-beginning)))) - (l2 (if (org-region-active-p) (org-current-line (region-end)))) - (have-col - (save-excursion - (goto-char beg) - (not (re-search-forward "^[ \t]*|[^-|][^|]*[^#!$*_^| \t][^|]*|" end t)))) + (let* ((region (org-region-active-p)) + (l1 (and region + (save-excursion (goto-char (region-beginning)) + (copy-marker (line-beginning-position))))) + (l2 (and region + (save-excursion (goto-char (region-end)) + (copy-marker (line-beginning-position))))) + (l (copy-marker (line-beginning-position))) (col (org-table-current-column)) - (forcenew (car (assoc newchar org-recalc-marks))) - epos new) - (when l1 - (message "Change region to what mark? Type # * ! $ or SPC: ") - (setq newchar (char-to-string (read-char-exclusive)) - forcenew (car (assoc newchar org-recalc-marks)))) - (if (and newchar (not forcenew)) - (user-error "Invalid NEWCHAR `%s' in `org-table-rotate-recalc-marks'" - newchar)) - (if l1 (org-goto-line l1)) + (newchar (if region + (char-to-string + (read-char-exclusive + "Change region to what mark? Type # * ! $ or SPC: ")) + newchar)) + (no-special-column + (save-excursion + (goto-char (org-table-begin)) + (re-search-forward + "^[ \t]*|[^-|][^|]*[^#!$*_^| \t][^|]*|" (org-table-end) t)))) + (when (and newchar (not (assoc newchar org-recalc-marks))) + (user-error "Invalid character `%s' in `org-table-rotate-recalc-marks'" + newchar)) + (when l1 (goto-char l1)) (save-excursion - (beginning-of-line 1) + (beginning-of-line) (unless (looking-at org-table-dataline-regexp) (user-error "Not at a table data line"))) - (unless have-col + (when no-special-column (org-table-goto-column 1) - (org-table-insert-column) - (org-table-goto-column (1+ col))) - (setq epos (point-at-eol)) + (org-table-insert-column)) + (let ((previous-line-end (line-end-position)) + (newchar + (save-excursion + (beginning-of-line) + (cond ((not (looking-at "^[ \t]*| *\\([#!$*^_ ]\\) *|")) "#") + (newchar) + (t (cadr (member (match-string 1) + (append (mapcar #'car org-recalc-marks) + '(" "))))))))) + ;; Rotate mark in first row. + (org-table-get-field 1 (format " %s " newchar)) + ;; Rotate marks in additional rows if a region is active. + (when region + (save-excursion + (forward-line) + (while (<= (point) l2) + (when (looking-at org-table-dataline-regexp) + (org-table-get-field 1 (format " %s " newchar))) + (forward-line)))) + ;; Only align if rotation actually changed lines' length. + (when (/= previous-line-end (line-end-position)) (org-table-align))) + (goto-char l) + (org-table-goto-column (if no-special-column (1+ col) col)) + (when l1 (set-marker l1 nil)) + (when l2 (set-marker l2 nil)) + (set-marker l nil) + (when (called-interactively-p 'interactive) + (message "%s" (cdr (assoc newchar org-recalc-marks)))))) + +;;;###autoload +(defun org-table-analyze () + "Analyze table at point and store results. + +This function sets up the following dynamically scoped variables: + + `org-table-column-name-regexp', + `org-table-column-names', + `org-table-current-begin-pos', + `org-table-current-line-types', + `org-table-current-ncol', + `org-table-dlines', + `org-table-hlines', + `org-table-local-parameters', + `org-table-named-field-locations'." + (let ((beg (org-table-begin)) + (end (org-table-end))) (save-excursion - (beginning-of-line 1) - (org-table-get-field - 1 (if (looking-at "^[ \t]*| *\\([#!$*^_ ]\\) *|") - (concat " " - (setq new (or forcenew - (cadr (member (match-string 1) marks)))) - " ") - " # "))) - (if (and l1 l2) - (progn - (org-goto-line l1) - (while (progn (beginning-of-line 2) (not (= (org-current-line) l2))) - (and (looking-at org-table-dataline-regexp) - (org-table-get-field 1 (concat " " new " ")))) - (org-goto-line l1))) - (if (not (= epos (point-at-eol))) (org-table-align)) - (org-goto-line l) - (and (org-called-interactively-p 'interactive) - (message "%s" (cdr (assoc new org-recalc-marks)))))) + (goto-char beg) + ;; Extract column names. + (setq org-table-column-names nil) + (when (save-excursion + (re-search-forward "^[ \t]*| *! *\\(|.*\\)" end t)) + (let ((c 1)) + (dolist (name (org-split-string (match-string 1) " *| *")) + (cl-incf c) + (when (string-match "\\`[a-zA-Z][_a-zA-Z0-9]*\\'" name) + (push (cons name (int-to-string c)) org-table-column-names))))) + (setq org-table-column-names (nreverse org-table-column-names)) + (setq org-table-column-name-regexp + (format "\\$\\(%s\\)\\>" + (regexp-opt (mapcar #'car org-table-column-names) t))) + ;; Extract local parameters. + (setq org-table-local-parameters nil) + (save-excursion + (while (re-search-forward "^[ \t]*| *\\$ *\\(|.*\\)" end t) + (dolist (field (org-split-string (match-string 1) " *| *")) + (when (string-match + "\\`\\([a-zA-Z][_a-zA-Z0-9]*\\|%\\) *= *\\(.*\\)" field) + (push (cons (match-string 1 field) (match-string 2 field)) + org-table-local-parameters))))) + ;; Update named fields locations. We minimize `count-lines' + ;; processing by storing last known number of lines in LAST. + (setq org-table-named-field-locations nil) + (save-excursion + (let ((last (cons (point) 0))) + (while (re-search-forward "^[ \t]*| *\\([_^]\\) *\\(|.*\\)" end t) + (let ((c (match-string 1)) + (fields (org-split-string (match-string 2) " *| *"))) + (save-excursion + (forward-line (if (equal c "_") 1 -1)) + (let ((fields1 + (and (looking-at "^[ \t]*|[^|]*\\(|.*\\)") + (org-split-string (match-string 1) " *| *"))) + (line (cl-incf (cdr last) (count-lines (car last) (point)))) + (col 1)) + (setcar last (point)) ; Update last known position. + (while (and fields fields1) + (let ((field (pop fields)) + (v (pop fields1))) + (cl-incf col) + (when (and (stringp field) + (stringp v) + (string-match "\\`[a-zA-Z][_a-zA-Z0-9]*\\'" + field)) + (push (cons field v) org-table-local-parameters) + (push (list field line col) + org-table-named-field-locations)))))))))) + ;; Re-use existing markers when possible. + (if (markerp org-table-current-begin-pos) + (move-marker org-table-current-begin-pos (point)) + (setq org-table-current-begin-pos (point-marker))) + ;; Analyze the line types. + (let ((l 0) hlines dlines types) + (while (looking-at "[ \t]*|\\(-\\)?") + (push (if (match-end 1) 'hline 'dline) types) + (if (match-end 1) (push l hlines) (push l dlines)) + (forward-line) + (cl-incf l)) + (push 'hline types) ; Add an imaginary extra hline to the end. + (setq org-table-current-line-types (apply #'vector (nreverse types))) + (setq org-table-dlines (apply #'vector (cons nil (nreverse dlines)))) + (setq org-table-hlines (apply #'vector (cons nil (nreverse hlines))))) + ;; Get the number of columns from the first data line in table. + (goto-char beg) + (forward-line (aref org-table-dlines 1)) + (let* ((fields + (org-split-string + (buffer-substring (line-beginning-position) (line-end-position)) + "[ \t]*|[ \t]*")) + (nfields (length fields)) + al al2) + (setq org-table-current-ncol nfields) + (let ((last-dline + (aref org-table-dlines (1- (length org-table-dlines))))) + (dotimes (i nfields) + (let ((column (1+ i))) + (push (list (format "LR%d" column) last-dline column) al) + (push (cons (format "LR%d" column) (nth i fields)) al2)))) + (setq org-table-named-field-locations + (append org-table-named-field-locations al)) + (setq org-table-local-parameters + (append org-table-local-parameters al2)))))) + +(defun org-table-goto-field (ref &optional create-column-p) + "Move point to a specific field in the current table. + +REF is either the name of a field its absolute reference, as +a string. No column is created unless CREATE-COLUMN-P is +non-nil. If it is a function, it is called with the column +number as its argument as is used as a predicate to know if the +column can be created. + +This function assumes the table is already analyzed (i.e., using +`org-table-analyze')." + (let* ((coordinates + (cond + ((cdr (assoc ref org-table-named-field-locations))) + ((string-match "\\`@\\([1-9][0-9]*\\)\\$\\([1-9][0-9]*\\)\\'" ref) + (list (condition-case nil + (aref org-table-dlines + (string-to-number (match-string 1 ref))) + (error (user-error "Invalid row number in %s" ref))) + (string-to-number (match-string 2 ref)))) + (t (user-error "Unknown field: %s" ref)))) + (line (car coordinates)) + (column (nth 1 coordinates)) + (create-new-column (if (functionp create-column-p) + (funcall create-column-p column) + create-column-p))) + (when coordinates + (goto-char org-table-current-begin-pos) + (forward-line line) + (org-table-goto-column column nil create-new-column)))) ;;;###autoload (defun org-table-maybe-recalculate-line () @@ -2481,7 +2622,7 @@ of the new mark." (interactive) (and org-table-allow-automatic-line-recalculation (not (and (memq last-command org-recalc-commands) - (equal org-last-recalc-line (org-current-line)))) + (eq org-last-recalc-line (line-beginning-position)))) (save-excursion (beginning-of-line 1) (looking-at org-table-auto-recalculate-regexp)) (org-table-recalculate) t)) @@ -2505,20 +2646,18 @@ of the new mark." suppress-store suppress-analysis) "Replace the table field value at the cursor by the result of a calculation. -This function makes use of Dave Gillespie's Calc package, in my view the -most exciting program ever written for GNU Emacs. So you need to have Calc -installed in order to use this function. - In a table, this command replaces the value in the current field with the result of a formula. It also installs the formula as the \"current\" column formula, by storing it in a special line below the table. When called -with a `C-u' prefix, the current field must be a named field, and the -formula is installed as valid in only this specific field. +with a `\\[universal-argument]' prefix the formula is installed as a \ +field formula. -When called with two `C-u' prefixes, insert the active equation -for the field back into the current field, so that it can be -edited there. This is useful in order to use \\[org-table-show-reference] -to check the referenced fields. +When called with a `\\[universal-argument] \\[universal-argument]' prefix, \ +insert the active equation for the field +back into the current field, so that it can be edited there. This is \ +useful +in order to use \\`\\[org-table-show-reference]' to \ +check the referenced fields. When called, the command first prompts for a formula, which is read in the minibuffer. Previously entered formulas are available through the @@ -2527,7 +2666,7 @@ These stored formulas are adapted correctly when moving, inserting, or deleting columns with the corresponding commands. The formula can be any algebraic expression understood by the Calc package. -For details, see the Org-mode manual. +For details, see the Org mode manual. This function can also be called from Lisp programs and offers additional arguments: EQUATION can be the formula to apply. If this @@ -2537,13 +2676,13 @@ SUPPRESS-CONST suppresses the interpretation of constants in the formula, assuming that this has been done already outside the function. SUPPRESS-STORE means the formula should not be stored, either because it is already stored, or because it is a modified equation that should -not overwrite the stored one." +not overwrite the stored one. SUPPRESS-ANALYSIS prevents any call to +`org-table-analyze'." (interactive "P") (org-table-check-inside-data-field) - (or suppress-analysis (org-table-get-specials)) + (or suppress-analysis (org-table-analyze)) (if (equal arg '(16)) (let ((eq (org-table-current-field-formula))) - (or eq (user-error "No equation active for current field")) (org-table-get-field nil eq) (org-table-align) (setq org-table-may-need-update t)) @@ -2557,7 +2696,7 @@ not overwrite the stored one." (org-table-get-formula equation (equal arg '(4))))) (n0 (org-table-current-column)) (org-tbl-calc-modes (copy-sequence org-calc-default-modes)) - (numbers nil) ; was a variable, now fixed default + (numbers nil) ; was a variable, now fixed default (keep-empty nil) n form form0 formrpl formrg bw fmt x ev orig c lispp literal duration duration-output-format) @@ -2603,12 +2742,15 @@ not overwrite the stored one." (setq fmt (replace-match "" t t fmt))) (unless (string-match "\\S-" fmt) (setq fmt nil)))) - (if (and (not suppress-const) org-table-formula-use-constants) - (setq formula (org-table-formula-substitute-names formula))) + (when (and (not suppress-const) org-table-formula-use-constants) + (setq formula (org-table-formula-substitute-names formula))) (setq orig (or (get-text-property 1 :orig-formula formula) "?")) + (setq formula (org-table-formula-handle-first/last-rc formula)) (while (> ndown 0) (setq fields (org-split-string - (buffer-substring-no-properties (point-at-bol) (point-at-eol)) + (org-trim + (buffer-substring-no-properties + (line-beginning-position) (line-end-position))) " *| *")) ;; replace fields with duration values if relevant (if duration @@ -2641,9 +2783,10 @@ not overwrite the stored one." t t form))) ;; Check for old vertical references - (setq form (org-table-rewrite-old-row-references form)) + (org-table--error-on-old-row-references form) ;; Insert remote references - (while (string-match "\\ (length (match-string 0 form)) 1)) - (setq formrg (save-match-data - (org-table-get-range (match-string 0 form) nil n0))) + (setq formrg + (save-match-data + (org-table-get-range + (match-string 0 form) org-table-current-begin-pos n0))) (setq formrpl (save-match-data (org-table-make-reference @@ -2676,15 +2821,20 @@ not overwrite the stored one." (string-match (regexp-quote form) formrpl))) (setq form (replace-match formrpl t t form)) (user-error "Spreadsheet error: invalid reference \"%s\"" form))) - ;; Insert simple ranges - (while (string-match "\\$\\([0-9]+\\)\\.\\.\\$\\([0-9]+\\)" form) + ;; Insert simple ranges, i.e. included in the current row. + (while (string-match + "\\$\\(\\([-+]\\)?[0-9]+\\)\\.\\.\\$\\(\\([-+]\\)?[0-9]+\\)" + form) (setq form (replace-match (save-match-data (org-table-make-reference - (org-sublist - fields (string-to-number (match-string 1 form)) - (string-to-number (match-string 2 form))) + (cl-subseq fields + (+ (if (match-end 2) n0 0) + (string-to-number (match-string 1 form)) + -1) + (+ (if (match-end 4) n0 0) + (string-to-number (match-string 3 form)))) keep-empty numbers lispp)) t t form))) (setq form0 form) @@ -2692,14 +2842,16 @@ not overwrite the stored one." (while (string-match "\\$\\(\\([-+]\\)?[0-9]+\\)" form) (setq n (+ (string-to-number (match-string 1 form)) (if (match-end 2) n0 0)) - x (nth (1- (if (= n 0) n0 (max n 1))) fields)) - (unless x (user-error "Invalid field specifier \"%s\"" - (match-string 0 form))) - (setq form (replace-match - (save-match-data - (org-table-make-reference - x keep-empty numbers lispp)) - t t form))) + x (nth (1- (if (= n 0) n0 (max n 1))) fields) + formrpl (save-match-data + (org-table-make-reference + x keep-empty numbers lispp))) + (when (or (not x) + (save-match-data + (string-match (regexp-quote formula) formrpl))) + (user-error "Invalid field specifier \"%s\"" + (match-string 0 form))) + (setq form (replace-match formrpl t t form))) (if lispp (setq ev (condition-case nil @@ -2709,20 +2861,23 @@ not overwrite the stored one." ev (if duration (org-table-time-seconds-to-string (string-to-number ev) duration-output-format) ev)) - (or (fboundp 'calc-eval) - (user-error "Calc does not seem to be installed, and is needed to evaluate the formula")) - ;; Use <...> time-stamps so that Calc can handle them - (while (string-match (concat "\\[" org-ts-regexp1 "\\]") form) - (setq form (replace-match "<\\1>" nil nil form))) - ;; I18n-ize local time-stamps by setting (system-time-locale "C") - (when (string-match org-ts-regexp2 form) - (let* ((ts (match-string 0 form)) - (tsp (apply 'encode-time (save-match-data (org-parse-time-string ts)))) - (system-time-locale "C") - (tf (or (and (save-match-data (string-match "[0-9]\\{1,2\\}:[0-9]\\{2\\}" ts)) - (cdr org-time-stamp-formats)) - (car org-time-stamp-formats)))) - (setq form (replace-match (format-time-string tf tsp) t t form)))) + + ;; Use <...> time-stamps so that Calc can handle them. + (setq form + (replace-regexp-in-string org-ts-regexp-inactive "<\\1>" form)) + ;; Internationalize local time-stamps by setting locale to + ;; "C". + (setq form + (replace-regexp-in-string + org-ts-regexp + (lambda (ts) + (let ((system-time-locale "C")) + (format-time-string + (org-time-stamp-format + (string-match-p "[0-9]\\{1,2\\}:[0-9]\\{2\\}" ts)) + (apply #'encode-time + (save-match-data (org-parse-time-string ts)))))) + form t t)) (setq ev (if (and duration (string-match "^[0-9]+:[0-9]+\\(?::[0-9]+\\)?$" form)) form @@ -2742,7 +2897,7 @@ Orig: %s $xyz-> %s @r$c-> %s $1-> %s\n" orig formula form0 form)) - (if (listp ev) + (if (consp ev) (princ (format " %s^\nError: %s" (make-string (car ev) ?\-) (nth 1 ev))) (princ (format "Result: %s\nFormat: %s\nFinal: %s" @@ -2750,14 +2905,14 @@ $1-> %s\n" orig formula form0 form)) (if fmt (format fmt (string-to-number ev)) ev))))) (setq bw (get-buffer-window "*Substitution History*")) (org-fit-window-to-buffer bw) - (unless (and (org-called-interactively-p 'any) (not ndown)) + (unless (and (called-interactively-p 'any) (not ndown)) (unless (let (inhibit-redisplay) (y-or-n-p "Debugging Formula. Continue to next? ")) (org-table-align) (user-error "Abort")) (delete-window bw) (message ""))) - (if (listp ev) (setq fmt nil ev "#ERROR")) + (when (consp ev) (setq fmt nil ev "#ERROR")) (org-table-justify-field-maybe (format org-table-formula-field-format (if fmt (format fmt (string-to-number ev)) ev))) @@ -2776,146 +2931,152 @@ $1-> %s\n" orig formula form0 form)) (defun org-table-get-range (desc &optional tbeg col highlight corners-only) "Get a calc vector from a column, according to descriptor DESC. + Optional arguments TBEG and COL can give the beginning of the table and the current column, to avoid unnecessary parsing. HIGHLIGHT means just highlight the range. When CORNERS-ONLY is set, only return the corners of the range as -a list (line1 column1 line2 column2) where line1 and line2 are line numbers -in the buffer and column1 and column2 are table column numbers." - (if (not (equal (string-to-char desc) ?@)) - (setq desc (concat "@" desc))) - (save-excursion - (or tbeg (setq tbeg (org-table-begin))) - (or col (setq col (org-table-current-column))) - (let ((thisline (org-current-line)) - beg end c1 c2 r1 r2 rangep tmp) - (unless (string-match org-table-range-regexp desc) - (user-error "Invalid table range specifier `%s'" desc)) - (setq rangep (match-end 3) - r1 (and (match-end 1) (match-string 1 desc)) - r2 (and (match-end 4) (match-string 4 desc)) - c1 (and (match-end 2) (substring (match-string 2 desc) 1)) - c2 (and (match-end 5) (substring (match-string 5 desc) 1))) - - (and c1 (setq c1 (+ (string-to-number c1) - (if (memq (string-to-char c1) '(?- ?+)) col 0)))) - (and c2 (setq c2 (+ (string-to-number c2) - (if (memq (string-to-char c2) '(?- ?+)) col 0)))) - (if (equal r1 "") (setq r1 nil)) - (if (equal r2 "") (setq r2 nil)) - (if r1 (setq r1 (org-table-get-descriptor-line r1))) - (if r2 (setq r2 (org-table-get-descriptor-line r2))) - ; (setq r2 (or r2 r1) c2 (or c2 c1)) - (if (not r1) (setq r1 thisline)) - (if (not r2) (setq r2 thisline)) - (if (or (not c1) (= 0 c1)) (setq c1 col)) - (if (or (not c2) (= 0 c2)) (setq c2 col)) - (if (and (not corners-only) - (or (not rangep) (and (= r1 r2) (= c1 c2)))) - ;; just one field - (progn - (org-goto-line r1) - (while (not (looking-at org-table-dataline-regexp)) - (beginning-of-line 2)) - (prog1 (org-trim (org-table-get-field c1)) - (if highlight (org-table-highlight-rectangle (point) (point))))) - ;; A range, return a vector - ;; First sort the numbers to get a regular rectangle - (if (< r2 r1) (setq tmp r1 r1 r2 r2 tmp)) - (if (< c2 c1) (setq tmp c1 c1 c2 c2 tmp)) - (if corners-only - ;; Only return the corners of the range - (list r1 c1 r2 c2) - ;; Copy the range values into a list - (org-goto-line r1) - (while (not (looking-at org-table-dataline-regexp)) - (beginning-of-line 2)) - (org-table-goto-column c1) - (setq beg (point)) - (org-goto-line r2) - (while (not (looking-at org-table-dataline-regexp)) - (beginning-of-line 0)) - (org-table-goto-column c2) - (setq end (point)) - (if highlight - (org-table-highlight-rectangle - beg (progn (skip-chars-forward "^|\n") (point)))) - ;; return string representation of calc vector - (mapcar 'org-trim - (apply 'append (org-table-copy-region beg end)))))))) - -(defun org-table-get-descriptor-line (desc &optional cline bline table) - "Analyze descriptor DESC and retrieve the corresponding line number. -The cursor is currently in line CLINE, the table begins in line BLINE, -and TABLE is a vector with line types." - (if (string-match "^[0-9]+$" desc) +a list (line1 column1 line2 column2) where line1 and line2 are +line numbers relative to beginning of table, or TBEG, and column1 +and column2 are table column numbers." + (let* ((desc (if (string-match-p "\\`\\$[0-9]+\\.\\.\\$[0-9]+\\'" desc) + (replace-regexp-in-string "\\$" "@0$" desc) + desc)) + (col (or col (org-table-current-column))) + (tbeg (or tbeg (org-table-begin))) + (thisline (count-lines tbeg (line-beginning-position)))) + (unless (string-match org-table-range-regexp desc) + (user-error "Invalid table range specifier `%s'" desc)) + (let ((rangep (match-end 3)) + (r1 (let ((r (and (match-end 1) (match-string 1 desc)))) + (or (save-match-data + (and (org-string-nw-p r) + (org-table--descriptor-line r thisline))) + thisline))) + (r2 (let ((r (and (match-end 4) (match-string 4 desc)))) + (or (save-match-data + (and (org-string-nw-p r) + (org-table--descriptor-line r thisline))) + thisline))) + (c1 (let ((c (and (match-end 2) (substring (match-string 2 desc) 1)))) + (if (or (not c) (= (string-to-number c) 0)) col + (+ (string-to-number c) + (if (memq (string-to-char c) '(?- ?+)) col 0))))) + (c2 (let ((c (and (match-end 5) (substring (match-string 5 desc) 1)))) + (if (or (not c) (= (string-to-number c) 0)) col + (+ (string-to-number c) + (if (memq (string-to-char c) '(?- ?+)) col 0)))))) + (save-excursion + (if (and (not corners-only) + (or (not rangep) (and (= r1 r2) (= c1 c2)))) + ;; Just one field. + (progn + (forward-line (- r1 thisline)) + (while (not (looking-at org-table-dataline-regexp)) + (forward-line)) + (prog1 (org-trim (org-table-get-field c1)) + (when highlight (org-table-highlight-rectangle)))) + ;; A range, return a vector. First sort the numbers to get + ;; a regular rectangle. + (let ((first-row (min r1 r2)) + (last-row (max r1 r2)) + (first-column (min c1 c2)) + (last-column (max c1 c2))) + (if corners-only (list first-row first-column last-row last-column) + ;; Copy the range values into a list. + (forward-line (- first-row thisline)) + (while (not (looking-at org-table-dataline-regexp)) + (forward-line) + (cl-incf first-row)) + (org-table-goto-column first-column) + (let ((beg (point))) + (forward-line (- last-row first-row)) + (while (not (looking-at org-table-dataline-regexp)) + (forward-line -1)) + (org-table-goto-column last-column) + (let ((end (point))) + (when highlight + (org-table-highlight-rectangle + beg (progn (skip-chars-forward "^|\n") (point)))) + ;; Return string representation of calc vector. + (mapcar #'org-trim + (apply #'append + (org-table-copy-region beg end)))))))))))) + +(defun org-table--descriptor-line (desc cline) + "Return relative line number corresponding to descriptor DESC. +The cursor is currently in relative line number CLINE." + (if (string-match "\\`[0-9]+\\'" desc) (aref org-table-dlines (string-to-number desc)) - (setq cline (or cline (org-current-line)) - bline (or bline org-table-current-begin-line) - table (or table org-table-current-line-types)) - (if (or - (not (string-match "^\\(\\([-+]\\)?\\(I+\\)\\)?\\(\\([-+]\\)?\\([0-9]+\\)\\)?" desc)) - ;; 1 2 3 4 5 6 - (and (not (match-end 3)) (not (match-end 6))) - (and (match-end 3) (match-end 6) (not (match-end 5)))) - (user-error "Invalid row descriptor `%s'" desc)) - (let* ((hdir (and (match-end 2) (match-string 2 desc))) - (hn (if (match-end 3) (- (match-end 3) (match-beginning 3)) nil)) - (odir (and (match-end 5) (match-string 5 desc))) - (on (if (match-end 6) (string-to-number (match-string 6 desc)))) - (i (- cline bline)) + (when (or (not (string-match + "^\\(\\([-+]\\)?\\(I+\\)\\)?\\(\\([-+]\\)?\\([0-9]+\\)\\)?" + ;; 1 2 3 4 5 6 + desc)) + (and (not (match-end 3)) (not (match-end 6))) + (and (match-end 3) (match-end 6) (not (match-end 5)))) + (user-error "Invalid row descriptor `%s'" desc)) + (let* ((hn (and (match-end 3) (- (match-end 3) (match-beginning 3)))) + (hdir (match-string 2 desc)) + (odir (match-string 5 desc)) + (on (and (match-end 6) (string-to-number (match-string 6 desc)))) (rel (and (match-end 6) (or (and (match-end 1) (not (match-end 3))) (match-end 5))))) - (if (and hn (not hdir)) - (progn - (setq i 0 hdir "+") - (if (eq (aref table 0) 'hline) (setq hn (1- hn))))) - (if (and (not hn) on (not odir)) - (user-error "Should never happen");;(aref org-table-dlines on) - (if (and hn (> hn 0)) - (setq i (org-table-find-row-type table i 'hline (equal hdir "-") - nil hn cline desc))) - (if on - (setq i (org-table-find-row-type table i 'dline (equal odir "-") - rel on cline desc))) - (+ bline i))))) - -(defun org-table-find-row-type (table i type backwards relative n cline desc) - "FIXME: Needs more documentation." - (let ((l (length table))) - (while (> n 0) - (while (and (setq i (+ i (if backwards -1 1))) - (>= i 0) (< i l) - (not (eq (aref table i) type)) - (if (and relative (eq (aref table i) 'hline)) - (cond - ((eq org-table-relative-ref-may-cross-hline t) t) - ((eq org-table-relative-ref-may-cross-hline 'error) - (user-error "Row descriptor %s used in line %d crosses hline" desc cline)) - (t (setq i (- i (if backwards -1 1)) - n 1) - nil)) - t))) - (setq n (1- n))) - (if (or (< i 0) (>= i l)) - (user-error "Row descriptor %s used in line %d leads outside table" - desc cline) - i))) - -(defun org-table-rewrite-old-row-references (s) - (if (string-match "&[-+0-9I]" s) - (user-error "Formula contains old &row reference, please rewrite using @-syntax") - s)) + (when (and hn (not hdir)) + (setq cline 0) + (setq hdir "+") + (when (eq (aref org-table-current-line-types 0) 'hline) (cl-decf hn))) + (when (and (not hn) on (not odir)) (user-error "Should never happen")) + (when hn + (setq cline + (org-table--row-type 'hline hn cline (equal hdir "-") nil desc))) + (when on + (setq cline + (org-table--row-type 'dline on cline (equal odir "-") rel desc))) + cline))) + +(defun org-table--row-type (type n i backwards relative desc) + "Return relative line of Nth row with type TYPE. +Search starts from relative line I. When BACKWARDS in non-nil, +look before I. When RELATIVE is non-nil, the reference is +relative. DESC is the original descriptor that started the +search, as a string." + (let ((l (length org-table-current-line-types))) + (catch :exit + (dotimes (_ n) + (while (and (cl-incf i (if backwards -1 1)) + (>= i 0) + (< i l) + (not (eq (aref org-table-current-line-types i) type)) + ;; We are going to cross a hline. Check if this is + ;; an authorized move. + (cond + ((not relative)) + ((not (eq (aref org-table-current-line-types i) 'hline))) + ((eq org-table-relative-ref-may-cross-hline t)) + ((eq org-table-relative-ref-may-cross-hline 'error) + (user-error "Row descriptor %s crosses hline" desc)) + (t (cl-decf i (if backwards -1 1)) ; Step back. + (throw :exit nil))))))) + (cond ((or (< i 0) (>= i l)) + (user-error "Row descriptor %s leads outside table" desc)) + ;; The last hline doesn't exist. Instead, point to last row + ;; in table. + ((= i (1- l)) (1- i)) + (t i)))) + +(defun org-table--error-on-old-row-references (s) + (when (string-match "&[-+0-9I]" s) + (user-error "Formula contains old &row reference, please rewrite using @-syntax"))) (defun org-table-make-reference (elements keep-empty numbers lispp) "Convert list ELEMENTS to something appropriate to insert into formula. KEEP-EMPTY indicated to keep empty fields, default is to skip them. NUMBERS indicates that everything should be converted to numbers. LISPP non-nil means to return something appropriate for a Lisp -list, 'literal is for the format specifier L." +list, `literal' is for the format specifier L." ;; Calc nan (not a number) is used for the conversion of the empty ;; field to a reference for several reasons: (i) It is accepted in a ;; Calc formula (e. g. "" or "()" would result in a Calc error). @@ -2961,162 +3122,185 @@ list, 'literal is for the format specifier L." elements ",") "]")))) -;;;###autoload -(defun org-table-set-constants () - "Set `org-table-formula-constants-local' in the current buffer." - (let (cst consts const-str) - (save-excursion - (goto-char (point-min)) - (while (re-search-forward "^[ \t]*#\\+CONSTANTS: \\(.*\\)" nil t) - (setq const-str (substring-no-properties (match-string 1))) - (setq consts (append consts (org-split-string const-str "[ \t]+"))) - (when consts - (let (e) - (while (setq e (pop consts)) - (when (string-match "^\\([a-zA-Z0][_a-zA-Z0-9]*\\)=\\(.*\\)" e) - (if (assoc-string (match-string 1 e) cst) - (setq cst (delete (assoc-string (match-string 1 e) cst) cst))) - (push (cons (match-string 1 e) (match-string 2 e)) cst))) - (setq org-table-formula-constants-local cst))))))) +(defun org-table-message-once-per-second (t1 &rest args) + "If there has been more than one second since T1, display message. +ARGS are passed as arguments to the `message' function. Returns +current time if a message is printed, otherwise returns T1. If +T1 is nil, always messages." + (let ((curtime (current-time))) + (if (or (not t1) (< 0 (nth 1 (time-subtract curtime t1)))) + (progn (apply 'message args) + curtime) + t1))) ;;;###autoload (defun org-table-recalculate (&optional all noalign) "Recalculate the current table line by applying all stored formulas. + With prefix arg ALL, do this for all lines in the table. -With the prefix argument ALL is `(16)' \ -\(a double \\[universal-prefix] \\[universal-prefix] prefix), or if -it is the symbol `iterate', recompute the table until it no longer changes. + +When called with a `\\[universal-argument] \\[universal-argument]' prefix, or \ +if ALL is the symbol `iterate', +recompute the table until it no longer changes. + If NOALIGN is not nil, do not re-align the table after the computations are done. This is typically used internally to save time, if it is known that the table will be realigned a little later anyway." (interactive "P") - (or (memq this-command org-recalc-commands) - (setq org-recalc-commands (cons this-command org-recalc-commands))) + (unless (memq this-command org-recalc-commands) + (push this-command org-recalc-commands)) (unless (org-at-table-p) (user-error "Not at a table")) (if (or (eq all 'iterate) (equal all '(16))) (org-table-iterate) - (org-table-get-specials) + (org-table-analyze) (let* ((eqlist (sort (org-table-get-stored-formulas) (lambda (a b) (string< (car a) (car b))))) - (eqlist1 (copy-sequence eqlist)) (inhibit-redisplay (not debug-on-error)) (line-re org-table-dataline-regexp) - (thisline (org-current-line)) - (thiscol (org-table-current-column)) - seen-fields lhs1 - beg end entry eqlnum eqlname eqlname1 eql (cnt 0) eq a name name1) - ;; Insert constants in all formulas - (setq eqlist - (mapcar (lambda (x) - (when (string-match "\\`$[<>]" (car x)) - (setq lhs1 (car x)) - (setq x (cons (substring - (org-table-formula-handle-first/last-rc - (car x)) 1) - (cdr x))) - (if (assoc (car x) eqlist1) - (user-error "\"%s=\" formula tries to overwrite existing formula for column %s" - lhs1 (car x)))) - (cons - (org-table-formula-handle-first/last-rc (car x)) - (org-table-formula-substitute-names - (org-table-formula-handle-first/last-rc (cdr x))))) - eqlist)) - ;; Split the equation list - (while (setq eq (pop eqlist)) - (if (<= (string-to-char (car eq)) ?9) - (push eq eqlnum) - (push eq eqlname))) - (setq eqlnum (nreverse eqlnum) eqlname (nreverse eqlname)) - ;; Expand ranges in lhs of formulas - (setq eqlname (org-table-expand-lhs-ranges eqlname)) - - ;; Get the correct line range to process - (if all - (progn - (setq end (move-marker (make-marker) (1+ (org-table-end)))) - (goto-char (setq beg (org-table-begin))) - (if (re-search-forward org-table-calculate-mark-regexp end t) - ;; This is a table with marked lines, compute selected lines - (setq line-re org-table-recalculate-regexp) - ;; Move forward to the first non-header line - (if (and (re-search-forward org-table-dataline-regexp end t) - (re-search-forward org-table-hline-regexp end t) - (re-search-forward org-table-dataline-regexp end t)) - (setq beg (match-beginning 0)) - nil))) ;; just leave beg where it is - (setq beg (point-at-bol) - end (move-marker (make-marker) (1+ (point-at-eol))))) - (goto-char beg) - (and all (message "Re-applying formulas to full table...")) - - ;; First find the named fields, and mark them untouchable. - ;; Also check if several field/range formulas try to set the same field. - (remove-text-properties beg end '(org-untouchable t)) - (while (setq eq (pop eqlname)) - (setq name (car eq) - a (assoc name org-table-named-field-locations)) - (setq name1 name) - (if a (setq name1 (format "@%d$%d" (org-table-line-to-dline (nth 1 a)) - (nth 2 a)))) - (when (member name1 seen-fields) - (user-error "Several field/range formulas try to set %s" name1)) - (push name1 seen-fields) - - (and (not a) - (string-match "@\\([0-9]+\\)\\$\\([0-9]+\\)" name) - (setq a (list name - (condition-case nil - (aref org-table-dlines - (string-to-number (match-string 1 name))) - (error (user-error "Invalid row number in %s" - name))) - (string-to-number (match-string 2 name))))) - (when (and a (or all (equal (nth 1 a) thisline))) - (message "Re-applying formula to field: %s" name) - (org-goto-line (nth 1 a)) - (org-table-goto-column (nth 2 a)) - (push (append a (list (cdr eq))) eqlname1) - (org-table-put-field-property :org-untouchable t))) - (setq eqlname1 (nreverse eqlname1)) - - ;; Now evaluate the column formulas, but skip fields covered by - ;; field formulas - (goto-char beg) - (while (re-search-forward line-re end t) - (unless (string-match "^ *[_^!$/] *$" (org-table-get-field 1)) - ;; Unprotected line, recalculate - (and all (message "Re-applying formulas to full table...(line %d)" - (setq cnt (1+ cnt)))) - (setq org-last-recalc-line (org-current-line)) - (setq eql eqlnum) - (while (setq entry (pop eql)) - (org-goto-line org-last-recalc-line) - (org-table-goto-column (string-to-number (car entry)) nil 'force) - (unless (get-text-property (point) :org-untouchable) - (org-table-eval-formula nil (cdr entry) - 'noalign 'nocst 'nostore 'noanalysis))))) - - ;; Now evaluate the field formulas - (while (setq eq (pop eqlname1)) - (message "Re-applying formula to field: %s" (car eq)) - (org-goto-line (nth 1 eq)) - (org-table-goto-column (nth 2 eq)) - (org-table-eval-formula nil (nth 3 eq) 'noalign 'nocst - 'nostore 'noanalysis)) - - (org-goto-line thisline) - (org-table-goto-column thiscol) - (remove-text-properties (point-min) (point-max) '(org-untouchable t)) - (or noalign (and org-table-may-need-update (org-table-align)) - (and all (message "Re-applying formulas to %d lines...done" cnt))) - - ;; back to initial position - (message "Re-applying formulas...done") - (org-goto-line thisline) - (org-table-goto-column thiscol) - (or noalign (and org-table-may-need-update (org-table-align)) - (and all (message "Re-applying formulas...done")))))) + (log-first-time (current-time)) + (log-last-time log-first-time) + (cnt 0) + beg end eqlcol eqlfield) + ;; Insert constants in all formulas. + (when eqlist + (org-table-save-field + ;; Expand equations, then split the equation list between + ;; column formulas and field formulas. + (dolist (eq eqlist) + (let* ((rhs (org-table-formula-substitute-names + (org-table-formula-handle-first/last-rc (cdr eq)))) + (old-lhs (car eq)) + (lhs + (org-table-formula-handle-first/last-rc + (cond + ((string-match "\\`@-?I+" old-lhs) + (user-error "Can't assign to hline relative reference")) + ((string-match "\\`$[<>]" old-lhs) + (let ((new (org-table-formula-handle-first/last-rc + old-lhs))) + (when (assoc new eqlist) + (user-error "\"%s=\" formula tries to overwrite \ +existing formula for column %s" + old-lhs + new)) + new)) + (t old-lhs))))) + (if (string-match-p "\\`\\$[0-9]+\\'" lhs) + (push (cons lhs rhs) eqlcol) + (push (cons lhs rhs) eqlfield)))) + (setq eqlcol (nreverse eqlcol)) + ;; Expand ranges in lhs of formulas + (setq eqlfield (org-table-expand-lhs-ranges (nreverse eqlfield))) + ;; Get the correct line range to process. + (if all + (progn + (setq end (copy-marker (org-table-end))) + (goto-char (setq beg org-table-current-begin-pos)) + (cond + ((re-search-forward org-table-calculate-mark-regexp end t) + ;; This is a table with marked lines, compute selected + ;; lines. + (setq line-re org-table-recalculate-regexp)) + ;; Move forward to the first non-header line. + ((and (re-search-forward org-table-dataline-regexp end t) + (re-search-forward org-table-hline-regexp end t) + (re-search-forward org-table-dataline-regexp end t)) + (setq beg (match-beginning 0))) + ;; Just leave BEG at the start of the table. + (t nil))) + (setq beg (line-beginning-position) + end (copy-marker (line-beginning-position 2)))) + (goto-char beg) + ;; Mark named fields untouchable. Also check if several + ;; field/range formulas try to set the same field. + (remove-text-properties beg end '(org-untouchable t)) + (let ((current-line (count-lines org-table-current-begin-pos + (line-beginning-position))) + seen-fields) + (dolist (eq eqlfield) + (let* ((name (car eq)) + (location (assoc name org-table-named-field-locations)) + (eq-line (or (nth 1 location) + (and (string-match "\\`@\\([0-9]+\\)" name) + (aref org-table-dlines + (string-to-number + (match-string 1 name)))))) + (reference + (if location + ;; Turn field coordinates associated to NAME + ;; into an absolute reference. + (format "@%d$%d" + (org-table-line-to-dline eq-line) + (nth 2 location)) + name))) + (when (member reference seen-fields) + (user-error "Several field/range formulas try to set %s" + reference)) + (push reference seen-fields) + (when (or all (eq eq-line current-line)) + (org-table-goto-field name) + (org-table-put-field-property :org-untouchable t))))) + ;; Evaluate the column formulas, but skip fields covered by + ;; field formulas. + (goto-char beg) + (while (re-search-forward line-re end t) + (unless (string-match "\\` *[_^!$/] *\\'" (org-table-get-field 1)) + ;; Unprotected line, recalculate. + (cl-incf cnt) + (when all + (setq log-last-time + (org-table-message-once-per-second + log-last-time + "Re-applying formulas to full table...(line %d)" cnt))) + (if (markerp org-last-recalc-line) + (move-marker org-last-recalc-line (line-beginning-position)) + (setq org-last-recalc-line + (copy-marker (line-beginning-position)))) + (dolist (entry eqlcol) + (goto-char org-last-recalc-line) + (org-table-goto-column + (string-to-number (substring (car entry) 1)) nil 'force) + (unless (get-text-property (point) :org-untouchable) + (org-table-eval-formula + nil (cdr entry) 'noalign 'nocst 'nostore 'noanalysis))))) + ;; Evaluate the field formulas. + (dolist (eq eqlfield) + (let ((reference (car eq)) + (formula (cdr eq))) + (setq log-last-time + (org-table-message-once-per-second + (and all log-last-time) + "Re-applying formula to field: %s" (car eq))) + (org-table-goto-field + reference + ;; Possibly create a new column, as long as + ;; `org-table-formula-create-columns' allows it. + (let ((column-count (progn (end-of-line) + (1- (org-table-current-column))))) + (lambda (column) + (when (> column 1000) + (user-error "Formula column target too large")) + (and (> column column-count) + (or (eq org-table-formula-create-columns t) + (and (eq org-table-formula-create-columns 'warn) + (progn + (org-display-warning + "Out-of-bounds formula added columns") + t)) + (and (eq org-table-formula-create-columns 'prompt) + (yes-or-no-p + "Out-of-bounds formula. Add columns? "))))))) + (org-table-eval-formula nil formula t t t t)))) + ;; Clean up markers and internal text property. + (remove-text-properties (point-min) (point-max) '(org-untouchable t)) + (set-marker end nil) + (unless noalign + (when org-table-may-need-update (org-table-align)) + (when all + (org-table-message-once-per-second + log-first-time "Re-applying formulas to %d lines... done" cnt))) + (org-table-message-once-per-second + (and all log-first-time) "Re-applying formulas... done"))))) ;;;###autoload (defun org-table-iterate (&optional arg) @@ -3145,10 +3329,15 @@ with the prefix ARG." (defun org-table-recalculate-buffer-tables () "Recalculate all tables in the current buffer." (interactive) - (save-excursion - (save-restriction - (widen) - (org-table-map-tables (lambda () (org-table-recalculate t)) t)))) + (org-with-wide-buffer + (org-table-map-tables + (lambda () + ;; Reason for separate `org-table-align': When repeating + ;; (org-table-recalculate t) `org-table-may-need-update' gets in + ;; the way. + (org-table-recalculate t t) + (org-table-align)) + t))) ;;;###autoload (defun org-table-iterate-buffer-tables () @@ -3158,85 +3347,90 @@ with the prefix ARG." (i imax) (checksum (md5 (buffer-string))) c1) - (save-excursion - (save-restriction - (widen) - (catch 'exit - (while (> i 0) - (setq i (1- i)) - (org-table-map-tables (lambda () (org-table-recalculate t)) t) - (if (equal checksum (setq c1 (md5 (buffer-string)))) - (progn - (message "Convergence after %d iterations" (- imax i)) - (throw 'exit t)) - (setq checksum c1))) - (user-error "No convergence after %d iterations" imax)))))) + (org-with-wide-buffer + (catch 'exit + (while (> i 0) + (setq i (1- i)) + (org-table-map-tables (lambda () (org-table-recalculate t t)) t) + (if (equal checksum (setq c1 (md5 (buffer-string)))) + (progn + (org-table-map-tables #'org-table-align t) + (message "Convergence after %d iterations" (- imax i)) + (throw 'exit t)) + (setq checksum c1))) + (org-table-map-tables #'org-table-align t) + (user-error "No convergence after %d iterations" imax))))) (defun org-table-calc-current-TBLFM (&optional arg) "Apply the #+TBLFM in the line at point to the table." (interactive "P") (unless (org-at-TBLFM-p) (user-error "Not at a #+TBLFM line")) (let ((formula (buffer-substring - (point-at-bol) - (point-at-eol))) - s e) + (line-beginning-position) + (line-end-position)))) (save-excursion ;; Insert a temporary formula at right after the table (goto-char (org-table-TBLFM-begin)) - (setq s (point-marker)) - (insert (concat formula "\n")) - (setq e (point-marker)) - ;; Recalculate the table - (beginning-of-line 0) ; move to the inserted line - (skip-chars-backward " \r\n\t") - (if (org-at-table-p) + (let ((s (point-marker))) + (insert formula "\n") + (let ((e (point-marker))) + ;; Recalculate the table. + (beginning-of-line 0) ; move to the inserted line + (skip-chars-backward " \r\n\t") (unwind-protect - (org-call-with-arg 'org-table-recalculate (or arg t)) - ;; delete the formula inserted temporarily - (delete-region s e)))))) + (org-call-with-arg #'org-table-recalculate (or arg t)) + ;; Delete the formula inserted temporarily. + (delete-region s e) + (set-marker s nil) + (set-marker e nil))))))) (defun org-table-TBLFM-begin () "Find the beginning of the TBLFM lines and return its position. Return nil when the beginning of TBLFM line was not found." (save-excursion (when (progn (forward-line 1) - (re-search-backward - org-table-TBLFM-begin-regexp - nil t)) - (point-at-bol 2)))) + (re-search-backward org-table-TBLFM-begin-regexp nil t)) + (line-beginning-position 2)))) (defun org-table-expand-lhs-ranges (equations) "Expand list of formulas. -If some of the RHS in the formulas are ranges or a row reference, expand -them to individual field equations for each field." - (let (e res lhs rhs range r1 r2 c1 c2) - (while (setq e (pop equations)) - (setq lhs (car e) rhs (cdr e)) - (cond - ((string-match "^@-?[-+0-9]+\\$-?[0-9]+$" lhs) - ;; This just refers to one fixed field - (push e res)) - ((string-match "^[a-zA-Z][_a-zA-Z0-9]*$" lhs) - ;; This just refers to one fixed named field - (push e res)) - ((string-match "^@[0-9]+$" lhs) - (loop for ic from 1 to org-table-current-ncol do - (push (cons (format "%s$%d" lhs ic) rhs) res) - (put-text-property 0 (length (caar res)) - :orig-eqn e (caar res)))) - (t - (setq range (org-table-get-range lhs org-table-current-begin-pos - 1 nil 'corners)) - (setq r1 (nth 0 range) c1 (nth 1 range) - r2 (nth 2 range) c2 (nth 3 range)) - (setq r1 (org-table-line-to-dline r1)) - (setq r2 (org-table-line-to-dline r2 'above)) - (loop for ir from r1 to r2 do - (loop for ic from c1 to c2 do - (push (cons (format "@%d$%d" ir ic) rhs) res) - (put-text-property 0 (length (caar res)) - :orig-eqn e (caar res))))))) - (nreverse res))) +If some of the RHS in the formulas are ranges or a row reference, +expand them to individual field equations for each field. This +function assumes the table is already analyzed (i.e., using +`org-table-analyze')." + (let (res) + (dolist (e equations (nreverse res)) + (let ((lhs (car e)) + (rhs (cdr e))) + (cond + ((string-match-p "\\`@-?[-+0-9]+\\$-?[0-9]+\\'" lhs) + ;; This just refers to one fixed field. + (push e res)) + ((string-match-p "\\`[a-zA-Z][_a-zA-Z0-9]*\\'" lhs) + ;; This just refers to one fixed named field. + (push e res)) + ((string-match-p "\\`\\$[0-9]+\\'" lhs) + ;; Column formulas are treated specially and are not + ;; expanded. + (push e res)) + ((string-match "\\`@[0-9]+\\'" lhs) + (dotimes (ic org-table-current-ncol) + (push (cons (propertize (format "%s$%d" lhs (1+ ic)) :orig-eqn e) + rhs) + res))) + (t + (let* ((range (org-table-get-range + lhs org-table-current-begin-pos 1 nil 'corners)) + (r1 (org-table-line-to-dline (nth 0 range))) + (c1 (nth 1 range)) + (r2 (org-table-line-to-dline (nth 2 range) 'above)) + (c2 (nth 3 range))) + (cl-loop for ir from r1 to r2 do + (cl-loop for ic from c1 to c2 do + (push (cons (propertize + (format "@%d$%d" ir ic) :orig-eqn e) + rhs) + res)))))))))) (defun org-table-formula-handle-first/last-rc (s) "Replace @<, @>, $<, $> with first/last row/column of the table. @@ -3262,32 +3456,40 @@ borders of the table using the @< @> $< $> makers." (- nmax len -1))) (if (or (< n 1) (> n nmax)) (user-error "Reference \"%s\" in expression \"%s\" points outside table" - (match-string 0 s) s)) + (match-string 0 s) s)) (setq start (match-beginning 0)) (setq s (replace-match (format "%s%d" (match-string 1 s) n) t t s))))) s) (defun org-table-formula-substitute-names (f) "Replace $const with values in string F." - (let ((start 0) a (f1 f) (pp (/= (string-to-char f) ?'))) - ;; First, check for column names - (while (setq start (string-match org-table-column-name-regexp f start)) - (setq start (1+ start)) - (setq a (assoc (match-string 1 f) org-table-column-names)) - (setq f (replace-match (concat "$" (cdr a)) t t f))) - ;; Parameters and constants - (setq start 0) - (while (setq start (string-match "\\$\\([a-zA-Z][_a-zA-Z0-9]*\\)\\|\\(\\]" (car entry)) 'column) - ((equal (string-to-char (car entry)) ?@) 'field) - ((string-match "^[0-9]" (car entry)) 'column) - (t 'named))) - (when (setq title (assq type titles)) - (or (bobp) (insert "\n")) - (insert (org-add-props (cdr title) nil 'face font-lock-comment-face)) - (setq titles (remove title titles))) - (if (equal key (car entry)) (setq startline (org-current-line))) - (setq s (concat (if (member (string-to-char (car entry)) '(?@ ?$)) "" "$") - (car entry) " = " (cdr entry) "\n")) - (remove-text-properties 0 (length s) '(face nil) s) - (insert s)) - (if (eq org-table-use-standard-references t) + (let ((at-tblfm (org-at-TBLFM-p))) + (unless (or at-tblfm (org-at-table-p)) + (user-error "Not at a table")) + (save-excursion + ;; Move point within the table before analyzing it. + (when at-tblfm (re-search-backward "^[ \t]*|")) + (org-table-analyze)) + (let ((key (org-table-current-field-formula 'key 'noerror)) + (eql (sort (org-table-get-stored-formulas t (and at-tblfm (point))) + #'org-table-formula-less-p)) + (pos (point-marker)) + (source (copy-marker (line-beginning-position))) + (startline 1) + (wc (current-window-configuration)) + (sel-win (selected-window)) + (titles '((column . "# Column Formulas\n") + (field . "# Field and Range Formulas\n") + (named . "# Named Field Formulas\n")))) + (org-switch-to-buffer-other-window "*Edit Formulas*") + (erase-buffer) + ;; Keep global-font-lock-mode from turning on font-lock-mode + (let ((font-lock-global-modes '(not fundamental-mode))) + (fundamental-mode)) + (setq-local font-lock-global-modes (list 'not major-mode)) + (setq-local org-pos pos) + (setq-local org-table--fedit-source source) + (setq-local org-window-configuration wc) + (setq-local org-selected-window sel-win) + (use-local-map org-table-fedit-map) + (add-hook 'post-command-hook #'org-table-fedit-post-command t t) + (easy-menu-add org-table-fedit-menu) + (setq startline (org-current-line)) + (dolist (entry eql) + (let* ((type (cond + ((string-match "\\`$\\([0-9]+\\|[<>]+\\)\\'" (car entry)) + 'column) + ((equal (string-to-char (car entry)) ?@) 'field) + (t 'named))) + (title (assq type titles))) + (when title + (unless (bobp) (insert "\n")) + (insert + (org-add-props (cdr title) nil 'face font-lock-comment-face)) + (setq titles (remove title titles))) + (when (equal key (car entry)) (setq startline (org-current-line))) + (let ((s (concat + (if (memq (string-to-char (car entry)) '(?@ ?$)) "" "$") + (car entry) " = " (cdr entry) "\n"))) + (remove-text-properties 0 (length s) '(face nil) s) + (insert s)))) + (when (eq org-table-use-standard-references t) (org-table-fedit-toggle-ref-type)) - (org-goto-line startline) - (message "%s" "Edit formulas, finish with C-c C-c or C-c '. See menu for more commands."))) + (org-goto-line startline) + (message "%s" (substitute-command-keys "\\\ +Edit formulas, finish with `\\[org-ctrl-c-ctrl-c]' or `\\[org-edit-special]'. \ +See menu for more commands."))))) (defun org-table-fedit-post-command () (when (not (memq this-command '(lisp-complete-symbol))) (let ((win (selected-window))) (save-excursion - (condition-case nil - (org-table-show-reference) - (error nil)) + (ignore-errors (org-table-show-reference)) (select-window win))))) (defun org-table-formula-to-user (s) @@ -3537,23 +3748,24 @@ minutes or seconds." (format "%.1f" (/ (float secs0) 60))) ((eq output-format 'seconds) (format "%d" secs0)) - (t (org-format-seconds "%.2h:%.2m:%.2s" secs0))))) + (t (format-seconds "%.2h:%.2m:%.2s" secs0))))) (if (< secs 0) (concat "-" res) res))) (defun org-table-fedit-convert-buffer (function) "Convert all references in this buffer, using FUNCTION." - (let ((line (org-current-line))) + (let ((origin (copy-marker (line-beginning-position)))) (goto-char (point-min)) (while (not (eobp)) - (insert (funcall function (buffer-substring (point) (point-at-eol)))) - (delete-region (point) (point-at-eol)) - (or (eobp) (forward-char 1))) - (org-goto-line line))) + (insert (funcall function (buffer-substring (point) (line-end-position)))) + (delete-region (point) (line-end-position)) + (forward-line)) + (goto-char origin) + (set-marker origin nil))) (defun org-table-fedit-toggle-ref-type () "Convert all references in the buffer from B3 to @3$2 and back." (interactive) - (org-set-local 'org-table-buffer-is-an (not org-table-buffer-is-an)) + (setq-local org-table-buffer-is-an (not org-table-buffer-is-an)) (org-table-fedit-convert-buffer (if org-table-buffer-is-an 'org-table-convert-refs-to-an 'org-table-convert-refs-to-rc)) @@ -3579,16 +3791,16 @@ minutes or seconds." (defun org-table-fedit-shift-reference (dir) (cond - ((org-at-regexp-p "\\(\\<[a-zA-Z]\\)&") + ((org-in-regexp "\\(\\<[a-zA-Z]\\)&") (if (memq dir '(left right)) (org-rematch-and-replace 1 (eq dir 'left)) (user-error "Cannot shift reference in this direction"))) - ((org-at-regexp-p "\\(\\<[a-zA-Z]\\{1,2\\}\\)\\([0-9]+\\)") + ((org-in-regexp "\\(\\<[a-zA-Z]\\{1,2\\}\\)\\([0-9]+\\)") ;; A B3-like reference (if (memq dir '(up down)) (org-rematch-and-replace 2 (eq dir 'up)) (org-rematch-and-replace 1 (eq dir 'left)))) - ((org-at-regexp-p + ((org-in-regexp "\\(@\\|\\.\\.\\)\\([-+]?\\(I+\\>\\|[0-9]+\\)\\)\\(\\$\\([-+]?[0-9]+\\)\\)?") ;; An internal reference (if (memq dir '(up down)) @@ -3649,32 +3861,31 @@ a translation reference." With prefix ARG, apply the new formulas to the table." (interactive "P") (org-table-remove-rectangle-highlight) - (if org-table-use-standard-references - (progn - (org-table-fedit-convert-buffer 'org-table-convert-refs-to-rc) - (setq org-table-buffer-is-an nil))) - (let ((pos org-pos) (sel-win org-selected-window) eql var form) + (when org-table-use-standard-references + (org-table-fedit-convert-buffer 'org-table-convert-refs-to-rc) + (setq org-table-buffer-is-an nil)) + (let ((pos org-pos) + (sel-win org-selected-window) + (source org-table--fedit-source) + eql) (goto-char (point-min)) (while (re-search-forward "^\\(@[-+I<>0-9.$@]+\\|@?[0-9]+\\|\\$\\([a-zA-Z0-9]+\\|[<>]+\\)\\) *= *\\(.*\\(\n[ \t]+.*$\\)*\\)" nil t) - (setq var (if (match-end 2) (match-string 2) (match-string 1)) - form (match-string 3)) - (setq form (org-trim form)) - (when (not (equal form "")) - (while (string-match "[ \t]*\n[ \t]*" form) - (setq form (replace-match " " t t form))) - (when (assoc var eql) - (user-error "Double formulas for %s" var)) - (push (cons var form) eql))) - (setq org-pos nil) + (let ((var (match-string 1)) + (form (org-trim (match-string 3)))) + (unless (equal form "") + (while (string-match "[ \t]*\n[ \t]*" form) + (setq form (replace-match " " t t form))) + (when (assoc var eql) + (user-error "Double formulas for %s" var)) + (push (cons var form) eql)))) (set-window-configuration org-window-configuration) (select-window sel-win) - (goto-char pos) - (unless (org-at-table-p) - (user-error "Lost table position - cannot install formulas")) + (goto-char source) (org-table-store-formulas eql) - (move-marker pos nil) + (set-marker pos nil) + (set-marker source nil) (kill-buffer "*Edit Formulas*") (if arg (org-table-recalculate 'all) @@ -3733,9 +3944,11 @@ With prefix ARG, apply the new formulas to the table." (defvar org-show-positions nil) (defun org-table-show-reference (&optional local) - "Show the location/value of the $ expression at point." + "Show the location/value of the $ expression at point. +When LOCAL is non-nil, show references for the table at point." (interactive) (org-table-remove-rectangle-highlight) + (when local (org-table-analyze)) (catch 'exit (let ((pos (if local (point) org-pos)) (face2 'highlight) @@ -3743,41 +3956,41 @@ With prefix ARG, apply the new formulas to the table." (win (selected-window)) (org-show-positions nil) var name e what match dest) - (if local (org-table-get-specials)) (setq what (cond - ((org-at-regexp-p "^@[0-9]+[ \t=]") + ((org-in-regexp "^@[0-9]+[ \t=]") (setq match (concat (substring (match-string 0) 0 -1) "$1.." (substring (match-string 0) 0 -1) "$100")) 'range) - ((or (org-at-regexp-p org-table-range-regexp2) - (org-at-regexp-p org-table-translate-regexp) - (org-at-regexp-p org-table-range-regexp)) + ((or (org-in-regexp org-table-range-regexp2) + (org-in-regexp org-table-translate-regexp) + (org-in-regexp org-table-range-regexp)) (setq match (save-match-data (org-table-convert-refs-to-rc (match-string 0)))) 'range) - ((org-at-regexp-p "\\$[a-zA-Z][a-zA-Z0-9]*") 'name) - ((org-at-regexp-p "\\$[0-9]+") 'column) + ((org-in-regexp "\\$[a-zA-Z][a-zA-Z0-9]*") 'name) + ((org-in-regexp "\\$[0-9]+") 'column) ((not local) nil) (t (user-error "No reference at point"))) match (and what (or match (match-string 0)))) (when (and match (not (equal (match-beginning 0) (point-at-bol)))) (org-table-add-rectangle-overlay (match-beginning 0) (match-end 0) 'secondary-selection)) - (org-add-hook 'before-change-functions - 'org-table-remove-rectangle-highlight) - (if (eq what 'name) (setq var (substring match 1))) + (add-hook 'before-change-functions + #'org-table-remove-rectangle-highlight) + (when (eq what 'name) (setq var (substring match 1))) (when (eq what 'range) - (or (equal (string-to-char match) ?@) (setq match (concat "@" match))) + (unless (eq (string-to-char match) ?@) (setq match (concat "@" match))) (setq match (org-table-formula-substitute-names match))) (unless local (save-excursion - (end-of-line 1) + (end-of-line) (re-search-backward "^\\S-" nil t) - (beginning-of-line 1) - (when (looking-at "\\(\\$[0-9a-zA-Z]+\\|@[0-9]+\\$[0-9]+\\|[a-zA-Z]+\\([0-9]+\\|&\\)\\) *=") + (beginning-of-line) + (when (looking-at "\\(\\$[0-9a-zA-Z]+\\|@[0-9]+\\$[0-9]+\\|[a-zA-Z]+\ +\\([0-9]+\\|&\\)\\) *=") (setq dest (save-match-data (org-table-convert-refs-to-rc (match-string 1)))) @@ -3790,60 +4003,52 @@ With prefix ARG, apply the new formulas to the table." (marker-buffer pos))))) (goto-char pos) (org-table-force-dataline) - (when dest - (setq name (substring dest 1)) - (cond - ((string-match "^\\$[a-zA-Z][a-zA-Z0-9]*" dest) - (setq e (assoc name org-table-named-field-locations)) - (org-goto-line (nth 1 e)) - (org-table-goto-column (nth 2 e))) - ((string-match "^@\\([0-9]+\\)\\$\\([0-9]+\\)" dest) - (let ((l (string-to-number (match-string 1 dest))) - (c (string-to-number (match-string 2 dest)))) - (org-goto-line (aref org-table-dlines l)) - (org-table-goto-column c))) - (t (org-table-goto-column (string-to-number name)))) - (move-marker pos (point)) - (org-table-highlight-rectangle nil nil face2)) - (cond - ((equal dest match)) - ((not match)) - ((eq what 'range) - (condition-case nil - (save-excursion - (org-table-get-range match nil nil 'highlight)) - (error nil))) - ((setq e (assoc var org-table-named-field-locations)) - (org-goto-line (nth 1 e)) - (org-table-goto-column (nth 2 e)) - (org-table-highlight-rectangle (point) (point)) - (message "Named field, column %d of line %d" (nth 2 e) (nth 1 e))) - ((setq e (assoc var org-table-column-names)) - (org-table-goto-column (string-to-number (cdr e))) - (org-table-highlight-rectangle (point) (point)) - (goto-char (org-table-begin)) - (if (re-search-forward (concat "^[ \t]*| *! *.*?| *\\(" var "\\) *|") - (org-table-end) t) - (progn - (goto-char (match-beginning 1)) - (org-table-highlight-rectangle) - (message "Named column (column %s)" (cdr e))) - (user-error "Column name not found"))) - ((eq what 'column) - ;; column number - (org-table-goto-column (string-to-number (substring match 1))) - (org-table-highlight-rectangle (point) (point)) - (message "Column %s" (substring match 1))) - ((setq e (assoc var org-table-local-parameters)) - (goto-char (org-table-begin)) - (if (re-search-forward (concat "^[ \t]*| *\\$ *.*?| *\\(" var "=\\)") nil t) - (progn - (goto-char (match-beginning 1)) - (org-table-highlight-rectangle) - (message "Local parameter.")) - (user-error "Parameter not found"))) - (t + (let ((table-start + (if local org-table-current-begin-pos (org-table-begin)))) + (when dest + (setq name (substring dest 1)) + (cond + ((string-match-p "\\`\\$[a-zA-Z][a-zA-Z0-9]*" dest) + (org-table-goto-field dest)) + ((string-match-p "\\`@\\([1-9][0-9]*\\)\\$\\([1-9][0-9]*\\)\\'" + dest) + (org-table-goto-field dest)) + (t (org-table-goto-column (string-to-number name)))) + (move-marker pos (point)) + (org-table-highlight-rectangle nil nil face2)) (cond + ((equal dest match)) + ((not match)) + ((eq what 'range) + (ignore-errors (org-table-get-range match table-start nil 'highlight))) + ((setq e (assoc var org-table-named-field-locations)) + (org-table-goto-field var) + (org-table-highlight-rectangle) + (message "Named field, column %d of line %d" (nth 2 e) (nth 1 e))) + ((setq e (assoc var org-table-column-names)) + (org-table-goto-column (string-to-number (cdr e))) + (org-table-highlight-rectangle) + (goto-char table-start) + (if (re-search-forward (concat "^[ \t]*| *! *.*?| *\\(" var "\\) *|") + (org-table-end) t) + (progn + (goto-char (match-beginning 1)) + (org-table-highlight-rectangle) + (message "Named column (column %s)" (cdr e))) + (user-error "Column name not found"))) + ((eq what 'column) + ;; Column number. + (org-table-goto-column (string-to-number (substring match 1))) + (org-table-highlight-rectangle) + (message "Column %s" (substring match 1))) + ((setq e (assoc var org-table-local-parameters)) + (goto-char table-start) + (if (re-search-forward (concat "^[ \t]*| *\\$ *.*?| *\\(" var "=\\)") nil t) + (progn + (goto-char (match-beginning 1)) + (org-table-highlight-rectangle) + (message "Local parameter.")) + (user-error "Parameter not found"))) ((not var) (user-error "No reference at point")) ((setq e (assoc var org-table-formula-constants-local)) (message "Local Constant: $%s=%s in #+CONSTANTS line." @@ -3854,19 +4059,19 @@ With prefix ARG, apply the new formulas to the table." ((setq e (and (fboundp 'constants-get) (constants-get var))) (message "Constant: $%s=%s, from `constants.el'%s." var e (format " (%s units)" constants-unit-system))) - (t (user-error "Undefined name $%s" var))))) - (goto-char pos) - (when (and org-show-positions - (not (memq this-command '(org-table-fedit-scroll - org-table-fedit-scroll-down)))) - (push pos org-show-positions) - (push org-table-current-begin-pos org-show-positions) - (let ((min (apply 'min org-show-positions)) - (max (apply 'max org-show-positions))) - (set-window-start (selected-window) min) - (goto-char max) - (or (pos-visible-in-window-p max) - (set-window-start (selected-window) max)))) + (t (user-error "Undefined name $%s" var))) + (goto-char pos) + (when (and org-show-positions + (not (memq this-command '(org-table-fedit-scroll + org-table-fedit-scroll-down)))) + (push pos org-show-positions) + (push table-start org-show-positions) + (let ((min (apply 'min org-show-positions)) + (max (apply 'max org-show-positions))) + (set-window-start (selected-window) min) + (goto-char max) + (or (pos-visible-in-window-p max) + (set-window-start (selected-window) max))))) (select-window win)))) (defun org-table-force-dataline () @@ -3926,43 +4131,49 @@ Use COMMAND to do the motion, repeat if necessary to end up in a data line." (push ov org-table-rectangle-overlays))) (defun org-table-highlight-rectangle (&optional beg end face) - "Highlight rectangular region in a table." - (setq beg (or beg (point)) end (or end (point))) - (let ((b (min beg end)) - (e (max beg end)) - l1 c1 l2 c2 tmp) - (and (boundp 'org-show-positions) - (setq org-show-positions (cons b (cons e org-show-positions)))) - (goto-char (min beg end)) - (setq l1 (org-current-line) - c1 (org-table-current-column)) - (goto-char (max beg end)) - (setq l2 (org-current-line) - c2 (org-table-current-column)) - (if (> c1 c2) (setq tmp c1 c1 c2 c2 tmp)) - (org-goto-line l1) - (beginning-of-line 1) - (loop for line from l1 to l2 do - (when (looking-at org-table-dataline-regexp) - (org-table-goto-column c1) - (skip-chars-backward "^|\n") (setq beg (point)) - (org-table-goto-column c2) - (skip-chars-forward "^|\n") (setq end (point)) - (org-table-add-rectangle-overlay beg end face)) - (beginning-of-line 2)) - (goto-char b)) - (add-hook 'before-change-functions 'org-table-remove-rectangle-highlight)) - -(defun org-table-remove-rectangle-highlight (&rest ignore) + "Highlight rectangular region in a table. +When buffer positions BEG and END are provided, use them to +delimit the region to highlight. Otherwise, refer to point. Use +FACE, when non-nil, for the highlight." + (let* ((beg (or beg (point))) + (end (or end (point))) + (b (min beg end)) + (e (max beg end)) + (start-coordinates + (save-excursion + (goto-char b) + (cons (line-beginning-position) (org-table-current-column)))) + (end-coordinates + (save-excursion + (goto-char e) + (cons (line-beginning-position) (org-table-current-column))))) + (when (boundp 'org-show-positions) + (setq org-show-positions (cons b (cons e org-show-positions)))) + (goto-char (car start-coordinates)) + (let ((column-start (min (cdr start-coordinates) (cdr end-coordinates))) + (column-end (max (cdr start-coordinates) (cdr end-coordinates))) + (last-row (car end-coordinates))) + (while (<= (point) last-row) + (when (looking-at org-table-dataline-regexp) + (org-table-goto-column column-start) + (skip-chars-backward "^|\n") + (let ((p (point))) + (org-table-goto-column column-end) + (skip-chars-forward "^|\n") + (org-table-add-rectangle-overlay p (point) face))) + (forward-line))) + (goto-char (car start-coordinates))) + (add-hook 'before-change-functions #'org-table-remove-rectangle-highlight)) + +(defun org-table-remove-rectangle-highlight (&rest _ignore) "Remove the rectangle overlays." (unless org-inhibit-highlight-removal (remove-hook 'before-change-functions 'org-table-remove-rectangle-highlight) (mapc 'delete-overlay org-table-rectangle-overlays) (setq org-table-rectangle-overlays nil))) -(defvar org-table-coordinate-overlays nil +(defvar-local org-table-coordinate-overlays nil "Collects the coordinate grid overlays, so that they can be removed.") -(make-variable-buffer-local 'org-table-coordinate-overlays) (defun org-table-overlay-coordinates () "Add overlays to the table at point, to show row/column coordinates." @@ -4017,19 +4228,20 @@ Use COMMAND to do the motion, repeat if necessary to end up in a data line." ;;; The orgtbl minor mode ;; Define a minor mode which can be used in other modes in order to -;; integrate the org-mode table editor. - -;; This is really a hack, because the org-mode table editor uses several -;; keys which normally belong to the major mode, for example the TAB and -;; RET keys. Here is how it works: The minor mode defines all the keys -;; necessary to operate the table editor, but wraps the commands into a -;; function which tests if the cursor is currently inside a table. If that -;; is the case, the table editor command is executed. However, when any of -;; those keys is used outside a table, the function uses `key-binding' to -;; look up if the key has an associated command in another currently active -;; keymap (minor modes, major mode, global), and executes that command. -;; There might be problems if any of the keys used by the table editor is -;; otherwise used as a prefix key. +;; integrate the Org table editor. + +;; This is really a hack, because the Org table editor uses several +;; keys which normally belong to the major mode, for example the TAB +;; and RET keys. Here is how it works: The minor mode defines all the +;; keys necessary to operate the table editor, but wraps the commands +;; into a function which tests if the cursor is currently inside +;; a table. If that is the case, the table editor command is +;; executed. However, when any of those keys is used outside a table, +;; the function uses `key-binding' to look up if the key has an +;; associated command in another currently active keymap (minor modes, +;; major mode, global), and executes that command. There might be +;; problems if any of the keys used by the table editor is otherwise +;; used as a prefix key. ;; Another challenge is that the key binding for TAB can be tab or \C-i, ;; likewise the binding for RET can be return or \C-m. Orgtbl-mode @@ -4079,16 +4291,16 @@ Use COMMAND to do the motion, repeat if necessary to end up in a data line." ;; FIXME: maybe it should use emulation-mode-map-alists? (and c (setq minor-mode-map-alist (cons c (delq c minor-mode-map-alist))))) - (org-set-local (quote org-table-may-need-update) t) - (org-add-hook 'before-change-functions 'org-before-change-function - nil 'local) - (org-set-local 'org-old-auto-fill-inhibit-regexp - auto-fill-inhibit-regexp) - (org-set-local 'auto-fill-inhibit-regexp - (if auto-fill-inhibit-regexp - (concat orgtbl-line-start-regexp "\\|" - auto-fill-inhibit-regexp) - orgtbl-line-start-regexp)) + (setq-local org-table-may-need-update t) + (add-hook 'before-change-functions 'org-before-change-function + nil 'local) + (setq-local org-old-auto-fill-inhibit-regexp + auto-fill-inhibit-regexp) + (setq-local auto-fill-inhibit-regexp + (if auto-fill-inhibit-regexp + (concat orgtbl-line-start-regexp "\\|" + auto-fill-inhibit-regexp) + orgtbl-line-start-regexp)) (add-to-invisibility-spec '(org-cwidth)) (when (fboundp 'font-lock-add-keywords) (font-lock-add-keywords nil orgtbl-extra-font-lock-keywords) @@ -4188,27 +4400,26 @@ to execute outside of tables." cmd (orgtbl-make-binding fun nfunc key)) (org-defkey orgtbl-mode-map key cmd)) - ;; Special treatment needed for TAB and RET + ;; Special treatment needed for TAB, RET and DEL (org-defkey orgtbl-mode-map [(return)] (orgtbl-make-binding 'orgtbl-ret 100 [(return)] "\C-m")) (org-defkey orgtbl-mode-map "\C-m" (orgtbl-make-binding 'orgtbl-ret 101 "\C-m" [(return)])) - (org-defkey orgtbl-mode-map [(tab)] (orgtbl-make-binding 'orgtbl-tab 102 [(tab)] "\C-i")) (org-defkey orgtbl-mode-map "\C-i" (orgtbl-make-binding 'orgtbl-tab 103 "\C-i" [(tab)])) - (org-defkey orgtbl-mode-map [(shift tab)] (orgtbl-make-binding 'org-table-previous-field 104 [(shift tab)] [(tab)] "\C-i")) + (org-defkey orgtbl-mode-map [backspace] + (orgtbl-make-binding 'org-delete-backward-char 109 + [backspace] (kbd "DEL"))) - - (unless (featurep 'xemacs) - (org-defkey orgtbl-mode-map [S-iso-lefttab] - (orgtbl-make-binding 'org-table-previous-field 107 - [S-iso-lefttab] [backtab] [(shift tab)] - [(tab)] "\C-i"))) + (org-defkey orgtbl-mode-map [S-iso-lefttab] + (orgtbl-make-binding 'org-table-previous-field 107 + [S-iso-lefttab] [backtab] [(shift tab)] + [(tab)] "\C-i")) (org-defkey orgtbl-mode-map [backtab] (orgtbl-make-binding 'org-table-previous-field 108 @@ -4269,7 +4480,7 @@ to execute outside of tables." "--" ("Radio tables" ["Insert table template" orgtbl-insert-radio-table - (assq major-mode orgtbl-radio-table-templates)] + (cl-assoc-if #'derived-mode-p orgtbl-radio-table-templates)] ["Comment/uncomment table" orgtbl-toggle-comment t]) "--" ["Set Column Formula" org-table-eval-formula :active (org-at-table-p) :keys "C-c ="] @@ -4290,7 +4501,10 @@ to execute outside of tables." org-table-toggle-coordinate-overlays :active (org-at-table-p) :keys "C-c }" :style toggle :selected org-table-overlay-coordinates] - )) + "--" + ("Plot" + ["Ascii plot" orgtbl-ascii-plot :active (org-at-table-p) :keys "C-c \" a"] + ["Gnuplot" org-plot/gnuplot :active (org-at-table-p) :keys "C-c \" g"]))) t)) (defun orgtbl-ctrl-c-ctrl-c (arg) @@ -4316,7 +4530,6 @@ With prefix arg, also recompute table." (when (orgtbl-send-table 'maybe) (run-hooks 'orgtbl-after-send-table-hook))) ((eq action 'recalc) - (org-table-set-constants) (save-excursion (beginning-of-line 1) (skip-chars-backward " \r\n\t") @@ -4325,7 +4538,7 @@ With prefix arg, also recompute table." (t (let (orgtbl-mode) (call-interactively (key-binding "\C-c\C-c"))))))) -(defun orgtbl-create-or-convert-from-region (arg) +(defun orgtbl-create-or-convert-from-region (_arg) "Create table or convert region to table, if no conflicting binding. This installs the table binding `C-c |', but only if there is no conflicting binding to this key outside orgtbl-mode." @@ -4369,11 +4582,9 @@ overwritten, and the table is not marked as requiring realignment." (org-table-blank-field)) t) (eq N 1) - (looking-at "[^|\n]* +|")) + (looking-at "[^|\n]* \\( \\)|")) (let (org-table-may-need-update) - (goto-char (1- (match-end 0))) - (org-delete-backward-char 1) - (goto-char (match-beginning 0)) + (delete-region (match-beginning 1) (match-end 1)) (self-insert-command N)) (setq org-table-may-need-update t) (let* (orgtbl-mode @@ -4398,6 +4609,7 @@ overwritten, and the table is not marked as requiring realignment." (setq org-self-insert-command-undo-counter (1+ org-self-insert-command-undo-counter)))))))) +;;;###autoload (defvar orgtbl-exp-regexp "^\\([-+]?[0-9][0-9.]*\\)[eE]\\([-+]?[0-9]+\\)$" "Regular expression matching exponentials as produced by calc.") @@ -4418,23 +4630,24 @@ a radio table." (beginning-of-line 0))) rtn))) -(defun orgtbl-send-replace-tbl (name txt) - "Find and replace table NAME with TXT." +(defun orgtbl-send-replace-tbl (name text) + "Find and replace table NAME with TEXT." (save-excursion (goto-char (point-min)) - (unless (re-search-forward - (concat "BEGIN +RECEIVE +ORGTBL +" name "\\([ \t]\\|$\\)") nil t) - (user-error "Don't know where to insert translated table")) - (goto-char (match-beginning 0)) - (beginning-of-line 2) - (save-excursion - (let ((beg (point))) - (unless (re-search-forward - (concat "END +RECEIVE +ORGTBL +" name) nil t) - (user-error "Cannot find end of insertion region")) - (beginning-of-line 1) - (delete-region beg (point)))) - (insert txt "\n"))) + (let* ((location-flag nil) + (name (regexp-quote name)) + (begin-re (format "BEGIN +RECEIVE +ORGTBL +%s\\([ \t]\\|$\\)" name)) + (end-re (format "END +RECEIVE +ORGTBL +%s\\([ \t]\\|$\\)" name))) + (while (re-search-forward begin-re nil t) + (unless location-flag (setq location-flag t)) + (let ((beg (line-beginning-position 2))) + (unless (re-search-forward end-re nil t) + (user-error "Cannot find end of receiver location at %d" beg)) + (beginning-of-line) + (delete-region beg (point)) + (insert text "\n"))) + (unless location-flag + (user-error "No valid receiver location found in the buffer"))))) ;;;###autoload (defun org-table-to-lisp (&optional txt) @@ -4442,76 +4655,43 @@ a radio table." The structure will be a list. Each item is either the symbol `hline' for a horizontal separator line, or a list of field values as strings. The table is taken from the parameter TXT, or from the buffer at point." - (unless txt - (unless (org-at-table-p) - (user-error "No table at point"))) - (let* ((txt (or txt - (buffer-substring-no-properties (org-table-begin) - (org-table-end)))) - (lines (org-split-string txt "[ \t]*\n[ \t]*"))) - - (mapcar - (lambda (x) - (if (string-match org-table-hline-regexp x) - 'hline - (org-split-string (org-trim x) "\\s-*|\\s-*"))) - lines))) + (unless (or txt (org-at-table-p)) (user-error "No table at point")) + (let ((txt (or txt + (buffer-substring-no-properties (org-table-begin) + (org-table-end))))) + (mapcar (lambda (x) + (if (string-match org-table-hline-regexp x) 'hline + (org-split-string (org-trim x) "\\s-*|\\s-*"))) + (org-split-string txt "[ \t]*\n[ \t]*")))) (defun orgtbl-send-table (&optional maybe) - "Send a transformed version of this table to the receiver position. -With argument MAYBE, fail quietly if no transformation is defined for -this table." + "Send a transformed version of table at point to the receiver position. +With argument MAYBE, fail quietly if no transformation is defined +for this table." (interactive) (catch 'exit (unless (org-at-table-p) (user-error "Not at a table")) ;; when non-interactive, we assume align has just happened. - (when (org-called-interactively-p 'any) (org-table-align)) + (when (called-interactively-p 'any) (org-table-align)) (let ((dests (orgtbl-gather-send-defs)) - (txt (buffer-substring-no-properties (org-table-begin) - (org-table-end))) + (table (org-table-to-lisp + (buffer-substring-no-properties (org-table-begin) + (org-table-end)))) (ntbl 0)) - (unless dests (if maybe (throw 'exit nil) - (user-error "Don't know how to transform this table"))) + (unless dests + (if maybe (throw 'exit nil) + (user-error "Don't know how to transform this table"))) (dolist (dest dests) - (let* ((name (plist-get dest :name)) - (transform (plist-get dest :transform)) - (params (plist-get dest :params)) - (skip (plist-get params :skip)) - (skipcols (plist-get params :skipcols)) - (no-escape (plist-get params :no-escape)) - beg - (lines (org-table-clean-before-export - (nthcdr (or skip 0) - (org-split-string txt "[ \t]*\n[ \t]*")))) - (i0 (if org-table-clean-did-remove-column 2 1)) - (lines (if no-escape lines - (mapcar (lambda(l) (replace-regexp-in-string - "\\([&%#_^]\\)" "\\\\\\1{}" l)) lines))) - (table (mapcar - (lambda (x) - (if (string-match org-table-hline-regexp x) - 'hline - (org-remove-by-index - (org-split-string (org-trim x) "\\s-*|\\s-*") - skipcols i0))) - lines)) - (fun (if (= i0 2) 'cdr 'identity)) - (org-table-last-alignment - (org-remove-by-index (funcall fun org-table-last-alignment) - skipcols i0)) - (org-table-last-column-widths - (org-remove-by-index (funcall fun org-table-last-column-widths) - skipcols i0)) - (txt (if (fboundp transform) - (funcall transform table params) - (user-error "No such transformation function %s" transform)))) - (orgtbl-send-replace-tbl name txt)) - (setq ntbl (1+ ntbl))) + (let ((name (plist-get dest :name)) + (transform (plist-get dest :transform)) + (params (plist-get dest :params))) + (unless (fboundp transform) + (user-error "No such transformation function %s" transform)) + (orgtbl-send-replace-tbl name (funcall transform table params))) + (cl-incf ntbl)) (message "Table converted and installed at %d receiver location%s" ntbl (if (> ntbl 1) "s" "")) - (if (> ntbl 0) - ntbl - nil)))) + (and (> ntbl 0) ntbl)))) (defun org-remove-by-index (list indices &optional i0) "Remove the elements in LIST with indices in INDICES. @@ -4549,7 +4729,7 @@ First element has index 0, or I0 if given." (defun orgtbl-insert-radio-table () "Insert a radio table template appropriate for this major mode." (interactive) - (let* ((e (assq major-mode orgtbl-radio-table-templates)) + (let* ((e (cl-assoc-if #'derived-mode-p orgtbl-radio-table-templates)) (txt (nth 1 e)) name pos) (unless e (user-error "No radio table setup defined for %s" major-mode)) @@ -4561,356 +4741,512 @@ First element has index 0, or I0 if given." (insert txt) (goto-char pos))) -;; Dynamically bound input and output for table formatting. -(defvar *orgtbl-table* nil - "Carries the current table through formatting routines.") -(defvar *orgtbl-rtn* nil - "Formatting routines push the output lines here.") -;; Formatting parameters for the current table section. -(defvar *orgtbl-hline* nil "Text used for horizontal lines.") -(defvar *orgtbl-sep* nil "Text used as a column separator.") -(defvar *orgtbl-default-fmt* nil "Default format for each entry.") -(defvar *orgtbl-fmt* nil "Format for each entry.") -(defvar *orgtbl-efmt* nil "Format for numbers.") -(defvar *orgtbl-lfmt* nil "Format for an entire line, overrides fmt.") -(defvar *orgtbl-llfmt* nil "Specializes lfmt for the last row.") -(defvar *orgtbl-lstart* nil "Text starting a row.") -(defvar *orgtbl-llstart* nil "Specializes lstart for the last row.") -(defvar *orgtbl-lend* nil "Text ending a row.") -(defvar *orgtbl-llend* nil "Specializes lend for the last row.") - -(defsubst orgtbl-get-fmt (fmt i) - "Retrieve the format from FMT corresponding to the Ith column." - (if (and (not (functionp fmt)) (consp fmt)) - (plist-get fmt i) - fmt)) - -(defsubst orgtbl-apply-fmt (fmt &rest args) - "Apply format FMT to arguments ARGS. -When FMT is nil, return the first argument from ARGS." - (cond ((functionp fmt) (apply fmt args)) - (fmt (apply 'format fmt args)) - (args (car args)) - (t args))) - -(defsubst orgtbl-eval-str (str) - "If STR is a function, evaluate it with no arguments." - (if (functionp str) - (funcall str) - str)) - -(defun orgtbl-format-line (line) - "Format LINE as a table row." - (if (eq line 'hline) (if *orgtbl-hline* (push *orgtbl-hline* *orgtbl-rtn*)) - (let* ((i 0) - (line - (mapcar - (lambda (f) - (setq i (1+ i)) - (let* ((efmt (orgtbl-get-fmt *orgtbl-efmt* i)) - (f (if (and efmt (string-match orgtbl-exp-regexp f)) - (orgtbl-apply-fmt efmt (match-string 1 f) - (match-string 2 f)) - f))) - (orgtbl-apply-fmt (or (orgtbl-get-fmt *orgtbl-fmt* i) - *orgtbl-default-fmt*) - f))) - line))) - (push (if *orgtbl-lfmt* - (apply #'orgtbl-apply-fmt *orgtbl-lfmt* line) - (concat (orgtbl-eval-str *orgtbl-lstart*) - (mapconcat 'identity line *orgtbl-sep*) - (orgtbl-eval-str *orgtbl-lend*))) - *orgtbl-rtn*)))) - -(defun orgtbl-format-section (section-stopper) - "Format lines until the first occurrence of SECTION-STOPPER." - (let (prevline) - (progn - (while (not (eq (car *orgtbl-table*) section-stopper)) - (if prevline (orgtbl-format-line prevline)) - (setq prevline (pop *orgtbl-table*))) - (if prevline (let ((*orgtbl-lstart* *orgtbl-llstart*) - (*orgtbl-lend* *orgtbl-llend*) - (*orgtbl-lfmt* *orgtbl-llfmt*)) - (orgtbl-format-line prevline)))))) - ;;;###autoload -(defun orgtbl-to-generic (table params &optional backend) +(defun orgtbl-to-generic (table params) "Convert the orgtbl-mode TABLE to some other format. + This generic routine can be used for many standard cases. -TABLE is a list, each entry either the symbol `hline' for a horizontal -separator line, or a list of fields for that line. -PARAMS is a property list of parameters that can influence the conversion. -A third optional argument BACKEND can be used to convert the content of -the cells using a specific export back-end. -For the generic converter, some parameters are obligatory: you need to -specify either :lfmt, or all of (:lstart :lend :sep). +TABLE is a list, each entry either the symbol `hline' for +a horizontal separator line, or a list of fields for that +line. PARAMS is a property list of parameters that can +influence the conversion. Valid parameters are: -:splice When set to t, return only table body lines, don't wrap - them into :tstart and :tend. Default is nil. When :splice - is non-nil, this also means that the exporter should not look - for and interpret header and footer sections. +:backend, :raw + + Export back-end used as a basis to transcode elements of the + table, when no specific parameter applies to it. It is also + used to translate cells contents. You can prevent this by + setting :raw property to a non-nil value. -:hline String to be inserted on horizontal separation lines. - May be nil to ignore hlines. +:splice -:sep Separator between two fields -:remove-nil-lines Do not include lines that evaluate to nil. + When non-nil, only convert rows, not the table itself. This is + equivalent to setting to the empty string both :tstart + and :tend, which see. + +:skip + + When set to an integer N, skip the first N lines of the table. + Horizontal separation lines do count for this parameter! + +:skipcols + + List of columns that should be skipped. If the table has + a column with calculation marks, that column is automatically + discarded beforehand. + +:hline + + String to be inserted on horizontal separation lines. May be + nil to ignore these lines altogether. + +:sep + + Separator between two fields, as a string. Each in the following group may be either a string or a function of no arguments returning a string: -:tstart String to start the table. Ignored when :splice is t. -:tend String to end the table. Ignored when :splice is t. -:lstart String to start a new table line. -:llstart String to start the last table line, defaults to :lstart. -:lend String to end a table line -:llend String to end the last table line, defaults to :lend. - -Each in the following group may be a string, a function of one -argument (the field or line) returning a string, or a plist -mapping columns to either of the above: - -:lfmt Format for entire line, with enough %s to capture all fields. - If this is present, :lstart, :lend, and :sep are ignored. -:llfmt Format for the entire last line, defaults to :lfmt. -:fmt A format to be used to wrap the field, should contain - %s for the original field value. For example, to wrap - everything in dollars, you could use :fmt \"$%s$\". - This may also be a property list with column numbers and - formats. For example :fmt (2 \"$%s$\" 4 \"%s%%\") -:hlstart :hllstart :hlend :hllend :hlsep :hlfmt :hllfmt :hfmt - Same as above, specific for the header lines in the table. - All lines before the first hline are treated as header. - If any of these is not present, the data line value is used. +:tstart, :tend + + Strings to start and end the table. Ignored when :splice is t. + +:lstart, :lend + + Strings to start and end a new table line. + +:llstart, :llend + + Strings to start and end the last table line. Default, + respectively, to :lstart and :lend. + +Each in the following group may be a string or a function of one +argument (either the cells in the current row, as a list of +strings, or the current cell) returning a string: + +:lfmt + + Format string for an entire row, with enough %s to capture all + fields. When non-nil, :lstart, :lend, and :sep are ignored. + +:llfmt + + Format for the entire last line, defaults to :lfmt. + +:fmt + + A format to be used to wrap the field, should contain %s for + the original field value. For example, to wrap everything in + dollars, you could use :fmt \"$%s$\". This may also be + a property list with column numbers and format strings, or + functions, e.g., + + (:fmt (2 \"$%s$\" 4 (lambda (c) (format \"$%s$\" c)))) + +:hlstart :hllstart :hlend :hllend :hsep :hlfmt :hllfmt :hfmt + + Same as above, specific for the header lines in the table. + All lines before the first hline are treated as header. If + any of these is not present, the data line value is used. This may be either a string or a function of two arguments: -:efmt Use this format to print numbers with exponentials. - The format should have %s twice for inserting mantissa - and exponent, for example \"%s\\\\times10^{%s}\". This - may also be a property list with column numbers and - formats. :fmt will still be applied after :efmt. - -In addition to this, the parameters :skip and :skipcols are always handled -directly by `orgtbl-send-table'. See manual." - (let* ((splicep (plist-get params :splice)) - (hline (plist-get params :hline)) - (skipheadrule (plist-get params :skipheadrule)) - (remove-nil-linesp (plist-get params :remove-nil-lines)) - (remove-newlines (plist-get params :remove-newlines)) - (*orgtbl-hline* hline) - (*orgtbl-table* table) - (*orgtbl-sep* (plist-get params :sep)) - (*orgtbl-efmt* (plist-get params :efmt)) - (*orgtbl-lstart* (plist-get params :lstart)) - (*orgtbl-llstart* (or (plist-get params :llstart) *orgtbl-lstart*)) - (*orgtbl-lend* (plist-get params :lend)) - (*orgtbl-llend* (or (plist-get params :llend) *orgtbl-lend*)) - (*orgtbl-lfmt* (plist-get params :lfmt)) - (*orgtbl-llfmt* (or (plist-get params :llfmt) *orgtbl-lfmt*)) - (*orgtbl-fmt* (plist-get params :fmt)) - *orgtbl-rtn*) - ;; Convert cells content to backend BACKEND - (when backend - (setq *orgtbl-table* - (mapcar - (lambda(r) - (if (listp r) - (mapcar - (lambda (c) - (org-trim (org-export-string-as c backend t '(:with-tables t)))) - r) - r)) - *orgtbl-table*))) - ;; Put header - (unless splicep - (when (plist-member params :tstart) - (let ((tstart (orgtbl-eval-str (plist-get params :tstart)))) - (if tstart (push tstart *orgtbl-rtn*))))) - ;; If we have a heading, format it and handle the trailing hline. - (if (and (not splicep) - (or (consp (car *orgtbl-table*)) - (consp (nth 1 *orgtbl-table*))) - (memq 'hline (cdr *orgtbl-table*))) - (progn - (when (eq 'hline (car *orgtbl-table*)) - ;; There is a hline before the first data line - (and hline (push hline *orgtbl-rtn*)) - (pop *orgtbl-table*)) - (let* ((*orgtbl-lstart* (or (plist-get params :hlstart) - *orgtbl-lstart*)) - (*orgtbl-llstart* (or (plist-get params :hllstart) - *orgtbl-llstart*)) - (*orgtbl-lend* (or (plist-get params :hlend) *orgtbl-lend*)) - (*orgtbl-llend* (or (plist-get params :hllend) - (plist-get params :hlend) *orgtbl-llend*)) - (*orgtbl-lfmt* (or (plist-get params :hlfmt) *orgtbl-lfmt*)) - (*orgtbl-llfmt* (or (plist-get params :hllfmt) - (plist-get params :hlfmt) *orgtbl-llfmt*)) - (*orgtbl-sep* (or (plist-get params :hlsep) *orgtbl-sep*)) - (*orgtbl-fmt* (or (plist-get params :hfmt) *orgtbl-fmt*))) - (orgtbl-format-section 'hline)) - (if (and hline (not skipheadrule)) (push hline *orgtbl-rtn*)) - (pop *orgtbl-table*))) - ;; Now format the main section. - (orgtbl-format-section nil) - (unless splicep - (when (plist-member params :tend) - (let ((tend (orgtbl-eval-str (plist-get params :tend)))) - (if tend (push tend *orgtbl-rtn*))))) - (mapconcat (if remove-newlines - (lambda (tend) - (replace-regexp-in-string "[\n\r\t\f]" "\\\\n" tend)) - 'identity) - (nreverse (if remove-nil-linesp - (remq nil *orgtbl-rtn*) - *orgtbl-rtn*)) "\n"))) +:efmt + + Use this format to print numbers with exponential. The format + should have %s twice for inserting mantissa and exponent, for + example \"%s\\\\times10^{%s}\". This may also be a property + list with column numbers and format strings or functions. + :fmt will still be applied after :efmt." + ;; Make sure `org-export-create-backend' is available. + (require 'ox) + (let* ((backend (plist-get params :backend)) + (custom-backend + ;; Build a custom back-end according to PARAMS. Before + ;; defining a translator, check if there is anything to do. + ;; When there isn't, let BACKEND handle the element. + (org-export-create-backend + :parent (or backend 'org) + :transcoders + `((table . ,(org-table--to-generic-table params)) + (table-row . ,(org-table--to-generic-row params)) + (table-cell . ,(org-table--to-generic-cell params)) + ;; Macros are not going to be expanded. However, no + ;; regular back-end has a transcoder for them. We + ;; provide one so they are not ignored, but displayed + ;; as-is instead. + (macro . (lambda (m c i) (org-element-macro-interpreter m nil)))))) + data info) + ;; Store TABLE as Org syntax in DATA. Tolerate non-string cells. + ;; Initialize communication channel in INFO. + (with-temp-buffer + (let ((org-inhibit-startup t)) (org-mode)) + (let ((standard-output (current-buffer))) + (dolist (e table) + (cond ((eq e 'hline) (princ "|--\n")) + ((consp e) + (princ "| ") (dolist (c e) (princ c) (princ " |")) + (princ "\n"))))) + ;; Add back-end specific filters, but not user-defined ones. In + ;; particular, make sure to call parse-tree filters on the + ;; table. + (setq info + (let ((org-export-filters-alist nil)) + (org-export-install-filters + (org-combine-plists + (org-export-get-environment backend nil params) + `(:back-end ,(org-export-get-backend backend)))))) + (setq data + (org-export-filter-apply-functions + (plist-get info :filter-parse-tree) + (org-element-map (org-element-parse-buffer) 'table + #'identity nil t) + info))) + (when (and backend (symbolp backend) (not (org-export-get-backend backend))) + (user-error "Unknown :backend value")) + (when (or (not backend) (plist-get info :raw)) (require 'ox-org)) + ;; Handle :skip parameter. + (let ((skip (plist-get info :skip))) + (when skip + (unless (wholenump skip) (user-error "Wrong :skip value")) + (let ((n 0)) + (org-element-map data 'table-row + (lambda (row) + (if (>= n skip) t + (org-element-extract-element row) + (cl-incf n) + nil)) + nil t)))) + ;; Handle :skipcols parameter. + (let ((skipcols (plist-get info :skipcols))) + (when skipcols + (unless (consp skipcols) (user-error "Wrong :skipcols value")) + (org-element-map data 'table + (lambda (table) + (let ((specialp (org-export-table-has-special-column-p table))) + (dolist (row (org-element-contents table)) + (when (eq (org-element-property :type row) 'standard) + (let ((c 1)) + (dolist (cell (nthcdr (if specialp 1 0) + (org-element-contents row))) + (when (memq c skipcols) + (org-element-extract-element cell)) + (cl-incf c)))))))))) + ;; Since we are going to export using a low-level mechanism, + ;; ignore special column and special rows manually. + (let ((special? (org-export-table-has-special-column-p data)) + ignore) + (org-element-map data (if special? '(table-cell table-row) 'table-row) + (lambda (datum) + (when (if (eq (org-element-type datum) 'table-row) + (org-export-table-row-is-special-p datum nil) + (org-export-first-sibling-p datum nil)) + (push datum ignore)))) + (setq info (plist-put info :ignore-list ignore))) + ;; We use a low-level mechanism to export DATA so as to skip all + ;; usual pre-processing and post-processing, i.e., hooks, Babel + ;; code evaluation, include keywords and macro expansion. Only + ;; back-end specific filters are retained. + (let ((output (org-export-data-with-backend data custom-backend info))) + ;; Remove final newline. + (if (org-string-nw-p output) (substring-no-properties output 0 -1) "")))) + +(defun org-table--generic-apply (value name &optional with-cons &rest args) + (cond ((null value) nil) + ((functionp value) `(funcall ',value ,@args)) + ((stringp value) + (cond ((consp (car args)) `(apply #'format ,value ,@args)) + (args `(format ,value ,@args)) + (t value))) + ((and with-cons (consp value)) + `(let ((val (cadr (memq column ',value)))) + (cond ((null val) contents) + ((stringp val) (format val ,@args)) + ((functionp val) (funcall val ,@args)) + (t (user-error "Wrong %s value" ,name))))) + (t (user-error "Wrong %s value" name)))) + +(defun org-table--to-generic-table (params) + "Return custom table transcoder according to PARAMS. +PARAMS is a plist. See `orgtbl-to-generic' for more +information." + (let ((backend (plist-get params :backend)) + (splice (plist-get params :splice)) + (tstart (plist-get params :tstart)) + (tend (plist-get params :tend))) + `(lambda (table contents info) + (concat + ,(and tstart (not splice) + `(concat ,(org-table--generic-apply tstart ":tstart") "\n")) + ,(if (or (not backend) tstart tend splice) 'contents + `(org-export-with-backend ',backend table contents info)) + ,(org-table--generic-apply (and (not splice) tend) ":tend"))))) + +(defun org-table--to-generic-row (params) + "Return custom table row transcoder according to PARAMS. +PARAMS is a plist. See `orgtbl-to-generic' for more +information." + (let* ((backend (plist-get params :backend)) + (lstart (plist-get params :lstart)) + (llstart (plist-get params :llstart)) + (hlstart (plist-get params :hlstart)) + (hllstart (plist-get params :hllstart)) + (lend (plist-get params :lend)) + (llend (plist-get params :llend)) + (hlend (plist-get params :hlend)) + (hllend (plist-get params :hllend)) + (lfmt (plist-get params :lfmt)) + (llfmt (plist-get params :llfmt)) + (hlfmt (plist-get params :hlfmt)) + (hllfmt (plist-get params :hllfmt))) + `(lambda (row contents info) + (if (eq (org-element-property :type row) 'rule) + ,(cond + ((plist-member params :hline) + (org-table--generic-apply (plist-get params :hline) ":hline")) + (backend `(org-export-with-backend ',backend row nil info))) + (let ((headerp (org-export-table-row-in-header-p row info)) + (lastp (not (org-export-get-next-element row info))) + (last-header-p (org-export-table-row-ends-header-p row info))) + (when contents + ;; Check if we can apply `:lfmt', `:llfmt', `:hlfmt', or + ;; `:hllfmt' to CONTENTS. Otherwise, fallback on + ;; `:lstart', `:lend' and their relatives. + ,(let ((cells + '(org-element-map row 'table-cell + (lambda (cell) + ;; Export all cells, without separators. + ;; + ;; Use `org-export-data-with-backend' + ;; instead of `org-export-data' to eschew + ;; cached values, which + ;; ignore :orgtbl-ignore-sep parameter. + (org-export-data-with-backend + cell + (plist-get info :back-end) + (org-combine-plists info '(:orgtbl-ignore-sep t)))) + info))) + `(cond + ,(and hllfmt + `(last-header-p ,(org-table--generic-apply + hllfmt ":hllfmt" nil cells))) + ,(and hlfmt + `(headerp ,(org-table--generic-apply + hlfmt ":hlfmt" nil cells))) + ,(and llfmt + `(lastp ,(org-table--generic-apply + llfmt ":llfmt" nil cells))) + (t + ,(if lfmt (org-table--generic-apply lfmt ":lfmt" nil cells) + `(concat + (cond + ,(and + (or hllstart hllend) + `(last-header-p + (concat + ,(org-table--generic-apply hllstart ":hllstart") + contents + ,(org-table--generic-apply hllend ":hllend")))) + ,(and + (or hlstart hlend) + `(headerp + (concat + ,(org-table--generic-apply hlstart ":hlstart") + contents + ,(org-table--generic-apply hlend ":hlend")))) + ,(and + (or llstart llend) + `(lastp + (concat + ,(org-table--generic-apply llstart ":llstart") + contents + ,(org-table--generic-apply llend ":llend")))) + (t + ,(cond + ((or lstart lend) + `(concat + ,(org-table--generic-apply lstart ":lstart") + contents + ,(org-table--generic-apply lend ":lend"))) + (backend + `(org-export-with-backend + ',backend row contents info)) + (t 'contents))))))))))))))) + +(defun org-table--to-generic-cell (params) + "Return custom table cell transcoder according to PARAMS. +PARAMS is a plist. See `orgtbl-to-generic' for more +information." + (let* ((backend (plist-get params :backend)) + (efmt (plist-get params :efmt)) + (fmt (plist-get params :fmt)) + (hfmt (plist-get params :hfmt)) + (sep (plist-get params :sep)) + (hsep (plist-get params :hsep))) + `(lambda (cell contents info) + (let ((headerp (org-export-table-row-in-header-p + (org-export-get-parent-element cell) info)) + (column (1+ (cdr (org-export-table-cell-address cell info))))) + ;; Make sure that contents are exported as Org data when :raw + ;; parameter is non-nil. + ,(when (and backend (plist-get params :raw)) + `(setq contents + ;; Since we don't know what are the pseudo object + ;; types defined in backend, we cannot pass them to + ;; `org-element-interpret-data'. As a consequence, + ;; they will be treated as pseudo elements, and + ;; will have newlines appended instead of spaces. + ;; Therefore, we must make sure :post-blank value + ;; is really turned into spaces. + (replace-regexp-in-string + "\n" " " + (org-trim + (org-element-interpret-data + (org-element-contents cell)))))) + (when contents + ;; Check if we can apply `:efmt' on CONTENTS. + ,(when efmt + `(when (string-match orgtbl-exp-regexp contents) + (let ((mantissa (match-string 1 contents)) + (exponent (match-string 2 contents))) + (setq contents ,(org-table--generic-apply + efmt ":efmt" t 'mantissa 'exponent))))) + ;; Check if we can apply FMT (or HFMT) on CONTENTS. + (cond + ,(and hfmt `(headerp (setq contents ,(org-table--generic-apply + hfmt ":hfmt" t 'contents)))) + ,(and fmt `(t (setq contents ,(org-table--generic-apply + fmt ":fmt" t 'contents)))))) + ;; If a separator is provided, use it instead of BACKEND's. + ;; Separators are ignored when LFMT (or equivalent) is + ;; provided. + ,(cond + ((or hsep sep) + `(if (or ,(and (not sep) '(not headerp)) + (plist-get info :orgtbl-ignore-sep) + (not (org-export-get-next-element cell info))) + ,(if (not backend) 'contents + `(org-export-with-backend ',backend cell contents info)) + (concat contents + ,(if (and sep hsep) `(if headerp ,hsep ,sep) + (or hsep sep))))) + (backend `(org-export-with-backend ',backend cell contents info)) + (t 'contents)))))) ;;;###autoload (defun orgtbl-to-tsv (table params) "Convert the orgtbl-mode table to TAB separated material." (orgtbl-to-generic table (org-combine-plists '(:sep "\t") params))) + ;;;###autoload (defun orgtbl-to-csv (table params) "Convert the orgtbl-mode table to CSV material. This does take care of the proper quoting of fields with comma or quotes." - (orgtbl-to-generic table (org-combine-plists - '(:sep "," :fmt org-quote-csv-field) - params))) + (orgtbl-to-generic table + (org-combine-plists '(:sep "," :fmt org-quote-csv-field) + params))) ;;;###autoload (defun orgtbl-to-latex (table params) "Convert the orgtbl-mode TABLE to LaTeX. -TABLE is a list, each entry either the symbol `hline' for a horizontal -separator line, or a list of fields for that line. -PARAMS is a property list of parameters that can influence the conversion. -Supports all parameters from `orgtbl-to-generic'. Most important for -LaTeX are: - -:splice When set to t, return only table body lines, don't wrap - them into a tabular environment. Default is nil. - -:fmt A format to be used to wrap the field, should contain %s for the - original field value. For example, to wrap everything in dollars, - use :fmt \"$%s$\". This may also be a property list with column - numbers and formats. For example :fmt (2 \"$%s$\" 4 \"%s%%\") - The format may also be a function that formats its one argument. - -:efmt Format for transforming numbers with exponentials. The format - should have %s twice for inserting mantissa and exponent, for - example \"%s\\\\times10^{%s}\". LaTeX default is \"%s\\\\,(%s)\". - This may also be a property list with column numbers and formats. - The format may also be a function that formats its two arguments. - -:llend If you find too much space below the last line of a table, - pass a value of \"\" for :llend to suppress the final \\\\. - -The general parameters :skip and :skipcols have already been applied when -this function is called." - (let* ((alignment (mapconcat (lambda (x) (if x "r" "l")) - org-table-last-alignment "")) - (params2 - (list - :tstart (concat "\\begin{tabular}{" alignment "}") - :tend "\\end{tabular}" - :lstart "" :lend " \\\\" :sep " & " - :efmt "%s\\,(%s)" :hline "\\hline"))) - (require 'ox-latex) - (orgtbl-to-generic table (org-combine-plists params2 params) 'latex))) + +TABLE is a list, each entry either the symbol `hline' for +a horizontal separator line, or a list of fields for that line. +PARAMS is a property list of parameters that can influence the +conversion. All parameters from `orgtbl-to-generic' are +supported. It is also possible to use the following ones: + +:booktabs + + When non-nil, use formal \"booktabs\" style. + +:environment + + Specify environment to use, as a string. If you use + \"longtable\", you may also want to specify :language property, + as a string, to get proper continuation strings." + (require 'ox-latex) + (orgtbl-to-generic + table + (org-combine-plists + ;; Provide sane default values. + (list :backend 'latex + :latex-default-table-mode 'table + :latex-tables-centered nil + :latex-tables-booktabs (plist-get params :booktabs) + :latex-table-scientific-notation nil + :latex-default-table-environment + (or (plist-get params :environment) "tabular")) + params))) ;;;###autoload (defun orgtbl-to-html (table params) "Convert the orgtbl-mode TABLE to HTML. -TABLE is a list, each entry either the symbol `hline' for a horizontal -separator line, or a list of fields for that line. -PARAMS is a property list of parameters that can influence the conversion. -Currently this function recognizes the following parameters: -:splice When set to t, return only table body lines, don't wrap - them into a environment. Default is nil. +TABLE is a list, each entry either the symbol `hline' for +a horizontal separator line, or a list of fields for that line. +PARAMS is a property list of parameters that can influence the +conversion. All parameters from `orgtbl-to-generic' are +supported. It is also possible to use the following one: -The general parameters :skip and :skipcols have already been applied when -this function is called. The function does *not* use `orgtbl-to-generic', -so you cannot specify parameters for it." +:attributes + + Attributes and values, as a plist, which will be used in +
tag." (require 'ox-html) - (let ((output (org-export-string-as - (orgtbl-to-orgtbl table nil) 'html t '(:with-tables t)))) - (if (not (plist-get params :splice)) output - (org-trim - (replace-regexp-in-string - "\\`
\n" "" - (replace-regexp-in-string "
\n*\\'" "" output)))))) + (orgtbl-to-generic + table + (org-combine-plists + ;; Provide sane default values. + (list :backend 'html + :html-table-data-tags '("" . "") + :html-table-use-header-tags-for-first-column nil + :html-table-align-individual-fields t + :html-table-row-tags '("" . "") + :html-table-attributes + (if (plist-member params :attributes) + (plist-get params :attributes) + '(:border "2" :cellspacing "0" :cellpadding "6" :rules "groups" + :frame "hsides"))) + params))) ;;;###autoload (defun orgtbl-to-texinfo (table params) - "Convert the orgtbl-mode TABLE to TeXInfo. -TABLE is a list, each entry either the symbol `hline' for a horizontal -separator line, or a list of fields for that line. -PARAMS is a property list of parameters that can influence the conversion. -Supports all parameters from `orgtbl-to-generic'. Most important for -TeXInfo are: - -:splice nil/t When set to t, return only table body lines, don't wrap - them into a multitable environment. Default is nil. - -:fmt fmt A format to be used to wrap the field, should contain - %s for the original field value. For example, to wrap - everything in @kbd{}, you could use :fmt \"@kbd{%s}\". - This may also be a property list with column numbers and - formats. For example :fmt (2 \"@kbd{%s}\" 4 \"@code{%s}\"). - Each format also may be a function that formats its one - argument. - -:cf \"f1 f2..\" The column fractions for the table. By default these - are computed automatically from the width of the columns - under org-mode. - -The general parameters :skip and :skipcols have already been applied when -this function is called." - (let* ((total (float (apply '+ org-table-last-column-widths))) - (colfrac (or (plist-get params :cf) - (mapconcat - (lambda (x) (format "%.3f" (/ (float x) total))) - org-table-last-column-widths " "))) - (params2 - (list - :tstart (concat "@multitable @columnfractions " colfrac) - :tend "@end multitable" - :lstart "@item " :lend "" :sep " @tab " - :hlstart "@headitem "))) - (require 'ox-texinfo) - (orgtbl-to-generic table (org-combine-plists params2 params) 'texinfo))) + "Convert the orgtbl-mode TABLE to Texinfo. + +TABLE is a list, each entry either the symbol `hline' for +a horizontal separator line, or a list of fields for that line. +PARAMS is a property list of parameters that can influence the +conversion. All parameters from `orgtbl-to-generic' are +supported. It is also possible to use the following one: + +:columns + + Column widths, as a string. When providing column fractions, + \"@columnfractions\" command can be omitted." + (require 'ox-texinfo) + (let ((output + (orgtbl-to-generic + table + (org-combine-plists + (list :backend 'texinfo + :texinfo-tables-verbatim nil + :texinfo-table-scientific-notation nil) + params))) + (columns (let ((w (plist-get params :columns))) + (cond ((not w) nil) + ((string-match-p "{\\|@columnfractions " w) w) + (t (concat "@columnfractions " w)))))) + (if (not columns) output + (replace-regexp-in-string + "@multitable \\(.*\\)" columns output t nil 1)))) ;;;###autoload (defun orgtbl-to-orgtbl (table params) "Convert the orgtbl-mode TABLE into another orgtbl-mode table. + +TABLE is a list, each entry either the symbol `hline' for +a horizontal separator line, or a list of fields for that line. +PARAMS is a property list of parameters that can influence the +conversion. All parameters from `orgtbl-to-generic' are +supported. + Useful when slicing one table into many. The :hline, :sep, -:lstart, and :lend provide orgtbl framing. The default nil :tstart -and :tend suppress strings without splicing; they can be set to -provide ORGTBL directives for the generated table." - (let* ((params2 - (list - :remove-newlines t - :tstart nil :tend nil - :hline "|---" - :sep " | " - :lstart "| " - :lend " |")) - (params (org-combine-plists params2 params))) - (with-temp-buffer - (insert (orgtbl-to-generic table params)) - (goto-char (point-min)) - (while (re-search-forward org-table-hline-regexp nil t) - (org-table-align)) - (buffer-substring 1 (buffer-size))))) +:lstart, and :lend provide orgtbl framing. :tstart and :tend can +be set to provide ORGTBL directives for the generated table." + (require 'ox-org) + (orgtbl-to-generic table (org-combine-plists params (list :backend 'org)))) (defun orgtbl-to-table.el (table params) - "Convert the orgtbl-mode TABLE into a table.el table." + "Convert the orgtbl-mode TABLE into a table.el table. +TABLE is a list, each entry either the symbol `hline' for +a horizontal separator line, or a list of fields for that line. +PARAMS is a property list of parameters that can influence the +conversion. All parameters from `orgtbl-to-generic' are +supported." (with-temp-buffer (insert (orgtbl-to-orgtbl table params)) (org-table-align) @@ -4920,19 +5256,137 @@ provide ORGTBL directives for the generated table." (defun orgtbl-to-unicode (table params) "Convert the orgtbl-mode TABLE into a table with unicode characters. -You need the ascii-art-to-unicode.el package for this. You can download -it here: http://gnuvola.org/software/j/aa2u/ascii-art-to-unicode.el." - (with-temp-buffer - (insert (orgtbl-to-table.el table params)) - (goto-char (point-min)) - (if (or (featurep 'ascii-art-to-unicode) - (require 'ascii-art-to-unicode nil t)) - (aa2u) - (unless (delq nil (mapcar (lambda (l) (string-match "aa2u" (car l))) org-stored-links)) - (push '("http://gnuvola.org/software/j/aa2u/ascii-art-to-unicode.el" - "Link to ascii-art-to-unicode.el") org-stored-links)) - (user-error "Please download ascii-art-to-unicode.el (use C-c C-l to insert the link to it)")) - (buffer-string))) + +TABLE is a list, each entry either the symbol `hline' for +a horizontal separator line, or a list of fields for that line. +PARAMS is a property list of parameters that can influence the +conversion. All parameters from `orgtbl-to-generic' are +supported. It is also possible to use the following ones: + +:ascii-art + + When non-nil, use \"ascii-art-to-unicode\" package to translate + the table. You can download it here: + http://gnuvola.org/software/j/aa2u/ascii-art-to-unicode.el. + +:narrow + + When non-nil, narrow columns width than provided width cookie, + using \"=>\" as an ellipsis, just like in an Org mode buffer." + (require 'ox-ascii) + (orgtbl-to-generic + table + (org-combine-plists + (list :backend 'ascii + :ascii-charset 'utf-8 + :ascii-table-widen-columns (not (plist-get params :narrow)) + :ascii-table-use-ascii-art (plist-get params :ascii-art)) + params))) + +;; Put the cursor in a column containing numerical values +;; of an Org table, +;; type C-c " a +;; A new column is added with a bar plot. +;; When the table is refreshed (C-u C-c *), +;; the plot is updated to reflect the new values. + +(defun orgtbl-ascii-draw (value min max &optional width characters) + "Draw an ascii bar in a table. +VALUE is the value to plot, it determines the width of the bar to draw. +MIN is the value that will be displayed as empty (zero width bar). +MAX is the value that will draw a bar filling all the WIDTH. +WIDTH is the span in characters from MIN to MAX. +CHARACTERS is a string that will compose the bar, with shades of grey +from pure white to pure black. It defaults to a 10 characters string +of regular ascii characters." + (let* ((width (ceiling (or width 12))) + (characters (or characters " .:;c!lhVHW")) + (len (1- (length characters))) + (value (float (if (numberp value) + value (string-to-number value)))) + (relative (/ (- value min) (- max min))) + (steps (round (* relative width len)))) + (cond ((< steps 0) "too small") + ((> steps (* width len)) "too large") + (t (let* ((int-division (/ steps len)) + (remainder (- steps (* int-division len)))) + (concat (make-string int-division (elt characters len)) + (string (elt characters remainder)))))))) + +;;;###autoload +(defun orgtbl-ascii-plot (&optional ask) + "Draw an ASCII bar plot in a column. + +With cursor in a column containing numerical values, this function +will draw a plot in a new column. + +ASK, if given, is a numeric prefix to override the default 12 +characters width of the plot. ASK may also be the `\\[universal-argument]' \ +prefix, +which will prompt for the width." + (interactive "P") + (let ((col (org-table-current-column)) + (min 1e999) ; 1e999 will be converted to infinity + (max -1e999) ; which is the desired result + (table (org-table-to-lisp)) + (length + (cond ((consp ask) + (read-number "Length of column " 12)) + ((numberp ask) ask) + (t 12)))) + ;; Skip any hline a the top of table. + (while (eq (car table) 'hline) (setq table (cdr table))) + ;; Skip table header if any. + (dolist (x (or (cdr (memq 'hline table)) table)) + (when (consp x) + (setq x (nth (1- col) x)) + (when (string-match + "^[-+]?\\([0-9]*[.]\\)?[0-9]*\\([eE][+-]?[0-9]+\\)?$" + x) + (setq x (string-to-number x)) + (when (> min x) (setq min x)) + (when (< max x) (setq max x))))) + (org-table-insert-column) + (org-table-move-column-right) + (org-table-store-formulas + (cons + (cons + (concat "$" (number-to-string (1+ col))) + (format "'(%s $%s %s %s %s)" + "orgtbl-ascii-draw" col min max length)) + (org-table-get-stored-formulas))) + (org-table-recalculate t))) + +;; Example of extension: unicode characters +;; Here are two examples of different styles. + +;; Unicode block characters are used to give a smooth effect. +;; See http://en.wikipedia.org/wiki/Block_Elements +;; Use one of those drawing functions +;; - orgtbl-ascii-draw (the default ascii) +;; - orgtbl-uc-draw-grid (unicode with a grid effect) +;; - orgtbl-uc-draw-cont (smooth unicode) + +;; This is best viewed with the "DejaVu Sans Mono" font +;; (use M-x set-default-font). + +(defun orgtbl-uc-draw-grid (value min max &optional width) + "Draw a bar in a table using block unicode characters. +It is a variant of orgtbl-ascii-draw with Unicode block +characters, for a smooth display. Bars appear as grids (to the +extent the font allows)." + ;; http://en.wikipedia.org/wiki/Block_Elements + ;; best viewed with the "DejaVu Sans Mono" font. + (orgtbl-ascii-draw value min max width + " \u258F\u258E\u258D\u258C\u258B\u258A\u2589")) + +(defun orgtbl-uc-draw-cont (value min max &optional width) + "Draw a bar in a table using block unicode characters. +It is a variant of orgtbl-ascii-draw with Unicode block +characters, for a smooth display. Bars are solid (to the extent +the font allows)." + (orgtbl-ascii-draw value min max width + " \u258F\u258E\u258D\u258C\u258B\u258A\u2589\u2588")) (defun org-table-get-remote-range (name-or-id form) "Get a field value or a list of values in a range from table at ID. @@ -4949,57 +5403,74 @@ The return value is either a single string for a single field, or a list of the fields in the rectangle." (save-match-data (let ((case-fold-search t) (id-loc nil) - ;; Protect a bunch of variables from being overwritten - ;; by the context of the remote table + ;; Protect a bunch of variables from being overwritten by + ;; the context of the remote table. org-table-column-names org-table-column-name-regexp org-table-local-parameters org-table-named-field-locations - org-table-current-line-types org-table-current-begin-line + org-table-current-line-types org-table-current-begin-pos org-table-dlines org-table-current-ncol org-table-hlines org-table-last-alignment org-table-last-column-widths org-table-last-alignment - org-table-last-column-widths tbeg + org-table-last-column-widths buffer loc) (setq form (org-table-convert-refs-to-rc form)) - (save-excursion - (save-restriction - (widen) - (save-excursion - (goto-char (point-min)) - (if (re-search-forward - (concat "^[ \t]*#\\+\\(tbl\\)?name:[ \t]*" - (regexp-quote name-or-id) "[ \t]*$") - nil t) - (setq buffer (current-buffer) loc (match-beginning 0)) - (setq id-loc (org-id-find name-or-id 'marker)) - (unless (and id-loc (markerp id-loc)) - (user-error "Can't find remote table \"%s\"" name-or-id)) - (setq buffer (marker-buffer id-loc) - loc (marker-position id-loc)) - (move-marker id-loc nil))) - (with-current-buffer buffer - (save-excursion - (save-restriction - (widen) - (goto-char loc) - (forward-char 1) - (unless (and (re-search-forward "^\\(\\*+ \\)\\|[ \t]*|" nil t) - (not (match-beginning 1))) - (user-error "Cannot find a table at NAME or ID %s" name-or-id)) - (setq tbeg (point-at-bol)) - (org-table-get-specials) - (setq form (org-table-formula-substitute-names - (org-table-formula-handle-first/last-rc form))) - (if (and (string-match org-table-range-regexp form) - (> (length (match-string 0 form)) 1)) - (save-match-data - (org-table-get-range (match-string 0 form) tbeg 1)) - form))))))))) + (org-with-wide-buffer + (goto-char (point-min)) + (if (re-search-forward + (concat "^[ \t]*#\\+\\(tbl\\)?name:[ \t]*" + (regexp-quote name-or-id) "[ \t]*$") + nil t) + (setq buffer (current-buffer) loc (match-beginning 0)) + (setq id-loc (org-id-find name-or-id 'marker)) + (unless (and id-loc (markerp id-loc)) + (user-error "Can't find remote table \"%s\"" name-or-id)) + (setq buffer (marker-buffer id-loc) + loc (marker-position id-loc)) + (move-marker id-loc nil)) + (with-current-buffer buffer + (org-with-wide-buffer + (goto-char loc) + (forward-char 1) + (unless (and (re-search-forward "^\\(\\*+ \\)\\|^[ \t]*|" nil t) + (not (match-beginning 1))) + (user-error "Cannot find a table at NAME or ID %s" name-or-id)) + (org-table-analyze) + (setq form (org-table-formula-substitute-names + (org-table-formula-handle-first/last-rc form))) + (if (and (string-match org-table-range-regexp form) + (> (length (match-string 0 form)) 1)) + (org-table-get-range + (match-string 0 form) org-table-current-begin-pos 1) + form))))))) + +(defun org-table-remote-reference-indirection (form) + "Return formula with table remote references substituted by indirection. +For example \"remote($1, @>$2)\" => \"remote(year_2013, @>$1)\". +This indirection works only with the format @ROW$COLUMN. The +format \"B3\" is not supported because it can not be +distinguished from a plain table name or ID." + (let ((regexp + ;; Same as in `org-table-eval-formula'. + (concat "\\")) (force-mode-line-update))) -(defun org-timer-cancel-timer () - "Cancel the current timer." - (interactive) - (when (eval org-timer-current-timer) - (run-hooks 'org-timer-cancel-hook) - (cancel-timer org-timer-current-timer) - (setq org-timer-current-timer nil) - (setq org-timer-timer-is-countdown nil) - (org-timer-set-mode-line 'off)) - (message "Last timer canceled")) - (defun org-timer-show-remaining-time () "Display the remaining time before the timer ends." (interactive) (require 'time) - (if (not org-timer-current-timer) + (if (not org-timer-countdown-timer) (message "No timer set") (let* ((rtime (decode-time - (time-subtract (timer--time org-timer-current-timer) + (time-subtract (timer--time org-timer-countdown-timer) (current-time)))) (rsecs (nth 0 rtime)) (rmins (nth 1 rtime))) (message "%d minute(s) %d seconds left before next time out" rmins rsecs)))) -(defvar org-clock-sound) - ;;;###autoload (defun org-timer-set-timer (&optional opt) - "Prompt for a duration and set a timer. + "Prompt for a duration in minutes or hh:mm:ss and set a timer. -If `org-timer-default-timer' is not zero, suggest this value as +If `org-timer-default-timer' is not \"0\", suggest this value as the default duration for the timer. If a timer is already set, prompt the user if she wants to replace it. Called with a numeric prefix argument, use this numeric value as -the duration of the timer. +the duration of the timer in minutes. Called with a `C-u' prefix arguments, use `org-timer-default-timer' without prompting the user for a duration. With two `C-u' prefix arguments, use `org-timer-default-timer' without prompting the user for a duration and automatically -replace any running timer." +replace any running timer. + +By default, the timer duration will be set to the number of +minutes in the Effort property, if any. You can ignore this by +using three `C-u' prefix arguments." (interactive "P") - (let ((minutes (or (and (numberp opt) (number-to-string opt)) - (and (listp opt) (not (null opt)) - (number-to-string org-timer-default-timer)) - (read-from-minibuffer - "How many minutes left? " - (if (not (eq org-timer-default-timer 0)) - (number-to-string org-timer-default-timer)))))) + (when (and org-timer-start-time + (not org-timer-countdown-timer)) + (user-error "Relative timer is running. Stop first")) + (let* ((default-timer + ;; `org-timer-default-timer' used to be a number, don't choke: + (if (numberp org-timer-default-timer) + (number-to-string org-timer-default-timer) + org-timer-default-timer)) + (effort-minutes (ignore-errors (org-get-at-eol 'effort-minutes 1))) + (minutes (or (and (numberp opt) (number-to-string opt)) + (and (not (equal opt '(64))) + effort-minutes + (number-to-string effort-minutes)) + (and (consp opt) default-timer) + (and (stringp opt) opt) + (read-from-minibuffer + "How much time left? (minutes or h:mm:ss) " + (and (not (string-equal default-timer "0")) default-timer))))) + (when (string-match "\\`[0-9]+\\'" minutes) + (setq minutes (concat minutes ":00"))) (if (not (string-match "[0-9]+" minutes)) (org-timer-show-remaining-time) - (let* ((mins (string-to-number (match-string 0 minutes))) - (secs (* mins 60)) - (hl (cond - ((string-match "Org Agenda" (buffer-name)) - (let* ((marker (or (get-text-property (point) 'org-marker) - (org-agenda-error))) - (hdmarker (or (get-text-property (point) 'org-hd-marker) - marker)) - (pos (marker-position marker))) - (with-current-buffer (marker-buffer marker) - (widen) - (goto-char pos) - (org-show-entry) - (or (ignore-errors (org-get-heading)) - (concat "File:" (file-name-nondirectory (buffer-file-name))))))) - ((derived-mode-p 'org-mode) - (or (ignore-errors (org-get-heading)) - (concat "File:" (file-name-nondirectory (buffer-file-name))))) - (t (error "Not in an Org buffer")))) - timer-set) - (if (or (and org-timer-current-timer - (or (equal opt '(16)) - (y-or-n-p "Replace current timer? "))) - (not org-timer-current-timer)) - (progn - (require 'org-clock) - (when org-timer-current-timer - (cancel-timer org-timer-current-timer)) - (setq org-timer-current-timer - (run-with-timer - secs nil `(lambda () - (setq org-timer-current-timer nil) - (org-notify ,(format "%s: time out" hl) ,org-clock-sound) - (setq org-timer-timer-is-countdown nil) - (org-timer-set-mode-line 'off) - (run-hooks 'org-timer-done-hook)))) - (run-hooks 'org-timer-set-hook) - (setq org-timer-timer-is-countdown t - org-timer-start-time - (time-add (current-time) (seconds-to-time (* mins 60)))) - (org-timer-set-mode-line 'on)) - (message "No timer set")))))) + (let ((secs (org-timer-hms-to-secs (org-timer-fix-incomplete minutes)))) + (if (and org-timer-countdown-timer + (not (or (equal opt '(16)) + (y-or-n-p "Replace current timer? ")))) + (message "No timer set") + (when (timerp org-timer-countdown-timer) + (cancel-timer org-timer-countdown-timer)) + (setq org-timer-countdown-timer-title + (org-timer--get-timer-title)) + (setq org-timer-countdown-timer + (org-timer--run-countdown-timer + secs org-timer-countdown-timer-title)) + (run-hooks 'org-timer-set-hook) + (setq org-timer-start-time + (time-add (current-time) (seconds-to-time secs))) + (setq org-timer-pause-time nil) + (org-timer-set-mode-line 'on)))))) + +(defun org-timer--run-countdown-timer (secs title) + "Start countdown timer that will last SECS. +TITLE will be appended to the notification message displayed when +time is up." + (let ((msg (format "%s: time out" title))) + (run-with-timer + secs nil `(lambda () + (setq org-timer-countdown-timer nil + org-timer-start-time nil) + (org-notify ,msg ,org-clock-sound) + (org-timer-set-mode-line 'off) + (run-hooks 'org-timer-done-hook))))) + +(defun org-timer--get-timer-title () + "Construct timer title from heading or file name of Org buffer." + (cond + ((derived-mode-p 'org-agenda-mode) + (let* ((marker (or (get-text-property (point) 'org-marker) + (org-agenda-error))) + (hdmarker (or (get-text-property (point) 'org-hd-marker) + marker))) + (with-current-buffer (marker-buffer marker) + (org-with-wide-buffer + (goto-char hdmarker) + (org-show-entry) + (or (ignore-errors (org-get-heading)) + (buffer-name (buffer-base-buffer))))))) + ((derived-mode-p 'org-mode) + (or (ignore-errors (org-get-heading)) + (buffer-name (buffer-base-buffer)))) + (t (error "Not in an Org buffer")))) (provide 'org-timer) diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el index aae65cc6d37..2db3eae2d8a 100644 --- a/lisp/org/org-version.el +++ b/lisp/org/org-version.el @@ -3,15 +3,15 @@ ;;; Code: ;;;###autoload (defun org-release () - "The release version of org-mode. - Inserted by installing org-mode or when a release is made." - (let ((org-release "8.2.10")) + "The release version of Org. +Inserted by installing Org mode or when a release is made." + (let ((org-release "9.0.9")) org-release)) ;;;###autoload (defun org-git-version () "The Git version of org-mode. - Inserted by installing org-mode or when a release is made." - (let ((org-git-version "release_8.2.10")) +Inserted by installing Org or when a release is made." + (let ((org-git-version "release_9.0.9")) org-git-version)) (provide 'org-version) diff --git a/lisp/org/org-w3m.el b/lisp/org/org-w3m.el index 8360bd07fe4..e9bbeff37c4 100644 --- a/lisp/org/org-w3m.el +++ b/lisp/org/org-w3m.el @@ -1,4 +1,4 @@ -;;; org-w3m.el --- Support from copy and paste from w3m to Org-mode +;;; org-w3m.el --- Support from Copy and Paste From w3m -*- lexical-binding: t; -*- ;; Copyright (C) 2008-2017 Free Software Foundation, Inc. @@ -25,9 +25,9 @@ ;;; Commentary: ;; This file implements copying HTML content from a w3m buffer and -;; transforming the text on the fly so that it can be pasted into -;; an org-mode buffer with hot links. It will also work for regions -;; in gnus buffers that have been washed with w3m. +;; transforming the text on the fly so that it can be pasted into an +;; Org buffer with hot links. It will also work for regions in gnus +;; buffers that have been washed with w3m. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; @@ -35,7 +35,7 @@ ;; Richard Riley ;; -;; The idea of transforming the HTML content with org-mode style is +;; The idea of transforming the HTML content with Org syntax is ;; proposed by Richard, I'm just coding it. ;; @@ -46,7 +46,7 @@ (defvar w3m-current-url) (defvar w3m-current-title) -(add-hook 'org-store-link-functions 'org-w3m-store-link) +(org-link-set-parameters "w3m" :store #'org-w3m-store-link) (defun org-w3m-store-link () "Store a link to a w3m buffer." (when (eq major-mode 'w3m-mode) @@ -60,7 +60,7 @@ "Copy current buffer content or active region with `org-mode' style links. This will encode `link-title' and `link-location' with `org-make-link-string', and insert the transformed test into the kill ring, -so that it can be yanked into an Org-mode buffer with links working correctly." +so that it can be yanked into an Org buffer with links working correctly." (interactive) (let* ((regionp (org-region-active-p)) (transform-start (point-min)) @@ -107,7 +107,7 @@ so that it can be yanked into an Org-mode buffer with links working correctly." (concat return-content (buffer-substring (point) transform-end)))) (org-kill-new return-content) - (message "Transforming links...done, use C-y to insert text into Org-mode file") + (message "Transforming links...done, use C-y to insert text into Org file") (message "Copy with link transformation complete.")))) (defun org-w3m-get-anchor-start () diff --git a/lisp/org/org.el b/lisp/org/org.el index 02a7a0c09af..5d10eed1511 100644 --- a/lisp/org/org.el +++ b/lisp/org/org.el @@ -1,4 +1,4 @@ -;;; org.el --- Outline-based notes management and organizer +;;; org.el --- Outline-based notes management and organizer -*- lexical-binding: t; -*- ;; Carstens outline-mode for keeping track of everything. ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. @@ -25,23 +25,24 @@ ;; ;;; Commentary: ;; -;; Org-mode is a mode for keeping notes, maintaining ToDo lists, and doing +;; Org is a mode for keeping notes, maintaining ToDo lists, and doing ;; project planning with a fast and effective plain-text system. ;; -;; Org-mode develops organizational tasks around NOTES files that contain -;; information about projects as plain text. Org-mode is implemented on -;; top of outline-mode, which makes it possible to keep the content of -;; large files well structured. Visibility cycling and structure editing -;; help to work with the tree. Tables are easily created with a built-in -;; table editor. Org-mode supports ToDo items, deadlines, time stamps, -;; and scheduling. It dynamically compiles entries into an agenda that -;; utilizes and smoothly integrates much of the Emacs calendar and diary. -;; Plain text URL-like links connect to websites, emails, Usenet -;; messages, BBDB entries, and any files related to the projects. For -;; printing and sharing of notes, an Org-mode file can be exported as a -;; structured ASCII file, as HTML, or (todo and agenda items only) as an -;; iCalendar file. It can also serve as a publishing tool for a set of -;; linked webpages. +;; Org mode develops organizational tasks around NOTES files that +;; contain information about projects as plain text. Org mode is +;; implemented on top of outline-mode, which makes it possible to keep +;; the content of large files well structured. Visibility cycling and +;; structure editing help to work with the tree. Tables are easily +;; created with a built-in table editor. Org mode supports ToDo +;; items, deadlines, time stamps, and scheduling. It dynamically +;; compiles entries into an agenda that utilizes and smoothly +;; integrates much of the Emacs calendar and diary. Plain text +;; URL-like links connect to websites, emails, Usenet messages, BBDB +;; entries, and any files related to the projects. For printing and +;; sharing of notes, an Org file can be exported as a structured ASCII +;; file, as HTML, or (todo and agenda items only) as an iCalendar +;; file. It can also serve as a publishing tool for a set of linked +;; webpages. ;; ;; Installation and Activation ;; --------------------------- @@ -51,11 +52,11 @@ ;; ;; Documentation ;; ------------- -;; The documentation of Org-mode can be found in the TeXInfo file. The +;; The documentation of Org mode can be found in the TeXInfo file. The ;; distribution also contains a PDF version of it. At the homepage of -;; Org-mode, you can read the same text online as HTML. There is also an +;; Org mode, you can read the same text online as HTML. There is also an ;; excellent reference card made by Philip Rooke. This card can be found -;; in the etc/ directory of Emacs 22. +;; in the doc/ directory. ;; ;; A list of recent changes can be found at ;; http://orgmode.org/Changes.html @@ -63,21 +64,29 @@ ;;; Code: (defvar org-inhibit-highlight-removal nil) ; dynamically scoped param -(defvar org-table-formula-constants-local nil +(defvar-local org-table-formula-constants-local nil "Local version of `org-table-formula-constants'.") -(make-variable-buffer-local 'org-table-formula-constants-local) ;;;; Require other packages -(eval-when-compile - (require 'cl) - (require 'gnus-sum)) +(require 'cl-lib) + +(eval-when-compile (require 'gnus-sum)) (require 'calendar) (require 'find-func) (require 'format-spec) -(load "org-loaddefs.el" t t t) +(or (eq this-command 'eval-buffer) + (condition-case nil + (load (concat (file-name-directory load-file-name) + "org-loaddefs.el") + nil t t t) + (error + (message "WARNING: No org-loaddefs.el file could be found from where org.el is loaded.") + (sit-for 3) + (message "You need to run \"make\" or \"make autoloads\" from Org lisp directory") + (sit-for 3)))) (require 'org-macs) (require 'org-compat) @@ -101,75 +110,87 @@ sure that we are at the beginning of the line.") "Matches a headline, putting stars and text into groups. Stars are put in group 1 and the trimmed body in group 2.") -;; Emacs 22 calendar compatibility: Make sure the new variables are available -(unless (boundp 'calendar-view-holidays-initially-flag) - (org-defvaralias 'calendar-view-holidays-initially-flag - 'view-calendar-holidays-initially)) -(unless (boundp 'calendar-view-diary-initially-flag) - (org-defvaralias 'calendar-view-diary-initially-flag - 'view-diary-entries-initially)) -(unless (boundp 'diary-fancy-buffer) - (org-defvaralias 'diary-fancy-buffer 'fancy-diary-buffer)) - +(declare-function calendar-check-holidays "holidays" (date)) +(declare-function cdlatex-environment "ext:cdlatex" (environment item)) +(declare-function isearch-no-upper-case-p "isearch" (string regexp-flag)) (declare-function org-add-archive-files "org-archive" (files)) - -(declare-function org-inlinetask-at-task-p "org-inlinetask" ()) -(declare-function org-inlinetask-outline-regexp "org-inlinetask" ()) -(declare-function org-inlinetask-toggle-visibility "org-inlinetask" ()) -(declare-function org-pop-to-buffer-same-window "org-compat" (&optional buffer-or-name norecord label)) +(declare-function org-agenda-entry-get-agenda-timestamp "org-agenda" (pom)) +(declare-function org-agenda-list "org-agenda" (&optional arg start-day span with-hour)) +(declare-function org-agenda-redo "org-agenda" (&optional all)) +(declare-function org-babel-do-in-edit-buffer "ob-core" (&rest body) t) +(declare-function org-babel-tangle-file "ob-tangle" (file &optional target-file lang)) +(declare-function org-beamer-mode "ox-beamer" (&optional prefix) t) (declare-function org-clock-get-last-clock-out-time "org-clock" ()) -(declare-function org-clock-timestamps-up "org-clock" (&optional n)) -(declare-function org-clock-timestamps-down "org-clock" (&optional n)) +(declare-function org-clock-out "org-clock" (&optional switch-to-state fail-quietly at-time)) (declare-function org-clock-remove-overlays "org-clock" (&optional beg end noremove)) +(declare-function org-clock-sum "org-clock" (&optional tstart tend headline-filter propname)) (declare-function org-clock-sum-current-item "org-clock" (&optional tstart)) +(declare-function org-clock-timestamps-down "org-clock" (&optional n)) +(declare-function org-clock-timestamps-up "org-clock" (&optional n)) (declare-function org-clock-update-time-maybe "org-clock" ()) (declare-function org-clocktable-shift "org-clock" (dir n)) - -(declare-function orgtbl-mode "org-table" (&optional arg)) -(declare-function org-clock-out "org-clock" (&optional switch-to-state fail-quietly at-time)) -(declare-function org-beamer-mode "ox-beamer" (&optional prefix) t) -(declare-function org-table-edit-field "org-table" (arg)) -(declare-function org-table-justify-field-maybe "org-table" (&optional new)) -(declare-function org-table-set-constants "org-table" ()) -(declare-function org-table-calc-current-TBLFM "org-table" (&optional arg)) -(declare-function org-id-get-create "org-id" (&optional force)) +(declare-function org-element-at-point "org-element" ()) +(declare-function org-element-cache-refresh "org-element" (pos)) +(declare-function org-element-cache-reset "org-element" (&optional all)) +(declare-function org-element-contents "org-element" (element)) +(declare-function org-element-context "org-element" (&optional element)) +(declare-function org-element-copy "org-element" (datum)) +(declare-function org-element-interpret-data "org-element" (data)) +(declare-function org-element-lineage "org-element" (blob &optional types with-self)) +(declare-function org-element-link-parser "org-element" ()) +(declare-function org-element-nested-p "org-element" (elem-a elem-b)) +(declare-function org-element-parse-buffer "org-element" (&optional granularity visible-only)) +(declare-function org-element-property "org-element" (property element)) +(declare-function org-element-put-property "org-element" (element property value)) +(declare-function org-element-swap-A-B "org-element" (elem-a elem-b)) +(declare-function org-element-type "org-element" (element)) +(declare-function org-element-update-syntax "org-element" ()) (declare-function org-id-find-id-file "org-id" (id)) -(declare-function org-tags-view "org-agenda" (&optional todo-only match)) -(declare-function org-agenda-list "org-agenda" - (&optional arg start-day span with-hour)) -(declare-function org-agenda-redo "org-agenda" (&optional all)) +(declare-function org-id-get-create "org-id" (&optional force)) +(declare-function org-inlinetask-at-task-p "org-inlinetask" ()) +(declare-function org-inlinetask-outline-regexp "org-inlinetask" ()) +(declare-function org-inlinetask-toggle-visibility "org-inlinetask" ()) +(declare-function org-plot/gnuplot "org-plot" (&optional params)) (declare-function org-table-align "org-table" ()) (declare-function org-table-begin "org-table" (&optional table-type)) +(declare-function org-table-beginning-of-field "org-table" (&optional n)) (declare-function org-table-blank-field "org-table" ()) +(declare-function org-table-calc-current-TBLFM "org-table" (&optional arg)) +(declare-function org-table-copy-region "org-table" (beg end &optional cut)) +(declare-function org-table-cut-region "org-table" (beg end)) +(declare-function org-table-edit-field "org-table" (arg)) (declare-function org-table-end "org-table" (&optional table-type)) +(declare-function org-table-end-of-field "org-table" (&optional n)) (declare-function org-table-insert-row "org-table" (&optional arg)) -(declare-function org-table-paste-rectangle "org-table" ()) +(declare-function org-table-justify-field-maybe "org-table" (&optional new)) (declare-function org-table-maybe-eval-formula "org-table" ()) (declare-function org-table-maybe-recalculate-line "org-table" ()) +(declare-function org-table-next-row "org-table" ()) +(declare-function org-table-paste-rectangle "org-table" ()) +(declare-function org-table-recalculate "org-table" (&optional all noalign)) +(declare-function org-table-wrap-region "org-table" (arg)) +(declare-function org-tags-view "org-agenda" (&optional todo-only match)) +(declare-function orgtbl-ascii-plot "org-table" (&optional ask)) +(declare-function orgtbl-mode "org-table" (&optional arg)) +(declare-function org-export-get-backend "ox" (name)) +(declare-function org-export-get-environment "ox" (&optional backend subtreep ext-plist)) +(declare-function org-latex-make-preamble "ox-latex" (info &optional template snippet?)) -(declare-function org-element--parse-objects "org-element" - (beg end acc restriction)) -(declare-function org-element-at-point "org-element" (&optional keep-trail)) -(declare-function org-element-contents "org-element" (element)) -(declare-function org-element-context "org-element" (&optional element)) -(declare-function org-element-interpret-data "org-element" - (data &optional parent)) -(declare-function org-element-map "org-element" - (data types fun &optional - info first-match no-recursion with-affiliated)) -(declare-function org-element-nested-p "org-element" (elem-a elem-b)) -(declare-function org-element-parse-buffer "org-element" - (&optional granularity visible-only)) -(declare-function org-element-property "org-element" (property element)) -(declare-function org-element-put-property "org-element" - (element property value)) -(declare-function org-element-swap-A-B "org-element" (elem-a elem-b)) -(declare-function org-element--parse-objects "org-element" - (beg end acc restriction)) -(declare-function org-element-parse-buffer "org-element" - (&optional granularity visible-only)) -(declare-function org-element-restriction "org-element" (element)) -(declare-function org-element-type "org-element" (element)) +(defsubst org-uniquify (list) + "Non-destructively remove duplicate elements from LIST." + (let ((res (copy-sequence list))) (delete-dups res))) + +(defsubst org-get-at-bol (property) + "Get text property PROPERTY at the beginning of line." + (get-text-property (point-at-bol) property)) + +(defsubst org-trim (s &optional keep-lead) + "Remove whitespace at the beginning and the end of string S. +When optional argument KEEP-LEAD is non-nil, removing blank lines +at the beginning of the string does not affect leading indentation." + (replace-regexp-in-string + (if keep-lead "\\`\\([ \t]*\n\\)+" "\\`[ \t\n\r]+") "" + (replace-regexp-in-string "[ \t\n\r]+\\'" "" s))) ;; load languages based on value of `org-babel-load-languages' (defvar org-babel-load-languages) @@ -178,28 +199,24 @@ Stars are put in group 1 and the trimmed body in group 2.") (defun org-babel-do-load-languages (sym value) "Load the languages defined in `org-babel-load-languages'." (set-default sym value) - (mapc (lambda (pair) - (let ((active (cdr pair)) (lang (symbol-name (car pair)))) - (if active - (progn - (require (intern (concat "ob-" lang)))) - (progn - (funcall 'fmakunbound - (intern (concat "org-babel-execute:" lang))) - (funcall 'fmakunbound - (intern (concat "org-babel-expand-body:" lang))))))) - org-babel-load-languages)) + (dolist (pair org-babel-load-languages) + (let ((active (cdr pair)) (lang (symbol-name (car pair)))) + (if active + (require (intern (concat "ob-" lang))) + (funcall 'fmakunbound + (intern (concat "org-babel-execute:" lang))) + (funcall 'fmakunbound + (intern (concat "org-babel-expand-body:" lang))))))) (declare-function org-babel-tangle-file "ob-tangle" (file &optional target-file lang)) ;;;###autoload (defun org-babel-load-file (file &optional compile) - "Load Emacs Lisp source code blocks in the Org-mode FILE. + "Load Emacs Lisp source code blocks in the Org FILE. This function exports the source code using `org-babel-tangle' and then loads the resulting file using `load-file'. With prefix arg (noninteractively: 2nd arg) COMPILE the tangled Emacs Lisp file to byte-code before it is loaded." (interactive "fFile to load: \nP") - (require 'ob-core) (let* ((age (lambda (file) (float-time (time-subtract (current-time) @@ -207,11 +224,13 @@ file to byte-code before it is loaded." (file-attributes file))))))) (base-name (file-name-sans-extension file)) (exported-file (concat base-name ".el"))) - ;; tangle if the org-mode file is newer than the elisp file + ;; tangle if the Org file is newer than the elisp file (unless (and (file-exists-p exported-file) (> (funcall age file) (funcall age exported-file))) + ;; Tangle-file traversal returns reversed list of tangled files + ;; and we want to evaluate the first target. (setq exported-file - (car (org-babel-tangle-file file exported-file "emacs-lisp")))) + (car (last (org-babel-tangle-file file exported-file "emacs-lisp"))))) (message "%s %s" (if compile (progn (byte-compile-file exported-file 'load) @@ -220,7 +239,7 @@ file to byte-code before it is loaded." exported-file))) (defcustom org-babel-load-languages '((emacs-lisp . t)) - "Languages which can be evaluated in Org-mode buffers. + "Languages which can be evaluated in Org buffers. This list can be used to load support for any of the languages below, note that each language will depend on a different set of system executables and/or Emacs modes. When a language is @@ -246,10 +265,12 @@ requirements) is loaded." (const :tag "Ditaa" ditaa) (const :tag "Dot" dot) (const :tag "Emacs Lisp" emacs-lisp) + (const :tag "Forth" forth) (const :tag "Fortran" fortran) (const :tag "Gnuplot" gnuplot) (const :tag "Haskell" haskell) (const :tag "IO" io) + (const :tag "J" J) (const :tag "Java" java) (const :tag "Javascript" js) (const :tag "LaTeX" latex) @@ -272,10 +293,12 @@ requirements) is loaded." (const :tag "Scala" scala) (const :tag "Scheme" scheme) (const :tag "Screen" screen) - (const :tag "Shell Script" sh) + (const :tag "Shell Script" shell) (const :tag "Shen" shen) (const :tag "Sql" sql) - (const :tag "Sqlite" sqlite)) + (const :tag "Sqlite" sqlite) + (const :tag "Stan" stan) + (const :tag "ebnf2ps" ebnf2ps)) :value-type (boolean :tag "Activate" :value t))) ;;;; Customization variables @@ -293,41 +316,318 @@ identifier." ;;;###autoload (defun org-version (&optional here full message) - "Show the org-mode version in the echo area. -With prefix argument HERE, insert it at point. -When FULL is non-nil, use a verbose version string. -When MESSAGE is non-nil, display a message with the version." - (interactive "P") - (let* ((org-dir (ignore-errors (org-find-library-dir "org"))) - (save-load-suffixes (when (boundp 'load-suffixes) load-suffixes)) - (load-suffixes (list ".el")) - (org-install-dir (ignore-errors (org-find-library-dir "org-loaddefs"))) - (org-trash (or - (and (fboundp 'org-release) (fboundp 'org-git-version)) - (org-load-noerror-mustsuffix (concat org-dir "org-version")))) - (load-suffixes save-load-suffixes) - (org-version (org-release)) - (git-version (org-git-version)) - (version (format "Org-mode version %s (%s @ %s)" - org-version - git-version - (if org-install-dir - (if (string= org-dir org-install-dir) - org-install-dir - (concat "mixed installation! " org-install-dir " and " org-dir)) - "org-loaddefs.el can not be found!"))) - (version1 (if full version org-version))) - (if (org-called-interactively-p 'interactive) - (if here - (insert version) - (message version)) - (if message (message version1)) + "Show the Org version. +Interactively, or when MESSAGE is non-nil, show it in echo area. +With prefix argument, or when HERE is non-nil, insert it at point. +In non-interactive uses, a reduced version string is output unless +FULL is given." + (interactive (list current-prefix-arg t (not current-prefix-arg))) + (let ((org-dir (ignore-errors (org-find-library-dir "org"))) + (save-load-suffixes (when (boundp 'load-suffixes) load-suffixes)) + (load-suffixes (list ".el")) + (org-install-dir + (ignore-errors (org-find-library-dir "org-loaddefs")))) + (unless (and (fboundp 'org-release) (fboundp 'org-git-version)) + (org-load-noerror-mustsuffix (concat org-dir "org-version"))) + (let* ((load-suffixes save-load-suffixes) + (release (org-release)) + (git-version (org-git-version)) + (version (format "Org mode version %s (%s @ %s)" + release + git-version + (if org-install-dir + (if (string= org-dir org-install-dir) + org-install-dir + (concat "mixed installation! " + org-install-dir + " and " + org-dir)) + "org-loaddefs.el can not be found!"))) + (version1 (if full version release))) + (when here (insert version1)) + (when message (message "%s" version1)) version1))) (defconst org-version (org-version)) -;;; Compatibility constants + +;;; Syntax Constants + +;;;; Block + +(defconst org-block-regexp + "^[ \t]*#\\+begin_?\\([^ \n]+\\)\\(\\([^\n]+\\)\\)?\n\\([^\000]+?\\)#\\+end_?\\1[ \t]*$" + "Regular expression for hiding blocks.") + +(defconst org-dblock-start-re + "^[ \t]*#\\+\\(?:BEGIN\\|begin\\):[ \t]+\\(\\S-+\\)\\([ \t]+\\(.*\\)\\)?" + "Matches the start line of a dynamic block, with parameters.") + +(defconst org-dblock-end-re "^[ \t]*#\\+\\(?:END\\|end\\)\\([: \t\r\n]\\|$\\)" + "Matches the end of a dynamic block.") + +;;;; Clock and Planning + +(defconst org-clock-string "CLOCK:" + "String used as prefix for timestamps clocking work hours on an item.") + +(defvar org-closed-string "CLOSED:" + "String used as the prefix for timestamps logging closing a TODO entry.") + +(defvar org-deadline-string "DEADLINE:" + "String to mark deadline entries. +\\ +A deadline is this string, followed by a time stamp. It must be +a word, terminated by a colon. You can insert a schedule keyword +and a timestamp with `\\[org-deadline]'.") + +(defvar org-scheduled-string "SCHEDULED:" + "String to mark scheduled TODO entries. +\\ +A schedule is this string, followed by a time stamp. It must be +a word, terminated by a colon. You can insert a schedule keyword +and a timestamp with `\\[org-schedule]'.") + +(defconst org-ds-keyword-length + (+ 2 + (apply #'max + (mapcar #'length + (list org-deadline-string org-scheduled-string + org-clock-string org-closed-string)))) + "Maximum length of the DEADLINE and SCHEDULED keywords.") + +(defconst org-planning-line-re + (concat "^[ \t]*" + (regexp-opt + (list org-closed-string org-deadline-string org-scheduled-string) + t)) + "Matches a line with planning info. +Matched keyword is in group 1.") + +(defconst org-clock-line-re + (concat "^[ \t]*" org-clock-string) + "Matches a line with clock info.") + +(defconst org-deadline-regexp (concat "\\<" org-deadline-string) + "Matches the DEADLINE keyword.") + +(defconst org-deadline-time-regexp + (concat "\\<" org-deadline-string " *<\\([^>]+\\)>") + "Matches the DEADLINE keyword together with a time stamp.") + +(defconst org-deadline-time-hour-regexp + (concat "\\<" org-deadline-string + " *<\\([^>]+[0-9]\\{1,2\\}:[0-9]\\{2\\}[0-9-+:hdwmy \t.]*\\)>") + "Matches the DEADLINE keyword together with a time-and-hour stamp.") + +(defconst org-deadline-line-regexp + (concat "\\<\\(" org-deadline-string "\\).*") + "Matches the DEADLINE keyword and the rest of the line.") + +(defconst org-scheduled-regexp (concat "\\<" org-scheduled-string) + "Matches the SCHEDULED keyword.") + +(defconst org-scheduled-time-regexp + (concat "\\<" org-scheduled-string " *<\\([^>]+\\)>") + "Matches the SCHEDULED keyword together with a time stamp.") + +(defconst org-scheduled-time-hour-regexp + (concat "\\<" org-scheduled-string + " *<\\([^>]+[0-9]\\{1,2\\}:[0-9]\\{2\\}[0-9-+:hdwmy \t.]*\\)>") + "Matches the SCHEDULED keyword together with a time-and-hour stamp.") + +(defconst org-closed-time-regexp + (concat "\\<" org-closed-string " *\\[\\([^]]+\\)\\]") + "Matches the CLOSED keyword together with a time stamp.") + +(defconst org-keyword-time-regexp + (concat "\\<" + (regexp-opt + (list org-scheduled-string org-deadline-string org-closed-string + org-clock-string) + t) + " *[[<]\\([^]>]+\\)[]>]") + "Matches any of the 4 keywords, together with the time stamp.") + +(defconst org-keyword-time-not-clock-regexp + (concat + "\\<" + (regexp-opt + (list org-scheduled-string org-deadline-string org-closed-string) t) + " *[[<]\\([^]>]+\\)[]>]") + "Matches any of the 3 keywords, together with the time stamp.") + +(defconst org-maybe-keyword-time-regexp + (concat "\\(\\<" + (regexp-opt + (list org-scheduled-string org-deadline-string org-closed-string + org-clock-string) + t) + "\\)?" + " *\\([[<][0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^]\r\n>]*?[]>]" + "\\|" + "<%%([^\r\n>]*>\\)") + "Matches a timestamp, possibly preceded by a keyword.") + +(defconst org-all-time-keywords + (mapcar (lambda (w) (substring w 0 -1)) + (list org-scheduled-string org-deadline-string + org-clock-string org-closed-string)) + "List of time keywords.") + +;;;; Drawer + +(defconst org-drawer-regexp "^[ \t]*:\\(\\(?:\\w\\|[-_]\\)+\\):[ \t]*$" + "Matches first or last line of a hidden block. +Group 1 contains drawer's name or \"END\".") + +(defconst org-property-start-re "^[ \t]*:PROPERTIES:[ \t]*$" + "Regular expression matching the first line of a property drawer.") + +(defconst org-property-end-re "^[ \t]*:END:[ \t]*$" + "Regular expression matching the last line of a property drawer.") + +(defconst org-clock-drawer-start-re "^[ \t]*:CLOCK:[ \t]*$" + "Regular expression matching the first line of a clock drawer.") + +(defconst org-clock-drawer-end-re "^[ \t]*:END:[ \t]*$" + "Regular expression matching the last line of a clock drawer.") + +(defconst org-property-drawer-re + (concat "^[ \t]*:PROPERTIES:[ \t]*\n" + "\\(?:[ \t]*:\\S-+:\\(?: .*\\)?[ \t]*\n\\)*?" + "[ \t]*:END:[ \t]*$") + "Matches an entire property drawer.") + +(defconst org-clock-drawer-re + (concat "\\(" org-clock-drawer-start-re "\\)[^\000]*?\\(" + org-clock-drawer-end-re "\\)\n?") + "Matches an entire clock drawer.") + +;;;; Headline + +(defconst org-heading-keyword-regexp-format + "^\\(\\*+\\)\\(?: +%s\\)\\(?: +\\(.*?\\)\\)?[ \t]*$" + "Printf format for a regexp matching a headline with some keyword. +This regexp will match the headline of any node which has the +exact keyword that is put into the format. The keyword isn't in +any group by default, but the stars and the body are.") + +(defconst org-heading-keyword-maybe-regexp-format + "^\\(\\*+\\)\\(?: +%s\\)?\\(?: +\\(.*?\\)\\)?[ \t]*$" + "Printf format for a regexp matching a headline, possibly with some keyword. +This regexp can match any headline with the specified keyword, or +without a keyword. The keyword isn't in any group by default, +but the stars and the body are.") + +(defconst org-archive-tag "ARCHIVE" + "The tag that marks a subtree as archived. +An archived subtree does not open during visibility cycling, and does +not contribute to the agenda listings.") + +(defconst org-comment-string "COMMENT" + "Entries starting with this keyword will never be exported. +\\ +An entry can be toggled between COMMENT and normal with +`\\[org-toggle-comment]'.") + + +;;;; LaTeX Environments and Fragments + +(defconst org-latex-regexps + '(("begin" "^[ \t]*\\(\\\\begin{\\([a-zA-Z0-9\\*]+\\)[^\000]+?\\\\end{\\2}\\)" 1 t) + ;; ("$" "\\([ \t(]\\|^\\)\\(\\(\\([$]\\)\\([^ \t\n,.$].*?\\(\n.*?\\)\\{0,5\\}[^ \t\n,.$]\\)\\4\\)\\)\\([ \t.,?;:'\")]\\|$\\)" 2 nil) + ;; \000 in the following regex is needed for org-inside-LaTeX-fragment-p + ("$1" "\\([^$]\\|^\\)\\(\\$[^ \t\r\n,;.$]\\$\\)\\(\\s.\\|\\s-\\|\\s(\\|\\s)\\|\\s\"\\|\000\\|'\\|$\\)" 2 nil) + ("$" "\\([^$]\\|^\\)\\(\\(\\$\\([^ \t\n,;.$][^$\n\r]*?\\(\n[^$\n\r]*?\\)\\{0,2\\}[^ \t\n,.$]\\)\\$\\)\\)\\(\\s.\\|\\s-\\|\\s(\\|\\s)\\|\\s\"\\|\000\\|'\\|$\\)" 2 nil) + ("\\(" "\\\\([^\000]*?\\\\)" 0 nil) + ("\\[" "\\\\\\[[^\000]*?\\\\\\]" 0 nil) + ("$$" "\\$\\$[^\000]*?\\$\\$" 0 nil)) + "Regular expressions for matching embedded LaTeX.") + +;;;; Node Property + +(defconst org-effort-property "Effort" + "The property that is being used to keep track of effort estimates. +Effort estimates given in this property need to have the format H:MM.") + +;;;; Table + +(defconst org-table-any-line-regexp "^[ \t]*\\(|\\|\\+-[-+]\\)" + "Detect an org-type or table-type table.") + +(defconst org-table-line-regexp "^[ \t]*|" + "Detect an org-type table line.") + +(defconst org-table-dataline-regexp "^[ \t]*|[^-]" + "Detect an org-type table line.") + +(defconst org-table-hline-regexp "^[ \t]*|-" + "Detect an org-type table hline.") + +(defconst org-table1-hline-regexp "^[ \t]*\\+-[-+]" + "Detect a table-type table hline.") + +(defconst org-table-any-border-regexp "^[ \t]*[^|+ \t]" + "Detect the first line outside a table when searching from within it. +This works for both table types.") + +(defconst org-TBLFM-regexp "^[ \t]*#\\+TBLFM: " + "Detect a #+TBLFM line.") + +;;;; Timestamp + +(defconst org-ts-regexp "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^\r\n>]*?\\)>" + "Regular expression for fast time stamp matching.") + +(defconst org-ts-regexp-inactive + "\\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^\r\n>]*?\\)\\]" + "Regular expression for fast inactive time stamp matching.") + +(defconst org-ts-regexp-both "[[<]\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^]\r\n>]*?\\)[]>]" + "Regular expression for fast time stamp matching.") + +(defconst org-ts-regexp0 + "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\)\\( +[^]+0-9>\r\n -]+\\)?\\( +\\([0-9]\\{1,2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)" + "Regular expression matching time strings for analysis. +This one does not require the space after the date, so it can be used +on a string that terminates immediately after the date.") + +(defconst org-ts-regexp1 "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\) *\\([^]+0-9>\r\n -]*\\)\\( \\([0-9]\\{1,2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)" + "Regular expression matching time strings for analysis.") + +(defconst org-ts-regexp2 (concat "<" org-ts-regexp1 "[^>\n]\\{0,16\\}>") + "Regular expression matching time stamps, with groups.") + +(defconst org-ts-regexp3 (concat "[[<]" org-ts-regexp1 "[^]>\n]\\{0,16\\}[]>]") + "Regular expression matching time stamps (also [..]), with groups.") + +(defconst org-tr-regexp (concat org-ts-regexp "--?-?" org-ts-regexp) + "Regular expression matching a time stamp range.") + +(defconst org-tr-regexp-both + (concat org-ts-regexp-both "--?-?" org-ts-regexp-both) + "Regular expression matching a time stamp range.") + +(defconst org-tsr-regexp (concat org-ts-regexp "\\(--?-?" + org-ts-regexp "\\)?") + "Regular expression matching a time stamp or time stamp range.") + +(defconst org-tsr-regexp-both + (concat org-ts-regexp-both "\\(--?-?" + org-ts-regexp-both "\\)?") + "Regular expression matching a time stamp or time stamp range. +The time stamps may be either active or inactive.") +(defconst org-repeat-re + "<[0-9]\\{4\\}-[0-9][0-9]-[0-9][0-9] [^>\n]*?\\([.+]?\\+[0-9]+[hdwmy]\\(/[0-9]+[hdwmy]\\)?\\)" + "Regular expression for specifying repeated events. +After a match, group 1 contains the repeat expression.") + +(defconst org-time-stamp-formats '("<%Y-%m-%d %a>" . "<%Y-%m-%d %a %H:%M>") + "Formats for `format-time-string' which are used for time stamps.") + + ;;; The custom variables (defgroup org nil @@ -337,7 +637,7 @@ When MESSAGE is non-nil, display a message with the version." :group 'calendar) (defcustom org-mode-hook nil - "Mode hook for Org-mode, run after the mode was turned on." + "Mode hook for Org mode, run after the mode was turned on." :group 'org :type 'hook) @@ -359,17 +659,17 @@ When MESSAGE is non-nil, display a message with the version." (defun org-load-modules-maybe (&optional force) "Load all extensions listed in `org-modules'." (when (or force (not org-modules-loaded)) - (mapc (lambda (ext) - (condition-case nil (require ext) - (error (message "Problems while trying to load feature `%s'" ext)))) - org-modules) + (dolist (ext org-modules) + (condition-case nil (require ext) + (error (message "Problems while trying to load feature `%s'" ext)))) (setq org-modules-loaded t))) (defun org-set-modules (var value) "Set VAR to VALUE and call `org-load-modules-maybe' with the force flag." (set var value) (when (featurep 'org) - (org-load-modules-maybe 'force))) + (org-load-modules-maybe 'force) + (org-element-cache-reset 'all))) (defcustom org-modules '(org-w3m org-bbdb org-bibtex org-docview org-gnus org-info org-irc org-mhe org-rmail) "Modules that should always be loaded together with org.el. @@ -397,6 +697,7 @@ For export specific modules, see also `org-export-backends'." (const :tag " crypt: Encryption of subtrees" org-crypt) (const :tag " ctags: Access to Emacs tags with links" org-ctags) (const :tag " docview: Links to doc-view buffers" org-docview) + (const :tag " eww: Store link to url of eww" org-eww) (const :tag " gnus: Links to GNUS folders/messages" org-gnus) (const :tag " habit: Track your consistency with habits" org-habit) (const :tag " id: Global IDs for identifying entries" org-id) @@ -407,52 +708,50 @@ For export specific modules, see also `org-export-backends'." (const :tag " mouse: Additional mouse support" org-mouse) (const :tag " protocol: Intercept calls from emacsclient" org-protocol) (const :tag " rmail: Links to RMAIL folders/messages" org-rmail) - (const :tag " w3m: Special cut/paste from w3m to Org-mode." org-w3m) + (const :tag " w3m: Special cut/paste from w3m to Org mode." org-w3m) (const :tag "C annotate-file: Annotate a file with org syntax" org-annotate-file) - (const :tag "C bookmark: Org-mode links to bookmarks" org-bookmark) + (const :tag "C bookmark: Org links to bookmarks" org-bookmark) (const :tag "C bullets: Add overlays to headlines stars" org-bullets) (const :tag "C checklist: Extra functions for checklists in repeated tasks" org-checklist) (const :tag "C choose: Use TODO keywords to mark decisions states" org-choose) (const :tag "C collector: Collect properties into tables" org-collector) - (const :tag "C depend: TODO dependencies for Org-mode\n\t\t\t(PARTIALLY OBSOLETE, see built-in dependency support))" org-depend) - (const :tag "C drill: Flashcards and spaced repetition for Org-mode" org-drill) - (const :tag "C elisp-symbol: Org-mode links to emacs-lisp symbols" org-elisp-symbol) + (const :tag "C depend: TODO dependencies for Org mode\n\t\t\t(PARTIALLY OBSOLETE, see built-in dependency support))" org-depend) + (const :tag "C drill: Flashcards and spaced repetition for Org mode" org-drill) + (const :tag "C elisp-symbol: Org links to emacs-lisp symbols" org-elisp-symbol) (const :tag "C eshell Support for links to working directories in eshell" org-eshell) (const :tag "C eval-light: Evaluate inbuffer-code on demand" org-eval-light) (const :tag "C eval: Include command output as text" org-eval) - (const :tag "C expiry: Expiry mechanism for Org-mode entries" org-expiry) + (const :tag "C expiry: Expiry mechanism for Org entries" org-expiry) (const :tag "C favtable: Lookup table of favorite references and links" org-favtable) (const :tag "C git-link: Provide org links to specific file version" org-git-link) (const :tag "C interactive-query: Interactive modification of tags query\n\t\t\t(PARTIALLY OBSOLETE, see secondary filtering)" org-interactive-query) - (const :tag "C invoice: Help manage client invoices in Org-mode" org-invoice) - (const :tag "C jira: Add a jira:ticket protocol to Org-mode" org-jira) + (const :tag "C invoice: Help manage client invoices in Org mode" org-invoice) (const :tag "C learn: SuperMemo's incremental learning algorithm" org-learn) (const :tag "C mac-iCal Imports events from iCal.app to the Emacs diary" org-mac-iCal) (const :tag "C mac-link: Grab links and url from various mac Applications" org-mac-link) - (const :tag "C mairix: Hook mairix search into Org-mode for different MUAs" org-mairix) - (const :tag "C man: Support for links to manpages in Org-mode" org-man) + (const :tag "C mairix: Hook mairix search into Org for different MUAs" org-mairix) + (const :tag "C man: Support for links to manpages in Org mode" org-man) (const :tag "C mew: Links to Mew folders/messages" org-mew) (const :tag "C mtags: Support for muse-like tags" org-mtags) (const :tag "C notmuch: Provide org links to notmuch searches or messages" org-notmuch) (const :tag "C panel: Simple routines for us with bad memory" org-panel) - (const :tag "C registry: A registry for Org-mode links" org-registry) - (const :tag "C screen: Visit screen sessions through Org-mode links" org-screen) + (const :tag "C registry: A registry for Org links" org-registry) + (const :tag "C screen: Visit screen sessions through Org links" org-screen) (const :tag "C secretary: Team management with org-mode" org-secretary) - (const :tag "C sqlinsert: Convert Org-mode tables to SQL insertions" orgtbl-sqlinsert) - (const :tag "C toc: Table of contents for Org-mode buffer" org-toc) - (const :tag "C track: Keep up with Org-mode development" org-track) + (const :tag "C sqlinsert: Convert Org tables to SQL insertions" orgtbl-sqlinsert) + (const :tag "C toc: Table of contents for Org buffer" org-toc) + (const :tag "C track: Keep up with Org mode development" org-track) (const :tag "C velocity Something like Notational Velocity for Org" org-velocity) (const :tag "C vm: Links to VM folders/messages" org-vm) (const :tag "C wikinodes: CamelCase wiki-like links" org-wikinodes) (const :tag "C wl: Links to Wanderlust folders/messages" org-wl) (repeat :tag "External packages" :inline t (symbol :tag "Package")))) -(defvar org-export--registered-backends) ; From ox.el. +(defvar org-export-registered-backends) ; From ox.el. (declare-function org-export-derived-backend-p "ox" (backend &rest backends)) (declare-function org-export-backend-name "ox" (backend) t) -(declare-function org-export-backend-options "ox" (cl-x) t) -(defcustom org-export-backends '(ascii html icalendar latex) +(defcustom org-export-backends '(ascii html icalendar latex odt) "List of export back-ends that should be always available. If a description starts with , the file is not part of Emacs @@ -469,8 +768,8 @@ interface or run the following code, where VAL stands for the new value of the variable, after updating it: (progn - (setq org-export--registered-backends - (org-remove-if-not + (setq org-export-registered-backends + (cl-remove-if-not (lambda (backend) (let ((name (org-export-backend-name backend))) (or (memq name val) @@ -478,9 +777,9 @@ value of the variable, after updating it: (dolist (b val) (and (org-export-derived-backend-p b name) (throw \\='parentp t))))))) - org-export--registered-backends)) - (let ((new-list (mapcar \\='org-export-backend-name - org-export--registered-backends))) + org-export-registered-backends)) + (let ((new-list (mapcar #\\='org-export-backend-name + org-export-registered-backends))) (dolist (backend val) (cond ((not (load (format \"ox-%s\" backend) t t)) @@ -493,16 +792,16 @@ Adding a back-end to this list will also pull the back-end it depends on, if any." :group 'org :group 'org-export - :version "24.4" - :package-version '(Org . "8.0") + :version "26.1" + :package-version '(Org . "9.0") :initialize 'custom-initialize-set :set (lambda (var val) (if (not (featurep 'ox)) (set-default var val) ;; Any back-end not required anymore (not present in VAL and not ;; a parent of any back-end in the new value) is removed from the ;; list of registered back-ends. - (setq org-export--registered-backends - (org-remove-if-not + (setq org-export-registered-backends + (cl-remove-if-not (lambda (backend) (let ((name (org-export-backend-name backend))) (or (memq name val) @@ -510,11 +809,11 @@ depends on, if any." (dolist (b val) (and (org-export-derived-backend-p b name) (throw 'parentp t))))))) - org-export--registered-backends)) + org-export-registered-backends)) ;; Now build NEW-LIST of both new back-ends and required ;; parents. - (let ((new-list (mapcar 'org-export-backend-name - org-export--registered-backends))) + (let ((new-list (mapcar #'org-export-backend-name + org-export-registered-backends))) (dolist (backend val) (cond ((not (load (format "ox-%s" backend) t t)) @@ -544,19 +843,18 @@ depends on, if any." (const :tag "C taskjuggler Export buffer to TaskJuggler format" taskjuggler))) (eval-after-load 'ox - '(mapc - (lambda (backend) - (condition-case nil (require (intern (format "ox-%s" backend))) - (error (message "Problems while trying to load export back-end `%s'" - backend)))) - org-export-backends)) + '(dolist (backend org-export-backends) + (condition-case nil (require (intern (format "ox-%s" backend))) + (error (message "Problems while trying to load export back-end `%s'" + backend))))) (defcustom org-support-shift-select nil "Non-nil means make shift-cursor commands select text when possible. +\\\ In Emacs 23, when `shift-select-mode' is on, shifted cursor keys start selecting a region, or enlarge regions started in this way. -In Org-mode, in special contexts, these same keys are used for +In Org mode, in special contexts, these same keys are used for other purposes, important enough to compete with shift selection. Org tries to balance these needs by supporting `shift-select-mode' outside these special contexts, under control of this variable. @@ -571,7 +869,7 @@ cursor keys will then execute Org commands in the following contexts: Outside these contexts, the commands will throw an error. When this variable is t and the cursor is not in a special -context, Org-mode will support shift-selection for making and +context, Org mode will support shift-selection for making and enlarging regions. To make this more effective, the bullet cycling will no longer happen anywhere in an item line, but only if the cursor is exactly on the bullet. @@ -579,16 +877,16 @@ if the cursor is exactly on the bullet. If you set this variable to the symbol `always', then the keys will not be special in headlines, property lines, and item lines, to make shift selection work there as well. If this is what you -want, you can use the following alternative commands: `C-c C-t' -and `C-c ,' to change TODO state and priority, `C-u C-u C-c C-t' -can be used to switch TODO sets, `C-c -' to cycle item bullet -types, and properties can be edited by hand or in column view. +want, you can use the following alternative commands: +`\\[org-todo]' and `\\[org-priority]' \ +to change TODO state and priority, +`\\[universal-argument] \\[universal-argument] \\[org-todo]' \ +can be used to switch TODO sets, +`\\[org-ctrl-c-minus]' to cycle item bullet types, +and properties can be edited by hand or in column view. However, when the cursor is on a timestamp, shift-cursor commands -will still edit the time stamp - this is just too good to give up. - -XEmacs user should have this variable set to nil, because -`shift-select-mode' is in Emacs 23 or later only." +will still edit the time stamp - this is just too good to give up." :group 'org :type '(choice (const :tag "Never" nil) @@ -622,12 +920,13 @@ already archived entries." :group 'org-archive) (defgroup org-startup nil - "Options concerning startup of Org-mode." + "Options concerning startup of Org mode." :tag "Org Startup" :group 'org) (defcustom org-startup-folded t - "Non-nil means entering Org-mode will switch to OVERVIEW. + "Non-nil means entering Org mode will switch to OVERVIEW. + This can also be configured on a per-file basis by adding one of the following lines anywhere in the buffer: @@ -636,9 +935,9 @@ the following lines anywhere in the buffer: #+STARTUP: content #+STARTUP: showeverything -By default, this option is ignored when Org opens agenda files -for the first time. If you want the agenda to honor the startup -option, set `org-agenda-inhibit-startup' to nil." +Set `org-agenda-inhibit-startup' to a non-nil value if you want +to ignore this option when Org opens agenda files for the first +time." :group 'org-startup :type '(choice (const :tag "nofold: show all" nil) @@ -647,9 +946,18 @@ option, set `org-agenda-inhibit-startup' to nil." (const :tag "show everything, even drawers" showeverything))) (defcustom org-startup-truncated t - "Non-nil means entering Org-mode will set `truncate-lines'. + "Non-nil means entering Org mode will set `truncate-lines'. This is useful since some lines containing links can be very long and -uninteresting. Also tables look terrible when wrapped." +uninteresting. Also tables look terrible when wrapped. + +The variable `org-startup-truncated' allows to configure +truncation for Org mode different to the other modes that use the +variable `truncate-lines' and as a shortcut instead of putting +the variable `truncate-lines' into the `org-mode-hook'. If one +wants to configure truncation for Org mode not statically but +dynamically e. g. in a hook like `ediff-prepare-buffer-hook' then +the variable `truncate-lines' has to be used because in such a +case it is too late to set the variable `org-startup-truncated'." :group 'org-startup :type 'boolean) @@ -742,26 +1050,26 @@ the following lines anywhere in the buffer: :type 'boolean) (defcustom org-insert-mode-line-in-empty-file nil - "Non-nil means insert the first line setting Org-mode in empty files. + "Non-nil means insert the first line setting Org mode in empty files. When the function `org-mode' is called interactively in an empty file, this -normally means that the file name does not automatically trigger Org-mode. -To ensure that the file will always be in Org-mode in the future, a -line enforcing Org-mode will be inserted into the buffer, if this option +normally means that the file name does not automatically trigger Org mode. +To ensure that the file will always be in Org mode in the future, a +line enforcing Org mode will be inserted into the buffer, if this option has been set." :group 'org-startup :type 'boolean) (defcustom org-replace-disputed-keys nil "Non-nil means use alternative key bindings for some keys. -Org-mode uses S- keys for changing timestamps and priorities. +Org mode uses S- keys for changing timestamps and priorities. These keys are also used by other packages like shift-selection-mode' \(built into Emacs 23), `CUA-mode' or `windmove.el'. -If you want to use Org-mode together with one of these other modes, -or more generally if you would like to move some Org-mode commands to +If you want to use Org mode together with one of these other modes, +or more generally if you would like to move some Org mode commands to other keys, set this variable and configure the keys with the variable `org-disputed-keys'. -This option is only relevant at load-time of Org-mode, and must be set +This option is only relevant at load-time of Org mode, and must be set *before* org.el is loaded. Changing it requires a restart of Emacs to become effective." :group 'org-startup @@ -769,18 +1077,13 @@ become effective." (defcustom org-use-extra-keys nil "Non-nil means use extra key sequence definitions for certain commands. -This happens automatically if you run XEmacs or if `window-system' -is nil. This variable lets you do the same manually. You must -set it before loading org. - -Example: on Carbon Emacs 22 running graphically, with an external -keyboard on a Powerbook, the default way of setting M-left might -not work for either Alt or ESC. Setting this variable will make -it work for ESC." +This happens automatically if `window-system' is nil. This +variable lets you do the same manually. You must set it before +loading Org." :group 'org-startup :type 'boolean) -(org-defvaralias 'org-CUA-compatible 'org-replace-disputed-keys) +(defvaralias 'org-CUA-compatible 'org-replace-disputed-keys) (defcustom org-disputed-keys '(([(shift up)] . [(meta p)]) @@ -789,90 +1092,52 @@ it work for ESC." ([(shift right)] . [(meta +)]) ([(control shift right)] . [(meta shift +)]) ([(control shift left)] . [(meta shift -)])) - "Keys for which Org-mode and other modes compete. + "Keys for which Org mode and other modes compete. This is an alist, cars are the default keys, second element specifies the alternative to use when `org-replace-disputed-keys' is t. Keys can be specified in any syntax supported by `define-key'. -The value of this option takes effect only at Org-mode's startup, +The value of this option takes effect only at Org mode startup, therefore you'll have to restart Emacs to apply it after changing." :group 'org-startup :type 'alist) (defun org-key (key) "Select key according to `org-replace-disputed-keys' and `org-disputed-keys'. -Or return the original if not disputed. -Also apply the translations defined in `org-xemacs-key-equivalents'." +Or return the original if not disputed." (when org-replace-disputed-keys (let* ((nkey (key-description key)) - (x (org-find-if (lambda (x) - (equal (key-description (car x)) nkey)) - org-disputed-keys))) + (x (cl-find-if (lambda (x) (equal (key-description (car x)) nkey)) + org-disputed-keys))) (setq key (if x (cdr x) key)))) - (when (featurep 'xemacs) - (setq key (or (cdr (assoc key org-xemacs-key-equivalents)) key))) key) -(defun org-find-if (predicate seq) - (catch 'exit - (while seq - (if (funcall predicate (car seq)) - (throw 'exit (car seq)) - (pop seq))))) - (defun org-defkey (keymap key def) "Define a key, possibly translated, as returned by `org-key'." (define-key keymap (org-key key) def)) (defcustom org-ellipsis nil - "The ellipsis to use in the Org-mode outline. + "The ellipsis to use in the Org mode outline. + When nil, just use the standard three dots. When a string, use that string instead. -When a face, use the standard 3 dots, but with the specified face. -The change affects only Org-mode (which will then use its own display table). + +The change affects only Org mode (which will then use its own display table). Changing this requires executing `\\[org-mode]' in a buffer to become effective." :group 'org-startup :type '(choice (const :tag "Default" nil) - (face :tag "Face" :value org-warning) - (string :tag "String" :value "...#"))) + (string :tag "String" :value "...#")) + :safe #'string-or-null-p) (defvar org-display-table nil "The display table for org-mode, in case `org-ellipsis' is non-nil.") (defgroup org-keywords nil - "Keywords in Org-mode." + "Keywords in Org mode." :tag "Org Keywords" :group 'org) -(defcustom org-deadline-string "DEADLINE:" - "String to mark deadline entries. -A deadline is this string, followed by a time stamp. Should be a word, -terminated by a colon. You can insert a schedule keyword and -a timestamp with \\[org-deadline]. -Changes become only effective after restarting Emacs." - :group 'org-keywords - :type 'string) - -(defcustom org-scheduled-string "SCHEDULED:" - "String to mark scheduled TODO entries. -A schedule is this string, followed by a time stamp. Should be a word, -terminated by a colon. You can insert a schedule keyword and -a timestamp with \\[org-schedule]. -Changes become only effective after restarting Emacs." - :group 'org-keywords - :type 'string) - -(defcustom org-closed-string "CLOSED:" - "String used as the prefix for timestamps logging closing a TODO entry." - :group 'org-keywords - :type 'string) - -(defcustom org-clock-string "CLOCK:" - "String used as prefix for timestamps clocking work hours on an item." - :group 'org-keywords - :type 'string) - (defcustom org-closed-keep-when-no-todo nil "Remove CLOSED: time-stamp when switching back to a non-todo state?" :group 'org-todo @@ -881,37 +1146,8 @@ Changes become only effective after restarting Emacs." :package-version '(Org . "8.0") :type 'boolean) -(defconst org-planning-or-clock-line-re (concat "^[ \t]*\\(" - org-scheduled-string "\\|" - org-deadline-string "\\|" - org-closed-string "\\|" - org-clock-string "\\)") - "Matches a line with planning or clock info.") - -(defcustom org-comment-string "COMMENT" - "Entries starting with this keyword will never be exported. -An entry can be toggled between COMMENT and normal with -\\[org-toggle-comment]. -Changes become only effective after restarting Emacs." - :group 'org-keywords - :type 'string) - -(defcustom org-quote-string "QUOTE" - "Entries starting with this keyword will be exported in fixed-width font. -Quoting applies only to the text in the entry following the headline, and does -not extend beyond the next headline, even if that is lower level. -An entry can be toggled between QUOTE and normal with -\\[org-toggle-fixed-width-section]." - :group 'org-keywords - :type 'string) - -(defconst org-repeat-re - "<[0-9]\\{4\\}-[0-9][0-9]-[0-9][0-9] [^>\n]*?\\([.+]?\\+[0-9]+[hdwmy]\\(/[0-9]+[hdwmy]\\)?\\)" - "Regular expression for specifying repeated events. -After a match, group 1 contains the repeat expression.") - (defgroup org-structure nil - "Options concerning the general structure of Org-mode files." + "Options concerning the general structure of Org files." :tag "Org Structure" :group 'org) @@ -920,92 +1156,88 @@ After a match, group 1 contains the repeat expression.") :tag "Org Reveal Location" :group 'org-structure) -(defconst org-context-choice - '(choice - (const :tag "Always" t) - (const :tag "Never" nil) - (repeat :greedy t :tag "Individual contexts" - (cons - (choice :tag "Context" - (const agenda) - (const org-goto) - (const occur-tree) - (const tags-tree) - (const link-search) - (const mark-goto) - (const bookmark-jump) - (const isearch) - (const default)) - (boolean)))) - "Contexts for the reveal options.") - -(defcustom org-show-hierarchy-above '((default . t)) - "Non-nil means show full hierarchy when revealing a location. -Org-mode often shows locations in an org-mode file which might have -been invisible before. When this is set, the hierarchy of headings -above the exposed location is shown. -Turning this off for example for sparse trees makes them very compact. -Instead of t, this can also be an alist specifying this option for different -contexts. Valid contexts are +(defcustom org-show-context-detail '((agenda . local) + (bookmark-jump . lineage) + (isearch . lineage) + (default . ancestors)) + "Alist between context and visibility span when revealing a location. + +\\Some actions may move point into invisible +locations. As a consequence, Org always expose a neighborhood +around point. How much is shown depends on the initial action, +or context. Valid contexts are + agenda when exposing an entry from the agenda - org-goto when using the command `org-goto' on key C-c C-j - occur-tree when using the command `org-occur' on key C-c / + org-goto when using the command `org-goto' (`\\[org-goto]') + occur-tree when using the command `org-occur' (`\\[org-sparse-tree] /') tags-tree when constructing a sparse tree based on tags matches link-search when exposing search matches associated with a link mark-goto when exposing the jump goal of a mark bookmark-jump when exposing a bookmark location isearch when exiting from an incremental search - default default for all contexts not set explicitly" - :group 'org-reveal-location - :type org-context-choice) - -(defcustom org-show-following-heading '((default . nil)) - "Non-nil means show following heading when revealing a location. -Org-mode often shows locations in an org-mode file which might have -been invisible before. When this is set, the heading following the -match is shown. -Turning this off for example for sparse trees makes them very compact, -but makes it harder to edit the location of the match. In such a case, -use the command \\[org-reveal] to show more context. -Instead of t, this can also be an alist specifying this option for different -contexts. See `org-show-hierarchy-above' for valid contexts." - :group 'org-reveal-location - :type org-context-choice) - -(defcustom org-show-siblings '((default . nil) (isearch t) (bookmark-jump t)) - "Non-nil means show all sibling heading when revealing a location. -Org-mode often shows locations in an org-mode file which might have -been invisible before. When this is set, the sibling of the current entry -heading are all made visible. If `org-show-hierarchy-above' is t, -the same happens on each level of the hierarchy above the current entry. - -By default this is on for the isearch context, off for all other contexts. -Turning this off for example for sparse trees makes them very compact, -but makes it harder to edit the location of the match. In such a case, -use the command \\[org-reveal] to show more context. -Instead of t, this can also be an alist specifying this option for different -contexts. See `org-show-hierarchy-above' for valid contexts." - :group 'org-reveal-location - :type org-context-choice - :version "24.4" - :package-version '(Org . "8.0")) + default default for all contexts not set explicitly + +Allowed visibility spans are + + minimal show current headline; if point is not on headline, + also show entry -(defcustom org-show-entry-below '((default . nil)) - "Non-nil means show the entry below a headline when revealing a location. -Org-mode often shows locations in an org-mode file which might have -been invisible before. When this is set, the text below the headline that is -exposed is also shown. + local show current headline, entry and next headline -By default this is off for all contexts. -Instead of t, this can also be an alist specifying this option for different -contexts. See `org-show-hierarchy-above' for valid contexts." + ancestors show current headline and its direct ancestors; if + point is not on headline, also show entry + + lineage show current headline, its direct ancestors and all + their children; if point is not on headline, also show + entry and first child + + tree show current headline, its direct ancestors and all + their children; if point is not on headline, also show + entry and all children + + canonical show current headline, its direct ancestors along with + their entries and children; if point is not located on + the headline, also show current entry and all children + +As special cases, a nil or t value means show all contexts in +`minimal' or `canonical' view, respectively. + +Some views can make displayed information very compact, but also +make it harder to edit the location of the match. In such +a case, use the command `org-reveal' (`\\[org-reveal]') to show +more context." :group 'org-reveal-location - :type org-context-choice) + :version "26.1" + :package-version '(Org . "9.0") + :type '(choice + (const :tag "Canonical" t) + (const :tag "Minimal" nil) + (repeat :greedy t :tag "Individual contexts" + (cons + (choice :tag "Context" + (const agenda) + (const org-goto) + (const occur-tree) + (const tags-tree) + (const link-search) + (const mark-goto) + (const bookmark-jump) + (const isearch) + (const default)) + (choice :tag "Detail level" + (const minimal) + (const local) + (const ancestors) + (const lineage) + (const tree) + (const canonical)))))) (defcustom org-indirect-buffer-display 'other-window "How should indirect tree buffers be displayed? + This applies to indirect buffers created with the commands -\\[org-tree-to-indirect-buffer] and \\[org-agenda-tree-to-indirect-buffer]. +`org-tree-to-indirect-buffer' and `org-agenda-tree-to-indirect-buffer'. + Valid values are: current-window Display in the current window other-window Just display in another window. @@ -1024,7 +1256,13 @@ new-frame Make a new frame each time. Note that in this case (defcustom org-use-speed-commands nil "Non-nil means activate single letter commands at beginning of a headline. This may also be a function to test for appropriate locations where speed -commands should be active." +commands should be active. + +For example, to activate speed commands when the point is on any +star at the beginning of the headline, you can do this: + + (setq org-use-speed-commands + (lambda () (and (looking-at org-outline-regexp) (looking-back \"^\\**\"))))" :group 'org-structure :type '(choice (const :tag "Never" nil) @@ -1054,10 +1292,10 @@ commands in the Help buffer using the `?' speed command." (sexp)))))) (defcustom org-bookmark-names-plist - '(:last-capture "org-capture-last-stored" - :last-refile "org-refile-last-stored" - :last-capture-marker "org-capture-last-stored-marker") - "Names for bookmarks automatically set by some Org commands. + '(:last-capture "org-capture-last-stored" + :last-refile "org-refile-last-stored" + :last-capture-marker "org-capture-last-stored-marker") + "Names for bookmarks automatically set by some Org commands. This can provide strings as names for a number of bookmarks Org sets automatically. The following keys are currently implemented: :last-capture @@ -1065,11 +1303,11 @@ automatically. The following keys are currently implemented: :last-refile When a key does not show up in the property list, the corresponding bookmark is not set." - :group 'org-structure - :type 'plist) + :group 'org-structure + :type 'plist) (defgroup org-cycle nil - "Options concerning visibility cycling in Org-mode." + "Options concerning visibility cycling in Org mode." :tag "Org Cycle" :group 'org-structure) @@ -1093,25 +1331,8 @@ than its value." (const :tag "No limit" nil) (integer :tag "Maximum level"))) -(defcustom org-drawers '("PROPERTIES" "CLOCK" "LOGBOOK" "RESULTS") - "Names of drawers. Drawers are not opened by cycling on the headline above. -Drawers only open with a TAB on the drawer line itself. A drawer looks like -this: - :DRAWERNAME: - ..... - :END: -The drawer \"PROPERTIES\" is special for capturing properties through -the property API. - -Drawers can be defined on the per-file basis with a line like: - -#+DRAWERS: HIDDEN STATE PROPERTIES" - :group 'org-structure - :group 'org-cycle - :type '(repeat (string :tag "Drawer Name"))) - (defcustom org-hide-block-startup nil - "Non-nil means entering Org-mode will fold all blocks. + "Non-nil means entering Org mode will fold all blocks. This can also be set in on a per-file basis with #+STARTUP: hideblocks @@ -1122,12 +1343,17 @@ This can also be set in on a per-file basis with (defcustom org-cycle-global-at-bob nil "Cycle globally if cursor is at beginning of buffer and not at a headline. -This makes it possible to do global cycling without having to use S-TAB or -\\[universal-argument] TAB. For this special case to work, the first line -of the buffer must not be a headline -- it may be empty or some other text. + +This makes it possible to do global cycling without having to use `S-TAB' +or `\\[universal-argument] TAB'. For this special case to work, the first \ +line of the buffer +must not be a headline -- it may be empty or some other text. + When used in this way, `org-cycle-hook' is disabled temporarily to make -sure the cursor stays at the beginning of the buffer. When this option is -nil, don't do anything special at the beginning of the buffer." +sure the cursor stays at the beginning of the buffer. + +When this option is nil, don't do anything special at the beginning of +the buffer." :group 'org-cycle :type 'boolean) @@ -1166,7 +1392,7 @@ visibility is cycled." "Number of empty lines needed to keep an empty line between collapsed trees. If you leave an empty line between the end of a subtree and the following headline, this empty line is hidden when the subtree is folded. -Org-mode will leave (exactly) one empty line visible if the number of +Org mode will leave (exactly) one empty line visible if the number of empty lines is equal or larger to the number given in this variable. So the default 2 means at least 2 empty lines after the end of a subtree are needed to produce free space between a collapsed subtree and the @@ -1192,7 +1418,6 @@ the values `folded', `children', or `subtree'." (defcustom org-cycle-hook '(org-cycle-hide-archived-subtrees org-cycle-hide-drawers - org-cycle-hide-inline-tasks org-cycle-show-empty-lines org-optimize-window-after-visibility-change) "Hook that is run after `org-cycle' has changed the buffer visibility. @@ -1202,10 +1427,12 @@ argument is a symbol. After a global state change, it can have the values `overview', `contents', or `all'. After a local state change, it can have the values `folded', `children', or `subtree'." :group 'org-cycle - :type 'hook) + :type 'hook + :version "26.1" + :package-version '(Org . "8.3")) (defgroup org-edit-structure nil - "Options concerning structure editing in Org-mode." + "Options concerning structure editing in Org mode." :tag "Org Edit Structure" :group 'org-structure) @@ -1229,23 +1456,25 @@ lines to the buffer: "Non-nil means adapt indentation to outline node level. When this variable is set, Org assumes that you write outlines by -indenting text in each node to align with the headline (after the stars). -The following issues are influenced by this variable: +indenting text in each node to align with the headline (after the +stars). The following issues are influenced by this variable: -- When this is set and the *entire* text in an entry is indented, the - indentation is increased by one space in a demotion command, and - decreased by one in a promotion command. If any line in the entry - body starts with text at column 0, indentation is not changed at all. +- The indentation is increased by one space in a demotion + command, and decreased by one in a promotion command. However, + in the latter case, if shifting some line in the entry body + would alter document structure (e.g., insert a new headline), + indentation is not changed at all. -- Property drawers and planning information is inserted indented when - this variable s set. When nil, they will not be indented. +- Property drawers and planning information is inserted indented + when this variable is set. When nil, they will not be indented. -- TAB indents a line relative to context. The lines below a headline - will be indented when this variable is set. +- TAB indents a line relative to current level. The lines below + a headline will be indented when this variable is set. -Note that this is all about true indentation, by adding and removing -space characters. See also `org-indent.el' which does level-dependent -indentation in a virtual way, i.e. at display time in Emacs." +Note that this is all about true indentation, by adding and +removing space characters. See also `org-indent.el' which does +level-dependent indentation in a virtual way, i.e. at display +time in Emacs." :group 'org-edit-structure :type 'boolean) @@ -1286,7 +1515,7 @@ This may also be a cons cell where the behavior for `C-a' and (const :tag "off" nil) (const :tag "on: before tags first" t) (const :tag "reversed: after tags first" reversed))))) -(org-defvaralias 'org-special-ctrl-a 'org-special-ctrl-a/e) +(defvaralias 'org-special-ctrl-a 'org-special-ctrl-a/e) (defcustom org-special-ctrl-k nil "Non-nil means `C-k' will behave specially in headlines. @@ -1386,9 +1615,11 @@ default the value to be used for all contexts not explicitly (defcustom org-insert-heading-respect-content nil "Non-nil means insert new headings after the current subtree. +\\ When nil, the new heading is created directly after the current line. -The commands \\[org-insert-heading-respect-content] and \\[org-insert-todo-heading-respect-content] turn -this variable on for the duration of the command." +The commands `\\[org-insert-heading-respect-content]' and \ +`\\[org-insert-todo-heading-respect-content]' turn this variable on +for the duration of the command." :group 'org-structure :type 'boolean) @@ -1398,11 +1629,7 @@ this variable on for the duration of the command." The value is an alist, with `heading' and `plain-list-item' as CAR, and a boolean flag as CDR. The cdr may also be the symbol `auto', in which case Org will look at the surrounding headings/items and try to -make an intelligent decision whether to insert a blank line or not. - -For plain lists, if `org-list-empty-line-terminates-plain-lists' is set, -the setting here is ignored and no empty line is inserted to avoid breaking -the list structure." +make an intelligent decision whether to insert a blank line or not." :group 'org-edit-structure :type '(list (cons (const heading) @@ -1422,8 +1649,7 @@ the list structure." (defcustom org-enable-fixed-width-editor t "Non-nil means lines starting with \":\" are treated as fixed-width. This currently only means they are never auto-wrapped. -When nil, such lines will be treated like ordinary lines. -See also the QUOTE keyword." +When nil, such lines will be treated like ordinary lines." :group 'org-edit-structure :type 'boolean) @@ -1441,7 +1667,7 @@ When nil, you can use these keybindings to navigate the buffer: :type 'boolean) (defgroup org-sparse-trees nil - "Options concerning sparse trees in Org-mode." + "Options concerning sparse trees in Org mode." :tag "Org Sparse Trees" :group 'org-structure) @@ -1454,14 +1680,26 @@ changed by an edit command." (defcustom org-remove-highlights-with-change t "Non-nil means any change to the buffer will remove temporary highlights. +\\\ Such highlights are created by `org-occur' and `org-clock-display'. -When nil, `C-c C-c' needs to be used to get rid of the highlights. -The highlights created by `org-preview-latex-fragment' always need -`C-c C-c' to be removed." +When nil, `\\[org-ctrl-c-ctrl-c]' needs to be used \ +to get rid of the highlights. +The highlights created by `org-toggle-latex-fragment' always need +`\\[org-toggle-latex-fragment]' to be removed." :group 'org-sparse-trees :group 'org-time :type 'boolean) +(defcustom org-occur-case-fold-search t + "Non-nil means `org-occur' should be case-insensitive. +If set to `smart' the search will be case-insensitive only if it +doesn't specify any upper case character." + :group 'org-sparse-trees + :version "26.1" + :type '(choice + (const :tag "Case-sensitive" nil) + (const :tag "Case-insensitive" t) + (const :tag "Case-insensitive for lower case searches only" 'smart))) (defcustom org-occur-hook '(org-first-headline-recenter) "Hook that is run after `org-occur' has constructed a sparse tree. @@ -1471,18 +1709,18 @@ as possible." :type 'hook) (defgroup org-imenu-and-speedbar nil - "Options concerning imenu and speedbar in Org-mode." + "Options concerning imenu and speedbar in Org mode." :tag "Org Imenu and Speedbar" :group 'org-structure) (defcustom org-imenu-depth 2 - "The maximum level for Imenu access to Org-mode headlines. + "The maximum level for Imenu access to Org headlines. This also applied for speedbar access." :group 'org-imenu-and-speedbar :type 'integer) (defgroup org-table nil - "Options concerning tables in Org-mode." + "Options concerning tables in Org mode." :tag "Org Table" :group 'org) @@ -1499,12 +1737,12 @@ do the following: TAB or RET are pressed to move to another field. With optimization this happens only if changes to a field might have changed the column width. Optimization requires replacing the functions `self-insert-command', -`delete-char', and `backward-delete-char' in Org-mode buffers, with a -slight (in fact: unnoticeable) speed impact for normal typing. Org-mode is -very good at guessing when a re-align will be necessary, but you can always -force one with \\[org-ctrl-c-ctrl-c]. +`delete-char', and `backward-delete-char' in Org buffers, with a +slight (in fact: unnoticeable) speed impact for normal typing. Org is very +good at guessing when a re-align will be necessary, but you can always +force one with `\\[org-ctrl-c-ctrl-c]'. -If you would like to use the optimized version in Org-mode, but the +If you would like to use the optimized version in Org mode, but the un-optimized version in OrgTbl-mode, see the variable `orgtbl-optimized'. This variable can be used to turn on and off the table editor during a session, @@ -1517,8 +1755,7 @@ See also the variable `org-table-auto-blank-field'." (const :tag "on" t) (const :tag "on, optimized" optimized))) -(defcustom org-self-insert-cluster-for-undo (or (featurep 'xemacs) - (version<= emacs-version "24.1")) +(defcustom org-self-insert-cluster-for-undo nil "Non-nil means cluster self-insert commands for undo when possible. If this is set, then, like in the Emacs command loop, 20 consecutive characters will be undone together. @@ -1534,24 +1771,95 @@ calls `table-recognize-table'." :type 'boolean) (defgroup org-link nil - "Options concerning links in Org-mode." + "Options concerning links in Org mode." :tag "Org Link" :group 'org) -(defvar org-link-abbrev-alist-local nil +(defvar-local org-link-abbrev-alist-local nil "Buffer-local version of `org-link-abbrev-alist', which see. The value of this is taken from the #+LINK lines.") -(make-variable-buffer-local 'org-link-abbrev-alist-local) + +(defcustom org-link-parameters + '(("doi" :follow org--open-doi-link) + ("elisp" :follow org--open-elisp-link) + ("file" :complete org-file-complete-link) + ("ftp" :follow (lambda (path) (browse-url (concat "ftp:" path)))) + ("help" :follow org--open-help-link) + ("http" :follow (lambda (path) (browse-url (concat "http:" path)))) + ("https" :follow (lambda (path) (browse-url (concat "https:" path)))) + ("mailto" :follow (lambda (path) (browse-url (concat "mailto:" path)))) + ("message" :follow (lambda (path) (browse-url (concat "message:" path)))) + ("news" :follow (lambda (path) (browse-url (concat "news:" path)))) + ("shell" :follow org--open-shell-link)) + "An alist of properties that defines all the links in Org mode. +The key in each association is a string of the link type. +Subsequent optional elements make up a p-list of link properties. + +:follow - A function that takes the link path as an argument. + +:export - A function that takes the link path, description and +export-backend as arguments. + +:store - A function responsible for storing the link. See the +function `org-store-link-functions'. + +:complete - A function that inserts a link with completion. The +function takes one optional prefix arg. + +:face - A face for the link, or a function that returns a face. +The function takes one argument which is the link path. The +default face is `org-link'. + +:mouse-face - The mouse-face. The default is `highlight'. + +:display - `full' will not fold the link in descriptive +display. Default is `org-link'. + +:help-echo - A string or function that takes (window object position) +as arguments and returns a string. + +:keymap - A keymap that is active on the link. The default is +`org-mouse-map'. + +:htmlize-link - A function for the htmlize-link. Defaults +to (list :uri \"type:path\") + +:activate-func - A function to run at the end of font-lock +activation. The function must accept (link-start link-end path bracketp) +as arguments." + :group 'org-link + :type '(alist :tag "Link display parameters" + :value-type plist)) + +(defun org-link-get-parameter (type key) + "Get TYPE link property for KEY. +TYPE is a string and KEY is a plist keyword." + (plist-get + (cdr (assoc type org-link-parameters)) + key)) + +(defun org-link-set-parameters (type &rest parameters) + "Set link TYPE properties to PARAMETERS. + PARAMETERS should be :key val pairs." + (let ((data (assoc type org-link-parameters))) + (if data (setcdr data (org-combine-plists (cdr data) parameters)) + (push (cons type parameters) org-link-parameters) + (org-make-link-regexps) + (org-element-update-syntax)))) + +(defun org-link-types () + "Return a list of known link types." + (mapcar #'car org-link-parameters)) (defcustom org-link-abbrev-alist nil "Alist of link abbreviations. The car of each element is a string, to be replaced at the start of a link. The cdrs are replacement values, like (\"linkkey\" . REPLACE). Abbreviated -links in Org-mode buffers can have an optional tag after a double colon, e.g. +links in Org buffers can have an optional tag after a double colon, e.g., [[linkkey:tag][description]] -The `linkkey' must be a word word, starting with a letter, followed +The `linkkey' must be a single word, starting with a letter, followed by letters, numbers, `-' or `_'. If REPLACE is a string, the tag will simply be appended to create the link. @@ -1603,11 +1911,18 @@ adaptive Use relative path for files in the current directory and sub- (const noabbrev) (const adaptive))) -(defcustom org-activate-links '(bracket angle plain radio tag date footnote) - "Types of links that should be activated in Org-mode files. -This is a list of symbols, each leading to the activation of a certain link -type. In principle, it does not hurt to turn on most link types - there may -be a small gain when turning off unused link types. The types are: +(defvaralias 'org-activate-links 'org-highlight-links) +(defcustom org-highlight-links '(bracket angle plain radio tag date footnote) + "Types of links that should be highlighted in Org files. + +This is a list of symbols, each one of them leading to the +highlighting of a certain link type. + +You can still open links that are not highlighted. + +In principle, it does not hurt to turn on highlighting for all +link types. There may be a small gain when turning off unused +link types. The types are: bracket The recommended [[link][description]] or [[link]] links with hiding. angle Links in angular brackets that may contain whitespace like @@ -1618,8 +1933,10 @@ tag Tag settings in a headline (link to tag search). date Time stamps (link to calendar). footnote Footnote labels. -Changing this variable requires a restart of Emacs to become effective." +If you set this variable during an Emacs session, use `org-mode-restart' +in the Org buffer so that the change takes effect." :group 'org-link + :group 'org-appearance :type '(set :greedy t (const :tag "Double bracket links" bracket) (const :tag "Angular bracket links" angle) @@ -1639,7 +1956,7 @@ return the description to use." :type '(choice (const nil) (function))) (defgroup org-link-store nil - "Options concerning storing links in Org-mode." + "Options concerning storing links in Org mode." :tag "Org Store Link" :group 'org-link) @@ -1684,32 +2001,36 @@ It should match if the message is from the user him/herself." (defcustom org-context-in-file-links t "Non-nil means file links from `org-store-link' contain context. -A search string will be added to the file name with :: as separator and -used to find the context when the link is activated by the command +\\ +A search string will be added to the file name with :: as separator +and used to find the context when the link is activated by the command `org-open-at-point'. When this option is t, the entire active region will be placed in the search string of the file link. If set to a positive integer, only the first n lines of context will be stored. -Using a prefix arg to the command \\[org-store-link] (`org-store-link') +Using a prefix arg to the command `org-store-link' (`\\[universal-argument] \ +\\[org-store-link]') negates this setting for the duration of the command." :group 'org-link-store :type '(choice boolean integer)) (defcustom org-keep-stored-link-after-insertion nil "Non-nil means keep link in list for entire session. - +\\ The command `org-store-link' adds a link pointing to the current location to an internal list. These links accumulate during a session. The command `org-insert-link' can be used to insert links into any -Org-mode file (offering completion for all stored links). When this -option is nil, every link which has been inserted once using \\[org-insert-link] -will be removed from the list, to make completing the unused links -more efficient." +Org file (offering completion for all stored links). + +When this option is nil, every link which has been inserted once using +`\\[org-insert-link]' will be removed from the list, to make completing the \ +unused +links more efficient." :group 'org-link-store :type 'boolean) (defgroup org-link-follow nil - "Options concerning following links in Org-mode." + "Options concerning following links in Org mode." :tag "Org Follow Link" :group 'org-link) @@ -1749,8 +2070,8 @@ In tables, the special behavior of RET has precedence." (defcustom org-mouse-1-follows-link (if (boundp 'mouse-1-click-follows-link) mouse-1-click-follows-link t) "Non-nil means mouse-1 on a link will follow the link. -A longer mouse click will still set point. Does not work on XEmacs. -Needs to be set before org.el is loaded." +A longer mouse click will still set point. Needs to be set +before org.el is loaded." :group 'org-link-follow :version "24.4" :package-version '(Org . "8.3") @@ -1766,16 +2087,22 @@ Changing this requires a restart of Emacs to work correctly." :type 'integer) (defcustom org-link-search-must-match-exact-headline 'query-to-create - "Non-nil means internal links in Org files must exactly match a headline. -When nil, the link search tries to match a phrase with all words -in the search text." + "Non-nil means internal fuzzy links can only match headlines. + +When nil, the a fuzzy link may point to a target or a named +construct in the document. When set to the special value +`query-to-create', offer to create a new headline when none +matched. + +Spaces and statistics cookies are ignored during heading searches." :group 'org-link-follow :version "24.1" :type '(choice (const :tag "Use fuzzy text search" nil) (const :tag "Match only exact headline" t) (const :tag "Match exact headline or query to create it" - query-to-create))) + query-to-create)) + :safe #'symbolp) (defcustom org-link-frame-setup '((vm . vm-visit-folder-other-frame) @@ -1836,7 +2163,7 @@ another window." "Non-nil means use indirect buffer to display infile links. Activating internal links (from one location in a file to another location in the same file) normally just jumps to the location. When the link is -activated with a \\[universal-argument] prefix (or with mouse-3), the link \ +activated with a `\\[universal-argument]' prefix (or with mouse-3), the link \ is displayed in another window. When this option is set, the other window actually displays an indirect buffer clone of the current buffer, to avoid any visibility @@ -1860,26 +2187,13 @@ window on that directory." :group 'org-link-follow :type 'boolean) -(defcustom org-link-mailto-program '(browse-url "mailto:%a?subject=%s") - "Function and arguments to call for following mailto links. -This is a list with the first element being a Lisp function, and the -remaining elements being arguments to the function. In string arguments, -%a will be replaced by the address, and %s will be replaced by the subject -if one was given like in ." - :group 'org-link-follow - :type '(choice - (const :tag "browse-url" (browse-url-mail "mailto:%a?subject=%s")) - (const :tag "compose-mail" (compose-mail "%a" "%s")) - (const :tag "message-mail" (message-mail "%a" "%s")) - (cons :tag "other" (function) (repeat :tag "argument" sexp)))) - (defcustom org-confirm-shell-link-function 'yes-or-no-p "Non-nil means ask for confirmation before executing shell links. Shell links can be dangerous: just think about a link [[shell:rm -rf ~/*][Google Search]] -This link would show up in your Org-mode document as \"Google Search\", +This link would show up in your Org document as \"Google Search\", but really it would remove your entire home directory. Therefore we advise against setting this variable to nil. Just change it to `y-or-n-p' if you want to confirm with a @@ -1891,7 +2205,7 @@ single keystroke rather than having to type \"yes\"." (const :tag "no confirmation (dangerous)" nil))) (put 'org-confirm-shell-link-function 'safe-local-variable - #'(lambda (x) (member x '(yes-or-no-p y-or-n-p)))) + (lambda (x) (member x '(yes-or-no-p y-or-n-p)))) (defcustom org-confirm-shell-link-not-regexp "" "A regexp to skip confirmation for shell links." @@ -1905,7 +2219,7 @@ Elisp links can be dangerous: just think about a link [[elisp:(shell-command \"rm -rf ~/*\")][Google Search]] -This link would show up in your Org-mode document as \"Google Search\", +This link would show up in your Org document as \"Google Search\", but really it would remove your entire home directory. Therefore we advise against setting this variable to nil. Just change it to `y-or-n-p' if you want to confirm with a @@ -1917,7 +2231,7 @@ single keystroke rather than having to type \"yes\"." (const :tag "no confirmation (dangerous)" nil))) (put 'org-confirm-shell-link-function 'safe-local-variable - #'(lambda (x) (member x '(yes-or-no-p y-or-n-p)))) + (lambda (x) (member x '(yes-or-no-p y-or-n-p)))) (defcustom org-confirm-elisp-link-not-regexp "" "A regexp to skip confirmation for Elisp links." @@ -1934,30 +2248,23 @@ See `org-file-apps'.") (defconst org-file-apps-defaults-macosx '((remote . emacs) - (t . "open %s") (system . "open %s") ("ps.gz" . "gv %s") ("eps.gz" . "gv %s") ("dvi" . "xdvi %s") - ("fig" . "xfig %s")) + ("fig" . "xfig %s") + (t . "open %s")) "Default file applications on a macOS system. The system \"open\" is known as a default, but we use X11 applications for some files for which the OS does not have a good default. See `org-file-apps'.") (defconst org-file-apps-defaults-windowsnt - (list - '(remote . emacs) - (cons t - (list (if (featurep 'xemacs) - 'mswindows-shell-execute - 'w32-shell-execute) - "open" 'file)) - (cons 'system - (list (if (featurep 'xemacs) - 'mswindows-shell-execute - 'w32-shell-execute) - "open" 'file))) + (list '(remote . emacs) + (cons 'system (lambda (file _path) + (with-no-warnings (w32-shell-execute "open" file)))) + (cons t (lambda (file _path) + (with-no-warnings (w32-shell-execute "open" file))))) "Default file applications on a Windows NT system. The system \"open\" is used for most files. See `org-file-apps'.") @@ -1968,11 +2275,15 @@ See `org-file-apps'.") ("\\.x?html?\\'" . default) ("\\.pdf\\'" . default)) "External applications for opening `file:path' items in a document. -Org-mode uses system defaults for different file types, but +\\\ + +Org mode uses system defaults for different file types, but you can use this variable to set the application for a given file extension. The entries in this list are cons cells where the car identifies -files and the cdr the corresponding command. Possible values for the -file identifier are +files and the cdr the corresponding command. + +Possible values for the file identifier are: + \"string\" A string as a file identifier can be interpreted in different ways, depending on its contents: @@ -1985,8 +2296,8 @@ file identifier are filename matches the regexp. If you want to use groups here, use shy groups. - Example: (\"\\.x?html\\\\='\" . \"firefox %s\") - (\"\\(?:xhtml\\|html\\)\" . \"firefox %s\") + Example: (\"\\\\.x?html\\\\\\='\" . \"firefox %s\") + (\"\\\\(?:xhtml\\\\|html\\\\)\\\\\\='\" . \"firefox %s\") to open *.html and *.xhtml with firefox. - Regular expression which contains (non-shy) groups: @@ -1998,10 +2309,11 @@ file identifier are that does not use any of the group matches, this case is handled identically to the second one (i.e. match against file name only). - In a custom lisp form, you can access the group matches with + In a custom function, you can access the group matches with (match-string n link). - Example: (\"\\.pdf::\\(\\d+\\)\\\\='\" . \"evince -p %1 %s\") + Example: (\"\\\\.pdf::\\\\(\\\\d+\\\\)\\\\\\='\" . \ +\"evince -p %1 %s\") to open [[file:document.pdf::5]] with evince at page 5. `directory' Matches a directory @@ -2013,28 +2325,32 @@ file identifier are command `emacs' will open most files in Emacs. Beware that this will also open html files inside Emacs, unless you add (\"html\" . default) to the list as well. - t Default for files not matched by any of the other options. `system' The system command to open files, like `open' on Windows and macOS, and mailcap under GNU/Linux. This is the command - that will be selected if you call `C-c C-o' with a double - \\[universal-argument] \\[universal-argument] prefix. + that will be selected if you call `org-open-at-point' with a + double prefix argument (`\\[universal-argument] \ +\\[universal-argument] \\[org-open-at-point]'). + t Default for files not matched by any of the other options. Possible values for the command are: + `emacs' The file will be visited by the current Emacs process. `default' Use the default application for this file type, which is the association for t in the list, most likely in the system-specific - part. - This can be used to overrule an unwanted setting in the + part. This can be used to overrule an unwanted setting in the system-specific variable. `system' Use the system command for opening files, like \"open\". This command is specified by the entry whose car is `system'. Most likely, the system-specific version of this variable does define this command, but you can overrule/replace it here. +`mailcap' Use command specified in the mailcaps. string A command to be executed by a shell; %s will be replaced by the path to the file. - sexp A Lisp form which will be evaluated. The file path will - be available in the Lisp variable `file'. + function A Lisp function, which will be called with two arguments: + the file path and the original link string, without the + \"file:\" prefix. + For more examples, see the system specific constants `org-file-apps-defaults-macosx' `org-file-apps-defaults-windowsnt' @@ -2054,7 +2370,7 @@ For more examples, see the system specific constants (const :tag "Use default" default) (const :tag "Use the system command" system) (string :tag "Command") - (sexp :tag "Lisp form"))))) + (function :tag "Function"))))) (defcustom org-doi-server-url "http://dx.doi.org/" "The URL of the DOI server." @@ -2063,22 +2379,22 @@ For more examples, see the system specific constants :group 'org-link-follow) (defgroup org-refile nil - "Options concerning refiling entries in Org-mode." + "Options concerning refiling entries in Org mode." :tag "Org Refile" :group 'org) (defcustom org-directory "~/org" - "Directory with org files. + "Directory with Org files. This is just a default location to look for Org files. There is no need -at all to put your files into this directory. It is only used in the +at all to put your files into this directory. It is used in the following situations: 1. When a capture template specifies a target file that is not an absolute path. The path will then be interpreted relative to `org-directory' -2. When a capture note is filed away in an interactive way (when exiting the - note buffer with `C-1 C-c C-c'. The user is prompted for an org file, - with `org-directory' as the default path." +2. When the value of variable `org-agenda-files' is a single file, any + relative paths in this file will be taken as relative to + `org-directory'." :group 'org-refile :group 'org-capture :type 'directory) @@ -2089,9 +2405,7 @@ Used as a fall back file for org-capture.el, for templates that do not specify a target file." :group 'org-refile :group 'org-capture - :type '(choice - (const :tag "Default from remember-data-file" nil) - file)) + :type 'file) (defcustom org-goto-interface 'outline "The default interface to be used for `org-goto'. @@ -2154,7 +2468,7 @@ will temporarily be changed to `time'." (const :tag "Record timestamp with note." note))) (defcustom org-refile-targets nil - "Targets for refiling entries with \\[org-refile]. + "Targets for refiling entries with `\\[org-refile]'. This is a list of cons cells. Each cell contains: - a specification of the files to be considered, either a list of files, or a symbol whose function or variable value will be used to retrieve @@ -2218,12 +2532,15 @@ of the subtree." (defcustom org-refile-use-cache nil "Non-nil means cache refile targets to speed up the process. +\\\ The cache for a particular file will be updated automatically when the buffer has been killed, or when any of the marker used for flagging refile targets no longer points at a live buffer. If you have added new entries to a buffer that might themselves be targets, -you need to clear the cache manually by pressing `C-0 C-c C-w' or, if you -find that easier, `C-u C-u C-u C-c C-w'." +you need to clear the cache manually by pressing `C-0 \\[org-refile]' or, +if you find that easier, \ +`\\[universal-argument] \\[universal-argument] \\[universal-argument] \ +\\[org-refile]'." :group 'org-refile :version "24.1" :type 'boolean) @@ -2246,13 +2563,13 @@ When `full-file-path', include the full file path." (defcustom org-outline-path-complete-in-steps t "Non-nil means complete the outline path in hierarchical steps. -When Org-mode uses the refile interface to select an outline path -\(see variable `org-refile-use-outline-path'), the completion of -the path can be done is a single go, or if can be done in steps down -the headline hierarchy. Going in steps is probably the best if you -do not use a special completion package like `ido' or `icicles'. -However, when using these packages, going in one step can be very -fast, while still showing the whole path to the entry." +When Org uses the refile interface to select an outline path (see +`org-refile-use-outline-path'), the completion of the path can be +done in a single go, or it can be done in steps down the headline +hierarchy. Going in steps is probably the best if you do not use +a special completion package like `ido' or `icicles'. However, +when using these packages, going in one step can be very fast, +while still showing the whole path to the entry." :group 'org-refile :type 'boolean) @@ -2285,12 +2602,12 @@ converted to a headline before refiling." :type 'boolean) (defgroup org-todo nil - "Options concerning TODO items in Org-mode." + "Options concerning TODO items in Org mode." :tag "Org TODO" :group 'org) (defgroup org-progress nil - "Options concerning Progress logging in Org-mode." + "Options concerning Progress logging in Org mode." :tag "Org Progress" :group 'org-time) @@ -2308,12 +2625,12 @@ Each sequence starts with a symbol, either `sequence' or `type', indicating if the keywords should be interpreted as a sequence of action steps, or as different types of TODO items. The first keywords are states requiring action - these states will select a headline -for inclusion into the global TODO list Org-mode produces. If one of -the \"keywords\" is the vertical bar, \"|\", the remaining keywords +for inclusion into the global TODO list Org produces. If one of the +\"keywords\" is the vertical bar, \"|\", the remaining keywords signify that no further action is necessary. If \"|\" is not found, the last keyword is treated as the only DONE state of the sequence. -The command \\[org-todo] cycles an entry through these states, and one +The command `\\[org-todo]' cycles an entry through these states, and one additional state where no keyword is present. For details about this cycling, see the manual. @@ -2356,44 +2673,37 @@ taken from the (otherwise obsolete) variable `org-todo-interpretation'." (lambda (widget) (widget-put widget :args (mapcar - #'(lambda (x) - (widget-convert - (cons 'const x))) + (lambda (x) + (widget-convert + (cons 'const x))) org-todo-interpretation-widgets)) widget)) (repeat (string :tag "Keyword")))))) -(defvar org-todo-keywords-1 nil +(defvar-local org-todo-keywords-1 nil "All TODO and DONE keywords active in a buffer.") -(make-variable-buffer-local 'org-todo-keywords-1) (defvar org-todo-keywords-for-agenda nil) (defvar org-done-keywords-for-agenda nil) -(defvar org-drawers-for-agenda nil) (defvar org-todo-keyword-alist-for-agenda nil) (defvar org-tag-alist-for-agenda nil "Alist of all tags from all agenda files.") (defvar org-tag-groups-alist-for-agenda nil "Alist of all groups tags from all current agenda files.") -(defvar org-tag-groups-alist nil) -(make-variable-buffer-local 'org-tag-groups-alist) +(defvar-local org-tag-groups-alist nil) (defvar org-agenda-contributing-files nil) -(defvar org-not-done-keywords nil) -(make-variable-buffer-local 'org-not-done-keywords) -(defvar org-done-keywords nil) -(make-variable-buffer-local 'org-done-keywords) -(defvar org-todo-heads nil) -(make-variable-buffer-local 'org-todo-heads) -(defvar org-todo-sets nil) -(make-variable-buffer-local 'org-todo-sets) -(defvar org-todo-log-states nil) -(make-variable-buffer-local 'org-todo-log-states) -(defvar org-todo-kwd-alist nil) -(make-variable-buffer-local 'org-todo-kwd-alist) -(defvar org-todo-key-alist nil) -(make-variable-buffer-local 'org-todo-key-alist) -(defvar org-todo-key-trigger nil) -(make-variable-buffer-local 'org-todo-key-trigger) +(defvar-local org-current-tag-alist nil + "Alist of all tag groups in current buffer. +This variable takes into consideration `org-tag-alist', +`org-tag-persistent-alist' and TAGS keywords in the buffer.") +(defvar-local org-not-done-keywords nil) +(defvar-local org-done-keywords nil) +(defvar-local org-todo-heads nil) +(defvar-local org-todo-sets nil) +(defvar-local org-todo-log-states nil) +(defvar-local org-todo-kwd-alist nil) +(defvar-local org-todo-key-alist nil) +(defvar-local org-todo-key-trigger nil) (defcustom org-todo-interpretation 'sequence "Controls how TODO keywords are interpreted. @@ -2407,7 +2717,8 @@ more information." (const type))) (defcustom org-use-fast-todo-selection t - "Non-nil means use the fast todo selection scheme with C-c C-t. + "\\\ +Non-nil means use the fast todo selection scheme with `\\[org-todo]'. This variable describes if and under what circumstances the cycling mechanism for TODO keywords will be replaced by a single-key, direct selection scheme. @@ -2415,8 +2726,9 @@ selection scheme. When nil, fast selection is never used. When the symbol `prefix', it will be used when `org-todo' is called -with a prefix argument, i.e. `C-u C-c C-t' in an Org-mode buffer, and -`C-u t' in an agenda buffer. +with a prefix argument, i.e. `\\[universal-argument] \\[org-todo]' \ +in an Org buffer, and +`\\[universal-argument] t' in an agenda buffer. When t, fast selection is used by default. In this case, the prefix argument forces cycling instead. @@ -2436,6 +2748,9 @@ ALL-HEADLINES means update todo statistics by including headlines with no TODO keyword as well, counting them as not done. A list of TODO keywords means the same, but skip keywords that are not in this list. +When set to a list of two lists, the first list contains keywords +to consider as TODO keywords, the second list contains keywords +to consider as DONE keywords. When this is set, todo statistics is updated in the parent of the current entry each time a todo state is changed." @@ -2445,6 +2760,9 @@ current entry each time a todo state is changed." (const :tag "Yes, including all entries" all-headlines) (repeat :tag "Yes, for TODOs in this list" (string :tag "TODO keyword")) + (list :tag "Yes, for TODOs and DONEs in these lists" + (repeat (string :tag "TODO keyword")) + (repeat (string :tag "DONE keyword"))) (other :tag "No TODO statistics" nil))) (defcustom org-hierarchical-todo-statistics t @@ -2529,7 +2847,7 @@ to change is while Emacs is running is through the customize interface." (defcustom org-treat-insert-todo-heading-as-state-change nil "Non-nil means inserting a TODO heading is treated as state change. -So when the command \\[org-insert-todo-heading] is used, state change +So when the command `\\[org-insert-todo-heading]' is used, state change logging will apply if appropriate. When nil, the new TODO item will be inserted directly, and no logging will take place." :group 'org-todo @@ -2667,20 +2985,23 @@ When nil, only the date will be recorded." (refile . "Refiled on %t") (clock-out . "")) "Headings for notes added to entries. -The value is an alist, with the car being a symbol indicating the note -context, and the cdr is the heading to be used. The heading may also be the -empty string. -%t in the heading will be replaced by a time stamp. -%T will be an active time stamp instead the default inactive one -%d will be replaced by a short-format time stamp. -%D will be replaced by an active short-format time stamp. -%s will be replaced by the new TODO state, in double quotes. -%S will be replaced by the old TODO state, in double quotes. -%u will be replaced by the user name. -%U will be replaced by the full user name. - -In fact, it is not a good idea to change the `state' entry, because -agenda log mode depends on the format of these entries." + +The value is an alist, with the car being a symbol indicating the +note context, and the cdr is the heading to be used. The heading +may also be the empty string. The following placeholders can be +used: + + %t a time stamp. + %T an active time stamp instead the default inactive one + %d a short-format time stamp. + %D an active short-format time stamp. + %s the new TODO state or time stamp (inactive), in double quotes. + %S the old TODO state or time stamp (inactive), in double quotes. + %u the user name. + %U full user name. + +In fact, it is not a good idea to change the `state' entry, +because Agenda Log mode depends on the format of these entries." :group 'org-todo :group 'org-progress :type '(list :greedy t @@ -2719,7 +3040,10 @@ If this variable is set, `org-log-state-notes-insert-after-drawers' will be ignored. You can set the property LOG_INTO_DRAWER to overrule this setting for -a subtree." +a subtree. + +Do not check directly this variable in a Lisp program. Call +function `org-log-into-drawer' instead." :group 'org-todo :group 'org-progress :type '(choice @@ -2727,18 +3051,20 @@ a subtree." (const :tag "LOGBOOK" t) (string :tag "Other"))) -(org-defvaralias 'org-log-state-notes-into-drawer 'org-log-into-drawer) +(defvaralias 'org-log-state-notes-into-drawer 'org-log-into-drawer) (defun org-log-into-drawer () - "Return the value of `org-log-into-drawer', but let properties overrule. -If the current entry has or inherits a LOG_INTO_DRAWER property, it will be -used instead of the default value." + "Name of the log drawer, as a string, or nil. +This is the value of `org-log-into-drawer'. However, if the +current entry has or inherits a LOG_INTO_DRAWER property, it will +be used instead of the default value." (let ((p (org-entry-get nil "LOG_INTO_DRAWER" 'inherit t))) - (cond - ((not p) org-log-into-drawer) - ((equal p "nil") nil) - ((equal p "t") "LOGBOOK") - (t p)))) + (cond ((equal p "nil") nil) + ((equal p "t") "LOGBOOK") + ((stringp p) p) + (p "LOGBOOK") + ((stringp org-log-into-drawer) org-log-into-drawer) + (org-log-into-drawer "LOGBOOK")))) (defcustom org-log-state-notes-insert-after-drawers nil "Non-nil means insert state change notes after any drawers in entry. @@ -2804,7 +3130,7 @@ property to one or more of these keywords." (defgroup org-priorities nil - "Priorities in Org-mode." + "Priorities in Org mode." :tag "Org Priorities" :group 'org-todo) @@ -2862,24 +3188,13 @@ as an argument and return the numeric priority." (function))) (defgroup org-time nil - "Options concerning time stamps and deadlines in Org-mode." + "Options concerning time stamps and deadlines in Org mode." :tag "Org Time" :group 'org) -(defcustom org-insert-labeled-timestamps-at-point nil - "Non-nil means SCHEDULED and DEADLINE timestamps are inserted at point. -When nil, these labeled time stamps are forces into the second line of an -entry, just after the headline. When scheduling from the global TODO list, -the time stamp will always be forced into the second line." - :group 'org-time - :type 'boolean) - -(defconst org-time-stamp-formats '("<%Y-%m-%d %a>" . "<%Y-%m-%d %a %H:%M>") - "Formats for `format-time-string' which are used for time stamps. -It is not recommended to change this constant.") - (defcustom org-time-stamp-rounding-minutes '(0 5) "Number of minutes to round time stamps to. +\\\ These are two values, the first applies when first creating a time stamp. The second applies when changing it with the commands `S-up' and `S-down'. When changing the time stamp, this means that it will change in steps @@ -2889,14 +3204,15 @@ When a setting is 0 or 1, insert the time unmodified. Useful rounding numbers should be factors of 60, so for example 5, 10, 15. When this is larger than 1, you can still force an exact time stamp by using -a double prefix argument to a time stamp command like `C-c .' or `C-c !', +a double prefix argument to a time stamp command like \ +`\\[org-time-stamp]' or `\\[org-time-stamp-inactive], and by using a prefix arg to `S-up/down' to specify the exact number of minutes to shift." :group 'org-time - :get #'(lambda (var) ; Make sure both elements are there - (if (integerp (default-value var)) - (list (default-value var) 5) - (default-value var))) + :get (lambda (var) ; Make sure both elements are there + (if (integerp (default-value var)) + (list (default-value var) 5) + (default-value var))) :type '(list (integer :tag "when inserting times") (integer :tag "when modifying times"))) @@ -3013,7 +3329,7 @@ in minutes (even for durations longer than an hour)." (const t))))) (defcustom org-time-clocksum-use-fractional nil - "When non-nil, \\[org-clock-display] uses fractional times. + "When non-nil, `\\[org-clock-display]' uses fractional times. See `org-time-clocksum-format' for more on time clock formats." :group 'org-time :group 'org-clock @@ -3021,7 +3337,7 @@ See `org-time-clocksum-format' for more on time clock formats." :type 'boolean) (defcustom org-time-clocksum-use-effort-durations nil - "When non-nil, \\[org-clock-display] uses effort durations. + "When non-nil, `\\[org-clock-display]' uses effort durations. E.g. by default, one day is considered to be a 8 hours effort, so a task that has been clocked for 16 hours will be displayed as during 2 days in the clock display or in the clocktable. @@ -3052,9 +3368,9 @@ is used." :group 'org-time :type '(choice (string :tag "Format string") (set (group :inline t (const :tag "Years" :years) - (string :tag "Format string")) + (string :tag "Format string")) (group :inline t (const :tag "Months" :months) - (string :tag "Format string")) + (string :tag "Format string")) (group :inline t (const :tag "Weeks" :weeks) (string :tag "Format string")) (group :inline t (const :tag "Days" :days) @@ -3097,8 +3413,8 @@ This affects the following situations: For example, if it is April and you enter \"feb 2\", this will be read as Feb 2, *next* year. \"May 5\", however, will be this year. 2. The user gives a day, but no month. - For example, if today is the 15th, and you enter \"3\", Org-mode will - read this as the third of *next* month. However, if you enter \"17\", + For example, if today is the 15th, and you enter \"3\", Org will read + this as the third of *next* month. However, if you enter \"17\", it will be considered as *this* month. If you set this variable to the symbol `time', then also the following @@ -3176,22 +3492,9 @@ In the calendar, the date can be selected with mouse-1. However, the minibuffer will also be active, and you can simply enter the date as well. When nil, only the minibuffer will be available." :group 'org-time - :type 'boolean) -(org-defvaralias 'org-popup-calendar-for-date-prompt - 'org-read-date-popup-calendar) - -(make-obsolete-variable - 'org-read-date-minibuffer-setup-hook - "Set `org-read-date-minibuffer-local-map' instead." "24.4") -(defcustom org-read-date-minibuffer-setup-hook nil - "Hook to be used to set up keys for the date/time interface. -Add key definitions to `minibuffer-local-map', which will be a -temporary copy. - -WARNING: This option is obsolete, you should use -`org-read-date-minibuffer-local-map' to set up keys." - :group 'org-time - :type 'hook) + :type 'boolean) +(defvaralias 'org-popup-calendar-for-date-prompt + 'org-read-date-popup-calendar) (defcustom org-extend-today-until 0 "The hour when your day really ends. Must be an integer. @@ -3240,52 +3543,76 @@ moved to the new date." :type 'boolean) (defgroup org-tags nil - "Options concerning tags in Org-mode." + "Options concerning tags in Org mode." :tag "Org Tags" :group 'org) (defcustom org-tag-alist nil - "List of tags allowed in Org-mode files. -When this list is nil, Org-mode will base TAG input on what is already in the -buffer. -The value of this variable is an alist, the car of each entry must be a -keyword as a string, the cdr may be a character that is used to select -that tag through the fast-tag-selection interface. -See the manual for details." + "Default tags available in Org files. + +The value of this variable is an alist. Associations either: + + (TAG) + (TAG . SELECT) + (SPECIAL) + +where TAG is a tag as a string, SELECT is character, used to +select that tag through the fast tag selection interface, and +SPECIAL is one of the following keywords: `:startgroup', +`:startgrouptag', `:grouptags', `:engroup', `:endgrouptag' or +`:newline'. These keywords are used to define a hierarchy of +tags. See manual for details. + +When this variable is nil, Org mode bases tag input on what is +already in the buffer. The value can be overridden locally by +using a TAGS keyword, e.g., + + #+TAGS: tag1 tag2 + +See also `org-tag-persistent-alist' to sidestep this behavior." :group 'org-tags :type '(repeat (choice (cons (string :tag "Tag name") (character :tag "Access char")) - (list :tag "Start radio group" - (const :startgroup) - (option (string :tag "Group description"))) - (list :tag "Group tags delimiter" - (const :grouptags)) - (list :tag "End radio group" - (const :endgroup) - (option (string :tag "Group description"))) + (const :tag "Start radio group" (:startgroup)) + (const :tag "Start tag group, non distinct" (:startgrouptag)) + (const :tag "Group tags delimiter" (:grouptags)) + (const :tag "End radio group" (:endgroup)) + (const :tag "End tag group, non distinct" (:endgrouptag)) (const :tag "New line" (:newline))))) (defcustom org-tag-persistent-alist nil - "List of tags that will always appear in all Org-mode files. -This is in addition to any in buffer settings or customizations -of `org-tag-alist'. -When this list is nil, Org-mode will base TAG input on `org-tag-alist'. -The value of this variable is an alist, the car of each entry must be a -keyword as a string, the cdr may be a character that is used to select -that tag through the fast-tag-selection interface. -See the manual for details. -To disable these tags on a per-file basis, insert anywhere in the file: - #+STARTUP: noptag" + "Tags always available in Org files. + +The value of this variable is an alist. Associations either: + + (TAG) + (TAG . SELECT) + (SPECIAL) + +where TAG is a tag as a string, SELECT is a character, used to +select that tag through the fast tag selection interface, and +SPECIAL is one of the following keywords: `:startgroup', +`:startgrouptag', `:grouptags', `:engroup', `:endgrouptag' or +`:newline'. These keywords are used to define a hierarchy of +tags. See manual for details. + +Unlike to `org-tag-alist', tags defined in this variable do not +depend on a local TAGS keyword. Instead, to disable these tags +on a per-file basis, insert anywhere in the file: + + #+STARTUP: noptag" :group 'org-tags :type '(repeat (choice - (cons (string :tag "Tag name") - (character :tag "Access char")) + (cons (string :tag "Tag name") + (character :tag "Access char")) (const :tag "Start radio group" (:startgroup)) + (const :tag "Start tag group, non distinct" (:startgrouptag)) (const :tag "Group tags delimiter" (:grouptags)) (const :tag "End radio group" (:endgroup)) + (const :tag "End tag group, non distinct" (:endgrouptag)) (const :tag "New line" (:newline))))) (defcustom org-complete-tags-always-offer-all-agenda-tags nil @@ -3296,9 +3623,7 @@ tags in that file can be created dynamically (there are none). (add-hook \\='org-capture-mode-hook (lambda () - (set (make-local-variable - \\='org-complete-tags-always-offer-all-agenda-tags) - t)))" + (setq-local org-complete-tags-always-offer-all-agenda-tags t)))" :group 'org-tags :version "24.1" :type 'boolean) @@ -3340,7 +3665,7 @@ displaying the tags menu is not even shown, until you press C-c again." "Non-nil means fast tags selection interface will also offer TODO states. This is an undocumented feature, you should not rely on it.") -(defcustom org-tags-column (if (featurep 'xemacs) -76 -77) +(defcustom org-tags-column -77 "The column to which tags should be indented in a headline. If this number is positive, it specifies the column. If it is negative, it means that the tags should be flushright to that column. For example, @@ -3437,7 +3762,7 @@ is better to limit inheritance to certain tags using the variables "Hook that is run after the tags in a line have changed.") (defgroup org-properties nil - "Options concerning properties in Org-mode." + "Options concerning properties in Org mode." :tag "Org Properties" :group 'org) @@ -3504,14 +3829,14 @@ in this variable)." (regexp :tag "Properties matched by regexp"))) (defun org-property-inherit-p (property) - "Check if PROPERTY is one that should be inherited." + "Return a non-nil value if PROPERTY should be inherited." (cond ((eq org-use-property-inheritance t) t) ((not org-use-property-inheritance) nil) ((stringp org-use-property-inheritance) (string-match org-use-property-inheritance property)) ((listp org-use-property-inheritance) - (member property org-use-property-inheritance)) + (member-ignore-case property org-use-property-inheritance)) (t (error "Invalid setting of `org-use-property-inheritance'")))) (defcustom org-columns-default-format "%25ITEM %TODO %3PRIORITY %TAGS" @@ -3532,26 +3857,6 @@ ellipses string, only part of the ellipses string will be shown." :group 'org-properties :type 'string) -(defcustom org-columns-modify-value-for-display-function nil - "Function that modifies values for display in column view. -For example, it can be used to cut out a certain part from a time stamp. -The function must take 2 arguments: - -column-title The title of the column (*not* the property name) -value The value that should be modified. - -The function should return the value that should be displayed, -or nil if the normal value should be used." - :group 'org-properties - :type '(choice (const nil) (function))) - -(defcustom org-effort-property "Effort" - "The property that is being used to keep track of effort estimates. -Effort estimates given in this property need to have the format H:MM." - :group 'org-properties - :group 'org-progress - :type '(string :tag "Property")) - (defconst org-global-properties-fixed '(("VISIBILITY_ALL" . "folded children content all") ("CLOCK_MODELINE_TOTAL_ALL" . "current today repeat all auto")) @@ -3582,18 +3887,17 @@ You can set buffer-local values for the same purpose in the variable (cons (string :tag "Property") (string :tag "Value")))) -(defvar org-file-properties nil +(defvar-local org-file-properties nil "List of property/value pairs that can be inherited by any entry. Valid for the current buffer. This variable is populated from #+PROPERTY lines.") -(make-variable-buffer-local 'org-file-properties) (defgroup org-agenda nil - "Options concerning agenda views in Org-mode." + "Options concerning agenda views in Org mode." :tag "Org Agenda" :group 'org) -(defvar org-category nil +(defvar-local org-category nil "Variable used by org files to set a category for agenda display. Such files should use a file variable to set it, for example @@ -3605,22 +3909,22 @@ or contain a special line If the file does not specify a category, then file's base name is used instead.") -(make-variable-buffer-local 'org-category) -(put 'org-category 'safe-local-variable #'(lambda (x) (or (symbolp x) (stringp x)))) +(put 'org-category 'safe-local-variable (lambda (x) (or (symbolp x) (stringp x)))) (defcustom org-agenda-files nil "The files to be used for agenda display. -Entries may be added to this list with \\[org-agenda-file-to-front] and removed with -\\[org-remove-file]. You can also use customize to edit the list. -If an entry is a directory, all files in that directory that are matched by -`org-agenda-file-regexp' will be part of the file list. +If an entry is a directory, all files in that directory that are matched +by `org-agenda-file-regexp' will be part of the file list. If the value of the variable is not a list but a single file name, then -the list of agenda files is actually stored and maintained in that file, one -agenda file per line. In this file paths can be given relative to +the list of agenda files is actually stored and maintained in that file, +one agenda file per line. In this file paths can be given relative to `org-directory'. Tilde expansion and environment variable substitution -are also made." +are also made. + +Entries may be added to this list with `\\[org-agenda-file-to-front]' +and removed with `\\[org-remove-file]'." :group 'org-agenda :type '(choice (repeat :tag "List of files and directories" file) @@ -3637,7 +3941,8 @@ regular expression will be included." (defcustom org-agenda-text-search-extra-files nil "List of extra files to be searched by text search commands. These files will be searched in addition to the agenda files by the -commands `org-search-view' (`C-c a s') and `org-occur-in-agenda-files'. +commands `org-search-view' (`\\[org-agenda] s') \ +and `org-occur-in-agenda-files'. Note that these files will only be searched for text search commands, not for the other agenda views like todo lists, tag searches or the weekly agenda. This variable is intended to list notes and possibly archive files @@ -3650,7 +3955,7 @@ scope." (const :tag "Agenda Archives" agenda-archives) (repeat :inline t (file)))) -(org-defvaralias 'org-agenda-multi-occur-extra-files +(defvaralias 'org-agenda-multi-occur-extra-files 'org-agenda-text-search-extra-files) (defcustom org-agenda-skip-unavailable-files nil @@ -3670,7 +3975,7 @@ forth between agenda and calendar." (defcustom org-calendar-insert-diary-entry-key [?i] "The key to be installed in `calendar-mode-map' for adding diary entries. This option is irrelevant until `org-agenda-diary-file' has been configured -to point to an Org-mode file. When that is the case, the command +to point to an Org file. When that is the case, the command `org-agenda-diary-entry' will be bound to the key given here, by default `i'. In the calendar, `i' normally adds entries to `diary-file'. So if you want to continue doing this, you need to change this to a different @@ -3700,7 +4005,7 @@ points to a file, `org-agenda-diary-entry' will be used instead." 'org-agenda-diary-entry)))))) (defgroup org-latex nil - "Options for embedding LaTeX code into Org-mode." + "Options for embedding LaTeX code into Org mode." :tag "Org LaTeX" :group 'org) @@ -3755,39 +4060,131 @@ Replace format-specifiers in the command as noted below and use `shell-command' to convert LaTeX to MathML. %j: Executable file in fully expanded form as specified by `org-latex-to-mathml-jar-file'. -%I: Input LaTeX file in fully expanded form -%o: Output MathML file +%I: Input LaTeX file in fully expanded form. +%i: The latex fragment to be converted. +%o: Output MathML file. + This command is used by `org-create-math-formula'. -When using MathToWeb as the converter, set this to -\"java -jar %j -unicode -force -df %o %I\"." +When using MathToWeb as the converter, set this option to +\"java -jar %j -unicode -force -df %o %I\". + +When using LaTeXML set this option to +\"latexmlmath \"%i\" --presentationmathml=%o\"." :group 'org-latex :version "24.1" :type '(choice (const :tag "None" nil) (string :tag "\nShell command"))) -(defcustom org-latex-create-formula-image-program 'dvipng - "Program to convert LaTeX fragments with. - -dvipng Process the LaTeX fragments to dvi file, then convert - dvi files to png files using dvipng. - This will also include processing of non-math environments. -imagemagick Convert the LaTeX fragments to pdf files and use imagemagick - to convert pdf files to png files" +(defcustom org-preview-latex-default-process 'dvipng + "The default process to convert LaTeX fragments to image files. +All available processes and theirs documents can be found in +`org-preview-latex-process-alist', which see." :group 'org-latex - :version "24.1" - :type '(choice - (const :tag "dvipng" dvipng) - (const :tag "imagemagick" imagemagick))) + :version "26.1" + :package-version '(Org . "9.0") + :type 'symbol) + +(defcustom org-preview-latex-process-alist + '((dvipng + :programs ("latex" "dvipng") + :description "dvi > png" + :message "you need to install the programs: latex and dvipng." + :image-input-type "dvi" + :image-output-type "png" + :image-size-adjust (1.0 . 1.0) + :latex-compiler ("latex -interaction nonstopmode -output-directory %o %f") + :image-converter ("dvipng -fg %F -bg %B -D %D -T tight -o %O %f")) + (dvisvgm + :programs ("latex" "dvisvgm") + :description "dvi > svg" + :message "you need to install the programs: latex and dvisvgm." + :use-xcolor t + :image-input-type "dvi" + :image-output-type "svg" + :image-size-adjust (1.7 . 1.5) + :latex-compiler ("latex -interaction nonstopmode -output-directory %o %f") + :image-converter ("dvisvgm %f -n -b min -c %S -o %O")) + (imagemagick + :programs ("latex" "convert") + :description "pdf > png" + :message "you need to install the programs: latex and imagemagick." + :use-xcolor t + :image-input-type "pdf" + :image-output-type "png" + :image-size-adjust (1.0 . 1.0) + :latex-compiler ("pdflatex -interaction nonstopmode -output-directory %o %f") + :image-converter + ("convert -density %D -trim -antialias %f -quality 100 %O"))) + "Definitions of external processes for LaTeX previewing. +Org mode can use some external commands to generate TeX snippet's images for +previewing or inserting into HTML files, e.g., \"dvipng\". This variable tells +`org-create-formula-image' how to call them. + +The value is an alist with the pattern (NAME . PROPERTIES). NAME is a symbol. +PROPERTIES accepts the following attributes: + + :programs list of strings, required programs. + :description string, describe the process. + :message string, message it when required programs cannot be found. + :image-input-type string, input file type of image converter (e.g., \"dvi\"). + :image-output-type string, output file type of image converter (e.g., \"png\"). + :use-xcolor boolean, when non-nil, LaTeX \"xcolor\" macro is used to + deal with background and foreground color of image. + Otherwise, dvipng style background and foreground color + format are generated. You may then refer to them in + command options with \"%F\" and \"%B\". + :image-size-adjust cons of numbers, the car element is used to adjust LaTeX + image size showed in buffer and the cdr element is for + HTML file. This option is only useful for process + developers, users should use variable + `org-format-latex-options' instead. + :post-clean list of strings, files matched are to be cleaned up once + the image is generated. When nil, the files with \".dvi\", + \".xdv\", \".pdf\", \".tex\", \".aux\", \".log\", \".svg\", + \".png\", \".jpg\", \".jpeg\" or \".out\" extension will + be cleaned up. + :latex-header list of strings, the LaTeX header of the snippet file. + When nil, the fallback value is used instead, which is + controlled by `org-format-latex-header', + `org-latex-default-packages-alist' and + `org-latex-packages-alist', which see. + :latex-compiler list of LaTeX commands, as strings. Each of them is given + to the shell. Place-holders \"%t\", \"%b\" and \"%o\" are + replaced with values defined below. + :image-converter list of image converter commands strings. Each of them is + given to the shell and supports any of the following + place-holders defined below. + +Place-holders used by `:image-converter' and `:latex-compiler': + + %f input file name + %b base name of input file + %o base directory of input file + %O absolute output file name + +Place-holders only used by `:image-converter': + + %F foreground of image + %B background of image + %D dpi, which is used to adjust image size by some processing commands. + %S the image size scale ratio, which is used to adjust image size by some + processing commands." + :group 'org-latex + :version "26.1" + :package-version '(Org . "9.0") + :type '(alist :tag "LaTeX to image backends" + :value-type (plist))) -(defcustom org-latex-preview-ltxpng-directory "ltxpng/" +(defcustom org-preview-latex-image-directory "ltximg/" "Path to store latex preview images. A relative path here creates many directories relative to the processed org files paths. An absolute path puts all preview images at the same place." :group 'org-latex - :version "24.3" + :version "26.1" + :package-version '(Org . "9.0") :type 'string) (defun org-format-latex-mathml-available-p () @@ -3805,8 +4202,8 @@ images at the same place." (defcustom org-format-latex-header "\\documentclass{article} \\usepackage[usenames]{color} -[PACKAGES] -[DEFAULT-PACKAGES] +\[PACKAGES] +\[DEFAULT-PACKAGES] \\pagestyle{empty} % do not remove % The settings below are copied from fullpage.sty \\setlength{\\textwidth}{\\paperwidth} @@ -3847,22 +4244,19 @@ header, or they will be appended." (default-value var))) (defcustom org-latex-default-packages-alist - '(("AUTO" "inputenc" t) - ("T1" "fontenc" t) - ("" "fixltx2e" nil) + '(("AUTO" "inputenc" t ("pdflatex")) + ("T1" "fontenc" t ("pdflatex")) ("" "graphicx" t) + ("" "grffile" t) ("" "longtable" nil) - ("" "float" nil) ("" "wrapfig" nil) ("" "rotating" nil) ("normalem" "ulem" t) ("" "amsmath" t) ("" "textcomp" t) - ("" "marvosym" t) - ("" "wasysym" t) ("" "amssymb" t) - ("" "hyperref" nil) - "\\tolerance=1000") + ("" "capt-of" nil) + ("" "hyperref" nil)) "Alist of default packages to be inserted in the header. Change this only if one of the packages here causes an @@ -3872,16 +4266,17 @@ The packages in this list are needed by one part or another of Org mode to function properly: - inputenc, fontenc: for basic font and character selection -- fixltx2e: Important patches of LaTeX itself - graphicx: for including images +- grffile: allow periods and spaces in graphics file names - longtable: For multipage tables -- float, wrapfig: for figure placement +- wrapfig: for figure placement - rotating: for sideways figures and tables - ulem: for underline and strike-through - amsmath: for subscript and superscript and math environments -- textcomp, marvosymb, wasysym, amssymb: for various symbols used +- textcomp, amssymb: for various symbols used for interpreting the entities in `org-entities'. You can skip some of these packages if you don't use any of their symbols. +- capt-of: for captions outside of floats - hyperref: for cross references Therefore you should not modify this variable unless you know @@ -3890,20 +4285,24 @@ you might be loading some other package that conflicts with one of the default packages. Each element is either a cell or a string. -A cell is of the format: +A cell is of the format - ( \"options\" \"package\" SNIPPET-FLAG). + (\"options\" \"package\" SNIPPET-FLAG COMPILERS) If SNIPPET-FLAG is non-nil, the package also needs to be included when compiling LaTeX snippets into images for inclusion into -non-LaTeX output. +non-LaTeX output. COMPILERS is a list of compilers that should +include the package, see `org-latex-compiler'. If the document +compiler is not in the list, and the list is non-nil, the package +will not be inserted in the final document. A string will be inserted as-is in the header of the document." :group 'org-latex :group 'org-export-latex :set 'org-set-packages-alist :get 'org-get-packages-alist - :version "24.1" + :version "26.1" + :package-version '(Org . "8.3") :type '(repeat (choice (list :tag "options/package pair" @@ -3947,7 +4346,7 @@ Make sure that you only list packages here which: (string :tag "A line of LaTeX")))) (defgroup org-appearance nil - "Settings for Org-mode appearance." + "Settings for Org mode appearance." :tag "Org Appearance" :group 'org) @@ -4038,6 +4437,11 @@ following symbols: :group 'org-appearance :type 'boolean) +(defcustom org-hide-macro-markers nil + "Non-nil mean font-lock should hide the brackets marking macro calls." + :group 'org-appearance + :type 'boolean) + (defcustom org-pretty-entities nil "Non-nil means show entities as UTF8 characters. When nil, the \\name form remains in the buffer." @@ -4124,7 +4528,7 @@ After a match, the match groups contain these elements: ;; set this option proved cumbersome. See this message/thread: ;; http://article.gmane.org/gmane.emacs.orgmode/68681 (defvar org-emphasis-regexp-components - '(" \t('\"{" "- \t.,:!?;'\")}\\" " \t\r\n,\"'" "." 1) + '(" \t('\"{" "- \t.,:!?;'\")}\\[" " \t\r\n" "." 1) "Components used to build the regular expression for emphasis. This is a list with five entries. Terminology: In an emphasis string like \" *strong word* \", we call the initial space PREMATCH, the final @@ -4142,17 +4546,17 @@ newline The maximum number of newlines allowed in an emphasis exp. You need to reload Org or to restart Emacs after customizing this.") (defcustom org-emphasis-alist - `(("*" bold) + '(("*" bold) ("/" italic) ("_" underline) ("=" org-verbatim verbatim) ("~" org-code verbatim) - ("+" ,(if (featurep 'xemacs) 'org-table '(:strike-through t)))) + ("+" (:strike-through t))) "Alist of characters and faces to emphasize text. Text starting and ending with a special character will be emphasized, for example *bold*, _underlined_ and /italic/. This variable sets the marker characters and the face to be used by font-lock for highlighting -in Org-mode Emacs buffers. +in Org buffers. You need to reload Org or to restart Emacs after customizing this." :group 'org-appearance @@ -4167,122 +4571,68 @@ You need to reload Org or to restart Emacs after customizing this." (plist :tag "Face property list")) (option (const verbatim))))) -(defvar org-protecting-blocks - '("src" "example" "latex" "ascii" "html" "ditaa" "dot" "r" "R") +(defvar org-protecting-blocks '("src" "example" "export") "Blocks that contain text that is quoted, i.e. not processed as Org syntax. This is needed for font-lock setup.") -;;; Miscellaneous options - -(defgroup org-completion nil - "Completion in Org-mode." - :tag "Org Completion" - :group 'org) - -(defcustom org-completion-use-ido nil - "Non-nil means use ido completion wherever possible. -Note that `ido-mode' must be active for this variable to be relevant. -If you decide to turn this variable on, you might well want to turn off -`org-outline-path-complete-in-steps'. -See also `org-completion-use-iswitchb'." - :group 'org-completion - :type 'boolean) - -(defcustom org-completion-use-iswitchb nil - "Non-nil means use iswitchb completion wherever possible. -Note that `iswitchb-mode' must be active for this variable to be relevant. -If you decide to turn this variable on, you might well want to turn off -`org-outline-path-complete-in-steps'. -Note that this variable has only an effect if `org-completion-use-ido' is nil." - :group 'org-completion - :type 'boolean) - -(defcustom org-completion-fallback-command 'hippie-expand - "The expansion command called by \\[pcomplete] in normal context. -Normal means, no org-mode-specific context." - :group 'org-completion - :type 'function) - ;;; Functions and variables from their packages ;; Declared here to avoid compiler warnings - -;; XEmacs only -(defvar outline-mode-menu-heading) -(defvar outline-mode-menu-show) -(defvar outline-mode-menu-hide) -(defvar zmacs-regions) ; XEmacs regions - -;; Emacs only (defvar mark-active) ;; Various packages -(declare-function calendar-iso-to-absolute "cal-iso" (date)) -(declare-function calendar-forward-day "cal-move" (arg)) -(declare-function calendar-goto-date "cal-move" (date)) -(declare-function calendar-goto-today "cal-move" ()) -(declare-function calendar-iso-from-absolute "cal-iso" (date)) -(defvar calc-embedded-close-formula) -(defvar calc-embedded-open-formula) -(declare-function cdlatex-tab "ext:cdlatex" ()) +(declare-function calc-eval "calc" (str &optional separator &rest args)) +(declare-function calendar-forward-day "cal-move" (arg)) +(declare-function calendar-goto-date "cal-move" (date)) +(declare-function calendar-goto-today "cal-move" ()) +(declare-function calendar-iso-from-absolute "cal-iso" (date)) +(declare-function calendar-iso-to-absolute "cal-iso" (date)) (declare-function cdlatex-compute-tables "ext:cdlatex" ()) -(declare-function dired-get-filename "dired" (&optional localp no-error-if-not-filep)) -(defvar font-lock-unfontify-region-function) -(declare-function iswitchb-read-buffer "iswitchb" - (prompt &optional - default require-match _predicate start matches-set)) -(defvar iswitchb-temp-buflist) -(declare-function org-gnus-follow-link "org-gnus" (&optional group article)) -(defvar org-agenda-tags-todo-honor-ignore-options) -(declare-function org-agenda-skip "org-agenda" ()) -(declare-function - org-agenda-format-item "org-agenda" - (extra txt &optional level category tags dotime remove-re habitp)) -(declare-function org-agenda-new-marker "org-agenda" (&optional pos)) -(declare-function org-agenda-change-all-lines "org-agenda" +(declare-function cdlatex-tab "ext:cdlatex" ()) +(declare-function dired-get-filename + "dired" + (&optional localp no-error-if-not-filep)) +(declare-function iswitchb-read-buffer + "iswitchb" + (prompt &optional + default require-match _predicate start matches-set)) +(declare-function org-agenda-change-all-lines + "org-agenda" (newhead hdmarker &optional fixface just-this)) -(declare-function org-agenda-set-restriction-lock "org-agenda" (&optional type)) +(declare-function org-agenda-check-for-timestamp-as-reason-to-ignore-todo-item + "org-agenda" + (&optional end)) +(declare-function org-agenda-copy-local-variable "org-agenda" (var)) +(declare-function org-agenda-format-item + "org-agenda" + (extra txt &optional level category tags dotime + remove-re habitp)) (declare-function org-agenda-maybe-redo "org-agenda" ()) -(declare-function org-agenda-save-markers-for-cut-and-paste "org-agenda" +(declare-function org-agenda-new-marker "org-agenda" (&optional pos)) +(declare-function org-agenda-save-markers-for-cut-and-paste + "org-agenda" (beg end)) -(declare-function org-agenda-copy-local-variable "org-agenda" (var)) -(declare-function org-agenda-check-for-timestamp-as-reason-to-ignore-todo-item - "org-agenda" (&optional end)) -(declare-function org-inlinetask-remove-END-maybe "org-inlinetask" ()) -(declare-function org-inlinetask-in-task-p "org-inlinetask" ()) +(declare-function org-agenda-set-restriction-lock "org-agenda" (&optional type)) +(declare-function org-agenda-skip "org-agenda" ()) +(declare-function org-attach-reveal "org-attach" (&optional if-exists)) +(declare-function org-gnus-follow-link "org-gnus" (&optional group article)) +(declare-function org-indent-mode "org-indent" (&optional arg)) (declare-function org-inlinetask-goto-beginning "org-inlinetask" ()) (declare-function org-inlinetask-goto-end "org-inlinetask" ()) -(declare-function org-indent-mode "org-indent" (&optional arg)) -(declare-function parse-time-string "parse-time" (string)) -(declare-function org-attach-reveal "org-attach" (&optional if-exists)) +(declare-function org-inlinetask-in-task-p "org-inlinetask" ()) +(declare-function org-inlinetask-remove-END-maybe "org-inlinetask" ()) (declare-function orgtbl-send-table "org-table" (&optional maybe)) -(defvar remember-data-file) -(defvar texmathp-why) +(declare-function parse-time-string "parse-time" (string)) (declare-function speedbar-line-directory "speedbar" (&optional depth)) -(declare-function table--at-cell-p "table" (position &optional object at-column)) - -(defvar org-latex-regexps) - -;;; Autoload and prepare some org modules - -;; Some table stuff that needs to be defined here, because it is used -;; by the functions setting up org-mode or checking for table context. - -(defconst org-table-any-line-regexp "^[ \t]*\\(|\\|\\+-[-+]\\)" - "Detect an org-type or table-type table.") -(defconst org-table-line-regexp "^[ \t]*|" - "Detect an org-type table line.") -(defconst org-table-dataline-regexp "^[ \t]*|[^-]" - "Detect an org-type table line.") -(defconst org-table-hline-regexp "^[ \t]*|-" - "Detect an org-type table hline.") -(defconst org-table1-hline-regexp "^[ \t]*\\+-[-+]" - "Detect a table-type table hline.") -(defconst org-table-any-border-regexp "^[ \t]*[^|+ \t]" - "Detect the first line outside a table when searching from within it. -This works for both table types.") -(defconst org-TBLFM-regexp "^[ \t]*#\\+TBLFM: " - "Detect a #+TBLFM line.") +(defvar align-mode-rules-list) +(defvar calc-embedded-close-formula) +(defvar calc-embedded-open-formula) +(defvar calc-embedded-open-mode) +(defvar font-lock-unfontify-region-function) +(defvar iswitchb-temp-buflist) +(defvar org-agenda-tags-todo-honor-ignore-options) +(defvar remember-data-file) +(defvar texmathp-why) ;;;###autoload (defun turn-on-orgtbl () @@ -4291,75 +4641,50 @@ This works for both table types.") (orgtbl-mode 1)) (defun org-at-table-p (&optional table-type) - "Return t if the cursor is inside an org-type table. -If TABLE-TYPE is non-nil, also check for table.el-type tables." - (if org-enable-table-editor - (save-excursion - (beginning-of-line 1) - (looking-at (if table-type org-table-any-line-regexp - org-table-line-regexp))) - nil)) -(defsubst org-table-p () (org-at-table-p)) + "Non-nil if the cursor is inside an Org table. +If TABLE-TYPE is non-nil, also check for table.el-type tables. +If `org-enable-table-editor' is nil, return nil unconditionally." + (and + org-enable-table-editor + (save-excursion + (beginning-of-line) + (looking-at-p (if table-type "[ \t]*[|+]" "[ \t]*|"))) + (or (not (derived-mode-p 'org-mode)) + (let ((e (org-element-lineage (org-element-at-point) '(table) t))) + (and e (or table-type (eq (org-element-property :type e) 'org))))))) (defun org-at-table.el-p () - "Return t if and only if we are at a table.el table." - (and (org-at-table-p 'any) - (save-excursion - (goto-char (org-table-begin 'any)) - (looking-at org-table1-hline-regexp)))) - -(defun org-table-recognize-table.el () - "If there is a table.el table nearby, recognize it and move into it." - (if org-table-tab-recognizes-table.el - (if (org-at-table.el-p) - (progn - (beginning-of-line 1) - (if (looking-at org-table-dataline-regexp) - nil - (if (looking-at org-table1-hline-regexp) - (progn - (beginning-of-line 2) - (if (looking-at org-table-any-border-regexp) - (beginning-of-line -1))))) - (if (re-search-forward "|" (org-table-end t) t) - (progn - (require 'table) - (if (table--at-cell-p (point)) - t - (message "recognizing table.el table...") - (table-recognize-table) - (message "recognizing table.el table...done"))) - (error "This should not happen")) - t) - nil) - nil)) + "Non-nil when point is at a table.el table." + (and (save-excursion (beginning-of-line) (looking-at "[ \t]*[|+]")) + (let ((element (org-element-at-point))) + (and (eq (org-element-type element) 'table) + (eq (org-element-property :type element) 'table.el))))) (defun org-at-table-hline-p () - "Return t if the cursor is inside a hline in a table." - (if org-enable-table-editor - (save-excursion - (beginning-of-line 1) - (looking-at org-table-hline-regexp)) - nil)) + "Non-nil when point is inside a hline in a table. +Assume point is already in a table. If `org-enable-table-editor' +is nil, return nil unconditionally." + (and org-enable-table-editor + (save-excursion + (beginning-of-line) + (looking-at org-table-hline-regexp)))) (defun org-table-map-tables (function &optional quietly) "Apply FUNCTION to the start of all tables in the buffer." - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (while (re-search-forward org-table-any-line-regexp nil t) - (unless quietly - (message "Mapping tables: %d%%" - (floor (* 100.0 (point)) (buffer-size)))) - (beginning-of-line 1) - (when (and (looking-at org-table-line-regexp) - ;; Exclude tables in src/example/verbatim/clocktable blocks - (not (org-in-block-p '("src" "example" "verbatim" "clocktable")))) - (save-excursion (funcall function)) - (or (looking-at org-table-line-regexp) - (forward-char 1))) - (re-search-forward org-table-any-border-regexp nil 1)))) + (org-with-wide-buffer + (goto-char (point-min)) + (while (re-search-forward org-table-any-line-regexp nil t) + (unless quietly + (message "Mapping tables: %d%%" + (floor (* 100.0 (point)) (buffer-size)))) + (beginning-of-line 1) + (when (and (looking-at org-table-line-regexp) + ;; Exclude tables in src/example/verbatim/clocktable blocks + (not (org-in-block-p '("src" "example" "verbatim" "clocktable")))) + (save-excursion (funcall function)) + (or (looking-at org-table-line-regexp) + (forward-char 1))) + (re-search-forward org-table-any-border-regexp nil 1))) (unless quietly (message "Mapping tables: done"))) (declare-function org-clock-save-markers-for-cut-and-paste "org-clock" (beg end)) @@ -4368,12 +4693,12 @@ If TABLE-TYPE is non-nil, also check for table.el-type tables." (&optional also-non-dangling-p prompt last-valid)) (defun org-at-TBLFM-p (&optional pos) - "Return t when point (or POS) is in #+TBLFM line." + "Non-nil when point (or POS) is in #+TBLFM line." (save-excursion - (let ((pos pos))) (goto-char (or pos (point))) - (beginning-of-line 1) - (looking-at org-TBLFM-regexp))) + (beginning-of-line) + (and (let ((case-fold-search t)) (looking-at org-TBLFM-regexp)) + (eq (org-element-type (org-element-at-point)) 'table)))) (defvar org-clock-start-time) (defvar org-clock-marker (make-marker) @@ -4410,7 +4735,7 @@ If yes, offer to stop it and to save the buffer with the changes." (add-hook 'kill-emacs-hook 'org-clock-save)) (defgroup org-archive nil - "Options concerning archiving in Org-mode." + "Options concerning archiving in Org mode." :tag "Org Archive" :group 'org-structure) @@ -4425,7 +4750,7 @@ When the filename is omitted, archiving happens in the same file. %s in the filename will be replaced by the current file name (without the directory part). Archiving to a different file is useful to keep archived entries from contributing to the -Org-mode Agenda. +Org Agenda. The archived entries will be filed as subtrees of the specified headline. When the headline is omitted, the subtrees are simply @@ -4473,16 +4798,6 @@ the hierarchy, it will be used." :group 'org-archive :type 'string) -(defcustom org-archive-tag "ARCHIVE" - "The tag that marks a subtree as archived. -An archived subtree does not open during visibility cycling, and does -not contribute to the agenda listings. -After changing this, font-lock must be restarted in the relevant buffers to -get the proper fontification." - :group 'org-archive - :group 'org-keywords - :type 'string) - (defcustom org-agenda-skip-archived-trees t "Non-nil means the agenda will skip any items located in archived trees. An archived tree is a tree marked with the tag ARCHIVE. The use of this @@ -4515,24 +4830,25 @@ collapsed state." :group 'org-sparse-trees :type 'boolean) -(defcustom org-sparse-tree-default-date-type 'scheduled-or-deadline +(defcustom org-sparse-tree-default-date-type nil "The default date type when building a sparse tree. When this is nil, a date is a scheduled or a deadline timestamp. Otherwise, these types are allowed: all: all timestamps active: only active timestamps (<...>) - inactive: only inactive timestamps (<...) + inactive: only inactive timestamps ([...]) scheduled: only scheduled timestamps deadline: only deadline timestamps" - :type '(choice (const :tag "Scheduled or deadline" scheduled-or-deadline) + :type '(choice (const :tag "Scheduled or deadline" nil) (const :tag "All timestamps" all) (const :tag "Only active timestamps" active) (const :tag "Only inactive timestamps" inactive) (const :tag "Only scheduled timestamps" scheduled) (const :tag "Only deadline timestamps" deadline) (const :tag "Only closed timestamps" closed)) - :version "24.3" + :version "26.1" + :package-version '(Org . "8.3") :group 'org-sparse-trees) (defun org-cycle-hide-archived-subtrees (state) @@ -4545,9 +4861,10 @@ Otherwise, these types are allowed: (end (if globalp (point-max) (org-end-of-subtree t)))) (org-hide-archived-subtrees beg end) (goto-char beg) - (if (looking-at (concat ".*:" org-archive-tag ":")) - (message "%s" (substitute-command-keys - "Subtree is archived and stays closed. Use \\[org-force-cycle-archived] to cycle it anyway."))))))) + (when (looking-at-p (concat ".*:" org-archive-tag ":")) + (message "%s" (substitute-command-keys + "Subtree is archived and stays closed. Use \ +`\\[org-force-cycle-archived]' to cycle it anyway."))))))) (defun org-force-cycle-archived () "Cycle subtree even if it is archived." @@ -4558,13 +4875,16 @@ Otherwise, these types are allowed: (defun org-hide-archived-subtrees (beg end) "Re-hide all archived subtrees after a visibility state change." - (save-excursion - (let* ((re (concat ":" org-archive-tag ":"))) - (goto-char beg) - (while (re-search-forward re end t) - (when (org-at-heading-p) - (org-flag-subtree t) - (org-end-of-subtree t)))))) + (org-with-wide-buffer + (let ((case-fold-search nil) + (re (concat org-outline-regexp-bol ".*:" org-archive-tag ":"))) + (goto-char beg) + ;; Include headline point is currently on. + (beginning-of-line) + (while (and (< (point) end) (re-search-forward re end t)) + (when (member org-archive-tag (org-get-tags)) + (org-flag-subtree t) + (org-end-of-subtree t)))))) (declare-function outline-end-of-heading "outline" ()) (declare-function outline-flag-region "outline" (from to flag)) @@ -4580,7 +4900,6 @@ Otherwise, these types are allowed: ;; Declare Column View Code -(declare-function org-columns-number-to-string "org-colview" (n fmt &optional printf)) (declare-function org-columns-get-format-and-top-level "org-colview" ()) (declare-function org-columns-compute "org-colview" (property)) @@ -4593,79 +4912,47 @@ Otherwise, these types are allowed: ;;; Variables for pre-computed regular expressions, all buffer local -(defvar org-drawer-regexp "^[ \t]*:PROPERTIES:[ \t]*$" - "Matches first line of a hidden block.") -(make-variable-buffer-local 'org-drawer-regexp) -(defvar org-todo-regexp nil - "Matches any of the TODO state keywords.") -(make-variable-buffer-local 'org-todo-regexp) -(defvar org-not-done-regexp nil - "Matches any of the TODO state keywords except the last one.") -(make-variable-buffer-local 'org-not-done-regexp) -(defvar org-not-done-heading-regexp nil - "Matches a TODO headline that is not done.") -(make-variable-buffer-local 'org-not-done-regexp) -(defvar org-todo-line-regexp nil - "Matches a headline and puts TODO state into group 2 if present.") -(make-variable-buffer-local 'org-todo-line-regexp) -(defvar org-complex-heading-regexp nil +(defvar-local org-todo-regexp nil + "Matches any of the TODO state keywords. +Since TODO keywords are case-sensitive, `case-fold-search' is +expected to be bound to nil when matching against this regexp.") + +(defvar-local org-not-done-regexp nil + "Matches any of the TODO state keywords except the last one. +Since TODO keywords are case-sensitive, `case-fold-search' is +expected to be bound to nil when matching against this regexp.") + +(defvar-local org-not-done-heading-regexp nil + "Matches a TODO headline that is not done. +Since TODO keywords are case-sensitive, `case-fold-search' is +expected to be bound to nil when matching against this regexp.") + +(defvar-local org-todo-line-regexp nil + "Matches a headline and puts TODO state into group 2 if present. +Since TODO keywords are case-sensitive, `case-fold-search' is +expected to be bound to nil when matching against this regexp.") + +(defvar-local org-complex-heading-regexp nil "Matches a headline and puts everything into groups: -group 1: the stars -group 2: The todo keyword, maybe + +group 1: Stars +group 2: The TODO keyword, maybe group 3: Priority cookie group 4: True headline -group 5: Tags") -(make-variable-buffer-local 'org-complex-heading-regexp) -(defvar org-complex-heading-regexp-format nil +group 5: Tags + +Since TODO keywords are case-sensitive, `case-fold-search' is +expected to be bound to nil when matching against this regexp.") + +(defvar-local org-complex-heading-regexp-format nil "Printf format to make regexp to match an exact headline. This regexp will match the headline of any node which has the exact headline text that is put into the format, but may have any TODO state, priority and tags.") -(make-variable-buffer-local 'org-complex-heading-regexp-format) -(defvar org-todo-line-tags-regexp nil + +(defvar-local org-todo-line-tags-regexp nil "Matches a headline and puts TODO state into group 2 if present. Also put tags into group 4 if tags are present.") -(make-variable-buffer-local 'org-todo-line-tags-regexp) -(defvar org-ds-keyword-length 12 - "Maximum length of the DEADLINE and SCHEDULED keywords.") -(make-variable-buffer-local 'org-ds-keyword-length) -(defvar org-deadline-regexp nil - "Matches the DEADLINE keyword.") -(make-variable-buffer-local 'org-deadline-regexp) -(defvar org-deadline-time-regexp nil - "Matches the DEADLINE keyword together with a time stamp.") -(make-variable-buffer-local 'org-deadline-time-regexp) -(defvar org-deadline-time-hour-regexp nil - "Matches the DEADLINE keyword together with a time-and-hour stamp.") -(make-variable-buffer-local 'org-deadline-time-hour-regexp) -(defvar org-deadline-line-regexp nil - "Matches the DEADLINE keyword and the rest of the line.") -(make-variable-buffer-local 'org-deadline-line-regexp) -(defvar org-scheduled-regexp nil - "Matches the SCHEDULED keyword.") -(make-variable-buffer-local 'org-scheduled-regexp) -(defvar org-scheduled-time-regexp nil - "Matches the SCHEDULED keyword together with a time stamp.") -(make-variable-buffer-local 'org-scheduled-time-regexp) -(defvar org-scheduled-time-hour-regexp nil - "Matches the SCHEDULED keyword together with a time-and-hour stamp.") -(make-variable-buffer-local 'org-scheduled-time-hour-regexp) -(defvar org-closed-time-regexp nil - "Matches the CLOSED keyword together with a time stamp.") -(make-variable-buffer-local 'org-closed-time-regexp) - -(defvar org-keyword-time-regexp nil - "Matches any of the 4 keywords, together with the time stamp.") -(make-variable-buffer-local 'org-keyword-time-regexp) -(defvar org-keyword-time-not-clock-regexp nil - "Matches any of the 3 keywords, together with the time stamp.") -(make-variable-buffer-local 'org-keyword-time-not-clock-regexp) -(defvar org-maybe-keyword-time-regexp nil - "Matches a timestamp, possibly preceded by a keyword.") -(make-variable-buffer-local 'org-maybe-keyword-time-regexp) -(defvar org-all-time-keywords nil - "List of time keywords.") -(make-variable-buffer-local 'org-all-time-keywords) (defconst org-plain-time-of-day-regexp (concat @@ -4771,32 +5058,6 @@ in the #+STARTUP line), the corresponding variable, and the value to set this variable to if the option is found. An optional forth element PUSH means to push this value onto the list in the variable.") -(defun org-update-property-plist (key val props) - "Update PROPS with KEY and VAL." - (let* ((appending (string= "+" (substring key (- (length key) 1)))) - (key (if appending (substring key 0 (- (length key) 1)) key)) - (remainder (org-remove-if (lambda (p) (string= (car p) key)) props)) - (previous (cdr (assoc key props)))) - (if appending - (cons (cons key (if previous (concat previous " " val) val)) remainder) - (cons (cons key val) remainder)))) - -(defconst org-block-regexp - "^[ \t]*#\\+begin_?\\([^ \n]+\\)\\(\\([^\n]+\\)\\)?\n\\([^\000]+?\\)#\\+end_?\\1[ \t]*$" - "Regular expression for hiding blocks.") -(defconst org-heading-keyword-regexp-format - "^\\(\\*+\\)\\(?: +%s\\)\\(?: +\\(.*?\\)\\)?[ \t]*$" - "Printf format for a regexp matching a headline with some keyword. -This regexp will match the headline of any node which has the -exact keyword that is put into the format. The keyword isn't in -any group by default, but the stars and the body are.") -(defconst org-heading-keyword-maybe-regexp-format - "^\\(\\*+\\)\\(?: +%s\\)?\\(?: +\\(.*?\\)\\)?[ \t]*$" - "Printf format for a regexp matching a headline, possibly with some keyword. -This regexp can match any headline with the specified keyword, or -without a keyword. The keyword isn't in any group by default, -but the stars and the body are.") - (defcustom org-group-tags t "When non-nil (the default), use group tags. This can be turned on/off through `org-toggle-tags-groups'." @@ -4820,386 +5081,378 @@ Support for group tags is controlled by the option (message "Groups tags support has been turned %s" (if org-group-tags "on" "off"))) -(defun org-set-regexps-and-options-for-tags () - "Precompute variables used for tags." - (when (derived-mode-p 'org-mode) - (org-set-local 'org-file-tags nil) - (let ((re (org-make-options-regexp '("FILETAGS" "TAGS"))) - (splitre "[ \t]+") - (start 0) - tags ftags key value) - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (while (re-search-forward re nil t) - (setq key (upcase (org-match-string-no-properties 1)) - value (org-match-string-no-properties 2)) - (if (stringp value) (setq value (org-trim value))) - (cond - ((equal key "TAGS") - (setq tags (append tags (if tags '("\\n") nil) - (org-split-string value splitre)))) - ((equal key "FILETAGS") - (when (string-match "\\S-" value) - (setq ftags - (append - ftags - (apply 'append - (mapcar (lambda (x) (org-split-string x ":")) - (org-split-string value))))))))))) - ;; Process the file tags. - (and ftags (org-set-local 'org-file-tags - (mapcar 'org-add-prop-inherited ftags))) - (org-set-local 'org-tag-groups-alist nil) - ;; Process the tags. - (when (and (not tags) org-tag-alist) - (setq tags - (mapcar - (lambda (tg) (cond ((eq (car tg) :startgroup) "{") - ((eq (car tg) :endgroup) "}") - ((eq (car tg) :grouptags) ":") - ((eq (car tg) :newline) "\n") - (t (concat (car tg) - (if (characterp (cdr tg)) - (format "(%s)" (char-to-string (cdr tg))) ""))))) - org-tag-alist))) - (let (tgs g) - (dolist (e tags) - (cond - ((equal e "{") - (progn (push '(:startgroup) tgs) - (when (equal (nth 1 tags) ":") - (push (list (replace-regexp-in-string - "(.+)$" "" (nth 0 tags))) - org-tag-groups-alist) - (setq g 0)))) - ((equal e ":") (push '(:grouptags) tgs)) - ((equal e "}") (push '(:endgroup) tgs) (if g (setq g nil))) - ((equal e "\\n") (push '(:newline) tgs)) - ((string-match (org-re "^\\([[:alnum:]_@#%]+\\)(\\(.\\))$") e) - (push (cons (match-string 1 e) - (string-to-char (match-string 2 e))) - tgs) - (if (and g (> g 0)) - (setcar org-tag-groups-alist - (append (car org-tag-groups-alist) - (list (match-string 1 e))))) - (if g (setq g (1+ g)))) - (t (push (list e) tgs) - (if (and g (> g 0)) - (setcar org-tag-groups-alist - (append (car org-tag-groups-alist) (list e)))) - (if g (setq g (1+ g)))))) - (org-set-local 'org-tag-alist nil) - (dolist (e tgs) - (or (and (stringp (car e)) - (assoc (car e) org-tag-alist)) - (push e org-tag-alist))) - ;; Return a list with tag variables - (list org-file-tags org-tag-alist org-tag-groups-alist))))) - -(defvar org-ota nil) -(defun org-set-regexps-and-options () - "Precompute regular expressions used in the current buffer." +(defun org-set-regexps-and-options (&optional tags-only) + "Precompute regular expressions used in the current buffer. +When optional argument TAGS-ONLY is non-nil, only compute tags +related expressions." (when (derived-mode-p 'org-mode) - (org-set-local 'org-todo-kwd-alist nil) - (org-set-local 'org-todo-key-alist nil) - (org-set-local 'org-todo-key-trigger nil) - (org-set-local 'org-todo-keywords-1 nil) - (org-set-local 'org-done-keywords nil) - (org-set-local 'org-todo-heads nil) - (org-set-local 'org-todo-sets nil) - (org-set-local 'org-todo-log-states nil) - (org-set-local 'org-file-properties nil) - (let ((re (org-make-options-regexp - '("CATEGORY" "TODO" "COLUMNS" "STARTUP" "ARCHIVE" - "LINK" "PRIORITIES" "CONSTANTS" "PROPERTY" "DRAWERS" - "SETUPFILE" "OPTIONS") - "\\(?:[a-zA-Z][0-9a-zA-Z_]*_TODO\\)")) - (splitre "[ \t]+") - (scripts org-use-sub-superscripts) - kwds kws0 kwsa key log value cat arch const links hw dws - tail sep kws1 prio props drawers ext-setup-or-nil setup-contents - (start 0)) - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (while - (or (and - ext-setup-or-nil - (not org-ota) - (let (ret) - (with-temp-buffer - (insert ext-setup-or-nil) - (let ((major-mode 'org-mode) org-ota) - (setq ret (save-match-data - (org-set-regexps-and-options-for-tags))))) - ;; Append setupfile tags to existing tags - (setq org-ota t) - (setq org-file-tags - (delq nil (append org-file-tags (nth 0 ret))) - org-tag-alist - (delq nil (append org-tag-alist (nth 1 ret))) - org-tag-groups-alist - (delq nil (append org-tag-groups-alist (nth 2 ret)))))) - (and ext-setup-or-nil - (string-match re ext-setup-or-nil start) - (setq start (match-end 0))) - (and (setq ext-setup-or-nil nil start 0) - (re-search-forward re nil t))) - (setq key (upcase (match-string 1 ext-setup-or-nil)) - value (org-match-string-no-properties 2 ext-setup-or-nil)) - (if (stringp value) (setq value (org-trim value))) - (cond - ((equal key "CATEGORY") - (setq cat value)) - ((member key '("SEQ_TODO" "TODO")) - (push (cons 'sequence (org-split-string value splitre)) kwds)) - ((equal key "TYP_TODO") - (push (cons 'type (org-split-string value splitre)) kwds)) - ((string-match "\\`\\([a-zA-Z][0-9a-zA-Z_]*\\)_TODO\\'" key) - ;; general TODO-like setup - (push (cons (intern (downcase (match-string 1 key))) - (org-split-string value splitre)) - kwds)) - ((equal key "COLUMNS") - (org-set-local 'org-columns-default-format value)) - ((equal key "LINK") - (when (string-match "^\\(\\S-+\\)[ \t]+\\(.+\\)" value) - (push (cons (match-string 1 value) - (org-trim (match-string 2 value))) - links))) - ((equal key "PRIORITIES") - (setq prio (org-split-string value " +"))) - ((equal key "PROPERTY") - (when (string-match "\\(\\S-+\\)\\s-+\\(.*\\)" value) - (setq props (org-update-property-plist (match-string 1 value) - (match-string 2 value) - props)))) - ((equal key "DRAWERS") - (setq drawers (delete-dups (append org-drawers (org-split-string value splitre))))) - ((equal key "CONSTANTS") - (org-table-set-constants)) - ((equal key "STARTUP") - (let ((opts (org-split-string value splitre)) - var val) - (dolist (l opts) - (when (setq l (assoc l org-startup-options)) - (setq var (nth 1 l) val (nth 2 l)) - (if (not (nth 3 l)) - (set (make-local-variable var) val) - (if (not (listp (symbol-value var))) - (set (make-local-variable var) nil)) - (set (make-local-variable var) (symbol-value var)) - (add-to-list var val)))))) - ((equal key "ARCHIVE") - (setq arch value) - (remove-text-properties 0 (length arch) - '(face t fontified t) arch)) - ((equal key "OPTIONS") - (if (string-match "\\([ \t]\\|\\`\\)\\^:\\(t\\|nil\\|{}\\)" value) - (setq scripts (read (match-string 2 value))))) - ((and (equal key "SETUPFILE") - ;; Prevent checking in Gnus messages - (not buffer-read-only)) - (setq setup-contents (org-file-contents - (expand-file-name - (org-remove-double-quotes value)) - 'noerror)) - (if (not ext-setup-or-nil) - (setq ext-setup-or-nil setup-contents start 0) - (setq ext-setup-or-nil - (concat (substring ext-setup-or-nil 0 start) - "\n" setup-contents "\n" - (substring ext-setup-or-nil start))))))) - ;; search for property blocks - (goto-char (point-min)) - (while (re-search-forward org-block-regexp nil t) - (when (equal "PROPERTY" (upcase (match-string 1))) - (setq value (replace-regexp-in-string - "[\n\r]" " " (match-string 4))) - (when (string-match "\\(\\S-+\\)\\s-+\\(.*\\)" value) - (setq props (org-update-property-plist (match-string 1 value) - (match-string 2 value) - props))))))) - (org-set-local 'org-use-sub-superscripts scripts) - (when cat - (org-set-local 'org-category (intern cat)) - (push (cons "CATEGORY" cat) props)) - (when prio - (if (< (length prio) 3) (setq prio '("A" "C" "B"))) - (setq prio (mapcar 'string-to-char prio)) - (org-set-local 'org-highest-priority (nth 0 prio)) - (org-set-local 'org-lowest-priority (nth 1 prio)) - (org-set-local 'org-default-priority (nth 2 prio))) - (and props (org-set-local 'org-file-properties (nreverse props))) - (and drawers (org-set-local 'org-drawers drawers)) - (and arch (org-set-local 'org-archive-location arch)) - (and links (setq org-link-abbrev-alist-local (nreverse links))) - ;; Process the TODO keywords - (unless kwds - ;; Use the global values as if they had been given locally. - (setq kwds (default-value 'org-todo-keywords)) - (if (stringp (car kwds)) - (setq kwds (list (cons org-todo-interpretation - (default-value 'org-todo-keywords))))) - (setq kwds (reverse kwds))) - (setq kwds (nreverse kwds)) - (let (inter kw) - (dolist (kws kwds) - (let ((kws (or - (run-hook-with-args-until-success - 'org-todo-setup-filter-hook kws) - kws))) - (setq inter (pop kws) sep (member "|" kws) - kws0 (delete "|" (copy-sequence kws)) - kwsa nil - kws1 (mapcar - (lambda (x) - ;; 1 2 - (if (string-match "^\\(.*?\\)\\(?:(\\([^!@/]\\)?.*?)\\)?$" x) - (progn - (setq kw (match-string 1 x) - key (and (match-end 2) (match-string 2 x)) - log (org-extract-log-state-settings x)) - (push (cons kw (and key (string-to-char key))) kwsa) - (and log (push log org-todo-log-states)) - kw) - (error "Invalid TODO keyword %s" x))) - kws0) - kwsa (if kwsa (append '((:startgroup)) - (nreverse kwsa) - '((:endgroup)))) - hw (car kws1) - dws (if sep (org-remove-keyword-keys (cdr sep)) (last kws1)) - tail (list inter hw (car dws) (org-last dws)))) - (add-to-list 'org-todo-heads hw 'append) - (push kws1 org-todo-sets) - (setq org-done-keywords (append org-done-keywords dws nil)) - (setq org-todo-key-alist (append org-todo-key-alist kwsa)) - (mapc (lambda (x) (push (cons x tail) org-todo-kwd-alist)) kws1) - (setq org-todo-keywords-1 (append org-todo-keywords-1 kws1 nil))) + (let ((alist (org--setup-collect-keywords + (org-make-options-regexp + (append '("FILETAGS" "TAGS" "SETUPFILE") + (and (not tags-only) + '("ARCHIVE" "CATEGORY" "COLUMNS" "CONSTANTS" + "LINK" "OPTIONS" "PRIORITIES" "PROPERTY" + "SEQ_TODO" "STARTUP" "TODO" "TYP_TODO"))))))) + ;; Startup options. Get this early since it does change + ;; behavior for other options (e.g., tags). + (let ((startup (cdr (assq 'startup alist)))) + (dolist (option startup) + (let ((entry (assoc-string option org-startup-options t))) + (when entry + (let ((var (nth 1 entry)) + (val (nth 2 entry))) + (if (not (nth 3 entry)) (set (make-local-variable var) val) + (unless (listp (symbol-value var)) + (set (make-local-variable var) nil)) + (add-to-list var val))))))) + (setq-local org-file-tags + (mapcar #'org-add-prop-inherited + (cdr (assq 'filetags alist)))) + (setq org-current-tag-alist + (append org-tag-persistent-alist + (let ((tags (cdr (assq 'tags alist)))) + (if tags (org-tag-string-to-alist tags) + org-tag-alist)))) + (setq org-tag-groups-alist + (org-tag-alist-to-groups org-current-tag-alist)) + (unless tags-only + ;; File properties. + (setq-local org-file-properties (cdr (assq 'property alist))) + ;; Archive location. + (let ((archive (cdr (assq 'archive alist)))) + (when archive (setq-local org-archive-location archive))) + ;; Category. + (let ((cat (org-string-nw-p (cdr (assq 'category alist))))) + (when cat + (setq-local org-category (intern cat)) + (setq-local org-file-properties + (org--update-property-plist + "CATEGORY" cat org-file-properties)))) + ;; Columns. + (let ((column (cdr (assq 'columns alist)))) + (when column (setq-local org-columns-default-format column))) + ;; Constants. + (setq org-table-formula-constants-local (cdr (assq 'constants alist))) + ;; Link abbreviations. + (let ((links (cdr (assq 'link alist)))) + (when links (setq org-link-abbrev-alist-local (nreverse links)))) + ;; Priorities. + (let ((priorities (cdr (assq 'priorities alist)))) + (when priorities + (setq-local org-highest-priority (nth 0 priorities)) + (setq-local org-lowest-priority (nth 1 priorities)) + (setq-local org-default-priority (nth 2 priorities)))) + ;; Scripts. + (let ((scripts (assq 'scripts alist))) + (when scripts + (setq-local org-use-sub-superscripts (cdr scripts)))) + ;; TODO keywords. + (setq-local org-todo-kwd-alist nil) + (setq-local org-todo-key-alist nil) + (setq-local org-todo-key-trigger nil) + (setq-local org-todo-keywords-1 nil) + (setq-local org-done-keywords nil) + (setq-local org-todo-heads nil) + (setq-local org-todo-sets nil) + (setq-local org-todo-log-states nil) + (let ((todo-sequences + (or (nreverse (cdr (assq 'todo alist))) + (let ((d (default-value 'org-todo-keywords))) + (if (not (stringp (car d))) d + ;; XXX: Backward compatibility code. + (list (cons org-todo-interpretation d))))))) + (dolist (sequence todo-sequences) + (let* ((sequence (or (run-hook-with-args-until-success + 'org-todo-setup-filter-hook sequence) + sequence)) + (sequence-type (car sequence)) + (keywords (cdr sequence)) + (sep (member "|" keywords)) + names alist) + (dolist (k (remove "|" keywords)) + (unless (string-match "^\\(.*?\\)\\(?:(\\([^!@/]\\)?.*?)\\)?$" + k) + (error "Invalid TODO keyword %s" k)) + (let ((name (match-string 1 k)) + (key (match-string 2 k)) + (log (org-extract-log-state-settings k))) + (push name names) + (push (cons name (and key (string-to-char key))) alist) + (when log (push log org-todo-log-states)))) + (let* ((names (nreverse names)) + (done (if sep (org-remove-keyword-keys (cdr sep)) + (last names))) + (head (car names)) + (tail (list sequence-type head (car done) (org-last done)))) + (add-to-list 'org-todo-heads head 'append) + (push names org-todo-sets) + (setq org-done-keywords (append org-done-keywords done nil)) + (setq org-todo-keywords-1 (append org-todo-keywords-1 names nil)) + (setq org-todo-key-alist + (append org-todo-key-alist + (and alist + (append '((:startgroup)) + (nreverse alist) + '((:endgroup)))))) + (dolist (k names) (push (cons k tail) org-todo-kwd-alist)))))) (setq org-todo-sets (nreverse org-todo-sets) org-todo-kwd-alist (nreverse org-todo-kwd-alist) - org-todo-key-trigger (delq nil (mapcar 'cdr org-todo-key-alist)) - org-todo-key-alist (org-assign-fast-keys org-todo-key-alist))) - ;; Compute the regular expressions and other local variables. - ;; Using `org-outline-regexp-bol' would complicate them much, - ;; because of the fixed white space at the end of that string. - (if (not org-done-keywords) - (setq org-done-keywords (and org-todo-keywords-1 - (list (org-last org-todo-keywords-1))))) - (setq org-ds-keyword-length (+ 2 (max (length org-deadline-string) - (length org-scheduled-string) - (length org-clock-string) - (length org-closed-string))) - org-drawer-regexp - (concat "^[ \t]*:\\(" - (mapconcat 'regexp-quote org-drawers "\\|") - "\\):[ \t]*$") - org-not-done-keywords - (org-delete-all org-done-keywords (copy-sequence org-todo-keywords-1)) - org-todo-regexp - (concat "\\(" - (mapconcat 'regexp-quote org-todo-keywords-1 "\\|") - "\\)") - org-not-done-regexp - (concat "\\(" - (mapconcat 'regexp-quote org-not-done-keywords "\\|") - "\\)") - org-not-done-heading-regexp - (format org-heading-keyword-regexp-format org-not-done-regexp) - org-todo-line-regexp - (format org-heading-keyword-maybe-regexp-format org-todo-regexp) - org-complex-heading-regexp - (concat "^\\(\\*+\\)" - "\\(?: +" org-todo-regexp "\\)?" - "\\(?: +\\(\\[#.\\]\\)\\)?" - "\\(?: +\\(.*?\\)\\)??" - (org-re "\\(?:[ \t]+\\(:[[:alnum:]_@#%:]+:\\)\\)?") - "[ \t]*$") - org-complex-heading-regexp-format - (concat "^\\(\\*+\\)" - "\\(?: +" org-todo-regexp "\\)?" - "\\(?: +\\(\\[#.\\]\\)\\)?" - "\\(?: +" - ;; Stats cookies can be stuck to body. - "\\(?:\\[[0-9%%/]+\\] *\\)*" - "\\(%s\\)" - "\\(?: *\\[[0-9%%/]+\\]\\)*" - "\\)" - (org-re "\\(?:[ \t]+\\(:[[:alnum:]_@#%%:]+:\\)\\)?") - "[ \t]*$") - org-todo-line-tags-regexp - (concat "^\\(\\*+\\)" - "\\(?: +" org-todo-regexp "\\)?" - "\\(?: +\\(.*?\\)\\)??" - (org-re "\\(?:[ \t]+\\(:[[:alnum:]:_@#%]+:\\)\\)?") - "[ \t]*$") - org-deadline-regexp (concat "\\<" org-deadline-string) - org-deadline-time-regexp - (concat "\\<" org-deadline-string " *<\\([^>]+\\)>") - org-deadline-time-hour-regexp - (concat "\\<" org-deadline-string - " *<\\([^>]+[0-9]\\{1,2\\}:[0-9]\\{2\\}[0-9-+:hdwmy \t.]*\\)>") - org-deadline-line-regexp - (concat "\\<\\(" org-deadline-string "\\).*") - org-scheduled-regexp - (concat "\\<" org-scheduled-string) - org-scheduled-time-regexp - (concat "\\<" org-scheduled-string " *<\\([^>]+\\)>") - org-scheduled-time-hour-regexp - (concat "\\<" org-scheduled-string - " *<\\([^>]+[0-9]\\{1,2\\}:[0-9]\\{2\\}[0-9-+:hdwmy \t.]*\\)>") - org-closed-time-regexp - (concat "\\<" org-closed-string " *\\[\\([^]]+\\)\\]") - org-keyword-time-regexp - (concat "\\<\\(" org-scheduled-string - "\\|" org-deadline-string - "\\|" org-closed-string - "\\|" org-clock-string "\\)" - " *[[<]\\([^]>]+\\)[]>]") - org-keyword-time-not-clock-regexp - (concat "\\<\\(" org-scheduled-string - "\\|" org-deadline-string - "\\|" org-closed-string - "\\)" - " *[[<]\\([^]>]+\\)[]>]") - org-maybe-keyword-time-regexp - (concat "\\(\\<\\(" org-scheduled-string - "\\|" org-deadline-string - "\\|" org-closed-string - "\\|" org-clock-string "\\)\\)?" - " *\\([[<][0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^]\r\n>]*?[]>]\\|<%%([^\r\n>]*>\\)") - org-all-time-keywords - (mapcar (lambda (w) (substring w 0 -1)) - (list org-scheduled-string org-deadline-string - org-clock-string org-closed-string))) - (setq org-ota nil) - (org-compute-latex-and-related-regexp)))) + org-todo-key-trigger (delq nil (mapcar #'cdr org-todo-key-alist)) + org-todo-key-alist (org-assign-fast-keys org-todo-key-alist)) + ;; Compute the regular expressions and other local variables. + ;; Using `org-outline-regexp-bol' would complicate them much, + ;; because of the fixed white space at the end of that string. + (unless org-done-keywords + (setq org-done-keywords + (and org-todo-keywords-1 (last org-todo-keywords-1)))) + (setq org-not-done-keywords + (org-delete-all org-done-keywords + (copy-sequence org-todo-keywords-1)) + org-todo-regexp (regexp-opt org-todo-keywords-1 t) + org-not-done-regexp (regexp-opt org-not-done-keywords t) + org-not-done-heading-regexp + (format org-heading-keyword-regexp-format org-not-done-regexp) + org-todo-line-regexp + (format org-heading-keyword-maybe-regexp-format org-todo-regexp) + org-complex-heading-regexp + (concat "^\\(\\*+\\)" + "\\(?: +" org-todo-regexp "\\)?" + "\\(?: +\\(\\[#.\\]\\)\\)?" + "\\(?: +\\(.*?\\)\\)??" + "\\(?:[ \t]+\\(:[[:alnum:]_@#%:]+:\\)\\)?" + "[ \t]*$") + org-complex-heading-regexp-format + (concat "^\\(\\*+\\)" + "\\(?: +" org-todo-regexp "\\)?" + "\\(?: +\\(\\[#.\\]\\)\\)?" + "\\(?: +" + ;; Stats cookies can be stuck to body. + "\\(?:\\[[0-9%%/]+\\] *\\)*" + "\\(%s\\)" + "\\(?: *\\[[0-9%%/]+\\]\\)*" + "\\)" + "\\(?:[ \t]+\\(:[[:alnum:]_@#%%:]+:\\)\\)?" + "[ \t]*$") + org-todo-line-tags-regexp + (concat "^\\(\\*+\\)" + "\\(?: +" org-todo-regexp "\\)?" + "\\(?: +\\(.*?\\)\\)??" + "\\(?:[ \t]+\\(:[[:alnum:]:_@#%]+:\\)\\)?" + "[ \t]*$")) + (org-compute-latex-and-related-regexp))))) + +(defun org--setup-collect-keywords (regexp &optional files alist) + "Return setup keywords values as an alist. + +REGEXP matches a subset of setup keywords. FILES is a list of +file names already visited. It is used to avoid circular setup +files. ALIST, when non-nil, is the alist computed so far. + +Return value contains the following keys: `archive', `category', +`columns', `constants', `filetags', `link', `priorities', +`property', `scripts', `startup', `tags' and `todo'." + (org-with-wide-buffer + (goto-char (point-min)) + (let ((case-fold-search t)) + (while (re-search-forward regexp nil t) + (let ((element (org-element-at-point))) + (when (eq (org-element-type element) 'keyword) + (let ((key (org-element-property :key element)) + (value (org-element-property :value element))) + (cond + ((equal key "ARCHIVE") + (when (org-string-nw-p value) + (push (cons 'archive value) alist))) + ((equal key "CATEGORY") (push (cons 'category value) alist)) + ((equal key "COLUMNS") (push (cons 'columns value) alist)) + ((equal key "CONSTANTS") + (let* ((constants (assq 'constants alist)) + (store (cdr constants))) + (dolist (pair (org-split-string value)) + (when (string-match "^\\([a-zA-Z0][_a-zA-Z0-9]*\\)=\\(.*\\)" + pair) + (let* ((name (match-string 1 pair)) + (value (match-string 2 pair)) + (old (assoc name store))) + (if old (setcdr old value) + (push (cons name value) store))))) + (if constants (setcdr constants store) + (push (cons 'constants store) alist)))) + ((equal key "FILETAGS") + (when (org-string-nw-p value) + (let ((old (assq 'filetags alist)) + (new (apply #'nconc + (mapcar (lambda (x) (org-split-string x ":")) + (org-split-string value))))) + (if old (setcdr old (append new (cdr old))) + (push (cons 'filetags new) alist))))) + ((equal key "LINK") + (when (string-match "\\`\\(\\S-+\\)[ \t]+\\(.+\\)" value) + (let ((links (assq 'link alist)) + (pair (cons (match-string-no-properties 1 value) + (match-string-no-properties 2 value)))) + (if links (push pair (cdr links)) + (push (list 'link pair) alist))))) + ((equal key "OPTIONS") + (when (and (org-string-nw-p value) + (string-match "\\^:\\(t\\|nil\\|{}\\)" value)) + (push (cons 'scripts (read (match-string 1 value))) alist))) + ((equal key "PRIORITIES") + (push (cons 'priorities + (let ((prio (org-split-string value))) + (if (< (length prio) 3) '(?A ?C ?B) + (mapcar #'string-to-char prio)))) + alist)) + ((equal key "PROPERTY") + (when (string-match "\\(\\S-+\\)[ \t]+\\(.*\\)" value) + (let* ((property (assq 'property alist)) + (value (org--update-property-plist + (match-string-no-properties 1 value) + (match-string-no-properties 2 value) + (cdr property)))) + (if property (setcdr property value) + (push (cons 'property value) alist))))) + ((equal key "STARTUP") + (let ((startup (assq 'startup alist))) + (if startup + (setcdr startup + (append (cdr startup) (org-split-string value))) + (push (cons 'startup (org-split-string value)) alist)))) + ((equal key "TAGS") + (let ((tag-cell (assq 'tags alist))) + (if tag-cell + (setcdr tag-cell (concat (cdr tag-cell) "\n" value)) + (push (cons 'tags value) alist)))) + ((member key '("TODO" "SEQ_TODO" "TYP_TODO")) + (let ((todo (assq 'todo alist)) + (value (cons (if (equal key "TYP_TODO") 'type 'sequence) + (org-split-string value)))) + (if todo (push value (cdr todo)) + (push (list 'todo value) alist)))) + ((equal key "SETUPFILE") + (unless buffer-read-only ; Do not check in Gnus messages. + (let ((f (and (org-string-nw-p value) + (expand-file-name + (org-unbracket-string "\"" "\"" value))))) + (when (and f (file-readable-p f) (not (member f files))) + (with-temp-buffer + (setq default-directory (file-name-directory f)) + (insert-file-contents f) + (setq alist + ;; Fake Org mode to benefit from cache + ;; without recurring needlessly. + (let ((major-mode 'org-mode)) + (org--setup-collect-keywords + regexp (cons f files) alist))))))))))))))) + alist) + +(defun org-tag-string-to-alist (s) + "Return tag alist associated to string S. +S is a value for TAGS keyword or produced with +`org-tag-alist-to-string'. Return value is an alist suitable for +`org-tag-alist' or `org-tag-persistent-alist'." + (let ((lines (mapcar #'split-string (split-string s "\n" t))) + (tag-re (concat "\\`\\([[:alnum:]_@#%]+" + "\\|{.+?}\\)" ; regular expression + "\\(?:(\\(.\\))\\)?\\'")) + alist group-flag) + (dolist (tokens lines (cdr (nreverse alist))) + (push '(:newline) alist) + (while tokens + (let ((token (pop tokens))) + (pcase token + ("{" + (push '(:startgroup) alist) + (when (equal (nth 1 tokens) ":") (setq group-flag t))) + ("}" + (push '(:endgroup) alist) + (setq group-flag nil)) + ("[" + (push '(:startgrouptag) alist) + (when (equal (nth 1 tokens) ":") (setq group-flag t))) + ("]" + (push '(:endgrouptag) alist) + (setq group-flag nil)) + (":" + (push '(:grouptags) alist)) + ((guard (string-match tag-re token)) + (let ((tag (match-string 1 token)) + (key (and (match-beginning 2) + (string-to-char (match-string 2 token))))) + ;; Push all tags in groups, no matter if they already + ;; appear somewhere else in the list. + (when (or group-flag (not (assoc tag alist))) + (push (cons tag key) alist)))))))))) + +(defun org-tag-alist-to-string (alist &optional skip-key) + "Return tag string associated to ALIST. + +ALIST is an alist, as defined in `org-tag-alist' or +`org-tag-persistent-alist', or produced with +`org-tag-string-to-alist'. + +Return value is a string suitable as a value for \"TAGS\" +keyword. + +When optional argument SKIP-KEY is non-nil, skip selection keys +next to tags." + (mapconcat (lambda (token) + (pcase token + (`(:startgroup) "{") + (`(:endgroup) "}") + (`(:startgrouptag) "[") + (`(:endgrouptag) "]") + (`(:grouptags) ":") + (`(:newline) "\\n") + ((and + (guard (not skip-key)) + `(,(and tag (pred stringp)) . ,(and key (pred characterp)))) + (format "%s(%c)" tag key)) + (`(,(and tag (pred stringp)) . ,_) tag) + (_ (user-error "Invalid tag token: %S" token)))) + alist + " ")) + +(defun org-tag-alist-to-groups (alist) + "Return group alist from tag ALIST. +ALIST is an alist, as defined in `org-tag-alist' or +`org-tag-persistent-alist', or produced with +`org-tag-string-to-alist'. Return value is an alist following +the pattern (GROUP-TAG TAGS) where GROUP-TAG is the tag, as +a string, summarizing TAGS, as a list of strings." + (let (groups group-status current-group) + (dolist (token alist (nreverse groups)) + (pcase token + (`(,(or :startgroup :startgrouptag)) (setq group-status t)) + (`(,(or :endgroup :endgrouptag)) + (when (eq group-status 'append) + (push (nreverse current-group) groups)) + (setq group-status nil)) + (`(:grouptags) (setq group-status 'append)) + ((and `(,tag . ,_) (guard group-status)) + (if (eq group-status 'append) (push tag current-group) + (setq current-group (list tag)))) + (_ nil))))) (defun org-file-contents (file &optional noerror) "Return the contents of FILE, as a string." - (if (or (not file) (not (file-readable-p file))) - (if (not noerror) - (error "Cannot read file \"%s\"" file) - (message "Cannot read file \"%s\"" file) - "") - (with-temp-buffer - (insert-file-contents file) - (buffer-string)))) + (if (and file (file-readable-p file)) + (with-temp-buffer + (insert-file-contents file) + (buffer-string)) + (funcall (if noerror 'message 'error) + "Cannot read file \"%s\"%s" + file + (let ((from (buffer-file-name (buffer-base-buffer)))) + (if from (concat " (referenced in file \"" from "\")") ""))))) (defun org-extract-log-state-settings (x) "Extract the log state setting from a TODO keyword string. This will extract info from a string like \"WAIT(w@/!)\"." - (let (kw key log1 log2) - (when (string-match "^\\(.*?\\)\\(?:(\\([^!@/]\\)?\\([!@]\\)?\\(?:/\\([!@]\\)\\)?)\\)?$" x) - (setq kw (match-string 1 x) - key (and (match-end 2) (match-string 2 x)) - log1 (and (match-end 3) (match-string 3 x)) - log2 (and (match-end 4) (match-string 4 x))) + (when (string-match "^\\(.*?\\)\\(?:(\\([^!@/]\\)?\\([!@]\\)?\\(?:/\\([!@]\\)\\)?)\\)?$" x) + (let ((kw (match-string 1 x)) + (log1 (and (match-end 3) (match-string 3 x))) + (log2 (and (match-end 4) (match-string 4 x)))) (and (or log1 log2) (list kw (and log1 (if (equal log1 "!") 'time 'note)) @@ -5216,8 +5469,8 @@ This will extract info from a string like \"WAIT(w@/!)\"." (defun org-assign-fast-keys (alist) "Assign fast keys to a keyword-key alist. Respect keys that are already there." - (let (new (alt ?0)) - (dolist (e alist) + (let (new e (alt ?0)) + (while (setq e (pop alist)) (if (or (memq (car e) '(:newline :grouptags :endgroup :startgroup)) (cdr e)) ;; Key already assigned. (push e new) @@ -5229,7 +5482,7 @@ Respect keys that are already there." (pop clist)) (unless clist (while (rassoc alt used) - (incf alt))) + (cl-incf alt))) (push (cons (car e) (or (car clist) alt)) new)))) (nreverse new))) @@ -5242,13 +5495,7 @@ Respect keys that are already there." (defvar org-finish-function nil "Function to be called when `C-c C-c' is used. This is for getting out of special buffers like capture.") - - -;; FIXME: Occasionally check by commenting these, to make sure -;; no other functions uses these, forgetting to let-bind them. -(org-no-warnings (defvar entry)) ;; unprefixed, from calendar.el (defvar org-last-state) -(org-no-warnings (defvar date)) ;; unprefixed, from calendar.el ;; Defined somewhere in this file, but used before definition. (defvar org-entities) ;; defined in org-entities.el @@ -5256,7 +5503,7 @@ This is for getting out of special buffers like capture.") (defvar org-org-menu) (defvar org-tbl-menu) -;;;; Define the Org-mode +;;;; Define the Org mode ;; We use a before-change function to check if a table might need ;; an update. @@ -5264,7 +5511,7 @@ This is for getting out of special buffers like capture.") "Indicates that a table might need an update. This variable is set by `org-before-change-function'. `org-table-align' sets it back to nil.") -(defun org-before-change-function (beg end) +(defun org-before-change-function (_beg _end) "Every change indicates that a table might need an update." (setq org-table-may-need-update t)) (defvar org-mode-map) @@ -5278,13 +5525,12 @@ This variable is set by `org-before-change-function'. (defvar buffer-face-mode-face) (require 'outline) -(if (and (not (keymapp outline-mode-map)) (featurep 'allout)) - (error "Conflict with outdated version of allout.el. Load org.el before allout.el, or upgrade to newer allout, for example by switching to Emacs 22")) -(require 'noutline "noutline" 'noerror) ;; stock XEmacs does not have it ;; Other stuff we need. (require 'time-date) +(unless (fboundp 'time-subtract) (defalias 'time-subtract 'subtract-time)) (require 'easymenu) +(autoload 'easy-menu-add "easymenu") (require 'overlay) ;; (require 'org-macs) moved higher up in the file before it is first used @@ -5305,15 +5551,15 @@ This variable is set by `org-before-change-function'. "Outline-based notes management and organizer, alias \"Carsten's outline-mode for keeping track of everything.\" -Org-mode develops organizational tasks around a NOTES file which -contains information about projects as plain text. Org-mode is -implemented on top of outline-mode, which is ideal to keep the content +Org mode develops organizational tasks around a NOTES file which +contains information about projects as plain text. Org mode is +implemented on top of Outline mode, which is ideal to keep the content of large files well structured. It supports ToDo items, deadlines and time stamps, which magically appear in the diary listing of the Emacs calendar. Tables are easily created with a built-in table editor. Plain text URL-like links connect to websites, emails (VM), Usenet messages (Gnus), BBDB entries, and any files related to the project. -For printing and sharing of notes, an Org-mode file (or a part of it) +For printing and sharing of notes, an Org file (or a part of it) can be exported as a structured ASCII or HTML file. The following commands are available: @@ -5323,29 +5569,18 @@ The following commands are available: ;; Get rid of Outline menus, they are not needed ;; Need to do this here because define-derived-mode sets up ;; the keymap so late. Still, it is a waste to call this each time - ;; we switch another buffer into org-mode. - (if (featurep 'xemacs) - (when (boundp 'outline-mode-menu-heading) - ;; Assume this is Greg's port, it uses easymenu - (easy-menu-remove outline-mode-menu-heading) - (easy-menu-remove outline-mode-menu-show) - (easy-menu-remove outline-mode-menu-hide)) - (define-key org-mode-map [menu-bar headings] 'undefined) - (define-key org-mode-map [menu-bar hide] 'undefined) - (define-key org-mode-map [menu-bar show] 'undefined)) + ;; we switch another buffer into Org mode. + (define-key org-mode-map [menu-bar headings] 'undefined) + (define-key org-mode-map [menu-bar hide] 'undefined) + (define-key org-mode-map [menu-bar show] 'undefined) (org-load-modules-maybe) - (when (featurep 'xemacs) - (easy-menu-add org-org-menu) - (easy-menu-add org-tbl-menu)) (org-install-agenda-files-menu) - (if org-descriptive-links (add-to-invisibility-spec '(org-link))) + (when org-descriptive-links (add-to-invisibility-spec '(org-link))) (add-to-invisibility-spec '(org-cwidth)) (add-to-invisibility-spec '(org-hide-block . t)) - (when (featurep 'xemacs) - (org-set-local 'line-move-ignore-invisible t)) - (org-set-local 'outline-regexp org-outline-regexp) - (org-set-local 'outline-level 'org-outline-level) + (setq-local outline-regexp org-outline-regexp) + (setq-local outline-level 'org-outline-level) (setq bidi-paragraph-direction 'left-to-right) (when (and org-ellipsis (fboundp 'set-display-table-slot) (boundp 'buffer-display-table) @@ -5354,55 +5589,50 @@ The following commands are available: (setq org-display-table (make-display-table))) (set-display-table-slot org-display-table 4 - (vconcat (mapcar - (lambda (c) (make-glyph-code c (and (not (stringp org-ellipsis)) - org-ellipsis))) - (if (stringp org-ellipsis) org-ellipsis "...")))) + (vconcat (mapcar (lambda (c) (make-glyph-code c 'org-ellipsis)) + (if (stringp org-ellipsis) org-ellipsis "...")))) (setq buffer-display-table org-display-table)) - (org-set-regexps-and-options-for-tags) (org-set-regexps-and-options) (org-set-font-lock-defaults) (when (and org-tag-faces (not org-tags-special-faces-re)) ;; tag faces set outside customize.... force initialization. (org-set-tag-faces 'org-tag-faces org-tag-faces)) ;; Calc embedded - (org-set-local 'calc-embedded-open-mode "# ") + (setq-local calc-embedded-open-mode "# ") ;; Modify a few syntax entries (modify-syntax-entry ?@ "w") (modify-syntax-entry ?\" "\"") (modify-syntax-entry ?\\ "_") (modify-syntax-entry ?~ "_") - (if org-startup-truncated (setq truncate-lines t)) - (when org-startup-indented (require 'org-indent) (org-indent-mode 1)) - (org-set-local 'font-lock-unfontify-region-function - 'org-unfontify-region) + (setq-local font-lock-unfontify-region-function 'org-unfontify-region) ;; Activate before-change-function - (org-set-local 'org-table-may-need-update t) - (org-add-hook 'before-change-functions 'org-before-change-function nil - 'local) + (setq-local org-table-may-need-update t) + (add-hook 'before-change-functions 'org-before-change-function nil 'local) ;; Check for running clock before killing a buffer - (org-add-hook 'kill-buffer-hook 'org-check-running-clock nil 'local) + (add-hook 'kill-buffer-hook 'org-check-running-clock nil 'local) ;; Initialize macros templates. (org-macro-initialize-templates) ;; Initialize radio targets. (org-update-radio-target-regexp) ;; Indentation. - (org-set-local 'indent-line-function 'org-indent-line) - (org-set-local 'indent-region-function 'org-indent-region) + (setq-local indent-line-function 'org-indent-line) + (setq-local indent-region-function 'org-indent-region) ;; Filling and auto-filling. (org-setup-filling) ;; Comments. (org-setup-comments-handling) + ;; Initialize cache. + (org-element-cache-reset) ;; Beginning/end of defun - (org-set-local 'beginning-of-defun-function 'org-backward-element) - (org-set-local 'end-of-defun-function - (lambda () - (if (not (org-at-heading-p)) - (org-forward-element) - (org-forward-element) - (forward-char -1)))) + (setq-local beginning-of-defun-function 'org-backward-element) + (setq-local end-of-defun-function + (lambda () + (if (not (org-at-heading-p)) + (org-forward-element) + (org-forward-element) + (forward-char -1)))) ;; Next error for sparse trees - (org-set-local 'next-error-function 'org-occur-next-match) + (setq-local next-error-function 'org-occur-next-match) ;; Make sure dependence stuff works reliably, even for users who set it ;; too late :-( (if org-enforce-todo-dependencies @@ -5417,78 +5647,65 @@ The following commands are available: 'org-block-todo-from-checkboxes)) ;; Align options lines - (org-set-local - 'align-mode-rules-list + (setq-local + align-mode-rules-list '((org-in-buffer-settings - (regexp . "^#\\+[A-Z_]+:\\(\\s-*\\)\\S-+") + (regexp . "^[ \t]*#\\+[A-Z_]+:\\(\\s-*\\)\\S-+") (modes . '(org-mode))))) ;; Imenu - (org-set-local 'imenu-create-index-function - 'org-imenu-get-tree) + (setq-local imenu-create-index-function 'org-imenu-get-tree) ;; Make isearch reveal context - (if (or (featurep 'xemacs) - (not (boundp 'outline-isearch-open-invisible-function))) - ;; Emacs 21 and XEmacs make use of the hook - (org-add-hook 'isearch-mode-end-hook 'org-isearch-end 'append 'local) - ;; Emacs 22 deals with this through a special variable - (org-set-local 'outline-isearch-open-invisible-function - (lambda (&rest ignore) (org-show-context 'isearch)))) + (setq-local outline-isearch-open-invisible-function + (lambda (&rest _) (org-show-context 'isearch))) ;; Setup the pcomplete hooks - (set (make-local-variable 'pcomplete-command-completion-function) - 'org-pcomplete-initial) - (set (make-local-variable 'pcomplete-command-name-function) - 'org-command-at-point) - (set (make-local-variable 'pcomplete-default-completion-function) - 'ignore) - (set (make-local-variable 'pcomplete-parse-arguments-function) - 'org-parse-arguments) - (set (make-local-variable 'pcomplete-termination-string) "") - (when (>= emacs-major-version 23) - (set (make-local-variable 'buffer-face-mode-face) 'org-default)) - - ;; If empty file that did not turn on org-mode automatically, make it to. - (if (and org-insert-mode-line-in-empty-file - (org-called-interactively-p 'any) - (= (point-min) (point-max))) - (insert "# -*- mode: org -*-\n\n")) + (setq-local pcomplete-command-completion-function 'org-pcomplete-initial) + (setq-local pcomplete-command-name-function 'org-command-at-point) + (setq-local pcomplete-default-completion-function 'ignore) + (setq-local pcomplete-parse-arguments-function 'org-parse-arguments) + (setq-local pcomplete-termination-string "") + (setq-local buffer-face-mode-face 'org-default) + + ;; If empty file that did not turn on Org mode automatically, make + ;; it to. + (when (and org-insert-mode-line-in-empty-file + (called-interactively-p 'any) + (= (point-min) (point-max))) + (insert "# -*- mode: org -*-\n\n")) (unless org-inhibit-startup (org-unmodified - (and org-startup-with-beamer-mode (org-beamer-mode)) + (when org-startup-with-beamer-mode (org-beamer-mode)) (when org-startup-align-all-tables - (org-table-map-tables 'org-table-align 'quietly)) - (when org-startup-with-inline-images - (org-display-inline-images)) - (when org-startup-with-latex-preview - (org-preview-latex-fragment)) - (unless org-inhibit-startup-visibility-stuff - (org-set-startup-visibility)))) - ;; Try to set org-hide correctly + (org-table-map-tables #'org-table-align t)) + (when org-startup-with-inline-images (org-display-inline-images)) + (when org-startup-with-latex-preview (org-toggle-latex-fragment '(16))) + (unless org-inhibit-startup-visibility-stuff (org-set-startup-visibility)) + (when org-startup-truncated (setq truncate-lines t)) + (when org-startup-indented (require 'org-indent) (org-indent-mode 1)) + (org-refresh-effort-properties))) + ;; Try to set `org-hide' face correctly. (let ((foreground (org-find-invisible-foreground))) - (if foreground - (set-face-foreground 'org-hide foreground)))) + (when foreground + (set-face-foreground 'org-hide foreground)))) ;; Update `customize-package-emacs-version-alist' (add-to-list 'customize-package-emacs-version-alist '(Org ("6.21b" . "23.1") ("6.33x" . "23.2") ("7.8.11" . "24.1") ("7.9.4" . "24.3") - ("8.2.6" . "24.4"))) + ("8.2.6" . "24.4") ("8.2.10" . "24.5") + ("9.0" . "26.1"))) (defvar org-mode-transpose-word-syntax-table - (let ((st (make-syntax-table))) - (mapc (lambda(c) (modify-syntax-entry - (string-to-char (car c)) "w p" st)) - org-emphasis-alist) - st)) + (let ((st (make-syntax-table text-mode-syntax-table))) + (dolist (c org-emphasis-alist st) + (modify-syntax-entry (string-to-char (car c)) "w p" st)))) (when (fboundp 'abbrev-table-put) (abbrev-table-put org-mode-abbrev-table :parents (list text-mode-abbrev-table))) -(put 'org-mode 'flyspell-mode-predicate 'org-mode-flyspell-verify) - (defun org-find-invisible-foreground () (let ((candidates (remove "unspecified-bg" @@ -5498,7 +5715,7 @@ The following commands are available: (mapcar (lambda (alist) (when (boundp alist) - (cdr (assoc 'background-color (symbol-value alist))))) + (cdr (assq 'background-color (symbol-value alist))))) '(default-frame-alist initial-frame-alist window-system-default-frame-alist)) (list (face-foreground 'org-hide)))))) (car (remove nil candidates)))) @@ -5541,8 +5758,6 @@ the rounding returns a past time." (require 'font-lock) (defconst org-non-link-chars "]\t\n\r<>") -(defvar org-link-types '("http" "https" "ftp" "mailto" "file" "news" - "shell" "elisp" "doi" "message")) (defvar org-link-types-re nil "Matches a link that has a url-like prefix like \"http:\"") (defvar org-link-re-with-space nil @@ -5591,27 +5806,26 @@ stacked delimiters is N. Escaping delimiters is not possible." next (concat "\\(?:" nothing left next right "\\)+" nothing))) (concat left "\\(" re "\\)" right))) -(defvar org-match-substring-regexp +(defconst org-match-substring-regexp (concat "\\(\\S-\\)\\([_^]\\)\\(" - "\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)" + "\\(?:" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)" "\\|" - "\\(" (org-create-multibrace-regexp "(" ")" org-match-sexp-depth) "\\)" + "\\(?:" (org-create-multibrace-regexp "(" ")" org-match-sexp-depth) "\\)" "\\|" - "\\(\\(?:\\*\\|[-+]?[^-+*!@#$%^_ \t\r\n,:\"?<>~;./{}=()]+\\)\\)\\)") + "\\(?:\\*\\|[+-]?[[:alnum:].,\\]*[[:alnum:]]\\)\\)") "The regular expression matching a sub- or superscript.") -(defvar org-match-substring-with-braces-regexp +(defconst org-match-substring-with-braces-regexp (concat - "\\(\\S-\\)\\([_^]\\)\\(" - "\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)" - "\\)") + "\\(\\S-\\)\\([_^]\\)" + "\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)") "The regular expression matching a sub- or superscript, forcing braces.") (defun org-make-link-regexps () "Update the link regular expressions. -This should be called after the variable `org-link-types' has changed." - (let ((types-re (regexp-opt org-link-types t))) +This should be called after the variable `org-link-parameters' has changed." + (let ((types-re (regexp-opt (org-link-types) t))) (setq org-link-types-re (concat "\\`" types-re ":") org-link-re-with-space @@ -5629,14 +5843,12 @@ This should be called after the variable `org-link-types' has changed." "\\([^" org-non-link-chars " ]" "[^\t\n\r]*\\)") org-angle-link-re - (concat "<" types-re ":" - "\\([^" org-non-link-chars " ]" - "[^" org-non-link-chars "]*" - "\\)>") + (format "<%s:\\([^>\n]*\\(?:\n[ \t]*[^> \t\n][^>\n]*\\)*\\)>" + types-re) org-plain-link-re (concat "\\<" types-re ":" - (org-re "\\([^ \t\n()<>]+\\(?:([[:word:]0-9_]+)\\|\\([^[:punct:] \t\n]\\|/\\)\\)\\)")) + "\\([^][ \t\n()<>]+\\(?:([[:word:]0-9_]+)\\|\\([^[:punct:] \t\n]\\|/\\)\\)\\)") ;; "\\([^]\t\n\r<>() ]+[^]\t\n\r<>,.;() ]\\)") org-bracket-link-regexp "\\[\\[\\([^][]+\\)\\]\\(\\[\\([^][]+\\)\\]\\)?\\]" @@ -5651,77 +5863,46 @@ This should be called after the variable `org-link-types' has changed." org-bracket-link-analytic-regexp++ (concat "\\[\\[" - "\\(" (regexp-opt (cons "coderef" org-link-types) t) ":\\)?" + "\\(" (regexp-opt (cons "coderef" (org-link-types)) t) ":\\)?" "\\([^]]+\\)" "\\]" "\\(\\[" "\\([^]]+\\)" "\\]\\)?" - "\\]") - org-any-link-re - (concat "\\(" org-bracket-link-regexp "\\)\\|\\(" - org-angle-link-re "\\)\\|\\(" - org-plain-link-re "\\)")))) - -(org-make-link-regexps) - -(defconst org-ts-regexp "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^\r\n>]*?\\)>" - "Regular expression for fast time stamp matching.") -(defconst org-ts-regexp-both "[[<]\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^]\r\n>]*?\\)[]>]" - "Regular expression for fast time stamp matching.") -(defconst org-ts-regexp0 - "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\)\\( +[^]+0-9>\r\n -]+\\)?\\( +\\([0-9]\\{1,2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)" - "Regular expression matching time strings for analysis. -This one does not require the space after the date, so it can be used -on a string that terminates immediately after the date.") -(defconst org-ts-regexp1 "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\) *\\([^]+0-9>\r\n -]*\\)\\( \\([0-9]\\{1,2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)" - "Regular expression matching time strings for analysis.") -(defconst org-ts-regexp2 (concat "<" org-ts-regexp1 "[^>\n]\\{0,16\\}>") - "Regular expression matching time stamps, with groups.") -(defconst org-ts-regexp3 (concat "[[<]" org-ts-regexp1 "[^]>\n]\\{0,16\\}[]>]") - "Regular expression matching time stamps (also [..]), with groups.") -(defconst org-tr-regexp (concat org-ts-regexp "--?-?" org-ts-regexp) - "Regular expression matching a time stamp range.") -(defconst org-tr-regexp-both - (concat org-ts-regexp-both "--?-?" org-ts-regexp-both) - "Regular expression matching a time stamp range.") -(defconst org-tsr-regexp (concat org-ts-regexp "\\(--?-?" - org-ts-regexp "\\)?") - "Regular expression matching a time stamp or time stamp range.") -(defconst org-tsr-regexp-both - (concat org-ts-regexp-both "\\(--?-?" - org-ts-regexp-both "\\)?") - "Regular expression matching a time stamp or time stamp range. -The time stamps may be either active or inactive.") + "\\]") + org-any-link-re + (concat "\\(" org-bracket-link-regexp "\\)\\|\\(" + org-angle-link-re "\\)\\|\\(" + org-plain-link-re "\\)")))) + +(org-make-link-regexps) (defvar org-emph-face nil) (defun org-do-emphasis-faces (limit) - "Run through the buffer and add overlays to emphasized strings." + "Run through the buffer and emphasize strings." (let (rtn a) (while (and (not rtn) (re-search-forward org-emph-re limit t)) (let* ((border (char-after (match-beginning 3))) (bre (regexp-quote (char-to-string border)))) - (if (and (not (= border (char-after (match-beginning 4)))) - (not (save-match-data - (string-match (concat bre ".*" bre) - (replace-regexp-in-string - "\n" " " - (substring (match-string 2) 1 -1)))))) - (progn - (setq rtn t) - (setq a (assoc (match-string 3) org-emphasis-alist)) - (font-lock-prepend-text-property (match-beginning 2) (match-end 2) - 'face - (nth 1 a)) - (and (nth 2 a) - (org-remove-flyspell-overlays-in - (match-beginning 0) (match-end 0))) - (add-text-properties (match-beginning 2) (match-end 2) - '(font-lock-multiline t org-emphasis t)) - (when org-hide-emphasis-markers - (add-text-properties (match-end 4) (match-beginning 5) - '(invisible org-link)) - (add-text-properties (match-beginning 3) (match-end 3) - '(invisible org-link)))))) + (when (and (not (= border (char-after (match-beginning 4)))) + (not (string-match-p (concat bre ".*" bre) + (replace-regexp-in-string + "\n" " " + (substring (match-string 2) 1 -1))))) + (setq rtn t) + (setq a (assoc (match-string 3) org-emphasis-alist)) + (font-lock-prepend-text-property (match-beginning 2) (match-end 2) + 'face + (nth 1 a)) + (and (nth 2 a) + (org-remove-flyspell-overlays-in + (match-beginning 0) (match-end 0))) + (add-text-properties (match-beginning 2) (match-end 2) + '(font-lock-multiline t org-emphasis t)) + (when org-hide-emphasis-markers + (add-text-properties (match-end 4) (match-beginning 5) + '(invisible org-link)) + (add-text-properties (match-beginning 3) (match-end 3) + '(invisible org-link))))) (goto-char (1+ (match-beginning 0)))) rtn)) @@ -5736,19 +5917,20 @@ If CHAR is not given (for example in an interactive call) it will be prompted for." (interactive) (let ((erc org-emphasis-regexp-components) - (prompt "") - (string "") beg end move c s) + (string "") beg end move s) (if (org-region-active-p) - (setq beg (region-beginning) end (region-end) + (setq beg (region-beginning) + end (region-end) string (buffer-substring beg end)) (setq move t)) (unless char (message "Emphasis marker or tag: [%s]" - (mapconcat (lambda(e) (car e)) org-emphasis-alist "")) + (mapconcat #'car org-emphasis-alist "")) (setq char (read-char-exclusive))) - (if (equal char ?\ ) - (setq s "" move nil) + (if (equal char ?\s) + (setq s "" + move nil) (unless (assoc (char-to-string char) org-emphasis-alist) (user-error "No such emphasis marker: \"%c\"" char)) (setq s (char-to-string char))) @@ -5757,7 +5939,7 @@ prompted for." (assoc (substring string 0 1) org-emphasis-alist)) (setq string (substring string 1 -1))) (setq string (concat s string s)) - (if beg (delete-region beg end)) + (when beg (delete-region beg end)) (unless (or (bolp) (string-match (concat "[" (nth 0 erc) "\n]") (char-to-string (char-before (point))))) @@ -5775,37 +5957,86 @@ prompted for." (defsubst org-rear-nonsticky-at (pos) (add-text-properties (1- pos) pos (list 'rear-nonsticky org-nonsticky-props))) -(defun org-activate-plain-links (limit) - "Run through the buffer and add overlays to links." - (let (f hl) - (when (and (re-search-forward (concat org-plain-link-re) limit t) - (not (org-in-src-block-p))) - (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0)) - (setq f (get-text-property (match-beginning 0) 'face)) - (setq hl (org-match-string-no-properties 0)) - (if (or (eq f 'org-tag) - (and (listp f) (memq 'org-tag f))) - nil - (add-text-properties (match-beginning 0) (match-end 0) - (list 'mouse-face 'highlight - 'face 'org-link - 'htmlize-link `(:uri ,hl) - 'keymap org-mouse-map)) - (org-rear-nonsticky-at (match-end 0))) - t))) +(defun org-activate-links (limit) + "Add link properties to links. +This includes angle, plain, and bracket links." + (catch :exit + (while (re-search-forward org-any-link-re limit t) + (let* ((start (match-beginning 0)) + (end (match-end 0)) + (style (cond ((eq ?< (char-after start)) 'angle) + ((eq ?\[ (char-after (1+ start))) 'bracket) + (t 'plain)))) + (when (and (memq style org-highlight-links) + ;; Do not confuse plain links with tags. + (not (and (eq style 'plain) + (let ((face (get-text-property + (max (1- start) (point-min)) 'face))) + (if (consp face) (memq 'org-tag face) + (eq 'org-tag face)))))) + (let* ((link-object (save-excursion + (goto-char start) + (save-match-data (org-element-link-parser)))) + (link (org-element-property :raw-link link-object)) + (type (org-element-property :type link-object)) + (path (org-element-property :path link-object)) + (properties ;for link's visible part + (list + 'face (pcase (org-link-get-parameter type :face) + ((and (pred functionp) face) (funcall face path)) + ((and (pred facep) face) face) + ((and (pred consp) face) face) ;anonymous + (_ 'org-link)) + 'mouse-face (or (org-link-get-parameter type :mouse-face) + 'highlight) + 'keymap (or (org-link-get-parameter type :keymap) + org-mouse-map) + 'help-echo (pcase (org-link-get-parameter type :help-echo) + ((and (pred stringp) echo) echo) + ((and (pred functionp) echo) echo) + (_ (concat "LINK: " link))) + 'htmlize-link (pcase (org-link-get-parameter type + :htmlize-link) + ((and (pred functionp) f) (funcall f)) + (_ `(:uri ,link))) + 'font-lock-multiline t))) + (org-remove-flyspell-overlays-in start end) + (org-rear-nonsticky-at end) + (if (not (eq 'bracket style)) + (add-text-properties start end properties) + ;; Handle invisible parts in bracket links. + (remove-text-properties start end '(invisible nil)) + (let ((hidden + (append `(invisible + ,(or (org-link-get-parameter type :display) + 'org-link)) + properties)) + (visible-start (or (match-beginning 4) (match-beginning 2))) + (visible-end (or (match-end 4) (match-end 2)))) + (add-text-properties start visible-start hidden) + (add-text-properties visible-start visible-end properties) + (add-text-properties visible-end end hidden) + (org-rear-nonsticky-at visible-start) + (org-rear-nonsticky-at visible-end))) + (let ((f (org-link-get-parameter type :activate-func))) + (when (functionp f) + (funcall f start end path (eq style 'bracket)))) + (throw :exit t))))) ;signal success + nil)) (defun org-activate-code (limit) - (if (re-search-forward "^[ \t]*\\(:\\(?: .*\\|$\\)\n?\\)" limit t) - (progn - (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0)) - (remove-text-properties (match-beginning 0) (match-end 0) - '(display t invisible t intangible t)) - t))) + (when (re-search-forward "^[ \t]*\\(:\\(?: .*\\|$\\)\n?\\)" limit t) + (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0)) + (remove-text-properties (match-beginning 0) (match-end 0) + '(display t invisible t intangible t)) + t)) -(defcustom org-src-fontify-natively nil - "When non-nil, fontify code in code blocks." +(defcustom org-src-fontify-natively t + "When non-nil, fontify code in code blocks. +See also the `org-block' face." :type 'boolean - :version "24.1" + :version "24.4" + :package-version '(Org . "8.3") :group 'org-appearance :group 'org-babel) @@ -5820,221 +6051,248 @@ by a #." (defun org-fontify-meta-lines-and-blocks (limit) (condition-case nil (org-fontify-meta-lines-and-blocks-1 limit) - (error (message "org-mode fontification error")))) + (error (message "org-mode fontification error in %S at %d" + (current-buffer) + (line-number-at-pos))))) (defun org-fontify-meta-lines-and-blocks-1 (limit) "Fontify #+ lines and blocks." (let ((case-fold-search t)) - (if (re-search-forward - "^\\([ \t]*#\\(\\(\\+[a-zA-Z]+:?\\| \\|$\\)\\(_\\([a-zA-Z]+\\)\\)?\\)[ \t]*\\(\\([^ \t\n]*\\)[ \t]*\\(.*\\)\\)\\)" - limit t) - (let ((beg (match-beginning 0)) - (block-start (match-end 0)) - (block-end nil) - (lang (match-string 7)) - (beg1 (line-beginning-position 2)) - (dc1 (downcase (match-string 2))) - (dc3 (downcase (match-string 3))) - end end1 quoting block-type ovl) - (cond - ((member dc1 '("+html:" "+ascii:" "+latex:")) - ;; a single line of backend-specific content - (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0)) - (remove-text-properties (match-beginning 0) (match-end 0) - '(display t invisible t intangible t)) - (add-text-properties (match-beginning 1) (match-end 3) - '(font-lock-fontified t face org-meta-line)) - (add-text-properties (match-beginning 6) (+ (match-end 6) 1) - '(font-lock-fontified t face org-block)) - ; for backend-specific code - t) - ((and (match-end 4) (equal dc3 "+begin")) - ;; Truly a block - (setq block-type (downcase (match-string 5)) - quoting (member block-type org-protecting-blocks)) - (when (re-search-forward - (concat "^[ \t]*#\\+end" (match-string 4) "\\>.*") - nil t) ;; on purpose, we look further than LIMIT - (setq end (min (point-max) (match-end 0)) - end1 (min (point-max) (1- (match-beginning 0)))) - (setq block-end (match-beginning 0)) - (when quoting - (remove-text-properties beg end - '(display t invisible t intangible t))) - (add-text-properties - beg end - '(font-lock-fontified t font-lock-multiline t)) - (add-text-properties beg beg1 '(face org-meta-line)) - (add-text-properties end1 (min (point-max) (1+ end)) - '(face org-meta-line)) ; for end_src - (cond - ((and lang (not (string= lang "")) org-src-fontify-natively) - (org-src-font-lock-fontify-block lang block-start block-end) - ;; remove old background overlays - (mapc (lambda (ov) - (if (eq (overlay-get ov 'face) 'org-block-background) - (delete-overlay ov))) - (overlays-at (/ (+ beg1 block-end) 2))) - ;; add a background overlay - (setq ovl (make-overlay beg1 block-end)) - (overlay-put ovl 'face 'org-block-background) - (overlay-put ovl 'evaporate t)) ;; make it go away when empty - (quoting - (add-text-properties beg1 (min (point-max) (1+ end1)) - '(face org-block))) ; end of source block - ((not org-fontify-quote-and-verse-blocks)) - ((string= block-type "quote") - (add-text-properties beg1 (min (point-max) (1+ end1)) '(face org-quote))) - ((string= block-type "verse") - (add-text-properties beg1 (min (point-max) (1+ end1)) '(face org-verse)))) - (add-text-properties beg beg1 '(face org-block-begin-line)) - (add-text-properties (min (point-max) (1+ end)) (min (point-max) (1+ end1)) - '(face org-block-end-line)) - t)) - ((member dc1 '("+title:" "+author:" "+email:" "+date:")) - (add-text-properties - beg (match-end 3) - (if (member (intern (substring dc1 1 -1)) org-hidden-keywords) - '(font-lock-fontified t invisible t) - '(font-lock-fontified t face org-document-info-keyword))) - (add-text-properties - (match-beginning 6) (min (point-max) (1+ (match-end 6))) - (if (string-equal dc1 "+title:") - '(font-lock-fontified t face org-document-title) - '(font-lock-fontified t face org-document-info)))) - ((or (equal dc1 "+results") - (member dc1 '("+begin:" "+end:" "+caption:" "+label:" - "+orgtbl:" "+tblfm:" "+tblname:" "+results:" - "+call:" "+header:" "+headers:" "+name:")) - (and (match-end 4) (equal dc3 "+attr"))) - (add-text-properties - beg (match-end 0) - '(font-lock-fontified t face org-meta-line)) - t) - ((member dc3 '(" " "")) - (add-text-properties - beg (match-end 0) - '(font-lock-fontified t face font-lock-comment-face))) - ((not (member (char-after beg) '(?\ ?\t))) - ;; just any other in-buffer setting, but not indented + (when (re-search-forward + "^\\([ \t]*#\\(\\(\\+[a-zA-Z]+:?\\| \\|$\\)\\(_\\([a-zA-Z]+\\)\\)?\\)[ \t]*\\(\\([^ \t\n]*\\)[ \t]*\\(.*\\)\\)\\)" + limit t) + (let ((beg (match-beginning 0)) + (block-start (match-end 0)) + (block-end nil) + (lang (match-string 7)) + (beg1 (line-beginning-position 2)) + (dc1 (downcase (match-string 2))) + (dc3 (downcase (match-string 3))) + end end1 quoting block-type) + (cond + ((and (match-end 4) (equal dc3 "+begin")) + ;; Truly a block + (setq block-type (downcase (match-string 5)) + quoting (member block-type org-protecting-blocks)) + (when (re-search-forward + (concat "^[ \t]*#\\+end" (match-string 4) "\\>.*") + nil t) ;; on purpose, we look further than LIMIT + (setq end (min (point-max) (match-end 0)) + end1 (min (point-max) (1- (match-beginning 0)))) + (setq block-end (match-beginning 0)) + (when quoting + (org-remove-flyspell-overlays-in beg1 end1) + (remove-text-properties beg end + '(display t invisible t intangible t))) (add-text-properties - beg (match-end 0) - '(font-lock-fontified t face org-meta-line)) - t) - (t nil)))))) - -(defun org-activate-angle-links (limit) - "Run through the buffer and add overlays to links." - (if (and (re-search-forward org-angle-link-re limit t) - (not (org-in-src-block-p))) - (progn - (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0)) - (add-text-properties (match-beginning 0) (match-end 0) - (list 'mouse-face 'highlight - 'keymap org-mouse-map)) - (org-rear-nonsticky-at (match-end 0)) - t))) + beg end '(font-lock-fontified t font-lock-multiline t)) + (add-text-properties beg beg1 '(face org-meta-line)) + (org-remove-flyspell-overlays-in beg beg1) + (add-text-properties ; For end_src + end1 (min (point-max) (1+ end)) '(face org-meta-line)) + (org-remove-flyspell-overlays-in end1 end) + (cond + ((and lang (not (string= lang "")) org-src-fontify-natively) + (org-src-font-lock-fontify-block lang block-start block-end) + (add-text-properties beg1 block-end '(src-block t))) + (quoting + (add-text-properties beg1 (min (point-max) (1+ end1)) + (list 'face + (list :inherit + (let ((face-name + (intern (format "org-block-%s" lang)))) + (append (and (facep face-name) (list face-name)) + '(org-block))))))) ; end of source block + ((not org-fontify-quote-and-verse-blocks)) + ((string= block-type "quote") + (add-face-text-property + beg1 (min (point-max) (1+ end1)) 'org-quote t)) + ((string= block-type "verse") + (add-face-text-property + beg1 (min (point-max) (1+ end1)) 'org-verse t))) + (add-text-properties beg beg1 '(face org-block-begin-line)) + (add-text-properties (min (point-max) (1+ end)) (min (point-max) (1+ end1)) + '(face org-block-end-line)) + t)) + ((member dc1 '("+title:" "+author:" "+email:" "+date:")) + (org-remove-flyspell-overlays-in + (match-beginning 0) + (if (equal "+title:" dc1) (match-end 2) (match-end 0))) + (add-text-properties + beg (match-end 3) + (if (member (intern (substring dc1 1 -1)) org-hidden-keywords) + '(font-lock-fontified t invisible t) + '(font-lock-fontified t face org-document-info-keyword))) + (add-text-properties + (match-beginning 6) (min (point-max) (1+ (match-end 6))) + (if (string-equal dc1 "+title:") + '(font-lock-fontified t face org-document-title) + '(font-lock-fontified t face org-document-info)))) + ((string-prefix-p "+caption" dc1) + (org-remove-flyspell-overlays-in (match-end 2) (match-end 0)) + (remove-text-properties (match-beginning 0) (match-end 0) + '(display t invisible t intangible t)) + ;; Handle short captions. + (save-excursion + (beginning-of-line) + (looking-at "\\([ \t]*#\\+caption\\(?:\\[.*\\]\\)?:\\)[ \t]*")) + (add-text-properties (line-beginning-position) (match-end 1) + '(font-lock-fontified t face org-meta-line)) + (add-text-properties (match-end 0) (line-end-position) + '(font-lock-fontified t face org-block)) + t) + ((member dc3 '(" " "")) + (org-remove-flyspell-overlays-in beg (match-end 0)) + (add-text-properties + beg (match-end 0) + '(font-lock-fontified t face font-lock-comment-face))) + (t ;; just any other in-buffer setting, but not indented + (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0)) + (remove-text-properties (match-beginning 0) (match-end 0) + '(display t invisible t intangible t)) + (add-text-properties beg (match-end 0) + '(font-lock-fontified t face org-meta-line)) + t)))))) + +(defun org-fontify-drawers (limit) + "Fontify drawers." + (when (re-search-forward org-drawer-regexp limit t) + (add-text-properties + (match-beginning 0) (match-end 0) + '(font-lock-fontified t face org-special-keyword)) + (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0)) + t)) + +(defun org-fontify-macros (limit) + "Fontify macros." + (when (re-search-forward "\\({{{\\).+?\\(}}}\\)" limit t) + (add-text-properties + (match-beginning 0) (match-end 0) + '(font-lock-fontified t face org-macro)) + (when org-hide-macro-markers + (add-text-properties (match-end 2) (match-beginning 2) + '(invisible t)) + (add-text-properties (match-beginning 1) (match-end 1) + '(invisible t))) + (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0)) + t)) (defun org-activate-footnote-links (limit) - "Run through the buffer and add overlays to footnotes." + "Add text properties for footnotes." (let ((fn (org-footnote-next-reference-or-definition limit))) (when fn - (let ((beg (nth 1 fn)) (end (nth 2 fn))) - (org-remove-flyspell-overlays-in beg end) + (let* ((beg (nth 1 fn)) + (end (nth 2 fn)) + (label (car fn)) + (referencep (/= (line-beginning-position) beg))) + (when (and referencep (nth 3 fn)) + (save-excursion + (goto-char beg) + (search-forward (or label "fn:")) + (org-remove-flyspell-overlays-in beg (match-end 0)))) (add-text-properties beg end (list 'mouse-face 'highlight 'keymap org-mouse-map 'help-echo - (if (= (point-at-bol) beg) - "Footnote definition" - "Footnote reference") + (if referencep "Footnote reference" + "Footnote definition") 'font-lock-fontified t 'font-lock-multiline t 'face 'org-footnote)))))) -(defun org-activate-bracket-links (limit) - "Run through the buffer and add overlays to bracketed links." - (if (and (re-search-forward org-bracket-link-regexp limit t) - (not (org-in-src-block-p))) - (let* ((hl (org-match-string-no-properties 1)) - (help (concat "LINK: " (save-match-data (org-link-unescape hl)))) - (ip (org-maybe-intangible - (list 'invisible 'org-link - 'keymap org-mouse-map 'mouse-face 'highlight - 'font-lock-multiline t 'help-echo help - 'htmlize-link `(:uri ,hl)))) - (vp (list 'keymap org-mouse-map 'mouse-face 'highlight - 'font-lock-multiline t 'help-echo help - 'htmlize-link `(:uri ,hl)))) - ;; We need to remove the invisible property here. Table narrowing - ;; may have made some of this invisible. - (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0)) - (remove-text-properties (match-beginning 0) (match-end 0) - '(invisible nil)) - (if (match-end 3) - (progn - (add-text-properties (match-beginning 0) (match-beginning 3) ip) - (org-rear-nonsticky-at (match-beginning 3)) - (add-text-properties (match-beginning 3) (match-end 3) vp) - (org-rear-nonsticky-at (match-end 3)) - (add-text-properties (match-end 3) (match-end 0) ip) - (org-rear-nonsticky-at (match-end 0))) - (add-text-properties (match-beginning 0) (match-beginning 1) ip) - (org-rear-nonsticky-at (match-beginning 1)) - (add-text-properties (match-beginning 1) (match-end 1) vp) - (org-rear-nonsticky-at (match-end 1)) - (add-text-properties (match-end 1) (match-end 0) ip) - (org-rear-nonsticky-at (match-end 0))) - t))) - (defun org-activate-dates (limit) - "Run through the buffer and add overlays to dates." - (if (and (re-search-forward org-tsr-regexp-both limit t) - (not (equal (char-before (match-beginning 0)) 91))) - (progn - (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0)) - (add-text-properties (match-beginning 0) (match-end 0) - (list 'mouse-face 'highlight - 'keymap org-mouse-map)) - (org-rear-nonsticky-at (match-end 0)) - (when org-display-custom-times - (if (match-end 3) - (org-display-custom-time (match-beginning 3) (match-end 3))) - (org-display-custom-time (match-beginning 1) (match-end 1))) - t))) - -(defvar org-target-link-regexp nil + "Add text properties for dates." + (when (and (re-search-forward org-tsr-regexp-both limit t) + (not (equal (char-before (match-beginning 0)) 91))) + (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0)) + (add-text-properties (match-beginning 0) (match-end 0) + (list 'mouse-face 'highlight + 'keymap org-mouse-map)) + (org-rear-nonsticky-at (match-end 0)) + (when org-display-custom-times + (if (match-end 3) + (org-display-custom-time (match-beginning 3) (match-end 3)) + (org-display-custom-time (match-beginning 1) (match-end 1)))) + t)) + +(defvar-local org-target-link-regexp nil "Regular expression matching radio targets in plain text.") -(make-variable-buffer-local 'org-target-link-regexp) -(defvar org-target-regexp "<<\\([^<>\n\r]+\\)>>" + +(defconst org-target-regexp (let ((border "[^<>\n\r \t]")) + (format "<<\\(%s\\|%s[^<>\n\r]*%s\\)>>" + border border border)) "Regular expression matching a link target.") -(defvar org-radio-target-regexp "<<<\\([^<>\n\r]+\\)>>>" + +(defconst org-radio-target-regexp (format "<%s>" org-target-regexp) "Regular expression matching a radio target.") -(defvar org-any-target-regexp "<<\n\r]+\\)>>>?" ; FIXME, not exact, would match <<> as a radio target. + +(defconst org-any-target-regexp + (format "%s\\|%s" org-radio-target-regexp org-target-regexp) "Regular expression matching any target.") (defun org-activate-target-links (limit) - "Run through the buffer and add overlays to target matches." + "Add text properties for target matches." (when org-target-link-regexp (let ((case-fold-search t)) - (if (re-search-forward org-target-link-regexp limit t) - (progn - (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0)) - (add-text-properties (match-beginning 0) (match-end 0) - (list 'mouse-face 'highlight - 'keymap org-mouse-map - 'help-echo "Radio target link" - 'org-linked-text t)) - (org-rear-nonsticky-at (match-end 0)) - t))))) + (when (re-search-forward org-target-link-regexp limit t) + (org-remove-flyspell-overlays-in (match-beginning 1) (match-end 1)) + (add-text-properties (match-beginning 1) (match-end 1) + (list 'mouse-face 'highlight + 'keymap org-mouse-map + 'help-echo "Radio target link" + 'org-linked-text t)) + (org-rear-nonsticky-at (match-end 1)) + t)))) (defun org-update-radio-target-regexp () - "Find all radio targets in this file and update the regular expression." + "Find all radio targets in this file and update the regular expression. +Also refresh fontification if needed." (interactive) - (when (memq 'radio org-activate-links) + (let ((old-regexp org-target-link-regexp) + (before-re "\\(?:^\\|[^[:alnum:]]\\)\\(") + (after-re "\\)\\(?:$\\|[^[:alnum:]]\\)") + (targets + (org-with-wide-buffer + (goto-char (point-min)) + (let (rtn) + (while (re-search-forward org-radio-target-regexp nil t) + ;; Make sure point is really within the object. + (backward-char) + (let ((obj (org-element-context))) + (when (eq (org-element-type obj) 'radio-target) + (cl-pushnew (org-element-property :value obj) rtn + :test #'equal)))) + rtn)))) (setq org-target-link-regexp - (org-make-target-link-regexp (org-all-targets 'radio))) - (org-restart-font-lock))) + (and targets + (concat before-re + (mapconcat + (lambda (x) + (replace-regexp-in-string + " +" "\\s-+" (regexp-quote x) t t)) + targets + "\\|") + after-re))) + (unless (equal old-regexp org-target-link-regexp) + ;; Clean-up cache. + (let ((regexp (cond ((not old-regexp) org-target-link-regexp) + ((not org-target-link-regexp) old-regexp) + (t + (concat before-re + (mapconcat + (lambda (re) + (substring re (length before-re) + (- (length after-re)))) + (list old-regexp org-target-link-regexp) + "\\|") + after-re))))) + (org-with-wide-buffer + (goto-char (point-min)) + (while (re-search-forward regexp nil t) + (org-element-cache-refresh (match-beginning 1))))) + ;; Re fontify buffer. + (when (memq 'radio org-highlight-links) + (org-restart-font-lock))))) (defun org-hide-wide-columns (limit) (let (s e) @@ -6042,20 +6300,18 @@ by a #." 'org-cwidth t)) (when s (setq e (next-single-property-change s 'org-cwidth)) - (add-text-properties s e (org-maybe-intangible '(invisible org-cwidth))) + (add-text-properties s e '(invisible org-cwidth)) (goto-char e) t))) (defvar org-latex-and-related-regexp nil "Regular expression for highlighting LaTeX, entities and sub/superscript.") -(defvar org-match-substring-regexp) -(defvar org-match-substring-with-braces-regexp) (defun org-compute-latex-and-related-regexp () "Compute regular expression for LaTeX, entities and sub/superscript. Result depends on variable `org-highlight-latex-and-related'." - (org-set-local - 'org-latex-and-related-regexp + (setq-local + org-latex-and-related-regexp (let* ((re-sub (cond ((not (memq 'script org-highlight-latex-and-related)) nil) ((eq org-use-sub-superscripts '{}) @@ -6081,9 +6337,13 @@ done, nil otherwise." (when (org-string-nw-p org-latex-and-related-regexp) (catch 'found (while (re-search-forward org-latex-and-related-regexp limit t) - (unless (memq (car-safe (get-text-property (1+ (match-beginning 0)) - 'face)) - '(org-code org-verbatim underline)) + (unless + (cl-some + (lambda (f) + (memq f '(org-code org-verbatim underline org-special-keyword))) + (save-excursion + (goto-char (1+ (match-beginning 0))) + (face-at-point nil t))) (let ((offset (if (memq (char-after (1+ (match-beginning 0))) '(?_ ?^)) 1 @@ -6102,63 +6362,32 @@ done, nil otherwise." (font-lock-mode -1) (font-lock-mode 1))) -(defun org-all-targets (&optional radio) - "Return a list of all targets in this file. -When optional argument RADIO is non-nil, only find radio -targets." - (let ((re (if radio org-radio-target-regexp org-target-regexp)) rtn) - (save-excursion - (goto-char (point-min)) - (while (re-search-forward re nil t) - ;; Make sure point is really within the object. - (backward-char) - (let ((obj (org-element-context))) - (when (memq (org-element-type obj) '(radio-target target)) - (add-to-list 'rtn (downcase (org-element-property :value obj)))))) - rtn))) - -(defun org-make-target-link-regexp (targets) - "Make regular expression matching all strings in TARGETS. -The regular expression finds the targets also if there is a line break -between words." - (and targets - (concat - "\\_<\\(" - (mapconcat - (lambda (x) - (setq x (regexp-quote x)) - (while (string-match " +" x) - (setq x (replace-match "\\s-+" t t x))) - x) - targets - "\\|") - "\\)\\_>"))) - (defun org-activate-tags (limit) - (if (re-search-forward (org-re "^\\*+.*[ \t]\\(:[[:alnum:]_@#%:]+:\\)[ \r\n]") limit t) - (progn - (org-remove-flyspell-overlays-in (match-beginning 1) (match-end 1)) - (add-text-properties (match-beginning 1) (match-end 1) - (list 'mouse-face 'highlight - 'keymap org-mouse-map)) - (org-rear-nonsticky-at (match-end 1)) - t))) + (when (re-search-forward + "^\\*+.*[ \t]\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$" limit t) + (org-remove-flyspell-overlays-in (match-beginning 1) (match-end 1)) + (add-text-properties (match-beginning 1) (match-end 1) + (list 'mouse-face 'highlight + 'keymap org-mouse-map)) + (org-rear-nonsticky-at (match-end 1)) + t)) (defun org-outline-level () "Compute the outline level of the heading at point. -If this is called at a normal headline, the level is the number of stars. -Use `org-reduced-level' to remove the effect of `org-odd-levels'." - (save-excursion - (if (not (condition-case nil - (org-back-to-heading t) - (error nil))) - 0 - (looking-at org-outline-regexp) - (1- (- (match-end 0) (match-beginning 0)))))) + +If this is called at a normal headline, the level is the number +of stars. Use `org-reduced-level' to remove the effect of +`org-odd-levels'. Unlike to `org-current-level', this function +takes into consideration inlinetasks." + (org-with-wide-buffer + (end-of-line) + (if (re-search-backward org-outline-regexp-bol nil t) + (1- (- (match-end 0) (match-beginning 0))) + 0))) (defvar org-font-lock-keywords nil) -(defsubst org-re-property (property &optional literal allow-null) +(defsubst org-re-property (property &optional literal allow-null value) "Return a regexp matching a PROPERTY line. When optional argument LITERAL is non-nil, do not quote PROPERTY. @@ -6166,17 +6395,25 @@ This is useful when PROPERTY is a regexp. When ALLOW-NULL is non-nil, match properties even without a value. Match group 3 is set to the value when it exists. If there is no -value and ALLOW-NULL is non-nil, it is set to the empty string." +value and ALLOW-NULL is non-nil, it is set to the empty string. + +With optional argument VALUE, match only property lines with +that value; in this case, ALLOW-NULL is ignored. VALUE is quoted +unless LITERAL is non-nil." (concat "^\\(?4:[ \t]*\\)" (format "\\(?1::\\(?2:%s\\):\\)" (if literal property (regexp-quote property))) - (if allow-null - "\\(?:\\(?3:$\\)\\|[ \t]+\\(?3:.*?\\)\\)\\(?5:[ \t]*\\)$" - "[ \t]+\\(?3:[^ \r\t\n]+.*?\\)\\(?5:[ \t]*\\)$"))) + (cond (value + (format "[ \t]+\\(?3:%s\\)\\(?5:[ \t]*\\)$" + (if literal value (regexp-quote value)))) + (allow-null + "\\(?:\\(?3:$\\)\\|[ \t]+\\(?3:.*?\\)\\)\\(?5:[ \t]*\\)$") + (t + "[ \t]+\\(?3:[^ \r\t\n]+.*?\\)\\(?5:[ \t]*\\)$")))) (defconst org-property-re - (org-re-property ".*?" 'literal t) + (org-re-property "\\S-+" 'literal t) "Regular expression matching a property line. There are four matching groups: 1: :PROPKEY: including the leading and trailing colon, @@ -6188,6 +6425,8 @@ There are four matching groups: (defvar org-font-lock-hook nil "Functions to be called for special font lock stuff.") +(defvar org-font-lock-extra-keywords nil) ;Dynamically scoped. + (defvar org-font-lock-set-keywords-hook nil "Functions that can manipulate `org-font-lock-extra-keywords'. This is called after `org-font-lock-extra-keywords' is defined, but before @@ -6201,7 +6440,7 @@ needs to be inserted at a specific position in the font-lock sequence.") (defun org-set-font-lock-defaults () "Set font lock defaults for the current buffer." (let* ((em org-fontify-emphasized-text) - (lk org-activate-links) + (lk org-highlight-links) (org-font-lock-extra-keywords (list ;; Call the hook @@ -6222,26 +6461,23 @@ needs to be inserted at a specific position in the font-lock sequence.") '("^[ \t]*|\\( *\\([$!_^/]\\) *|.*\\)|" (1 'org-formula t)) '("| *\\(<[lrc]?[0-9]*>\\)" (1 'org-formula t)) ;; Drawers - (list org-drawer-regexp '(0 'org-special-keyword t)) - (list "^[ \t]*:END:" '(0 'org-special-keyword t)) + '(org-fontify-drawers) ;; Properties (list org-property-re '(1 'org-special-keyword t) '(3 'org-property-value t)) - ;; Links - (if (memq 'tag lk) '(org-activate-tags (1 'org-tag prepend))) - (if (memq 'angle lk) '(org-activate-angle-links (0 'org-link t))) - (if (memq 'plain lk) '(org-activate-plain-links (0 'org-link t))) - (if (memq 'bracket lk) '(org-activate-bracket-links (0 'org-link t))) - (if (memq 'radio lk) '(org-activate-target-links (0 'org-link t))) - (if (memq 'date lk) '(org-activate-dates (0 'org-date t))) - (if (memq 'footnote lk) '(org-activate-footnote-links)) + ;; Link related fontification. + '(org-activate-links) + (when (memq 'tag lk) '(org-activate-tags (1 'org-tag prepend))) + (when (memq 'radio lk) '(org-activate-target-links (1 'org-link t))) + (when (memq 'date lk) '(org-activate-dates (0 'org-date t))) + (when (memq 'footnote lk) '(org-activate-footnote-links)) ;; Targets. (list org-any-target-regexp '(0 'org-target t)) ;; Diary sexps. '("^&?%%(.*\\|<%%([^>\n]*?>" (0 'org-sexp-date t)) ;; Macro - '("{{{.+}}}" (0 'org-macro t)) + '(org-fontify-macros) '(org-hide-wide-columns (0 nil append)) ;; TODO keyword (list (format org-heading-keyword-regexp-format @@ -6261,27 +6497,24 @@ needs to be inserted at a specific position in the font-lock sequence.") ;; Tags '(org-font-lock-add-tag-faces) ;; Tags groups - (if (and org-group-tags org-tag-groups-alist) - (list (concat org-outline-regexp-bol ".+\\(:" - (regexp-opt (mapcar 'car org-tag-groups-alist)) - ":\\).*$") - '(1 'org-tag-group prepend))) + (when (and org-group-tags org-tag-groups-alist) + (list (concat org-outline-regexp-bol ".+\\(:" + (regexp-opt (mapcar 'car org-tag-groups-alist)) + ":\\).*$") + '(1 'org-tag-group prepend))) ;; Special keywords (list (concat "\\<" org-deadline-string) '(0 'org-special-keyword t)) (list (concat "\\<" org-scheduled-string) '(0 'org-special-keyword t)) (list (concat "\\<" org-closed-string) '(0 'org-special-keyword t)) (list (concat "\\<" org-clock-string) '(0 'org-special-keyword t)) ;; Emphasis - (if em - (if (featurep 'xemacs) - '(org-do-emphasis-faces (0 nil append)) - '(org-do-emphasis-faces))) + (when em '(org-do-emphasis-faces)) ;; Checkboxes '("^[ \t]*\\(?:[-+*]\\|[0-9]+[.)]\\)[ \t]+\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\(\\[[- X]\\]\\)" 1 'org-checkbox prepend) - (if (cdr (assq 'checkbox org-list-automatic-rules)) - '("\\[\\([0-9]*%\\)\\]\\|\\[\\([0-9]*\\)/\\([0-9]*\\)\\]" - (0 (org-get-checkbox-statistics-face) t))) + (when (cdr (assq 'checkbox org-list-automatic-rules)) + '("\\[\\([0-9]*%\\)\\]\\|\\[\\([0-9]*\\)/\\([0-9]*\\)\\]" + (0 (org-get-checkbox-statistics-face) t))) ;; Description list items '("^[ \t]*[-+*][ \t]+\\(.*?[ \t]+::\\)\\([ \t]+\\|$\\)" 1 'org-list-dt prepend) @@ -6297,83 +6530,92 @@ needs to be inserted at a specific position in the font-lock sequence.") ;; Code '(org-activate-code (1 'org-code t)) ;; COMMENT - (list (format org-heading-keyword-regexp-format - (concat "\\(" - org-comment-string "\\|" org-quote-string - "\\)")) - '(2 'org-special-keyword t)) + (list (format + "^\\*+\\(?: +%s\\)?\\(?: +\\[#[A-Z0-9]\\]\\)? +\\(?9:%s\\)\\(?: \\|$\\)" + org-todo-regexp + org-comment-string) + '(9 'org-special-keyword t)) ;; Blocks and meta lines '(org-fontify-meta-lines-and-blocks)))) (setq org-font-lock-extra-keywords (delq nil org-font-lock-extra-keywords)) (run-hooks 'org-font-lock-set-keywords-hook) ;; Now set the full font-lock-keywords - (org-set-local 'org-font-lock-keywords org-font-lock-extra-keywords) - (org-set-local 'font-lock-defaults - '(org-font-lock-keywords t nil nil backward-paragraph)) - (kill-local-variable 'font-lock-keywords) nil)) + (setq-local org-font-lock-keywords org-font-lock-extra-keywords) + (setq-local font-lock-defaults + '(org-font-lock-keywords t nil nil backward-paragraph)) + (kill-local-variable 'font-lock-keywords) + nil)) (defun org-toggle-pretty-entities () "Toggle the composition display of entities as UTF8 characters." (interactive) - (org-set-local 'org-pretty-entities (not org-pretty-entities)) + (setq-local org-pretty-entities (not org-pretty-entities)) (org-restart-font-lock) (if org-pretty-entities (message "Entities are now displayed as UTF8 characters") (save-restriction (widen) - (org-decompose-region (point-min) (point-max)) + (decompose-region (point-min) (point-max)) (message "Entities are now displayed as plain text")))) -(defvar org-custom-properties-overlays nil +(defvar-local org-custom-properties-overlays nil "List of overlays used for custom properties.") -(make-variable-buffer-local 'org-custom-properties-overlays) (defun org-toggle-custom-properties-visibility () "Display or hide properties in `org-custom-properties'." (interactive) (if org-custom-properties-overlays - (progn (mapc 'delete-overlay org-custom-properties-overlays) + (progn (mapc #'delete-overlay org-custom-properties-overlays) (setq org-custom-properties-overlays nil)) - (unless (not org-custom-properties) - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (while (re-search-forward org-property-re nil t) - (mapc (lambda(p) - (when (equal p (substring (match-string 1) 1 -1)) - (let ((o (make-overlay (match-beginning 0) (1+ (match-end 0))))) - (overlay-put o 'invisible t) - (overlay-put o 'org-custom-property t) - (push o org-custom-properties-overlays)))) - org-custom-properties))))))) + (when org-custom-properties + (org-with-wide-buffer + (goto-char (point-min)) + (let ((regexp (org-re-property (regexp-opt org-custom-properties) t t))) + (while (re-search-forward regexp nil t) + (let ((end (cdr (save-match-data (org-get-property-block))))) + (when (and end (< (point) end)) + ;; Hide first custom property in current drawer. + (let ((o (make-overlay (match-beginning 0) (1+ (match-end 0))))) + (overlay-put o 'invisible t) + (overlay-put o 'org-custom-property t) + (push o org-custom-properties-overlays)) + ;; Hide additional custom properties in the same drawer. + (while (re-search-forward regexp end t) + (let ((o (make-overlay (match-beginning 0) (1+ (match-end 0))))) + (overlay-put o 'invisible t) + (overlay-put o 'org-custom-property t) + (push o org-custom-properties-overlays))))) + ;; Each entry is limited to a single property drawer. + (outline-next-heading))))))) (defun org-fontify-entities (limit) "Find an entity to fontify." (let (ee) (when org-pretty-entities (catch 'match + ;; "\_ "-family is left out on purpose. Only the first one, + ;; i.e., "\_ ", could be fontified anyway, and it would be + ;; confusing when adding a second white space character. (while (re-search-forward "\\\\\\(there4\\|sup[123]\\|frac[13][24]\\|[a-zA-Z]+\\)\\($\\|{}\\|[^[:alpha:]\n]\\)" limit t) - (if (and (not (org-in-indented-comment-line)) - (setq ee (org-entity-get (match-string 1))) - (= (length (nth 6 ee)) 1)) - (let* - ((end (if (equal (match-string 2) "{}") + (when (and (not (org-at-comment-p)) + (setq ee (org-entity-get (match-string 1))) + (= (length (nth 6 ee)) 1)) + (let* ((end (if (equal (match-string 2) "{}") (match-end 2) (match-end 1)))) - (add-text-properties - (match-beginning 0) end - (list 'font-lock-fontified t)) - (compose-region (match-beginning 0) end - (nth 6 ee) nil) - (backward-char 1) - (throw 'match t)))) + (add-text-properties + (match-beginning 0) end + (list 'font-lock-fontified t)) + (compose-region (match-beginning 0) end + (nth 6 ee) nil) + (backward-char 1) + (throw 'match t)))) nil)))) (defun org-fontify-like-in-org-mode (s &optional odd-levels) - "Fontify string S like in Org-mode." + "Fontify string S like in Org mode." (with-temp-buffer (insert s) (let ((org-odd-levels-only odd-levels)) @@ -6387,33 +6629,55 @@ needs to be inserted at a specific position in the font-lock sequence.") (defun org-get-level-face (n) "Get the right face for match N in font-lock matching of headlines." (setq org-l (- (match-end 2) (match-beginning 1) 1)) - (if org-odd-levels-only (setq org-l (1+ (/ org-l 2)))) + (when org-odd-levels-only (setq org-l (1+ (/ org-l 2)))) (if org-cycle-level-faces (setq org-f (nth (% (1- org-l) org-n-level-faces) org-level-faces)) (setq org-f (nth (1- (min org-l org-n-level-faces)) org-level-faces))) (cond ((eq n 1) (if org-hide-leading-stars 'org-hide org-f)) ((eq n 2) org-f) - (t (if org-level-color-stars-only nil org-f)))) + (t (unless org-level-color-stars-only org-f)))) +(defun org-face-from-face-or-color (context inherit face-or-color) + "Create a face list that inherits INHERIT, but sets the foreground color. +When FACE-OR-COLOR is not a string, just return it." + (if (stringp face-or-color) + (list :inherit inherit + (cdr (assoc context org-faces-easy-properties)) + face-or-color) + face-or-color)) (defun org-get-todo-face (kwd) "Get the right face for a TODO keyword KWD. If KWD is a number, get the corresponding match group." - (if (numberp kwd) (setq kwd (match-string kwd))) + (when (numberp kwd) (setq kwd (match-string kwd))) (or (org-face-from-face-or-color 'todo 'org-todo (cdr (assoc kwd org-todo-keyword-faces))) (and (member kwd org-done-keywords) 'org-done) 'org-todo)) -(defun org-face-from-face-or-color (context inherit face-or-color) - "Create a face list that inherits INHERIT, but sets the foreground color. -When FACE-OR-COLOR is not a string, just return it." - (if (stringp face-or-color) - (list :inherit inherit - (cdr (assoc context org-faces-easy-properties)) - face-or-color) - face-or-color)) +(defun org-get-priority-face (priority) + "Get the right face for PRIORITY. +PRIORITY is a character." + (or (org-face-from-face-or-color + 'priority 'org-priority (cdr (assq priority org-priority-faces))) + 'org-priority)) + +(defun org-get-tag-face (tag) + "Get the right face for TAG. +If TAG is a number, get the corresponding match group." + (let ((tag (if (wholenump tag) (match-string tag) tag))) + (or (org-face-from-face-or-color + 'tag 'org-tag (cdr (assoc tag org-tag-faces))) + 'org-tag))) + +(defun org-font-lock-add-priority-faces (limit) + "Add the special priority faces." + (while (re-search-forward "^\\*+ .*?\\(\\[#\\(.\\)\\]\\)" limit t) + (add-text-properties + (match-beginning 1) (match-end 1) + (list 'face (org-get-priority-face (string-to-char (match-string 2))) + 'font-lock-fontified t)))) (defun org-font-lock-add-tag-faces (limit) "Add the special tag faces." @@ -6424,39 +6688,18 @@ When FACE-OR-COLOR is not a string, just return it." 'font-lock-fontified t)) (backward-char 1)))) -(defun org-font-lock-add-priority-faces (limit) - "Add the special priority faces." - (while (re-search-forward "\\[#\\([A-Z0-9]\\)\\]" limit t) - (when (save-match-data (org-at-heading-p)) - (add-text-properties - (match-beginning 0) (match-end 0) - (list 'face (or (org-face-from-face-or-color - 'priority 'org-priority - (cdr (assoc (char-after (match-beginning 1)) - org-priority-faces))) - 'org-priority) - 'font-lock-fontified t))))) - -(defun org-get-tag-face (kwd) - "Get the right face for a TODO keyword KWD. -If KWD is a number, get the corresponding match group." - (if (numberp kwd) (setq kwd (match-string kwd))) - (or (org-face-from-face-or-color - 'tag 'org-tag (cdr (assoc kwd org-tag-faces))) - 'org-tag)) - -(defun org-unfontify-region (beg end &optional maybe_loudly) +(defun org-unfontify-region (beg end &optional _maybe_loudly) "Remove fontification and activation overlays from links." (font-lock-default-unfontify-region beg end) (let* ((buffer-undo-list t) (inhibit-read-only t) (inhibit-point-motion-hooks t) (inhibit-modification-hooks t) deactivate-mark buffer-file-name buffer-file-truename) - (org-decompose-region beg end) + (decompose-region beg end) (remove-text-properties beg end '(mouse-face t keymap t org-linked-text t invisible t intangible t - org-no-flyspell t org-emphasis t)) + org-emphasis t)) (org-remove-font-lock-display-properties beg end))) (defconst org-script-display '(((raise -0.3) (height 0.7)) @@ -6473,59 +6716,56 @@ and subscripts." (while (< beg end) (setq next (next-single-property-change beg 'display nil end) prop (get-text-property beg 'display)) - (if (member prop org-script-display) - (put-text-property beg next 'display nil)) + (when (member prop org-script-display) + (put-text-property beg next 'display nil)) (setq beg next)))) (defun org-raise-scripts (limit) "Add raise properties to sub/superscripts." - (when (and org-pretty-entities org-pretty-entities-include-sub-superscripts) - (if (re-search-forward - (if (eq org-use-sub-superscripts t) - org-match-substring-regexp - org-match-substring-with-braces-regexp) - limit t) - (let* ((pos (point)) table-p comment-p - (mpos (match-beginning 3)) - (emph-p (get-text-property mpos 'org-emphasis)) - (link-p (get-text-property mpos 'mouse-face)) - (keyw-p (eq 'org-special-keyword (get-text-property mpos 'face)))) - (goto-char (point-at-bol)) - (setq table-p (org-looking-at-p org-table-dataline-regexp) - comment-p (org-looking-at-p "^[ \t]*#[ +]")) - (goto-char pos) - ;; Handle a_b^c - (if (member (char-after) '(?_ ?^)) (goto-char (1- pos))) - (if (or comment-p emph-p link-p keyw-p) - t - (put-text-property (match-beginning 3) (match-end 0) - 'display - (if (equal (char-after (match-beginning 2)) ?^) - (nth (if table-p 3 1) org-script-display) - (nth (if table-p 2 0) org-script-display))) - (add-text-properties (match-beginning 2) (match-end 2) - (list 'invisible t - 'org-dwidth t 'org-dwidth-n 1)) - (if (and (eq (char-after (match-beginning 3)) ?{) - (eq (char-before (match-end 3)) ?})) - (progn - (add-text-properties - (match-beginning 3) (1+ (match-beginning 3)) - (list 'invisible t 'org-dwidth t 'org-dwidth-n 1)) - (add-text-properties - (1- (match-end 3)) (match-end 3) - (list 'invisible t 'org-dwidth t 'org-dwidth-n 1)))) - t))))) + (when (and org-pretty-entities org-pretty-entities-include-sub-superscripts + (re-search-forward + (if (eq org-use-sub-superscripts t) + org-match-substring-regexp + org-match-substring-with-braces-regexp) + limit t)) + (let* ((pos (point)) table-p comment-p + (mpos (match-beginning 3)) + (emph-p (get-text-property mpos 'org-emphasis)) + (link-p (get-text-property mpos 'mouse-face)) + (keyw-p (eq 'org-special-keyword (get-text-property mpos 'face)))) + (goto-char (point-at-bol)) + (setq table-p (looking-at-p org-table-dataline-regexp) + comment-p (looking-at-p "^[ \t]*#[ +]")) + (goto-char pos) + ;; Handle a_b^c + (when (member (char-after) '(?_ ?^)) (goto-char (1- pos))) + (unless (or comment-p emph-p link-p keyw-p) + (put-text-property (match-beginning 3) (match-end 0) + 'display + (if (equal (char-after (match-beginning 2)) ?^) + (nth (if table-p 3 1) org-script-display) + (nth (if table-p 2 0) org-script-display))) + (add-text-properties (match-beginning 2) (match-end 2) + (list 'invisible t + 'org-dwidth t 'org-dwidth-n 1)) + (if (and (eq (char-after (match-beginning 3)) ?{) + (eq (char-before (match-end 3)) ?})) + (progn + (add-text-properties + (match-beginning 3) (1+ (match-beginning 3)) + (list 'invisible t 'org-dwidth t 'org-dwidth-n 1)) + (add-text-properties + (1- (match-end 3)) (match-end 3) + (list 'invisible t 'org-dwidth t 'org-dwidth-n 1))))) + t))) ;;;; Visibility cycling, including org-goto and indirect buffer ;;; Cycling -(defvar org-cycle-global-status nil) -(make-variable-buffer-local 'org-cycle-global-status) +(defvar-local org-cycle-global-status nil) (put 'org-cycle-global-status 'org-state t) -(defvar org-cycle-subtree-status nil) -(make-variable-buffer-local 'org-cycle-subtree-status) +(defvar-local org-cycle-subtree-status nil) (put 'org-cycle-subtree-status 'org-state t) (defvar org-inlinetask-min-level) @@ -6537,52 +6777,58 @@ and subscripts." ;;;###autoload (defun org-cycle (&optional arg) - "TAB-action and visibility cycling for Org-mode. + "TAB-action and visibility cycling for Org mode. -This is the command invoked in Org-mode by the TAB key. Its main purpose -is outline visibility cycling, but it also invokes other actions +This is the command invoked in Org mode by the `TAB' key. Its main +purpose is outline visibility cycling, but it also invokes other actions in special contexts. -- When this function is called with a prefix argument, rotate the entire - buffer through 3 states (global cycling) +When this function is called with a `\\[universal-argument]' prefix, rotate \ +the entire +buffer through 3 states (global cycling) 1. OVERVIEW: Show only top-level headlines. 2. CONTENTS: Show all headlines of all levels, but no body text. 3. SHOW ALL: Show everything. - When called with two `C-u C-u' prefixes, switch to the startup visibility, - determined by the variable `org-startup-folded', and by any VISIBILITY - properties in the buffer. - When called with three `C-u C-u C-u' prefixed, show the entire buffer, - including any drawers. -- When inside a table, re-align the table and move to the next field. +With a `\\[universal-argument] \\[universal-argument]' prefix argument, \ +switch to the startup visibility, +determined by the variable `org-startup-folded', and by any VISIBILITY +properties in the buffer. + +With a `\\[universal-argument] \\[universal-argument] \ +\\[universal-argument]' prefix argument, show the entire buffer, including +any drawers. -- When point is at the beginning of a headline, rotate the subtree started - by this line through 3 different states (local cycling) +When inside a table, re-align the table and move to the next field. + +When point is at the beginning of a headline, rotate the subtree started +by this line through 3 different states (local cycling) 1. FOLDED: Only the main headline is shown. 2. CHILDREN: The main headline and the direct children are shown. From this state, you can move to one of the children and zoom in further. 3. SUBTREE: Show the entire subtree, including body text. - If there is no subtree, switch directly from CHILDREN to FOLDED. - -- When point is at the beginning of an empty headline and the variable - `org-cycle-level-after-item/entry-creation' is set, cycle the level - of the headline by demoting and promoting it to likely levels. This - speeds up creation document structure by pressing TAB once or several - times right after creating a new headline. - -- When there is a numeric prefix, go up to a heading with level ARG, do - a `show-subtree' and return to the previous cursor position. If ARG - is negative, go up that many levels. - -- When point is not at the beginning of a headline, execute the global - binding for TAB, which is re-indenting the line. See the option - `org-cycle-emulate-tab' for details. - -- Special case: if point is at the beginning of the buffer and there is - no headline in line 1, this function will act as if called with prefix arg - (C-u TAB, same as S-TAB) also when called without prefix arg. - But only if also the variable `org-cycle-global-at-bob' is t." +If there is no subtree, switch directly from CHILDREN to FOLDED. + +When point is at the beginning of an empty headline and the variable +`org-cycle-level-after-item/entry-creation' is set, cycle the level +of the headline by demoting and promoting it to likely levels. This +speeds up creation document structure by pressing `TAB' once or several +times right after creating a new headline. + +When there is a numeric prefix, go up to a heading with level ARG, do +a `show-subtree' and return to the previous cursor position. If ARG +is negative, go up that many levels. + +When point is not at the beginning of a headline, execute the global +binding for `TAB', which is re-indenting the line. See the option +`org-cycle-emulate-tab' for details. + +As a special case, if point is at the beginning of the buffer and there is +no headline in line 1, this function will act as if called with prefix arg +\(`\\[universal-argument] TAB', same as `S-TAB') also when called without \ +prefix arg, but only +if the variable `org-cycle-global-at-bob' is t." (interactive "P") (org-load-modules-maybe) (unless (or (run-hook-with-args-until-success 'org-tab-first-hook) @@ -6611,10 +6857,6 @@ in special contexts. org-cycle-hook)) (pos (point))) - (if (or bob-special (equal arg '(4))) - ;; special case: use global cycling - (setq arg t)) - (cond ((equal arg '(16)) @@ -6623,32 +6865,36 @@ in special contexts. (org-unlogged-message "Startup visibility, plus VISIBILITY properties")) ((equal arg '(64)) - (show-all) + (outline-show-all) (org-unlogged-message "Entire buffer visible, including drawers")) + ((equal arg '(4)) (org-cycle-internal-global)) + + ;; Try hiding block at point. + ((org-hide-block-toggle-maybe)) + ;; Try cdlatex TAB completion ((org-try-cdlatex-tab)) ;; Table: enter it or move to the next field. ((org-at-table-p 'any) (if (org-at-table.el-p) - (message "%s" "Use C-c ' to edit table.el tables") + (message "%s" (substitute-command-keys "\\\ +Use `\\[org-edit-special]' to edit table.el tables")) (if arg (org-table-edit-field t) (org-table-justify-field-maybe) (call-interactively 'org-table-next-field)))) - ((run-hook-with-args-until-success - 'org-tab-after-check-for-table-hook)) + ((run-hook-with-args-until-success 'org-tab-after-check-for-table-hook)) ;; Global cycling: delegate to `org-cycle-internal-global'. - ((eq arg t) (org-cycle-internal-global)) + (bob-special (org-cycle-internal-global)) ;; Drawers: delegate to `org-flag-drawer'. - ((and org-drawers org-drawer-regexp - (save-excursion - (beginning-of-line 1) - (looking-at org-drawer-regexp))) - (org-flag-drawer ; toggle block visibility + ((save-excursion + (beginning-of-line 1) + (looking-at org-drawer-regexp)) + (org-flag-drawer ; toggle block visibility (not (get-char-property (match-end 0) 'invisible)))) ;; Show-subtree, ARG levels up from here. @@ -6667,7 +6913,7 @@ in special contexts. ;; At an item/headline: delegate to `org-cycle-internal-local'. ((and (or (and org-cycle-include-plain-lists (org-at-item-p)) - (save-excursion (beginning-of-line 1) + (save-excursion (move-beginning-of-line 1) (looking-at org-outline-regexp))) (or (bolp) (not (eq org-cycle-emulate-tab 'exc-hl-bol)))) (org-cycle-internal-local)) @@ -6722,7 +6968,7 @@ in special contexts. (eq org-cycle-global-status 'contents)) ;; We just showed the table of contents - now show everything (run-hook-with-args 'org-pre-cycle-hook 'all) - (show-all) + (outline-show-all) (unless ga (org-unlogged-message "SHOW ALL")) (setq org-cycle-global-status 'all) (run-hook-with-args 'org-cycle-hook 'all)) @@ -6738,6 +6984,11 @@ in special contexts. (defvar org-called-with-limited-levels nil "Non-nil when `org-with-limited-levels' is currently active.") +(defun org-invisible-p (&optional pos) + "Non-nil if the character after POS is invisible. +If POS is nil, use `point' instead." + (get-char-property (or pos (point)) 'invisible)) + (defun org-cycle-internal-local () "Do the local cycling action." (let ((goal-column 0) eoh eol eos has-children children-skipped struct) @@ -6765,15 +7016,10 @@ in special contexts. (org-list-search-forward (org-item-beginning-re) eos t))))) ;; Determine end invisible part of buffer (EOL) (beginning-of-line 2) - ;; XEmacs doesn't have `next-single-char-property-change' - (if (featurep 'xemacs) - (while (and (not (eobp)) ;; this is like `next-line' - (get-char-property (1- (point)) 'invisible)) - (beginning-of-line 2)) - (while (and (not (eobp)) ;; this is like `next-line' - (get-char-property (1- (point)) 'invisible)) - (goto-char (next-single-char-property-change (point) 'invisible)) - (and (eolp) (beginning-of-line 2)))) + (while (and (not (eobp)) ;This is like `next-line'. + (get-char-property (1- (point)) 'invisible)) + (goto-char (next-single-char-property-change (point) 'invisible)) + (and (eolp) (beginning-of-line 2))) (setq eol (point))) ;; Find out what to do next and set `this-command' (cond @@ -6786,7 +7032,7 @@ in special contexts. (save-excursion (goto-char eos) (outline-next-heading) - (if (outline-invisible-p) (org-flag-heading nil)))) + (when (org-invisible-p) (org-flag-heading nil)))) ((and (or (>= eol eos) (not (string-match "\\S-" (buffer-substring eol eos)))) (or has-children @@ -6798,7 +7044,7 @@ in special contexts. (if (org-at-item-p) (org-list-set-item-visibility (point-at-bol) struct 'children) (org-show-entry) - (org-with-limited-levels (show-children)) + (org-with-limited-levels (org-show-children)) ;; FIXME: This slows down the func way too much. ;; How keep drawers hidden in subtree anyway? ;; (when (memq 'org-cycle-hide-drawers org-cycle-hook) @@ -6813,14 +7059,14 @@ in special contexts. (let* ((struct (org-list-struct)) (prevs (org-list-prevs-alist struct)) (end (org-list-get-bottom-point struct))) - (mapc (lambda (e) (org-list-set-item-visibility e struct 'folded)) - (org-list-get-all-items (point) struct prevs)) + (dolist (e (org-list-get-all-items (point) struct prevs)) + (org-list-set-item-visibility e struct 'folded)) (goto-char (if (< end eos) end eos))))))) (org-unlogged-message "CHILDREN") (save-excursion (goto-char eos) (outline-next-heading) - (if (outline-invisible-p) (org-flag-heading nil))) + (when (org-invisible-p) (org-flag-heading nil))) (setq org-cycle-subtree-status 'children) (unless (org-before-first-heading-p) (run-hook-with-args 'org-cycle-hook 'children))) @@ -6849,15 +7095,15 @@ in special contexts. ;;;###autoload (defun org-global-cycle (&optional arg) "Cycle the global visibility. For details see `org-cycle'. -With \\[universal-argument] prefix arg, switch to startup visibility. +With `\\[universal-argument]' prefix ARG, switch to startup visibility. With a numeric prefix, show all headlines up to that level." (interactive "P") (let ((org-cycle-include-plain-lists (if (derived-mode-p 'org-mode) org-cycle-include-plain-lists nil))) (cond ((integerp arg) - (show-all) - (hide-sublevels arg) + (outline-show-all) + (outline-hide-sublevels arg) (setq org-cycle-global-status 'contents)) ((equal arg '(4)) (org-set-startup-visibility) @@ -6874,9 +7120,9 @@ With a numeric prefix, show all headlines up to that level." (org-content)) ((or (eq org-startup-folded 'showeverything) (eq org-startup-folded nil)) - (show-all))) + (outline-show-all))) (unless (eq org-startup-folded 'showeverything) - (if org-hide-block-startup (org-hide-block-all)) + (when org-hide-block-startup (org-hide-block-all)) (org-set-visibility-according-to-property 'no-cleanup) (org-cycle-hide-archived-subtrees 'all) (org-cycle-hide-drawers 'all) @@ -6885,34 +7131,32 @@ With a numeric prefix, show all headlines up to that level." (defun org-set-visibility-according-to-property (&optional no-cleanup) "Switch subtree visibilities according to :VISIBILITY: property." (interactive) - (let (org-show-entry-below state) - (save-excursion - (goto-char (point-min)) - (while (re-search-forward - "^[ \t]*:VISIBILITY:[ \t]+\\([a-z]+\\)" - nil t) - (setq state (match-string 1)) - (save-excursion - (org-back-to-heading t) - (hide-subtree) - (org-reveal) - (cond - ((equal state '("fold" "folded")) - (hide-subtree)) - ((equal state "children") - (org-show-hidden-entry) - (show-children)) - ((equal state "content") - (save-excursion - (save-restriction - (org-narrow-to-subtree) - (org-content)))) - ((member state '("all" "showall")) - (show-subtree))))) - (unless no-cleanup - (org-cycle-hide-archived-subtrees 'all) - (org-cycle-hide-drawers 'all) - (org-cycle-show-empty-lines 'all))))) + (org-with-wide-buffer + (goto-char (point-min)) + (while (re-search-forward "^[ \t]*:VISIBILITY:" nil t) + (if (not (org-at-property-p)) (outline-next-heading) + (let ((state (match-string 3))) + (save-excursion + (org-back-to-heading t) + (outline-hide-subtree) + (org-reveal) + (cond + ((equal state "folded") + (outline-hide-subtree)) + ((equal state "children") + (org-show-hidden-entry) + (org-show-children)) + ((equal state "content") + (save-excursion + (save-restriction + (org-narrow-to-subtree) + (org-content)))) + ((member state '("all" "showall")) + (outline-show-subtree))))))) + (unless no-cleanup + (org-cycle-hide-archived-subtrees 'all) + (org-cycle-hide-drawers 'all) + (org-cycle-show-empty-lines 'all)))) ;; This function uses outline-regexp instead of the more fundamental ;; org-outline-regexp so that org-cycle-global works outside of Org @@ -6928,11 +7172,10 @@ results." (let ((level (save-excursion (goto-char (point-min)) - (if (re-search-forward (concat "^" outline-regexp) nil t) - (progn - (goto-char (match-beginning 0)) - (funcall outline-level)))))) - (and level (hide-sublevels level))))) + (when (re-search-forward (concat "^" outline-regexp) nil t) + (goto-char (match-beginning 0)) + (funcall outline-level))))) + (and level (outline-hide-sublevels level))))) (defun org-content (&optional arg) "Show all headlines in the buffer, like a table of contents. @@ -6950,9 +7193,9 @@ With numerical argument N, show content up to level N." t) (looking-at org-outline-regexp)) (if (integerp arg) - (show-children (1- arg)) - (show-branches)) - (if (bobp) (throw 'exit nil)))))) + (org-show-children (1- arg)) + (outline-show-branches)) + (when (bobp) (throw 'exit nil)))))) (defun org-optimize-window-after-visibility-change (state) "Adjust the window after a change in outline visibility. @@ -6967,13 +7210,11 @@ This function is the default value of the hook `org-cycle-hook'." (defun org-remove-empty-overlays-at (pos) "Remove outline overlays that do not contain non-white stuff." - (mapc - (lambda (o) - (and (eq 'outline (overlay-get o 'invisible)) - (not (string-match "\\S-" (buffer-substring (overlay-start o) - (overlay-end o)))) - (delete-overlay o))) - (overlays-at pos))) + (dolist (o (overlays-at pos)) + (and (eq 'outline (overlay-get o 'invisible)) + (not (string-match "\\S-" (buffer-substring (overlay-start o) + (overlay-end o)))) + (delete-overlay o)))) (defun org-clean-visibility-after-subtree-move () "Fix visibility issues after moving a subtree." @@ -6991,7 +7232,7 @@ This function is the default value of the hook `org-cycle-hook'." (point-at-eol) (point)))) (level (looking-at "\\*+")) - (re (if level (concat "^" (regexp-quote (match-string 0)) " ")))) + (re (when level (concat "^" (regexp-quote (match-string 0)) " ")))) (save-excursion (save-restriction (narrow-to-region beg end) @@ -6999,10 +7240,10 @@ This function is the default value of the hook `org-cycle-hook'." ;; Properly fold already folded siblings (goto-char (point-min)) (while (re-search-forward re nil t) - (if (and (not (outline-invisible-p)) - (save-excursion - (goto-char (point-at-eol)) (outline-invisible-p))) - (hide-entry)))) + (when (and (not (org-invisible-p)) + (save-excursion + (goto-char (point-at-eol)) (org-invisible-p))) + (outline-hide-entry)))) (org-cycle-show-empty-lines 'overview) (org-cycle-hide-drawers 'overview))))) @@ -7012,7 +7253,7 @@ The region to be covered depends on STATE when called through `org-cycle-hook'. Lisp program can use t for STATE to get the entire buffer covered. Note that an empty line is only shown if there are at least `org-cycle-separator-lines' empty lines before the headline." - (when (not (= org-cycle-separator-lines 0)) + (when (/= org-cycle-separator-lines 0) (save-excursion (let* ((n (abs org-cycle-separator-lines)) (re (cond @@ -7021,38 +7262,34 @@ are at least `org-cycle-separator-lines' empty lines before the headline." (t (let ((ns (number-to-string (- n 2)))) (concat "^\\(?:[ \t]*\n\\)\\{" ns "," ns "\\}" "[ \t]*\\(\n[ \t]*\n\\*+\\) "))))) - beg end b e) + beg end) (cond ((memq state '(overview contents t)) (setq beg (point-min) end (point-max))) ((memq state '(children folded)) - (setq beg (point) end (progn (org-end-of-subtree t t) - (beginning-of-line 2) - (point))))) + (setq beg (point) + end (progn (org-end-of-subtree t t) + (line-beginning-position 2))))) (when beg (goto-char beg) (while (re-search-forward re end t) (unless (get-char-property (match-end 1) 'invisible) - (setq e (match-end 1)) - (if (< org-cycle-separator-lines 0) - (setq b (save-excursion - (goto-char (match-beginning 0)) - (org-back-over-empty-lines) - (if (save-excursion - (goto-char (max (point-min) (1- (point)))) - (org-at-heading-p)) - (1- (point)) - (point)))) - (setq b (match-beginning 1))) - (outline-flag-region b e nil))))))) + (let ((e (match-end 1)) + (b (if (>= org-cycle-separator-lines 0) + (match-beginning 1) + (save-excursion + (goto-char (match-beginning 0)) + (skip-chars-backward " \t\n") + (line-end-position))))) + (outline-flag-region b e nil)))))))) ;; Never hide empty lines at the end of the file. (save-excursion (goto-char (point-max)) (outline-previous-heading) (outline-end-of-heading) - (if (and (looking-at "[ \t\n]+") - (= (match-end 0) (point-max))) - (outline-flag-region (point) (match-end 0) nil)))) + (when (and (looking-at "[ \t\n]+") + (= (match-end 0) (point-max))) + (outline-flag-region (point) (match-end 0) nil)))) (defun org-show-empty-lines-in-parent () "Move to the parent and re-show empty lines before visible headlines." @@ -7061,28 +7298,28 @@ are at least `org-cycle-separator-lines' empty lines before the headline." (org-cycle-show-empty-lines context)))) (defun org-files-list () - "Return `org-agenda-files' list, plus all open org-mode files. + "Return `org-agenda-files' list, plus all open Org files. This is useful for operations that need to scan all of a user's open and agenda-wise Org files." (let ((files (mapcar 'expand-file-name (org-agenda-files)))) (dolist (buf (buffer-list)) (with-current-buffer buf - (if (and (derived-mode-p 'org-mode) (buffer-file-name)) - (let ((file (expand-file-name (buffer-file-name)))) - (unless (member file files) - (push file files)))))) + (when (and (derived-mode-p 'org-mode) (buffer-file-name)) + (cl-pushnew (expand-file-name (buffer-file-name)) files)))) files)) (defsubst org-entry-beginning-position () "Return the beginning position of the current entry." - (save-excursion (outline-back-to-heading t) (point))) + (save-excursion (org-back-to-heading t) (point))) (defsubst org-entry-end-position () "Return the end position of the current entry." (save-excursion (outline-next-heading) (point))) -(defun org-cycle-hide-drawers (state) - "Re-hide all drawers after a visibility state change." +(defun org-cycle-hide-drawers (state &optional exceptions) + "Re-hide all drawers after a visibility state change. +When non-nil, optional argument EXCEPTIONS is a list of strings +specifying which drawers should not be hidden." (when (and (derived-mode-p 'org-mode) (not (memq state '(overview folded contents)))) (save-excursion @@ -7093,36 +7330,39 @@ open and agenda-wise Org files." (save-excursion (outline-next-heading) (point)) (org-end-of-subtree t))))) (goto-char beg) - (while (re-search-forward org-drawer-regexp end t) - (org-flag-drawer t)))))) - -(defun org-cycle-hide-inline-tasks (state) - "Re-hide inline tasks when switching to `contents' or `children' -visibility state." - (case state - (contents - (when (org-bound-and-true-p org-inlinetask-min-level) - (hide-sublevels (1- org-inlinetask-min-level)))) - (children - (when (featurep 'org-inlinetask) - (save-excursion - (while (and (outline-next-heading) - (org-inlinetask-at-task-p)) - (org-inlinetask-toggle-visibility) - (org-inlinetask-goto-end))))))) - -(defun org-flag-drawer (flag) - "When FLAG is non-nil, hide the drawer we are within. -Otherwise make it visible." - (save-excursion - (beginning-of-line 1) - (when (looking-at "^[ \t]*:[a-zA-Z][a-zA-Z0-9]*:") - (let ((b (match-end 0))) - (if (re-search-forward - "^[ \t]*:END:" - (save-excursion (outline-next-heading) (point)) t) - (outline-flag-region b (point-at-eol) flag) - (user-error ":END: line missing at position %s" b)))))) + (while (re-search-forward org-drawer-regexp (max end (point)) t) + (unless (member-ignore-case (match-string 1) exceptions) + (let ((drawer (org-element-at-point))) + (when (memq (org-element-type drawer) '(drawer property-drawer)) + (org-flag-drawer t drawer) + ;; Make sure to skip drawer entirely or we might flag + ;; it another time when matching its ending line with + ;; `org-drawer-regexp'. + (goto-char (org-element-property :end drawer)))))))))) + +(defun org-flag-drawer (flag &optional element) + "When FLAG is non-nil, hide the drawer we are at. +Otherwise make it visible. When optional argument ELEMENT is +a parsed drawer, as returned by `org-element-at-point', hide or +show that drawer instead." + (let ((drawer (or element + (and (save-excursion + (beginning-of-line) + (looking-at-p org-drawer-regexp)) + (org-element-at-point))))) + (when (memq (org-element-type drawer) '(drawer property-drawer)) + (let ((post (org-element-property :post-affiliated drawer))) + (save-excursion + (outline-flag-region + (progn (goto-char post) (line-end-position)) + (progn (goto-char (org-element-property :end drawer)) + (skip-chars-backward " \r\t\n") + (line-end-position)) + flag)) + ;; When the drawer is hidden away, make sure point lies in + ;; a visible part of the buffer. + (when (and flag (> (line-beginning-position) post)) + (goto-char post)))))) (defun org-subtree-end-visible-p () "Is the end of the current subtree visible?" @@ -7131,9 +7371,11 @@ Otherwise make it visible." (defun org-first-headline-recenter () "Move cursor to the first headline and recenter the headline." - (goto-char (point-min)) - (when (re-search-forward (concat "^\\(" org-outline-regexp "\\)") nil t) - (set-window-start (selected-window) (point-at-bol)))) + (let ((window (get-buffer-window))) + (when window + (goto-char (point-min)) + (when (re-search-forward (concat "^\\(" org-outline-regexp "\\)") nil t) + (set-window-start window (line-beginning-position)))))) ;;; Saving and restoring visibility @@ -7144,38 +7386,30 @@ The return value is a list of cons cells, with start and stop positions for each overlay. If USE-MARKERS is set, return the positions as markers." (let (beg end) - (save-excursion - (save-restriction - (widen) - (delq nil - (mapcar (lambda (o) - (when (eq (overlay-get o 'invisible) 'outline) - (setq beg (overlay-start o) - end (overlay-end o)) - (and beg end (> end beg) - (if use-markers - (cons (move-marker (make-marker) beg) - (move-marker (make-marker) end)) - (cons beg end))))) - (overlays-in (point-min) (point-max)))))))) + (org-with-wide-buffer + (delq nil + (mapcar (lambda (o) + (when (eq (overlay-get o 'invisible) 'outline) + (setq beg (overlay-start o) + end (overlay-end o)) + (and beg end (> end beg) + (if use-markers + (cons (copy-marker beg) + (copy-marker end t)) + (cons beg end))))) + (overlays-in (point-min) (point-max))))))) (defun org-set-outline-overlay-data (data) "Create visibility overlays for all positions in DATA. DATA should have been made by `org-outline-overlay-data'." - (let (o) - (save-excursion - (save-restriction - (widen) - (show-all) - (mapc (lambda (c) - (outline-flag-region (car c) (cdr c) t)) - data))))) + (org-with-wide-buffer + (outline-show-all) + (dolist (c data) (outline-flag-region (car c) (cdr c) t)))) ;;; Folding of blocks -(defvar org-hide-block-overlays nil +(defvar-local org-hide-block-overlays nil "Overlays hiding blocks.") -(make-variable-buffer-local 'org-hide-block-overlays) (defun org-block-map (function &optional start end) "Call FUNCTION at the head of all source blocks in the current buffer. @@ -7192,74 +7426,85 @@ Optional arguments START and END can be used to limit the range." (defun org-hide-block-toggle-all () "Toggle the visibility of all blocks in the current buffer." - (org-block-map #'org-hide-block-toggle)) + (org-block-map 'org-hide-block-toggle)) (defun org-hide-block-all () "Fold all blocks in the current buffer." (interactive) (org-show-block-all) - (org-block-map #'org-hide-block-toggle-maybe)) + (org-block-map 'org-hide-block-toggle-maybe)) (defun org-show-block-all () "Unfold all blocks in the current buffer." (interactive) - (mapc 'delete-overlay org-hide-block-overlays) + (mapc #'delete-overlay org-hide-block-overlays) (setq org-hide-block-overlays nil)) (defun org-hide-block-toggle-maybe () - "Toggle visibility of block at point." + "Toggle visibility of block at point. +Unlike to `org-hide-block-toggle', this function does not throw +an error. Return a non-nil value when toggling is successful." (interactive) - (let ((case-fold-search t)) - (if (save-excursion - (beginning-of-line 1) - (looking-at org-block-regexp)) - (progn (org-hide-block-toggle) - t) ;; to signal that we took action - nil))) ;; to signal that we did not + (ignore-errors (org-hide-block-toggle))) (defun org-hide-block-toggle (&optional force) - "Toggle the visibility of the current block." + "Toggle the visibility of the current block. +When optional argument FORCE is `off', make block visible. If it +is non-nil, hide it unconditionally. Throw an error when not at +a block. Return a non-nil value when toggling is successful." (interactive) - (save-excursion - (beginning-of-line) - (if (re-search-forward org-block-regexp nil t) - (let ((start (- (match-beginning 4) 1)) ;; beginning of body - (end (match-end 0)) ;; end of entire body - ov) - (if (memq t (mapcar (lambda (overlay) - (eq (overlay-get overlay 'invisible) - 'org-hide-block)) - (overlays-at start))) - (if (or (not force) (eq force 'off)) - (mapc (lambda (ov) - (when (member ov org-hide-block-overlays) - (setq org-hide-block-overlays - (delq ov org-hide-block-overlays))) - (when (eq (overlay-get ov 'invisible) - 'org-hide-block) - (delete-overlay ov))) - (overlays-at start))) - (setq ov (make-overlay start end)) - (overlay-put ov 'invisible 'org-hide-block) - ;; make the block accessible to isearch - (overlay-put - ov 'isearch-open-invisible - (lambda (ov) - (when (member ov org-hide-block-overlays) - (setq org-hide-block-overlays - (delq ov org-hide-block-overlays))) - (when (eq (overlay-get ov 'invisible) - 'org-hide-block) - (delete-overlay ov)))) - (push ov org-hide-block-overlays))) - (user-error "Not looking at a source block")))) - -;; org-tab-after-check-for-cycling-hook -(add-hook 'org-tab-first-hook 'org-hide-block-toggle-maybe) + (let ((element (org-element-at-point))) + (unless (memq (org-element-type element) + '(center-block comment-block dynamic-block example-block + export-block quote-block special-block + src-block verse-block)) + (user-error "Not at a block")) + (let* ((start (save-excursion + (goto-char (org-element-property :post-affiliated element)) + (line-end-position))) + (end (save-excursion + (goto-char (org-element-property :end element)) + (skip-chars-backward " \r\t\n") + (line-end-position))) + (overlays (overlays-at start))) + (cond + ;; Do nothing when not before or at the block opening line or + ;; at the block closing line. + ((let ((eol (line-end-position))) (and (> eol start) (/= eol end))) nil) + ((and (not (eq force 'off)) + (not (memq t (mapcar + (lambda (o) + (eq (overlay-get o 'invisible) 'org-hide-block)) + overlays)))) + (let ((ov (make-overlay start end))) + (overlay-put ov 'invisible 'org-hide-block) + ;; Make the block accessible to `isearch'. + (overlay-put + ov 'isearch-open-invisible + (lambda (ov) + (when (memq ov org-hide-block-overlays) + (setq org-hide-block-overlays (delq ov org-hide-block-overlays))) + (when (eq (overlay-get ov 'invisible) 'org-hide-block) + (delete-overlay ov)))) + (push ov org-hide-block-overlays) + ;; When the block is hidden away, make sure point is left in + ;; a visible part of the buffer. + (when (> (line-beginning-position) start) + (goto-char start) + (beginning-of-line)) + ;; Signal successful toggling. + t)) + ((or (not force) (eq force 'off)) + (dolist (ov overlays t) + (when (memq ov org-hide-block-overlays) + (setq org-hide-block-overlays (delq ov org-hide-block-overlays))) + (when (eq (overlay-get ov 'invisible) 'org-hide-block) + (delete-overlay ov)))))))) + ;; Remove overlays when changing major mode (add-hook 'org-mode-hook - (lambda () (org-add-hook 'change-major-mode-hook - 'org-show-block-all 'append 'local))) + (lambda () (add-hook 'change-major-mode-hook + 'org-show-block-all 'append 'local))) ;;; Org-goto @@ -7305,7 +7550,7 @@ Optional arguments START and END can be used to limit the range." (defconst org-goto-help "Browse buffer copy, to find location or copy text.%s RET=jump to location C-g=quit and return to previous location -[Up]/[Down]=next/prev headline TAB=cycle visibility [/] org-occur") +\[Up]/[Down]=next/prev headline TAB=cycle visibility [/] org-occur") (defvar org-goto-start-pos) ; dynamically scoped parameter @@ -7343,23 +7588,23 @@ With a prefix argument, use the alternative interface: e.g., if (selected-point (if (eq interface 'outline) (car (org-get-location (current-buffer) org-goto-help)) - (let ((pa (org-refile-get-location "Goto" nil nil t))) + (let ((pa (org-refile-get-location "Goto"))) (org-refile-check-position pa) (nth 3 pa))))) (if selected-point (progn (org-mark-ring-push org-goto-start-pos) (goto-char selected-point) - (if (or (outline-invisible-p) (org-invisible-p2)) - (org-show-context 'org-goto))) + (when (or (org-invisible-p) (org-invisible-p2)) + (org-show-context 'org-goto))) (message "Quit")))) (defvar org-goto-selected-point nil) ; dynamically scoped parameter (defvar org-goto-exit-command nil) ; dynamically scoped parameter (defvar org-goto-local-auto-isearch-map) ; defined below -(defun org-get-location (buf help) - "Let the user select a location in the Org-mode buffer BUF. +(defun org-get-location (_buf help) + "Let the user select a location in current buffer. This function uses a recursive edit. It returns the selected position or nil." (org-no-popups @@ -7372,7 +7617,7 @@ or nil." (save-window-excursion (delete-other-windows) (and (get-buffer "*org-goto*") (kill-buffer "*org-goto*")) - (org-pop-to-buffer-same-window + (pop-to-buffer-same-window (condition-case nil (make-indirect-buffer (current-buffer) "*org-goto*") (error (make-indirect-buffer (current-buffer) "*org-goto*")))) @@ -7390,11 +7635,9 @@ or nil." (setq buffer-read-only t) (if (and (boundp 'org-goto-start-pos) (integer-or-marker-p org-goto-start-pos)) - (let ((org-show-hierarchy-above t) - (org-show-siblings t) - (org-show-following-heading t)) - (goto-char org-goto-start-pos) - (and (outline-invisible-p) (org-show-context))) + (progn (goto-char org-goto-start-pos) + (when (org-invisible-p) + (org-show-set-visibility 'lineage))) (goto-char (point-min))) (let (org-special-ctrl-a/e) (org-beginning-of-line)) (message "Select location and press RET") @@ -7405,8 +7648,14 @@ or nil." (defvar org-goto-local-auto-isearch-map (make-sparse-keymap)) (set-keymap-parent org-goto-local-auto-isearch-map isearch-mode-map) -(define-key org-goto-local-auto-isearch-map "\C-i" 'isearch-other-control-char) -(define-key org-goto-local-auto-isearch-map "\C-m" 'isearch-other-control-char) +;; `isearch-other-control-char' was removed in Emacs 24.4. +(if (fboundp 'isearch-other-control-char) + (progn + (define-key org-goto-local-auto-isearch-map "\C-i" 'isearch-other-control-char) + (define-key org-goto-local-auto-isearch-map "\C-m" 'isearch-other-control-char)) + (define-key org-goto-local-auto-isearch-map "\C-i" nil) + (define-key org-goto-local-auto-isearch-map "\C-m" nil) + (define-key org-goto-local-auto-isearch-map [return] nil)) (defun org-goto-local-search-headings (string bound noerror) "Search and make sure that any matches are in headlines." @@ -7414,9 +7663,12 @@ or nil." (while (if isearch-forward (search-forward string bound noerror) (search-backward string bound noerror)) - (when (let ((context (mapcar 'car (save-match-data (org-context))))) - (and (member :headline context) - (not (member :tags context)))) + (when (save-match-data + (and (save-excursion + (beginning-of-line) + (looking-at org-complex-heading-regexp)) + (or (not (match-beginning 5)) + (< (point) (match-beginning 5))))) (throw 'return (point)))))) (defun org-goto-local-auto-isearch () @@ -7428,11 +7680,11 @@ or nil." (isearch-mode t) (isearch-process-search-char (string-to-char keys))))) -(defun org-goto-ret (&optional arg) +(defun org-goto-ret (&optional _arg) "Finish `org-goto' by going to the new location." (interactive "P") - (setq org-goto-selected-point (point) - org-goto-exit-command 'return) + (setq org-goto-selected-point (point)) + (setq org-goto-exit-command 'return) (throw 'exit nil)) (defun org-goto-left () @@ -7471,17 +7723,18 @@ or nil." (defun org-tree-to-indirect-buffer (&optional arg) "Create indirect buffer and narrow it to current subtree. + With a numerical prefix ARG, go up to this level and then take that tree. If ARG is negative, go up that many levels. If `org-indirect-buffer-display' is not `new-frame', the command removes the indirect buffer previously made with this command, to avoid proliferation of indirect buffers. However, when you call the command with a \ -\\[universal-argument] prefix, or -when `org-indirect-buffer-display' is `new-frame', the last buffer -is kept so that you can work with several indirect buffers at the same time. -If `org-indirect-buffer-display' is `dedicated-frame', the \ -\\[universal-argument] prefix also +`\\[universal-argument]' prefix, or +when `org-indirect-buffer-display' is `new-frame', the last buffer is kept +so that you can work with several indirect buffers at the same time. If +`org-indirect-buffer-display' is `dedicated-frame', the \ +`\\[universal-argument]' prefix also requests that a new frame be made for the new buffer, so that the dedicated frame is not changed." (interactive "P") @@ -7493,26 +7746,26 @@ frame is not changed." (org-back-to-heading t) (when (numberp arg) (setq level (org-outline-level)) - (if (< arg 0) (setq arg (+ level arg))) + (when (< arg 0) (setq arg (+ level arg))) (while (> (setq level (org-outline-level)) arg) (org-up-heading-safe))) (setq beg (point) - heading (org-get-heading)) + heading (org-get-heading 'no-tags)) (org-end-of-subtree t t) - (if (org-at-heading-p) (backward-char 1)) + (when (org-at-heading-p) (backward-char 1)) (setq end (point))) - (if (and (buffer-live-p org-last-indirect-buffer) - (not (eq org-indirect-buffer-display 'new-frame)) - (not arg)) - (kill-buffer org-last-indirect-buffer)) - (setq ibuf (org-get-indirect-buffer cbuf) + (when (and (buffer-live-p org-last-indirect-buffer) + (not (eq org-indirect-buffer-display 'new-frame)) + (not arg)) + (kill-buffer org-last-indirect-buffer)) + (setq ibuf (org-get-indirect-buffer cbuf heading) org-last-indirect-buffer ibuf) (cond ((or (eq org-indirect-buffer-display 'new-frame) (and arg (eq org-indirect-buffer-display 'dedicated-frame))) (select-frame (make-frame)) (delete-other-windows) - (org-pop-to-buffer-same-window ibuf) + (pop-to-buffer-same-window ibuf) (org-set-frame-title heading)) ((eq org-indirect-buffer-display 'dedicated-frame) (raise-frame @@ -7521,26 +7774,28 @@ frame is not changed." org-indirect-dedicated-frame) (setq org-indirect-dedicated-frame (make-frame))))) (delete-other-windows) - (org-pop-to-buffer-same-window ibuf) + (pop-to-buffer-same-window ibuf) (org-set-frame-title (concat "Indirect: " heading))) ((eq org-indirect-buffer-display 'current-window) - (org-pop-to-buffer-same-window ibuf)) + (pop-to-buffer-same-window ibuf)) ((eq org-indirect-buffer-display 'other-window) (pop-to-buffer ibuf)) (t (error "Invalid value"))) - (if (featurep 'xemacs) - (save-excursion (org-mode) (turn-on-font-lock))) (narrow-to-region beg end) - (show-all) + (outline-show-all) (goto-char pos) (run-hook-with-args 'org-cycle-hook 'all) (and (window-live-p cwin) (select-window cwin)))) -(defun org-get-indirect-buffer (&optional buffer) +(defun org-get-indirect-buffer (&optional buffer heading) (setq buffer (or buffer (current-buffer))) (let ((n 1) (base (buffer-name buffer)) bname) (while (buffer-live-p - (get-buffer (setq bname (concat base "-" (number-to-string n))))) + (get-buffer + (setq bname + (concat base "-" + (if heading (concat heading "-" (number-to-string n)) + (number-to-string n)))))) (setq n (1+ n))) (condition-case nil (make-indirect-buffer buffer bname 'clone) @@ -7548,57 +7803,70 @@ frame is not changed." (defun org-set-frame-title (title) "Set the title of the current frame to the string TITLE." - ;; FIXME: how to name a single frame in XEmacs??? - (unless (featurep 'xemacs) - (modify-frame-parameters (selected-frame) (list (cons 'name title))))) + (modify-frame-parameters (selected-frame) (list (cons 'name title)))) ;;;; Structure editing ;;; Inserting headlines -(defun org-previous-line-empty-p (&optional next) - "Is the previous line a blank line? -When NEXT is non-nil, check the next line instead." +(defun org--line-empty-p (n) + "Is the Nth next line empty? + +Counts the current line as N = 1 and the previous line as N = 0; +see `beginning-of-line'." (save-excursion (and (not (bobp)) - (or (beginning-of-line (if next 2 0)) t) + (or (beginning-of-line n) t) (save-match-data (looking-at "[ \t]*$"))))) -(defun org-insert-heading (&optional arg invisible-ok) - "Insert a new heading or an item with the same depth at point. - -If point is at the beginning of a heading or a list item, insert -a new heading or a new item above the current one. If point is -at the beginning of a normal line, turn the line into a heading. +(defun org-previous-line-empty-p () + "Is the previous line a blank line? +When NEXT is non-nil, check the next line instead." + (org--line-empty-p 0)) -If point is in the middle of a headline or a list item, split the -headline or the item and create a new headline/item with the text -in the current line after point \(see `org-M-RET-may-split-line' -on how to modify this behavior). +(defun org-next-line-empty-p () + "Is the previous line a blank line? +When NEXT is non-nil, check the next line instead." + (org--line-empty-p 2)) -With one universal prefix argument, set the user option -`org-insert-heading-respect-content' to t for the duration of -the command. This modifies the behavior described above in this -ways: on list items and at the beginning of normal lines, force -the insertion of a heading after the current subtree. +(defun org-insert-heading (&optional arg invisible-ok top) + "Insert a new heading or an item with the same depth at point. -With two universal prefix arguments, insert the heading at the -end of the grandparent subtree. For example, if point is within -a 2nd-level heading, then it will insert a 2nd-level heading at -the end of the 1st-level parent heading. +If point is at the beginning of a heading or a list item, insert +a new heading or a new item above the current one. When at the +beginning of a regular line of text, turn it into a heading. + +If point is in the middle of a line, split it and create a new +headline/item with the text in the current line after point (see +`org-M-RET-may-split-line' on how to modify this behavior). As +a special case, on a headline, splitting can only happen on the +title itself. E.g., this excludes breaking stars or tags. + +With a `\\[universal-argument]' prefix, set \ +`org-insert-heading-respect-content' to +a non-nil value for the duration of the command. This forces the +insertion of a heading after the current subtree, independently +on the location of point. + +With a `\\[universal-argument] \\[universal-argument]' prefix, \ +insert the heading at the end of the tree +above the current heading. For example, if point is within a +2nd-level heading, then it will insert a 2nd-level heading at +the end of the 1st-level parent subtree. When INVISIBLE-OK is set, stop at invisible headlines when going back. This is important for non-interactive uses of the -command." +command. + +When optional argument TOP is non-nil, insert a level 1 heading, +unconditionally." (interactive "P") - (if (org-called-interactively-p 'any) (org-reveal)) - (let ((itemp (org-in-item-p)) + (let ((itemp (and (not top) (org-in-item-p))) (may-split (org-get-alist-option org-M-RET-may-split-line 'headline)) (respect-content (or org-insert-heading-respect-content (equal arg '(4)))) - (initial-content "") - (adjust-empty-lines t)) + (initial-content "")) (cond @@ -7621,9 +7889,7 @@ command." (insert "\n* "))) (run-hooks 'org-insert-heading-hook)) - ((and itemp (not (member arg '((4) (16))))) - ;; Insert an item - (org-insert-item)) + ((and itemp (not (member arg '((4) (16)))) (org-insert-item))) (t ;; Maybe move at the end of the subtree @@ -7639,25 +7905,26 @@ command." (org-previous-line-empty-p) ;; We will decide later nil)) - ;; Get a level string to fall back on + ;; Get a level string to fall back on. (fix-level (if (org-before-first-heading-p) "*" (save-excursion (org-back-to-heading t) - (if (org-previous-line-empty-p) (setq empty-line-p t)) + (when (org-previous-line-empty-p) (setq empty-line-p t)) (looking-at org-outline-regexp) (make-string (1- (length (match-string 0))) ?*)))) (stars (save-excursion (condition-case nil - (progn + (if top "* " (org-back-to-heading invisible-ok) (when (and (not on-heading) (featurep 'org-inlinetask) (integerp org-inlinetask-min-level) (>= (length (match-string 0)) org-inlinetask-min-level)) - ;; Find a heading level before the inline task + ;; Find a heading level before the inline + ;; task. (while (and (setq level (org-up-heading-safe)) (>= level org-inlinetask-min-level))) (if (org-at-heading-p) @@ -7668,23 +7935,22 @@ command." (org-backward-heading-same-level 1 invisible-ok)) (= (point) (match-beginning 0))) - (not (org-previous-line-empty-p t))) + (not (org-next-line-empty-p))) (setq empty-line-p (or empty-line-p (org-previous-line-empty-p)))) (match-string 0)) (error (or fix-level "* "))))) (blank-a (cdr (assq 'heading org-blank-before-new-entry))) - (blank (if (eq blank-a 'auto) empty-line-p blank-a)) - pos hide-previous previous-pos) + (blank (if (eq blank-a 'auto) empty-line-p blank-a))) - ;; If we insert after content, move there and clean up whitespace - (when (and respect-content - (not (org-looking-at-p org-outline-regexp-bol))) + ;; If we insert after content, move there and clean up + ;; whitespace. + (when respect-content (if (not (org-before-first-heading-p)) (org-end-of-subtree nil t) (re-search-forward org-outline-regexp-bol) (beginning-of-line 0)) - (skip-chars-backward " \r\n") + (skip-chars-backward " \r\t\n") (and (not (looking-back "^\\*+" (line-beginning-position))) (looking-at "[ \t]+") (replace-match "")) (unless (eobp) (forward-char 1)) @@ -7692,14 +7958,17 @@ command." (unless (bobp) (backward-char 1)) (insert "\n"))) - ;; If we are splitting, grab the text that should be moved to the new headline + ;; If we are splitting, grab the text that should be moved + ;; to the new headline. (when may-split - (if (org-on-heading-p) - ;; This is a heading, we split intelligently (keeping tags) + (if (org-at-heading-p) + ;; This is a heading: split intelligently (keeping + ;; tags). (let ((pos (point))) - (goto-char (point-at-bol)) - (unless (looking-at org-complex-heading-regexp) - (error "This should not happen")) + (beginning-of-line) + (let ((case-fold-search nil)) + (unless (looking-at org-complex-heading-regexp) + (error "This should not happen"))) (when (and (match-beginning 4) (> pos (match-beginning 4)) (< pos (match-end 4))) @@ -7708,31 +7977,35 @@ command." (delete-region (point) (match-end 4)) (if (looking-at "[ \t]*$") (replace-match "") - (insert (make-string (length initial-content) ?\ ))) + (insert (make-string (length initial-content) ?\s))) (setq initial-content (org-trim initial-content))) (goto-char pos)) - ;; a normal line + ;; A normal line. (setq initial-content - (org-trim (buffer-substring (point) (point-at-eol)))) - (delete-region (point) (point-at-eol)))) + (org-trim + (delete-and-extract-region (point) (line-end-position)))))) - ;; If we are at the beginning of the line, insert before it. Else after + ;; If we are at the beginning of the line, insert before it. + ;; Otherwise, after it. (cond ((and (bolp) (looking-at "[ \t]*$"))) - ((and (bolp) (not (looking-at "[ \t]*$"))) - (open-line 1)) - (t - (goto-char (point-at-eol)) - (insert "\n"))) + ((bolp) (save-excursion (insert "\n"))) + (t (end-of-line) + (insert "\n"))) ;; Insert the new heading (insert stars) (just-one-space) (insert initial-content) - (when adjust-empty-lines - (if (or (not blank) - (and blank (not (org-previous-line-empty-p)))) - (org-N-empty-lines-before-current (if blank 1 0)))) + (unless (and blank (org-previous-line-empty-p)) + (org-N-empty-lines-before-current (if blank 1 0))) + ;; Adjust visibility, which may be messed up if we removed + ;; blank lines while previous entry was hidden. + (let ((bol (line-beginning-position))) + (dolist (o (overlays-at (1- bol))) + (when (and (eq (overlay-get o 'invisible) 'outline) + (eq (overlay-end o) bol)) + (move-overlay o (overlay-start o) (1- bol))))) (run-hooks 'org-insert-heading-hook))))))) (defun org-N-empty-lines-before-current (N) @@ -7752,20 +8025,23 @@ When NO-TAGS is non-nil, don't include tags. When NO-TODO is non-nil, don't include TODO keywords." (save-excursion (org-back-to-heading t) - (cond - ((and no-tags no-todo) - (looking-at org-complex-heading-regexp) - (match-string 4)) - (no-tags - (looking-at (concat org-outline-regexp - "\\(.*?\\)" - "\\(?:[ \t]+:[[:alnum:]:_@#%]+:\\)?[ \t]*$")) - (match-string 1)) - (no-todo - (looking-at org-todo-line-regexp) - (match-string 3)) - (t (looking-at org-heading-regexp) - (match-string 2))))) + (let ((case-fold-search nil)) + (cond + ((and no-tags no-todo) + (looking-at org-complex-heading-regexp) + ;; Return value has to be a string, but match group 4 is + ;; optional. + (or (match-string 4) "")) + (no-tags + (looking-at (concat org-outline-regexp + "\\(.*?\\)" + "\\(?:[ \t]+:[[:alnum:]:_@#%]+:\\)?[ \t]*$")) + (match-string 1)) + (no-todo + (looking-at org-todo-line-regexp) + (match-string 3)) + (t (looking-at org-heading-regexp) + (match-string 2)))))) (defvar orgstruct-mode) ; defined below @@ -7780,24 +8056,24 @@ This is a list with the following elements: - the tags string, or nil." (save-excursion (org-back-to-heading t) - (if (let (case-fold-search) - (looking-at - (if orgstruct-mode - org-heading-regexp - org-complex-heading-regexp))) - (if orgstruct-mode - (list (length (match-string 1)) - (org-reduced-level (length (match-string 1))) - nil - nil - (match-string 2) - nil) - (list (length (match-string 1)) - (org-reduced-level (length (match-string 1))) - (org-match-string-no-properties 2) - (and (match-end 3) (aref (match-string 3) 2)) - (org-match-string-no-properties 4) - (org-match-string-no-properties 5)))))) + (when (let (case-fold-search) + (looking-at + (if orgstruct-mode + org-heading-regexp + org-complex-heading-regexp))) + (if orgstruct-mode + (list (length (match-string 1)) + (org-reduced-level (length (match-string 1))) + nil + nil + (match-string 2) + nil) + (list (length (match-string 1)) + (org-reduced-level (length (match-string 1))) + (match-string-no-properties 2) + (and (match-end 3) (aref (match-string 3) 2)) + (match-string-no-properties 4) + (match-string-no-properties 5)))))) (defun org-get-entry () "Get the entry text, after heading, entire subtree." @@ -7805,6 +8081,24 @@ This is a list with the following elements: (org-back-to-heading t) (buffer-substring (point-at-bol 2) (org-end-of-subtree t)))) +(defun org-edit-headline (&optional heading) + "Edit the current headline. +Set it to HEADING when provided." + (interactive) + (org-with-wide-buffer + (org-back-to-heading t) + (let ((case-fold-search nil)) + (when (looking-at org-complex-heading-regexp) + (let* ((old (match-string-no-properties 4)) + (new (save-match-data + (org-trim (or heading (read-string "Edit: " old)))))) + (unless (equal old new) + (if old (replace-match new t t nil 4) + (goto-char (or (match-end 3) (match-end 2) (match-end 1))) + (insert " " new)) + (org-set-tags nil t) + (when (looking-at "[ \t]*$") (replace-match "")))))))) + (defun org-insert-heading-after-current () "Insert a new heading with same level as current, after current subtree." (interactive) @@ -7825,9 +8119,14 @@ This is a list with the following elements: (defun org-insert-todo-heading (arg &optional force-heading) "Insert a new heading with the same level and TODO state as current heading. -If the heading has no TODO state, or if the state is DONE, use the first -state (TODO by default). Also with one prefix arg, force first state. With -two prefix args, force inserting at the end of the parent subtree." + +If the heading has no TODO state, or if the state is DONE, use +the first state (TODO by default). Also with one prefix arg, +force first state. With two prefix args, force inserting at the +end of the parent subtree. + +When called at a plain list item, insert a new item with an +unchecked check box." (interactive "P") (when (or force-heading (not (org-insert-item 'checkbox))) (org-insert-heading (or (and (equal arg '(16)) '(16)) @@ -7835,19 +8134,18 @@ two prefix args, force inserting at the end of the parent subtree." (save-excursion (org-back-to-heading) (outline-previous-heading) - (looking-at org-todo-line-regexp)) - (let* - ((new-mark-x - (if (or (equal arg '(4)) - (not (match-beginning 2)) - (member (match-string 2) org-done-keywords)) - (car org-todo-keywords-1) - (match-string 2))) - (new-mark - (or - (run-hook-with-args-until-success - 'org-todo-get-default-hook new-mark-x nil) - new-mark-x))) + (let ((case-fold-search nil)) (looking-at org-todo-line-regexp))) + (let* ((new-mark-x + (if (or (equal arg '(4)) + (not (match-beginning 2)) + (member (match-string 2) org-done-keywords)) + (car org-todo-keywords-1) + (match-string 2))) + (new-mark + (or + (run-hook-with-args-until-success + 'org-todo-get-default-hook new-mark-x nil) + new-mark-x))) (beginning-of-line 1) (and (looking-at org-outline-regexp) (goto-char (match-end 0)) (if org-treat-insert-todo-heading-as-state-change @@ -7895,18 +8193,17 @@ See also `org-promote'." (org-fix-position-after-promote)) (defun org-demote-subtree () - "Demote the entire subtree. See `org-demote'. -See also `org-promote'." + "Demote the entire subtree. +See `org-demote' and `org-promote'." (interactive) (save-excursion (org-with-limited-levels (org-map-tree 'org-demote))) (org-fix-position-after-promote)) - (defun org-do-promote () "Promote the current heading higher up the tree. -If the region is active in `transient-mark-mode', promote all headings -in the region." +If the region is active in `transient-mark-mode', promote all +headings in the region." (interactive) (save-excursion (if (org-region-active-p) @@ -7916,8 +8213,8 @@ in the region." (defun org-do-demote () "Demote the current heading lower down the tree. -If the region is active in `transient-mark-mode', demote all headings -in the region." +If the region is active in `transient-mark-mode', demote all +headings in the region." (interactive) (save-excursion (if (org-region-active-p) @@ -7926,23 +8223,24 @@ in the region." (org-fix-position-after-promote)) (defun org-fix-position-after-promote () - "Make sure that after pro/demotion cursor position is right." + "Fix cursor position and indentation after demoting/promoting." (let ((pos (point))) (when (save-excursion - (beginning-of-line 1) - (looking-at org-todo-line-regexp) - (or (equal pos (match-end 1)) (equal pos (match-end 2)))) + (beginning-of-line) + (let ((case-fold-search nil)) (looking-at org-todo-line-regexp)) + (or (eq pos (match-end 1)) (eq pos (match-end 2)))) (cond ((eobp) (insert " ")) ((eolp) (insert " ")) - ((equal (char-after) ?\ ) (forward-char 1)))))) + ((equal (char-after) ?\s) (forward-char 1)))))) (defun org-current-level () "Return the level of the current entry, or nil if before the first headline. -The level is the number of stars at the beginning of the headline." - (save-excursion - (org-with-limited-levels - (if (ignore-errors (org-back-to-heading t)) - (funcall outline-level))))) +The level is the number of stars at the beginning of the +headline. Use `org-reduced-level' to remove the effect of +`org-odd-levels'. Unlike to `org-outline-level', this function +ignores inlinetasks." + (let ((level (org-with-limited-levels (org-outline-level)))) + (and (> level 0) level))) (defun org-get-previous-line-level () "Return the outline depth of the last headline before the current line. @@ -7978,50 +8276,39 @@ even level numbers will become the next higher odd number." ((< change 0) (max 1 (1+ (* 2 (/ (+ level (* 2 change)) 2)))))) (max 1 (+ level (or change 0))))) -(if (boundp 'define-obsolete-function-alias) - (if (or (featurep 'xemacs) (< emacs-major-version 23)) - (define-obsolete-function-alias 'org-get-legal-level - 'org-get-valid-level) - (define-obsolete-function-alias 'org-get-legal-level - 'org-get-valid-level "23.1"))) - (defun org-promote () - "Promote the current heading higher up the tree. -If the region is active in `transient-mark-mode', promote all headings -in the region." - (org-back-to-heading t) - (let* ((level (save-match-data (funcall outline-level))) - (after-change-functions (remove 'flyspell-after-change-function - after-change-functions)) - (up-head (concat (make-string (org-get-valid-level level -1) ?*) " ")) - (diff (abs (- level (length up-head) -1)))) - (cond ((and (= level 1) org-called-with-limited-levels - org-allow-promoting-top-level-subtree) - (replace-match "# " nil t)) - ((= level 1) - (user-error "Cannot promote to level 0. UNDO to recover if necessary")) - (t (replace-match up-head nil t))) - ;; Fixup tag positioning - (unless (= level 1) - (and org-auto-align-tags (org-set-tags nil 'ignore-column)) - (if org-adapt-indentation (org-fixup-indentation (- diff)))) - (run-hooks 'org-after-promote-entry-hook))) + "Promote the current heading higher up the tree." + (org-with-wide-buffer + (org-back-to-heading t) + (let* ((after-change-functions (remq 'flyspell-after-change-function + after-change-functions)) + (level (save-match-data (funcall outline-level))) + (up-head (concat (make-string (org-get-valid-level level -1) ?*) " ")) + (diff (abs (- level (length up-head) -1)))) + (cond + ((and (= level 1) org-allow-promoting-top-level-subtree) + (replace-match "# " nil t)) + ((= level 1) + (user-error "Cannot promote to level 0. UNDO to recover if necessary")) + (t (replace-match up-head nil t))) + (unless (= level 1) + (when org-auto-align-tags (org-set-tags nil 'ignore-column)) + (when org-adapt-indentation (org-fixup-indentation (- diff)))) + (run-hooks 'org-after-promote-entry-hook)))) (defun org-demote () - "Demote the current heading lower down the tree. -If the region is active in `transient-mark-mode', demote all headings -in the region." - (org-back-to-heading t) - (let* ((level (save-match-data (funcall outline-level))) - (after-change-functions (remove 'flyspell-after-change-function - after-change-functions)) - (down-head (concat (make-string (org-get-valid-level level 1) ?*) " ")) - (diff (abs (- level (length down-head) -1)))) - (replace-match down-head nil t) - ;; Fixup tag positioning - (and org-auto-align-tags (org-set-tags nil 'ignore-column)) - (if org-adapt-indentation (org-fixup-indentation diff)) - (run-hooks 'org-after-demote-entry-hook))) + "Demote the current heading lower down the tree." + (org-with-wide-buffer + (org-back-to-heading t) + (let* ((after-change-functions (remq 'flyspell-after-change-function + after-change-functions)) + (level (save-match-data (funcall outline-level))) + (down-head (concat (make-string (org-get-valid-level level 1) ?*) " ")) + (diff (abs (- level (length down-head) -1)))) + (replace-match down-head nil t) + (when org-auto-align-tags (org-set-tags nil 'ignore-column)) + (when org-adapt-indentation (org-fixup-indentation diff)) + (run-hooks 'org-after-demote-entry-hook)))) (defun org-cycle-level () "Cycle the level of an empty headline through possible states. @@ -8036,32 +8323,32 @@ After top level, it switches back to sibling level." (cond ;; If first headline in file, promote to top-level. ((= prev-level 0) - (loop repeat (/ (- cur-level 1) (org-level-increment)) - do (org-do-promote))) + (cl-loop repeat (/ (- cur-level 1) (org-level-increment)) + do (org-do-promote))) ;; If same level as prev, demote one. ((= prev-level cur-level) (org-do-demote)) ;; If parent is top-level, promote to top level if not already. ((= prev-level 1) - (loop repeat (/ (- cur-level 1) (org-level-increment)) - do (org-do-promote))) + (cl-loop repeat (/ (- cur-level 1) (org-level-increment)) + do (org-do-promote))) ;; If top-level, return to prev-level. ((= cur-level 1) - (loop repeat (/ (- prev-level 1) (org-level-increment)) - do (org-do-demote))) + (cl-loop repeat (/ (- prev-level 1) (org-level-increment)) + do (org-do-demote))) ;; If less than prev-level, promote one. ((< cur-level prev-level) (org-do-promote)) ;; If deeper than prev-level, promote until higher than ;; prev-level. ((> cur-level prev-level) - (loop repeat (+ 1 (/ (- cur-level prev-level) (org-level-increment))) - do (org-do-promote)))) + (cl-loop repeat (+ 1 (/ (- cur-level prev-level) (org-level-increment))) + do (org-do-promote)))) t)))) (defun org-map-tree (fun) "Call FUN for every heading underneath the current one." - (org-back-to-heading) + (org-back-to-heading t) (let ((level (funcall outline-level))) (save-excursion (funcall fun) @@ -8077,39 +8364,123 @@ After top level, it switches back to sibling level." (save-excursion (setq end (copy-marker end)) (goto-char beg) - (if (and (re-search-forward org-outline-regexp-bol nil t) - (< (point) end)) - (funcall fun)) + (when (and (re-search-forward org-outline-regexp-bol nil t) + (< (point) end)) + (funcall fun)) (while (and (progn (outline-next-heading) (< (point) end)) (not (eobp))) (funcall fun))))) -(defvar org-property-end-re) ; silence byte-compiler (defun org-fixup-indentation (diff) "Change the indentation in the current entry by DIFF. -However, if any line in the current entry has no indentation, or if it -would end up with no indentation after the change, nothing at all is done." - (save-excursion - (let ((end (save-excursion (outline-next-heading) - (point-marker))) - (prohibit (if (> diff 0) - "^\\S-" - (concat "^ \\{0," (int-to-string (- diff)) "\\}\\S-"))) - col) - (unless (save-excursion (end-of-line 1) - (re-search-forward prohibit end t)) - (while (and (< (point) end) - (re-search-forward "^[ \t]+" end t)) - (goto-char (match-end 0)) - (setq col (current-column)) - (if (< diff 0) (replace-match "")) - (org-indent-to-column (+ diff col)))) - (move-marker end nil)))) + +DIFF is an integer. Indentation is done according to the +following rules: + + - Planning information and property drawers are always indented + according to the new level of the headline; + + - Footnote definitions and their contents are ignored; + + - Inlinetasks' boundaries are not shifted; + + - Empty lines are ignored; + + - Other lines' indentation are shifted by DIFF columns, unless + it would introduce a structural change in the document, in + which case no shifting is done at all. + +Assume point is at a heading or an inlinetask beginning." + (org-with-wide-buffer + (narrow-to-region (line-beginning-position) + (save-excursion + (if (org-with-limited-levels (org-at-heading-p)) + (org-with-limited-levels (outline-next-heading)) + (org-inlinetask-goto-end)) + (point))) + (forward-line) + ;; Indent properly planning info and property drawer. + (when (looking-at-p org-planning-line-re) + (org-indent-line) + (forward-line)) + (when (looking-at org-property-drawer-re) + (goto-char (match-end 0)) + (forward-line) + (save-excursion (org-indent-region (match-beginning 0) (match-end 0)))) + (catch 'no-shift + (when (zerop diff) (throw 'no-shift nil)) + ;; If DIFF is negative, first check if a shift is possible at all + ;; (e.g., it doesn't break structure). This can only happen if + ;; some contents are not properly indented. + (let ((case-fold-search t)) + (when (< diff 0) + (let ((diff (- diff)) + (forbidden-re (concat org-outline-regexp + "\\|" + (substring org-footnote-definition-re 1)))) + (save-excursion + (while (not (eobp)) + (cond + ((looking-at-p "[ \t]*$") (forward-line)) + ((and (looking-at-p org-footnote-definition-re) + (let ((e (org-element-at-point))) + (and (eq (org-element-type e) 'footnote-definition) + (goto-char (org-element-property :end e)))))) + ((looking-at-p org-outline-regexp) (forward-line)) + ;; Give up if shifting would move before column 0 or + ;; if it would introduce a headline or a footnote + ;; definition. + (t + (skip-chars-forward " \t") + (let ((ind (current-column))) + (when (or (< ind diff) + (and (= ind diff) (looking-at-p forbidden-re))) + (throw 'no-shift nil))) + ;; Ignore contents of example blocks and source + ;; blocks if their indentation is meant to be + ;; preserved. Jump to block's closing line. + (beginning-of-line) + (or (and (looking-at-p "[ \t]*#\\+BEGIN_\\(EXAMPLE\\|SRC\\)") + (let ((e (org-element-at-point))) + (and (memq (org-element-type e) + '(example-block src-block)) + (or org-src-preserve-indentation + (org-element-property :preserve-indent e)) + (goto-char (org-element-property :end e)) + (progn (skip-chars-backward " \r\t\n") + (beginning-of-line) + t)))) + (forward-line)))))))) + ;; Shift lines but footnote definitions, inlinetasks boundaries + ;; by DIFF. Also skip contents of source or example blocks + ;; when indentation is meant to be preserved. + (while (not (eobp)) + (cond + ((and (looking-at-p org-footnote-definition-re) + (let ((e (org-element-at-point))) + (and (eq (org-element-type e) 'footnote-definition) + (goto-char (org-element-property :end e)))))) + ((looking-at-p org-outline-regexp) (forward-line)) + ((looking-at-p "[ \t]*$") (forward-line)) + (t + (indent-line-to (+ (org-get-indentation) diff)) + (beginning-of-line) + (or (and (looking-at-p "[ \t]*#\\+BEGIN_\\(EXAMPLE\\|SRC\\)") + (let ((e (org-element-at-point))) + (and (memq (org-element-type e) + '(example-block src-block)) + (or org-src-preserve-indentation + (org-element-property :preserve-indent e)) + (goto-char (org-element-property :end e)) + (progn (skip-chars-backward " \r\t\n") + (beginning-of-line) + t)))) + (forward-line))))))))) (defun org-convert-to-odd-levels () - "Convert an org-mode file with all levels allowed to one with odd levels. + "Convert an Org file with all levels allowed to one with odd levels. This will leave level 1 alone, convert level 2 to level 3, level 3 to level 5 etc." (interactive) @@ -8125,7 +8496,7 @@ level 5 etc." (end-of-line 1)))))) (defun org-convert-to-oddeven-levels () - "Convert an org-mode file with only odd levels to one with odd/even levels. + "Convert an Org file with only odd levels to one with odd/even levels. This promotes level 3 to level 2, level 5 to level 3 etc. If the file contains a section with an even level, conversion would destroy the structure of the file. An error is signaled in this @@ -8134,7 +8505,7 @@ case." (goto-char (point-min)) ;; First check if there are no even levels (when (re-search-forward "^\\(\\*\\*\\)+ " nil t) - (org-show-context t) + (org-show-set-visibility 'canonical) (error "Not all levels are odd in this file. Conversion not possible")) (when (yes-or-no-p "Are you sure you want to globally change levels to odd-even? ") (let ((outline-regexp org-outline-regexp) @@ -8177,7 +8548,7 @@ case." (setq beg (point))) (save-match-data (save-excursion (outline-end-of-heading) - (setq folded (outline-invisible-p))) + (setq folded (org-invisible-p))) (progn (org-end-of-subtree nil t) (unless (eobp) (backward-char)))) (outline-next-heading) @@ -8196,12 +8567,12 @@ case." (progn (goto-char beg0) (user-error "Cannot move past superior level or buffer limit"))) (setq cnt (1- cnt))) - (if (> arg 0) - ;; Moving forward - still need to move over subtree - (progn (org-end-of-subtree t t) - (save-excursion - (org-back-over-empty-lines) - (or (bolp) (newline))))) + (when (> arg 0) + ;; Moving forward - still need to move over subtree + (org-end-of-subtree t t) + (save-excursion + (org-back-over-empty-lines) + (or (bolp) (newline)))) (setq ne-ins (org-back-over-empty-lines)) (move-marker ins-point (point)) (setq txt (buffer-substring beg end)) @@ -8230,9 +8601,9 @@ case." (insert (make-string (- ne-ins ne-beg) ?\n))) (move-marker ins-point nil) (if folded - (hide-subtree) + (outline-hide-subtree) (org-show-entry) - (show-children) + (org-show-children) (org-cycle-hide-drawers 'children)) (org-clean-visibility-after-subtree-move) ;; move back to the initial column we were at @@ -8264,7 +8635,7 @@ of some markers in the region, even if CUT is non-nil. This is useful if the caller implements cut-and-paste as copy-then-paste-then-cut." (interactive "p") (let (beg end folded (beg0 (point))) - (if (org-called-interactively-p 'any) + (if (called-interactively-p 'any) (org-back-to-heading nil) ; take what looks like a subtree (org-back-to-heading t)) ; take what is really there (setq beg (point)) @@ -8273,11 +8644,14 @@ useful if the caller implements cut-and-paste as copy-then-paste-then-cut." (if nosubtrees (outline-next-heading) (save-excursion (outline-end-of-heading) - (setq folded (outline-invisible-p))) - (condition-case nil - (org-forward-heading-same-level (1- n) t) - (error nil)) + (setq folded (org-invisible-p))) + (ignore-errors (org-forward-heading-same-level (1- n) t)) (org-end-of-subtree t t))) + ;; Include the end of an inlinetask + (when (and (featurep 'org-inlinetask) + (looking-at-p (concat (org-inlinetask-outline-regexp) + "END[ \t]*$"))) + (end-of-line)) (setq end (point)) (goto-char beg0) (when (> end beg) @@ -8290,7 +8664,7 @@ useful if the caller implements cut-and-paste as copy-then-paste-then-cut." (if cut "Cut" "Copied") (length org-subtree-clip))))) -(defun org-paste-subtree (&optional level tree for-yank) +(defun org-paste-subtree (&optional level tree for-yank remove) "Paste the clipboard as a subtree, with modification of headline level. The entire subtree is promoted or demoted in order to match a new headline level. @@ -8313,15 +8687,17 @@ If optional TREE is given, use this text instead of the kill ring. When FOR-YANK is set, this is called by `org-yank'. In this case, do not move back over whitespace before inserting, and move point to the end of -the inserted text when done." +the inserted text when done. + +When REMOVE is non-nil, remove the subtree from the clipboard." (interactive "P") (setq tree (or tree (and kill-ring (current-kill 0)))) (unless (org-kill-is-subtree-p tree) (user-error "%s" - (substitute-command-keys - "The kill is not a (set of) tree(s) - please use \\[yank] to yank anyway"))) + (substitute-command-keys + "The kill is not a (set of) tree(s) - please use \\[yank] to yank anyway"))) (org-with-limited-levels - (let* ((visp (not (outline-invisible-p))) + (let* ((visp (not (org-invisible-p))) (txt tree) (^re_ "\\(\\*+\\)[ \t]*") (old-level (if (string-match org-outline-regexp-bol txt) @@ -8364,22 +8740,22 @@ the inserted text when done." (org-odd-levels-only nil) beg end newend) ;; Remove the forced level indicator - (if force-level - (delete-region (point-at-bol) (point))) + (when force-level + (delete-region (point-at-bol) (point))) ;; Paste (beginning-of-line (if (bolp) 1 2)) (setq beg (point)) (and (fboundp 'org-id-paste-tracker) (org-id-paste-tracker txt)) (insert-before-markers txt) - (unless (string-match "\n\\'" txt) (insert "\n")) + (unless (string-suffix-p "\n" txt) (insert "\n")) (setq newend (point)) (org-reinstall-markers-in-region beg) (setq end (point)) (goto-char beg) (skip-chars-forward " \t\n\r") (setq beg (point)) - (if (and (outline-invisible-p) visp) - (save-excursion (outline-show-heading))) + (when (and (org-invisible-p) visp) + (save-excursion (outline-show-heading))) ;; Shift if necessary (unless (= shift 0) (save-restriction @@ -8389,15 +8765,16 @@ the inserted text when done." (setq shift (+ delta shift))) (goto-char (point-min)) (setq newend (point-max)))) - (when (or (org-called-interactively-p 'interactive) for-yank) + (when (or (called-interactively-p 'interactive) for-yank) (message "Clipboard pasted as level %d subtree" new-level)) - (if (and (not for-yank) ; in this case, org-yank will decide about folding - kill-ring - (eq org-subtree-clip (current-kill 0)) - org-subtree-clip-folded) - ;; The tree was folded before it was killed/copied - (hide-subtree)) - (and for-yank (goto-char newend))))) + (when (and (not for-yank) ; in this case, org-yank will decide about folding + kill-ring + (eq org-subtree-clip (current-kill 0)) + org-subtree-clip-folded) + ;; The tree was folded before it was killed/copied + (outline-hide-subtree)) + (and for-yank (goto-char newend)) + (and remove (setq kill-ring (cdr kill-ring)))))) (defun org-kill-is-subtree-p (&optional txt) "Check if the current kill is an outline subtree, or a set of trees. @@ -8447,15 +8824,14 @@ called immediately, to move the markers with the entries." "Check if MARKER is between BEG and END. If yes, remember the marker and the distance to BEG." (when (and (marker-buffer marker) - (equal (marker-buffer marker) (current-buffer))) - (if (and (>= marker beg) (< marker end)) - (push (cons marker (- marker beg)) org-markers-to-move)))) + (equal (marker-buffer marker) (current-buffer)) + (>= marker beg) (< marker end)) + (push (cons marker (- marker beg)) org-markers-to-move))) (defun org-reinstall-markers-in-region (beg) "Move all remembered markers to their position relative to BEG." - (mapc (lambda (x) - (move-marker (car x) (+ beg (cdr x)))) - org-markers-to-move) + (dolist (x org-markers-to-move) + (move-marker (car x) (+ beg (cdr x)))) (setq org-markers-to-move nil)) (defun org-narrow-to-subtree () @@ -8467,7 +8843,7 @@ If yes, remember the marker and the distance to BEG." (narrow-to-region (progn (org-back-to-heading t) (point)) (progn (org-end-of-subtree t t) - (if (and (org-at-heading-p) (not (eobp))) (backward-char 1)) + (when (and (org-at-heading-p) (not (eobp))) (backward-char 1)) (point))))))) (defun org-narrow-to-block () @@ -8480,10 +8856,6 @@ If yes, remember the marker and the distance to BEG." (narrow-to-region (car blockp) (cdr blockp)) (user-error "Not in a block")))) -(eval-when-compile - (defvar org-property-drawer-re)) - -(defvar org-property-start-re) ;; defined below (defun org-clone-subtree-with-time-shift (n &optional shift) "Clone the task (subtree) at point N times. The clones will be inserted as siblings. @@ -8500,6 +8872,9 @@ stamps in the subtree shifted for each clone produced. If SHIFT is nil or the empty string, time stamps will be left alone. The ID property of the original subtree is removed. +In each clone, all the CLOCK entries will be removed. This +prevents Org from considering that the clocked times overlap. + If the original subtree did contain time stamps with a repeater, the following will happen: - the repeater will be removed in each clone @@ -8510,80 +8885,86 @@ the following will happen: - the start days in the repeater in the original entry will be shifted to past the last clone. In this way you can spell out a number of instances of a repeating task, -and still retain the repeater to cover future instances of the task." +and still retain the repeater to cover future instances of the task. + +As described above, N+1 clones are produced when the original +subtree has a repeater. Setting N to 0, then, can be used to +remove the repeater from a subtree and create a shifted clone +with the original repeater." (interactive "nNumber of clones to produce: ") - (let ((shift - (or shift - (if (and (not (equal current-prefix-arg '(4))) - (save-excursion - (re-search-forward org-ts-regexp-both - (save-excursion - (org-end-of-subtree t) - (point)) t))) - (read-from-minibuffer - "Date shift per clone (e.g. +1w, empty to copy unchanged): ") - ""))) ;; No time shift - (n-no-remove -1) - (drawer-re org-drawer-regexp) - beg end template task idprop - shift-n shift-what doshift nmin nmax) - (if (not (and (integerp n) (> n 0))) - (error "Invalid number of replications %s" n)) - (if (and (setq doshift (and (stringp shift) (string-match "\\S-" shift))) - (not (string-match "\\`[ \t]*\\+?\\([0-9]+\\)\\([hdwmy]\\)[ \t]*\\'" - shift))) - (error "Invalid shift specification %s" shift)) - (when doshift - (setq shift-n (string-to-number (match-string 1 shift)) - shift-what (cdr (assoc (match-string 2 shift) - '(("d" . day) ("w" . week) - ("m" . month) ("y" . year)))))) - (if (eq shift-what 'week) (setq shift-n (* 7 shift-n) shift-what 'day)) - (setq nmin 1 nmax n) - (org-back-to-heading t) - (setq beg (point)) - (setq idprop (org-entry-get nil "ID")) - (org-end-of-subtree t t) - (or (bolp) (insert "\n")) - (setq end (point)) - (setq template (buffer-substring beg end)) - (when (and doshift - (string-match "<[^<>\n]+ [.+]?\\+[0-9]+[hdwmy][^<>\n]*>" template)) - (delete-region beg end) - (setq end beg) - (setq nmin 0 nmax (1+ nmax) n-no-remove nmax)) - (goto-char end) - (loop for n from nmin to nmax do - ;; prepare clone - (with-temp-buffer - (insert template) - (org-mode) - (goto-char (point-min)) - (org-show-subtree) - (and idprop (if org-clone-delete-id - (org-entry-delete nil "ID") - (org-id-get-create t))) - (unless (= n 0) - (while (re-search-forward "^[ \t]*CLOCK:.*$" nil t) - (kill-whole-line)) - (goto-char (point-min)) - (while (re-search-forward drawer-re nil t) - (mapc (lambda (d) - (org-remove-empty-drawer-at d (point))) - org-drawers))) - (goto-char (point-min)) - (when doshift - (while (re-search-forward org-ts-regexp-both nil t) - (org-timestamp-change (* n shift-n) shift-what)) - (unless (= n n-no-remove) - (goto-char (point-min)) - (while (re-search-forward org-ts-regexp nil t) - (save-excursion - (goto-char (match-beginning 0)) - (if (looking-at "<[^<>\n]+\\( +[.+]?\\+[0-9]+[hdwmy]\\)") - (delete-region (match-beginning 1) (match-end 1))))))) - (setq task (buffer-string))) - (insert task)) + (unless (wholenump n) (user-error "Invalid number of replications %s" n)) + (when (org-before-first-heading-p) (user-error "No subtree to clone")) + (let* ((beg (save-excursion (org-back-to-heading t) (point))) + (end-of-tree (save-excursion (org-end-of-subtree t t) (point))) + (shift + (or shift + (if (and (not (equal current-prefix-arg '(4))) + (save-excursion + (goto-char beg) + (re-search-forward org-ts-regexp-both end-of-tree t))) + (read-from-minibuffer + "Date shift per clone (e.g. +1w, empty to copy unchanged): ") + ""))) ;No time shift + (doshift + (and (org-string-nw-p shift) + (or (string-match "\\`[ \t]*\\+?\\([0-9]+\\)\\([dwmy]\\)[ \t]*\\'" + shift) + (user-error "Invalid shift specification %s" shift))))) + (goto-char end-of-tree) + (unless (bolp) (insert "\n")) + (let* ((end (point)) + (template (buffer-substring beg end)) + (shift-n (and doshift (string-to-number (match-string 1 shift)))) + (shift-what (pcase (and doshift (match-string 2 shift)) + (`nil nil) + ("d" 'day) + ("w" (setq shift-n (* 7 shift-n)) 'day) + ("m" 'month) + ("y" 'year) + (_ (error "Unsupported time unit")))) + (nmin 1) + (nmax n) + (n-no-remove -1) + (idprop (org-entry-get nil "ID"))) + (when (and doshift + (string-match-p "<[^<>\n]+ [.+]?\\+[0-9]+[hdwmy][^<>\n]*>" + template)) + (delete-region beg end) + (setq end beg) + (setq nmin 0) + (setq nmax (1+ nmax)) + (setq n-no-remove nmax)) + (goto-char end) + (cl-loop for n from nmin to nmax do + (insert + ;; Prepare clone. + (with-temp-buffer + (insert template) + (org-mode) + (goto-char (point-min)) + (org-show-subtree) + (and idprop (if org-clone-delete-id + (org-entry-delete nil "ID") + (org-id-get-create t))) + (unless (= n 0) + (while (re-search-forward org-clock-line-re nil t) + (delete-region (line-beginning-position) + (line-beginning-position 2))) + (goto-char (point-min)) + (while (re-search-forward org-drawer-regexp nil t) + (org-remove-empty-drawer-at (point)))) + (goto-char (point-min)) + (when doshift + (while (re-search-forward org-ts-regexp-both nil t) + (org-timestamp-change (* n shift-n) shift-what)) + (unless (= n n-no-remove) + (goto-char (point-min)) + (while (re-search-forward org-ts-regexp nil t) + (save-excursion + (goto-char (match-beginning 0)) + (when (looking-at "<[^<>\n]+\\( +[.+]?\\+[0-9]+[hdwmy]\\)") + (delete-region (match-beginning 1) (match-end 1))))))) + (buffer-string))))) (goto-char beg))) ;;; Outline Sorting @@ -8621,7 +9002,8 @@ hook gets called. When a region or a plain list is sorted, the cursor will be in the first entry of the sorted region/list.") (defun org-sort-entries - (&optional with-case sorting-type getkey-func compare-func property) + (&optional with-case sorting-type getkey-func compare-func property + interactive?) "Sort entries on a certain level of an outline tree. If there is an active region, the entries in the region are sorted. Else, if the cursor is before the first entry, sort the top-level items. @@ -8632,33 +9014,40 @@ a time stamp, by a property, by priority order, or by a custom function. The command prompts for the sorting type unless it has been given to the function through the SORTING-TYPE argument, which needs to be a character, -\(?n ?N ?a ?A ?t ?T ?s ?S ?d ?D ?p ?P ?o ?O ?r ?R ?f ?F). Here is the -precise meaning of each character: +\(?n ?N ?a ?A ?t ?T ?s ?S ?d ?D ?p ?P ?o ?O ?r ?R ?f ?F ?k ?K). Here is +the precise meaning of each character: -n Numerically, by converting the beginning of the entry/item to a number. a Alphabetically, ignoring the TODO keyword and the priority, if any. -o By order of TODO keywords. -t By date/time, either the first active time stamp in the entry, or, if - none exist, by the first inactive one. -s By the scheduled date/time. -d By deadline date/time. c By creation time, which is assumed to be the first inactive time stamp at the beginning of a line. +d By deadline date/time. +k By clocking time. +n Numerically, by converting the beginning of the entry/item to a number. +o By order of TODO keywords. p By priority according to the cookie. r By the value of a property. +s By scheduled date/time. +t By date/time, either the first active time stamp in the entry, or, if + none exist, by the first inactive one. Capital letters will reverse the sort order. If the SORTING-TYPE is ?f or ?F, then GETKEY-FUNC specifies a function to be -called with point at the beginning of the record. It must return either -a string or a number that should serve as the sorting key for that record. +called with point at the beginning of the record. It must return a +value that is compatible with COMPARE-FUNC, the function used to +compare entries. Comparing entries ignores case by default. However, with an optional argument WITH-CASE, the sorting considers case as well. Sorting is done against the visible part of the headlines, it ignores hidden -links." - (interactive "P") +links. + +When sorting is done, call `org-after-sorting-entries-or-items-hook'. + +A non-nil value for INTERACTIVE? is used to signal that this +function is being called interactively." + (interactive (list current-prefix-arg nil nil nil nil t)) (let ((case-func (if with-case 'identity 'downcase)) (cmstr ;; The clock marker is lost when using `sort-subr', let's @@ -8677,10 +9066,10 @@ links." (setq end (region-end) what "region") (goto-char (region-beginning)) - (if (not (org-at-heading-p)) (outline-next-heading)) + (unless (org-at-heading-p) (outline-next-heading)) (setq start (point))) ((or (org-at-heading-p) - (condition-case nil (progn (org-back-to-heading) t) (error nil))) + (ignore-errors (progn (org-back-to-heading) t))) ;; we will sort the children of the current headline (org-back-to-heading) (setq start (point) @@ -8691,7 +9080,7 @@ links." (point)) what "children") (goto-char start) - (show-subtree) + (outline-show-subtree) (outline-next-heading)) (t ;; we will sort the top-level entries in this file @@ -8707,7 +9096,7 @@ links." (setq end (point-max)) (setq what "top-level") (goto-char start) - (show-all))) + (outline-show-all))) (setq beg (point)) (when (>= beg end) (goto-char start) (user-error "Nothing to sort")) @@ -8717,32 +9106,34 @@ links." re (concat "^" (regexp-quote stars) " +") re2 (concat "^" (regexp-quote (substring stars 0 -1)) "[ \t\n]") txt (buffer-substring beg end)) - (if (not (equal (substring txt -1) "\n")) (setq txt (concat txt "\n"))) - (if (and (not (equal stars "*")) (string-match re2 txt)) - (user-error "Region to sort contains a level above the first entry")) + (unless (equal (substring txt -1) "\n") (setq txt (concat txt "\n"))) + (when (and (not (equal stars "*")) (string-match re2 txt)) + (user-error "Region to sort contains a level above the first entry")) (unless sorting-type (message "Sort %s: [a]lpha [n]umeric [p]riority p[r]operty todo[o]rder [f]unc - [t]ime [s]cheduled [d]eadline [c]reated - A/N/P/R/O/F/T/S/D/C means reversed:" + [t]ime [s]cheduled [d]eadline [c]reated cloc[k]ing + A/N/P/R/O/F/T/S/D/C/K means reversed:" what) - (setq sorting-type (read-char-exclusive)) - - (unless getkey-func - (and (= (downcase sorting-type) ?f) - (setq getkey-func - (org-icompleting-read "Sort using function: " - obarray 'fboundp t nil nil)) - (setq getkey-func (intern getkey-func)))) - - (and (= (downcase sorting-type) ?r) - (not property) - (setq property - (org-icompleting-read "Property: " - (mapcar 'list (org-buffer-property-keys t)) - nil t)))) - + (setq sorting-type (read-char-exclusive))) + + (unless getkey-func + (and (= (downcase sorting-type) ?f) + (setq getkey-func + (or (and interactive? + (org-read-function + "Function for extracting keys: ")) + (error "Missing key extractor"))))) + + (and (= (downcase sorting-type) ?r) + (not property) + (setq property + (completing-read "Property: " + (mapcar #'list (org-buffer-property-keys t)) + nil t))) + + (when (member sorting-type '(?k ?K)) (org-clock-sum)) (message "Sorting entries...") (save-restriction @@ -8777,6 +9168,8 @@ links." (if (looking-at org-complex-heading-regexp) (funcall case-func (org-sort-remove-invisible (match-string 4))) nil)) + ((= dcst ?k) + (or (get-text-property (point) :org-clock-minutes) 0)) ((= dcst ?t) (let ((end (save-excursion (outline-next-heading) (point)))) (if (or (re-search-forward org-ts-regexp end t) @@ -8807,22 +9200,29 @@ links." ((= dcst ?r) (or (org-entry-get nil property) "")) ((= dcst ?o) - (if (looking-at org-complex-heading-regexp) - (- 9999 (length (member (match-string 2) - org-todo-keywords-1))))) + (when (looking-at org-complex-heading-regexp) + (let* ((m (match-string 2)) + (s (if (member m org-done-keywords) '- '+))) + (- 99 (funcall s (length (member m org-todo-keywords-1))))))) ((= dcst ?f) (if getkey-func (progn (setq tmp (funcall getkey-func)) - (if (stringp tmp) (setq tmp (funcall case-func tmp))) + (when (stringp tmp) (setq tmp (funcall case-func tmp))) tmp) (error "Invalid key function `%s'" getkey-func))) (t (error "Invalid sorting type `%c'" sorting-type)))) nil (cond ((= dcst ?a) 'string<) - ((= dcst ?f) compare-func) - ((member dcst '(?p ?t ?s ?d ?c)) '<))))) + ((= dcst ?f) + (or compare-func + (and interactive? + (org-read-function + (concat "Function for comparing keys " + "(empty for default `sort-subr' predicate): ") + 'allow-empty)))) + ((member dcst '(?p ?t ?s ?d ?c ?k)) '<))))) (run-hooks 'org-after-sorting-entries-or-items-hook) ;; Reset the clock marker if needed (when cmstr @@ -8832,60 +9232,18 @@ links." (move-marker org-clock-marker (point)))) (message "Sorting entries...done"))) -(defun org-do-sort (table what &optional with-case sorting-type) - "Sort TABLE of WHAT according to SORTING-TYPE. -The user will be prompted for the SORTING-TYPE if the call to this -function does not specify it. WHAT is only for the prompt, to indicate -what is being sorted. The sorting key will be extracted from -the car of the elements of the table. -If WITH-CASE is non-nil, the sorting will be case-sensitive." - (unless sorting-type - (message - "Sort %s: [a]lphabetic, [n]umeric, [t]ime. A/N/T means reversed:" - what) - (setq sorting-type (read-char-exclusive))) - (let ((dcst (downcase sorting-type)) - extractfun comparefun) - ;; Define the appropriate functions - (cond - ((= dcst ?n) - (setq extractfun 'string-to-number - comparefun (if (= dcst sorting-type) '< '>))) - ((= dcst ?a) - (setq extractfun (if with-case (lambda(x) (org-sort-remove-invisible x)) - (lambda(x) (downcase (org-sort-remove-invisible x)))) - comparefun (if (= dcst sorting-type) - 'string< - (lambda (a b) (and (not (string< a b)) - (not (string= a b))))))) - ((= dcst ?t) - (setq extractfun - (lambda (x) - (if (or (string-match org-ts-regexp x) - (string-match org-ts-regexp-both x)) - (float-time - (org-time-string-to-time (match-string 0 x))) - 0)) - comparefun (if (= dcst sorting-type) '< '>))) - (t (error "Invalid sorting type `%c'" sorting-type))) - - (sort (mapcar (lambda (x) (cons (funcall extractfun (car x)) (cdr x))) - table) - (lambda (a b) (funcall comparefun (car a) (car b)))))) - - ;;; The orgstruct minor mode ;; Define a minor mode which can be used in other modes in order to -;; integrate the org-mode structure editing commands. +;; integrate the Org mode structure editing commands. -;; This is really a hack, because the org-mode structure commands use +;; This is really a hack, because the Org mode structure commands use ;; keys which normally belong to the major mode. Here is how it ;; works: The minor mode defines all the keys necessary to operate the ;; structure commands, but wraps the commands into a function which ;; tests if the cursor is currently at a headline or a plain list ;; item. If that is the case, the structure command is used, -;; temporarily setting many Org-mode variables like regular +;; temporarily setting many Org mode variables like regular ;; expressions for filling etc. However, when any of those keys is ;; used at a different location, function uses `key-binding' to look ;; up if the key has an associated command in another currently active @@ -8917,10 +9275,10 @@ orgstruct(++)-mode." ;;;###autoload (define-minor-mode orgstruct-mode "Toggle the minor mode `orgstruct-mode'. -This mode is for using Org-mode structure commands in other -modes. The following keys behave as if Org-mode were active, if +This mode is for using Org mode structure commands in other +modes. The following keys behave as if Org mode were active, if the cursor is on a headline, or on a plain list item (both as -defined by Org-mode)." +defined by Org mode)." nil " OrgStruct" (make-sparse-keymap) (funcall (if orgstruct-mode 'add-to-invisibility-spec @@ -8937,40 +9295,38 @@ defined by Org-mode)." "Unconditionally turn on `orgstruct-mode'." (orgstruct-mode 1)) -(defvar org-fb-vars nil) -(make-variable-buffer-local 'org-fb-vars) +(defvar-local orgstruct-is-++ nil + "Is `orgstruct-mode' in ++ version in the current-buffer?") +(defvar-local org-fb-vars nil) (defun orgstruct++-mode (&optional arg) "Toggle `orgstruct-mode', the enhanced version of it. In addition to setting orgstruct-mode, this also exports all -indentation and autofilling variables from org-mode into the +indentation and autofilling variables from Org mode into the buffer. It will also recognize item context in multiline items." (interactive "P") (setq arg (prefix-numeric-value (or arg (if orgstruct-mode -1 1)))) (if (< arg 1) (progn (orgstruct-mode -1) - (mapc (lambda(v) - (org-set-local (car v) - (if (eq (car-safe (cadr v)) 'quote) (cadadr v) (cadr v)))) - org-fb-vars)) + (dolist (v org-fb-vars) + (set (make-local-variable (car v)) + (if (eq (car-safe (cadr v)) 'quote) + (cl-cadadr v) + (nth 1 v))))) (orgstruct-mode 1) (setq org-fb-vars nil) (unless org-local-vars (setq org-local-vars (org-get-local-variables))) (let (var val) - (mapc - (lambda (x) - (when (string-match - "^\\(paragraph-\\|auto-fill\\|normal-auto-fill\\|fill-paragraph\\|fill-prefix\\|indent-\\)" - (symbol-name (car x))) - (setq var (car x) val (nth 1 x)) - (push (list var `(quote ,(eval var))) org-fb-vars) - (org-set-local var (if (eq (car-safe val) 'quote) (nth 1 val) val)))) - org-local-vars) - (org-set-local 'orgstruct-is-++ t)))) - -(defvar orgstruct-is-++ nil - "Is `orgstruct-mode' in ++ version in the current-buffer?") -(make-variable-buffer-local 'orgstruct-is-++) + (dolist (x org-local-vars) + (when (string-match + "^\\(paragraph-\\|auto-fill\\|normal-auto-fill\\|fill-paragraph\ +\\|fill-prefix\\|indent-\\)" + (symbol-name (car x))) + (setq var (car x) val (nth 1 x)) + (push (list var `(quote ,(eval var))) org-fb-vars) + (set (make-local-variable var) + (if (eq (car-safe val) 'quote) (nth 1 val) val)))) + (setq-local orgstruct-is-++ t)))) ;;;###autoload (defun turn-on-orgstruct++ () @@ -8999,6 +9355,7 @@ buffer. It will also recognize item context in multiline items." org-ctrl-c-minus org-ctrl-c-star org-cycle + org-force-cycle-archived org-forward-heading-same-level org-insert-heading org-insert-heading-respect-content @@ -9018,6 +9375,7 @@ buffer. It will also recognize item context in multiline items." org-shifttab org-shifttab org-shiftup + org-show-children org-show-subtree org-sort org-up-element @@ -9025,8 +9383,7 @@ buffer. It will also recognize item context in multiline items." outline-next-visible-heading outline-previous-visible-heading outline-promote - outline-up-heading - show-children)) + outline-up-heading)) (let ((f (or (car-safe cell) cell)) (disable-when-heading-prefix (cdr-safe cell))) (when (fboundp f) @@ -9045,15 +9402,15 @@ buffer. It will also recognize item context in multiline items." (regexp-quote (cdr rep)) (car rep) (key-description binding))))) - (pushnew binding new-bindings :test 'equal))) + (cl-pushnew binding new-bindings :test 'equal))) (dolist (binding new-bindings) (let ((key (lookup-key orgstruct-mode-map binding))) (when (or (not key) (numberp key)) - (condition-case nil - (org-defkey orgstruct-mode-map - binding - (orgstruct-make-binding f binding disable-when-heading-prefix)) - (error nil))))))))) + (ignore-errors + (org-defkey orgstruct-mode-map + binding + (orgstruct-make-binding + f binding disable-when-heading-prefix)))))))))) (run-hooks 'orgstruct-setup-hook)) (defun orgstruct-make-binding (fun key disable-when-heading-prefix) @@ -9152,9 +9509,9 @@ definitions." ;; normalize contexts (mapcar (lambda(c) (cond ((listp (cadr c)) - (list (car c) (car c) (cadr c))) + (list (car c) (car c) (nth 1 c))) ((string= "" (cadr c)) - (list (car c) (car c) (caddr c))) + (list (car c) (car c) (nth 2 c))) (t c))) contexts)) (a alist) r s) @@ -9168,7 +9525,7 @@ definitions." (setq vrules (org-contextualize-validate-key (car c) contexts))) (mapc (lambda (vr) - (when (not (equal (car vr) (cadr vr))) + (unless (equal (car vr) (cadr vr)) (setq repl vr))) vrules) (if (not repl) (push c r) @@ -9185,39 +9542,37 @@ definitions." (delete-dups (mapcar (lambda (x) (let ((tpl (car x))) - (when (not (delq - nil - (mapcar (lambda (y) - (equal y tpl)) - s))) + (unless (delq + nil + (mapcar (lambda (y) + (equal y tpl)) + s)) x))) (reverse r)))))) (defun org-contextualize-validate-key (key contexts) "Check CONTEXTS for agenda or capture KEY." - (let (rr res) + (let (res) (dolist (r contexts) - (mapc - (lambda (rr) - (when - (and (equal key (car r)) - (if (functionp rr) (funcall rr) - (or (and (eq (car rr) 'in-file) - (buffer-file-name) - (string-match (cdr rr) (buffer-file-name))) - (and (eq (car rr) 'in-mode) - (string-match (cdr rr) (symbol-name major-mode))) - (and (eq (car rr) 'in-buffer) - (string-match (cdr rr) (buffer-name))) - (when (and (eq (car rr) 'not-in-file) - (buffer-file-name)) - (not (string-match (cdr rr) (buffer-file-name)))) - (when (eq (car rr) 'not-in-mode) - (not (string-match (cdr rr) (symbol-name major-mode)))) - (when (eq (car rr) 'not-in-buffer) - (not (string-match (cdr rr) (buffer-name))))))) - (push r res))) - (car (last r)))) + (dolist (rr (car (last r))) + (when + (and (equal key (car r)) + (if (functionp rr) (funcall rr) + (or (and (eq (car rr) 'in-file) + (buffer-file-name) + (string-match (cdr rr) (buffer-file-name))) + (and (eq (car rr) 'in-mode) + (string-match (cdr rr) (symbol-name major-mode))) + (and (eq (car rr) 'in-buffer) + (string-match (cdr rr) (buffer-name))) + (when (and (eq (car rr) 'not-in-file) + (buffer-file-name)) + (not (string-match (cdr rr) (buffer-file-name)))) + (when (eq (car rr) 'not-in-mode) + (not (string-match (cdr rr) (symbol-name major-mode)))) + (when (eq (car rr) 'not-in-buffer) + (not (string-match (cdr rr) (buffer-name))))))) + (push r res)))) (delete-dups (delq nil res)))) (defun org-context-p (&rest contexts) @@ -9235,45 +9590,47 @@ Possible values in the list of contexts are `table', `headline', and `item'." (org-in-item-p))) (goto-char pos)))) +(defconst org-unique-local-variables + '(org-element--cache + org-element--cache-objects + org-element--cache-sync-keys + org-element--cache-sync-requests + org-element--cache-sync-timer) + "List of local variables that cannot be transferred to another buffer.") + (defun org-get-local-variables () "Return a list of all local variables in an Org mode buffer." - (let (varlist) - (with-current-buffer (get-buffer-create "*Org tmp*") - (erase-buffer) - (org-mode) - (setq varlist (buffer-local-variables))) - (kill-buffer "*Org tmp*") - (delq nil - (mapcar - (lambda (x) - (setq x - (if (symbolp x) - (list x) - (list (car x) (cdr x)))) - (if (and (not (get (car x) 'org-state)) - (string-match - "^\\(org-\\|orgtbl-\\|outline-\\|comment-\\|paragraph-\\|auto-fill\\|normal-auto-fill\\|fill-paragraph\\|indent-\\)" - (symbol-name (car x)))) - x nil)) - varlist)))) + (delq nil + (mapcar + (lambda (x) + (let* ((binding (if (symbolp x) (list x) (list (car x) (cdr x)))) + (name (car binding))) + (and (not (get name 'org-state)) + (not (memq name org-unique-local-variables)) + (string-match-p + "\\`\\(org-\\|orgtbl-\\|outline-\\|comment-\\|paragraph-\\|\ +auto-fill\\|normal-auto-fill\\|fill-paragraph\\|indent-\\)" + (symbol-name name)) + binding))) + (with-temp-buffer + (org-mode) + (buffer-local-variables))))) (defun org-clone-local-variables (from-buffer &optional regexp) "Clone local variables from FROM-BUFFER. Optional argument REGEXP selects variables to clone." - (mapc - (lambda (pair) - (and (symbolp (car pair)) - (or (null regexp) - (string-match regexp (symbol-name (car pair)))) - (set (make-local-variable (car pair)) - (cdr pair)))) - (buffer-local-variables from-buffer))) + (dolist (pair (buffer-local-variables from-buffer)) + (pcase pair + (`(,name . ,value) ;ignore unbound variables + (when (and (not (memq name org-unique-local-variables)) + (or (null regexp) (string-match-p regexp (symbol-name name)))) + (set (make-local-variable name) value)))))) ;;;###autoload (defun org-run-like-in-org-mode (cmd) - "Run a command, pretending that the current buffer is in Org-mode. + "Run a command, pretending that the current buffer is in Org mode. This will temporarily bind local variables that are typically bound in -Org-mode to the values they have in Org-mode, and then interactively +Org mode to the values they have in Org mode, and then interactively call CMD." (org-load-modules-maybe) (unless org-local-vars @@ -9287,67 +9644,119 @@ call CMD." (eval `(let ,binds (call-interactively (quote ,cmd)))))) -;;;; Archiving - (defun org-get-category (&optional pos force-refresh) "Get the category applying to position POS." (save-match-data - (if force-refresh (org-refresh-category-properties)) + (when force-refresh (org-refresh-category-properties)) (let ((pos (or pos (point)))) (or (get-text-property pos 'org-category) (progn (org-refresh-category-properties) (get-text-property pos 'org-category)))))) -(defun org-refresh-category-properties () - "Refresh category text properties in the buffer." - (let ((case-fold-search t) - (inhibit-read-only t) - (def-cat (cond - ((null org-category) - (if buffer-file-name - (file-name-sans-extension - (file-name-nondirectory buffer-file-name)) - "???")) - ((symbolp org-category) (symbol-name org-category)) - (t org-category))) - beg end cat pos optionp) - (org-with-silent-modifications - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (put-text-property (point) (point-max) 'org-category def-cat) - (while (re-search-forward - "^\\(#\\+CATEGORY:\\|[ \t]*:CATEGORY:\\)\\(.*\\)" nil t) - (setq pos (match-end 0) - optionp (equal (char-after (match-beginning 0)) ?#) - cat (org-trim (match-string 2))) - (if optionp - (setq beg (point-at-bol) end (point-max)) - (org-back-to-heading t) - (setq beg (point) end (org-end-of-subtree t t))) - (put-text-property beg end 'org-category cat) - (put-text-property beg end 'org-category-position beg) - (goto-char pos))))))) +;;; Refresh properties (defun org-refresh-properties (dprop tprop) "Refresh buffer text properties. -DPROP is the drawer property and TPROP is the corresponding text -property to set." - (let ((case-fold-search t) - (inhibit-read-only t) p) +DPROP is the drawer property and TPROP is either the +corresponding text property to set, or an alist with each element +being a text property (as a symbol) and a function to apply to +the value of the drawer property." + (let* ((case-fold-search t) + (inhibit-read-only t) + (inherit? (org-property-inherit-p dprop)) + (property-re (org-re-property (concat (regexp-quote dprop) "\\+?") t)) + (global (and inherit? (org--property-global-value dprop nil)))) (org-with-silent-modifications - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (while (re-search-forward (concat "^[ \t]*:" dprop ": +\\(.*\\)[ \t]*$") nil t) - (setq p (org-match-string-no-properties 1)) - (save-excursion - (org-back-to-heading t) - (put-text-property - (point-at-bol) (or (outline-next-heading) (point-max)) tprop p)))))))) + (org-with-point-at 1 + ;; Set global values (e.g., values defined through + ;; "#+PROPERTY:" keywords) to the whole buffer. + (when global (put-text-property (point-min) (point-max) tprop global)) + ;; Set local values. + (while (re-search-forward property-re nil t) + (when (org-at-property-p) + (org-refresh-property tprop (org-entry-get (point) dprop) inherit?)) + (outline-next-heading)))))) + +(defun org-refresh-property (tprop p &optional inherit) + "Refresh the buffer text property TPROP from the drawer property P. +The refresh happens only for the current headline, or the whole +sub-tree if optional argument INHERIT is non-nil." + (unless (org-before-first-heading-p) + (save-excursion + (org-back-to-heading t) + (let ((start (point)) + (end (save-excursion + (if inherit (org-end-of-subtree t t) + (or (outline-next-heading) (point-max)))))) + (if (symbolp tprop) + ;; TPROP is a text property symbol. + (put-text-property start end tprop p) + ;; TPROP is an alist with (property . function) elements. + (pcase-dolist (`(,prop . ,f) tprop) + (put-text-property start end prop (funcall f p)))))))) +(defun org-refresh-category-properties () + "Refresh category text properties in the buffer." + (let ((case-fold-search t) + (inhibit-read-only t) + (default-category + (cond ((null org-category) + (if buffer-file-name + (file-name-sans-extension + (file-name-nondirectory buffer-file-name)) + "???")) + ((symbolp org-category) (symbol-name org-category)) + (t org-category)))) + (org-with-silent-modifications + (org-with-wide-buffer + ;; Set buffer-wide category. Search last #+CATEGORY keyword. + ;; This is the default category for the buffer. If none is + ;; found, fall-back to `org-category' or buffer file name. + (put-text-property + (point-min) (point-max) + 'org-category + (catch 'buffer-category + (goto-char (point-max)) + (while (re-search-backward "^[ \t]*#\\+CATEGORY:" (point-min) t) + (let ((element (org-element-at-point))) + (when (eq (org-element-type element) 'keyword) + (throw 'buffer-category + (org-element-property :value element))))) + default-category)) + ;; Set sub-tree specific categories. + (goto-char (point-min)) + (let ((regexp (org-re-property "CATEGORY"))) + (while (re-search-forward regexp nil t) + (let ((value (match-string-no-properties 3))) + (when (org-at-property-p) + (put-text-property + (save-excursion (org-back-to-heading t) (point)) + (save-excursion (org-end-of-subtree t t) (point)) + 'org-category + value))))))))) + +(defun org-refresh-stats-properties () + "Refresh stats text properties in the buffer." + (org-with-silent-modifications + (org-with-point-at 1 + (let ((regexp (concat org-outline-regexp-bol + ".*\\[\\([0-9]*\\)\\(?:%\\|/\\([0-9]*\\)\\)\\]"))) + (while (re-search-forward regexp nil t) + (let* ((numerator (string-to-number (match-string 1))) + (denominator (and (match-end 2) + (string-to-number (match-string 2)))) + (stats (cond ((not denominator) numerator) ;percent + ((= denominator 0) 0) + (t (/ (* numerator 100) denominator))))) + (put-text-property (point) (progn (org-end-of-subtree t t) (point)) + 'org-stats stats))))))) + +(defun org-refresh-effort-properties () + "Refresh effort properties" + (org-refresh-properties + org-effort-property + '((effort . identity) + (effort-minutes . org-duration-string-to-minutes)))) ;;;; Link Stuff @@ -9387,78 +9796,54 @@ property to set." (defvar org-store-link-plist nil "Plist with info about the most recently link created with `org-store-link'.") -(defvar org-link-protocols nil - "Link protocols added to Org-mode using `org-add-link-type'.") +(defun org-store-link-functions () + "Return a list of functions that are called to create and store a link. +The functions defined in the :store property of +`org-link-parameters'. -(defvar org-store-link-functions nil - "List of functions that are called to create and store a link. Each function will be called in turn until one returns a non-nil -value. Each function should check if it is responsible for creating -this link (for example by looking at the major mode). -If not, it must exit and return nil. -If yes, it should return a non-nil value after a calling -`org-store-link-props' with a list of properties and values. -Special properties are: +value. Each function should check if it is responsible for +creating this link (for example by looking at the major mode). +If not, it must exit and return nil. If yes, it should return +a non-nil value after calling `org-store-link-props' with a list +of properties and values. Special properties are: :type The link prefix, like \"http\". This must be given. :link The link, like \"http://www.astro.uva.nl/~dominik\". This is obligatory as well. :description Optional default description for the second pair - of brackets in an Org-mode link. The user can still change - this when inserting this link into an Org-mode buffer. + of brackets in an Org mode link. The user can still change + this when inserting this link into an Org mode buffer. In addition to these, any additional properties can be specified -and then used in capture templates.") - -(defun org-add-link-type (type &optional follow export) - "Add TYPE to the list of `org-link-types'. -Re-compute all regular expressions depending on `org-link-types' - -FOLLOW and EXPORT are two functions. - -FOLLOW should take the link path as the single argument and do whatever -is necessary to follow the link, for example find a file or display -a mail message. - -EXPORT should format the link path for export to one of the export formats. -It should be a function accepting three arguments: - - path the path of the link, the text after the prefix (like \"http:\") - desc the description of the link, if any, or a description added by - org-export-normalize-links if there is none - format the export format, a symbol like `html' or `latex' or `ascii'.. - -The function may use the FORMAT information to return different values -depending on the format. The return value will be put literally into -the exported file. If the return value is nil, this means Org should -do what it normally does with links which do not have EXPORT defined. - -Org-mode has a built-in default for exporting links. If you are happy with -this default, there is no need to define an export function for the link -type. For a simple example of an export function, see `org-bbdb.el'." - (add-to-list 'org-link-types type t) - (org-make-link-regexps) - (if (assoc type org-link-protocols) - (setcdr (assoc type org-link-protocols) (list follow export)) - (push (list type follow export) org-link-protocols))) +and then used in capture templates." + (cl-loop for link in org-link-parameters + with store-func + do (setq store-func (org-link-get-parameter (car link) :store)) + if store-func + collect store-func)) (defvar org-agenda-buffer-name) ; Defined in org-agenda.el (defvar org-id-link-to-org-use-id) ; Defined in org-id.el ;;;###autoload (defun org-store-link (arg) - "\\Store an org-link to the current location. + "Store an org-link to the current location. +\\ This link is added to `org-stored-links' and can later be inserted -into an org-buffer with \\[org-insert-link]. +into an Org buffer with `org-insert-link' (`\\[org-insert-link]'). -For some link types, a prefix arg is interpreted. -For links to Usenet articles, arg negates `org-gnus-prefer-web-links'. -For file links, arg negates `org-context-in-file-links'. +For some link types, a `\\[universal-argument]' prefix ARG is interpreted. \ +A single +`\\[universal-argument]' negates `org-context-in-file-links' for file links or +`org-gnus-prefer-web-links' for links to Usenet articles. -A double prefix arg force skipping storing functions that are not -part of Org's core. +A `\\[universal-argument] \\[universal-argument]' prefix ARG forces \ +skipping storing functions that are not +part of Org core. -A triple prefix arg force storing a link for each line in the +A `\\[universal-argument] \\[universal-argument] \\[universal-argument]' \ +prefix ARG forces storing a link for each line in the active region." (interactive "P") (org-load-modules-maybe) @@ -9473,111 +9858,111 @@ active region." (call-interactively 'org-store-link)) (move-beginning-of-line 2) (set-mark (point))))) - (org-with-limited-levels - (setq org-store-link-plist nil) - (let (link cpltxt desc description search - txt custom-id agenda-link sfuns sfunsn) - (cond + (setq org-store-link-plist nil) + (let (link cpltxt desc description search + txt custom-id agenda-link sfuns sfunsn) + (cond - ;; Store a link using an external link type - ((and (not (equal arg '(16))) - (setq sfuns - (delq - nil (mapcar (lambda (f) - (let (fs) (if (funcall f) (push f fs)))) - org-store-link-functions)) - sfunsn (mapcar (lambda (fu) (symbol-name (car fu))) sfuns)) - (or (and (cdr sfuns) - (funcall (intern - (completing-read - "Which function for creating the link? " - sfunsn nil t (car sfunsn))))) - (funcall (caar sfuns))) - (setq link (plist-get org-store-link-plist :link) - desc (or (plist-get org-store-link-plist - :description) - link)))) - - ;; Store a link from a source code buffer - ((org-src-edit-buffer-p) - (let (label gc) - (while (or (not label) - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (re-search-forward - (regexp-quote (format org-coderef-label-format label)) - nil t)))) - (when label (message "Label exists already") (sit-for 2)) - (setq label (read-string "Code line label: " label))) - (end-of-line 1) - (setq link (format org-coderef-label-format label)) - (setq gc (- 79 (length link))) - (if (< (current-column) gc) (org-move-to-column gc t) (insert " ")) - (insert link) - (setq link (concat "(" label ")") desc nil))) - - ;; We are in the agenda, link to referenced location - ((equal (org-bound-and-true-p org-agenda-buffer-name) (buffer-name)) - (let ((m (or (get-text-property (point) 'org-hd-marker) - (get-text-property (point) 'org-marker)))) - (when m - (org-with-point-at m - (setq agenda-link - (if (org-called-interactively-p 'any) - (call-interactively 'org-store-link) - (org-store-link nil))))))) - - ((eq major-mode 'calendar-mode) - (let ((cd (calendar-cursor-to-date))) - (setq link - (format-time-string - (car org-time-stamp-formats) - (apply 'encode-time - (list 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd) - nil nil nil)))) - (org-store-link-props :type "calendar" :date cd))) - - ((eq major-mode 'help-mode) - (setq link (concat "help:" (save-excursion - (goto-char (point-min)) - (looking-at "^[^ ]+") - (match-string 0)))) - (org-store-link-props :type "help")) - - ((eq major-mode 'w3-mode) - (setq cpltxt (if (and (buffer-name) - (not (string-match "Untitled" (buffer-name)))) - (buffer-name) - (url-view-url t)) - link (url-view-url t)) - (org-store-link-props :type "w3" :url (url-view-url t))) - - ((eq major-mode 'image-mode) - (setq cpltxt (concat "file:" - (abbreviate-file-name buffer-file-name)) - link cpltxt) - (org-store-link-props :type "image" :file buffer-file-name)) - - ;; In dired, store a link to the file of the current line - ((eq major-mode 'dired-mode) - (let ((file (dired-get-filename nil t))) - (setq file (if file - (abbreviate-file-name - (expand-file-name (dired-get-filename nil t))) - ;; otherwise, no file so use current directory. - default-directory)) - (setq cpltxt (concat "file:" file) - link cpltxt))) - - ((setq search (run-hook-with-args-until-success - 'org-create-file-search-functions)) - (setq link (concat "file:" (abbreviate-file-name buffer-file-name) - "::" search)) - (setq cpltxt (or description link))) - - ((and (buffer-file-name (buffer-base-buffer)) (derived-mode-p 'org-mode)) + ;; Store a link using an external link type + ((and (not (equal arg '(16))) + (setq sfuns + (delq + nil (mapcar (lambda (f) + (let (fs) (if (funcall f) (push f fs)))) + (org-store-link-functions))) + sfunsn (mapcar (lambda (fu) (symbol-name (car fu))) sfuns)) + (or (and (cdr sfuns) + (funcall (intern + (completing-read + "Which function for creating the link? " + sfunsn nil t (car sfunsn))))) + (funcall (caar sfuns))) + (setq link (plist-get org-store-link-plist :link) + desc (or (plist-get org-store-link-plist + :description) + link)))) + + ;; Store a link from a source code buffer. + ((org-src-edit-buffer-p) + (let ((coderef-format (org-src-coderef-format))) + (cond ((save-excursion + (beginning-of-line) + (looking-at (org-src-coderef-regexp coderef-format))) + (setq link (format "(%s)" (match-string-no-properties 3)))) + ((called-interactively-p 'any) + (let ((label (read-string "Code line label: "))) + (end-of-line) + (setq link (format coderef-format label)) + (let ((gc (- 79 (length link)))) + (if (< (current-column) gc) + (org-move-to-column gc t) + (insert " "))) + (insert link) + (setq link (concat "(" label ")")) + (setq desc nil))) + (t (setq link nil))))) + + ;; We are in the agenda, link to referenced location + ((equal (bound-and-true-p org-agenda-buffer-name) (buffer-name)) + (let ((m (or (get-text-property (point) 'org-hd-marker) + (get-text-property (point) 'org-marker)))) + (when m + (org-with-point-at m + (setq agenda-link + (if (called-interactively-p 'any) + (call-interactively 'org-store-link) + (org-store-link nil))))))) + + ((eq major-mode 'calendar-mode) + (let ((cd (calendar-cursor-to-date))) + (setq link + (format-time-string + (car org-time-stamp-formats) + (apply 'encode-time + (list 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd) + nil nil nil)))) + (org-store-link-props :type "calendar" :date cd))) + + ((eq major-mode 'help-mode) + (setq link (concat "help:" (save-excursion + (goto-char (point-min)) + (looking-at "^[^ ]+") + (match-string 0)))) + (org-store-link-props :type "help")) + + ((eq major-mode 'w3-mode) + (setq cpltxt (if (and (buffer-name) + (not (string-match "Untitled" (buffer-name)))) + (buffer-name) + (url-view-url t)) + link (url-view-url t)) + (org-store-link-props :type "w3" :url (url-view-url t))) + + ((eq major-mode 'image-mode) + (setq cpltxt (concat "file:" + (abbreviate-file-name buffer-file-name)) + link cpltxt) + (org-store-link-props :type "image" :file buffer-file-name)) + + ;; In dired, store a link to the file of the current line + ((derived-mode-p 'dired-mode) + (let ((file (dired-get-filename nil t))) + (setq file (if file + (abbreviate-file-name + (expand-file-name (dired-get-filename nil t))) + ;; otherwise, no file so use current directory. + default-directory)) + (setq cpltxt (concat "file:" file) + link cpltxt))) + + ((setq search (run-hook-with-args-until-success + 'org-create-file-search-functions)) + (setq link (concat "file:" (abbreviate-file-name buffer-file-name) + "::" search)) + (setq cpltxt (or description link))) + + ((and (buffer-file-name (buffer-base-buffer)) (derived-mode-p 'org-mode)) + (org-with-limited-levels (setq custom-id (org-entry-get nil "CUSTOM_ID")) (cond ;; Store a link using the target at point @@ -9590,7 +9975,7 @@ active region." link cpltxt)) ((and (featurep 'org-id) (or (eq org-id-link-to-org-use-id t) - (and (org-called-interactively-p 'any) + (and (called-interactively-p 'any) (or (eq org-id-link-to-org-use-id 'create-if-interactive) (and (eq org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id) @@ -9613,15 +9998,13 @@ active region." (abbreviate-file-name (buffer-file-name (buffer-base-buffer))))) ;; Add a context search string - (when (org-xor org-context-in-file-links arg) - (let* ((ee (org-element-at-point)) - (et (org-element-type ee)) - (ev (plist-get (cadr ee) :value)) - (ek (plist-get (cadr ee) :key)) - (eok (and (stringp ek) (string-match "name" ek)))) + (when (org-xor org-context-in-file-links + (equal arg '(4))) + (let* ((element (org-element-at-point)) + (name (org-element-property :name element))) (setq txt (cond ((org-at-heading-p) nil) - ((and (eq et 'keyword) eok) ev) + (name) ((org-region-active-p) (buffer-substring (region-beginning) (region-end))))) (when (or (null txt) (string-match "\\S-" txt)) @@ -9630,74 +10013,80 @@ active region." (condition-case nil (org-make-org-heading-search-string txt) (error ""))) - desc (or (and (eq et 'keyword) eok ev) + desc (or name (nth 4 (ignore-errors (org-heading-components))) "NONE"))))) - (if (string-match "::\\'" cpltxt) - (setq cpltxt (substring cpltxt 0 -2))) - (setq link cpltxt)))) - - ((buffer-file-name (buffer-base-buffer)) - ;; Just link to this file here. - (setq cpltxt (concat "file:" - (abbreviate-file-name - (buffer-file-name (buffer-base-buffer))))) - ;; Add a context string. - (when (org-xor org-context-in-file-links arg) - (setq txt (if (org-region-active-p) - (buffer-substring (region-beginning) (region-end)) - (buffer-substring (point-at-bol) (point-at-eol)))) - ;; Only use search option if there is some text. - (when (string-match "\\S-" txt) - (setq cpltxt - (concat cpltxt "::" (org-make-org-heading-search-string txt)) - desc "NONE"))) - (setq link cpltxt)) - - ((org-called-interactively-p 'interactive) - (user-error "No method for storing a link from this buffer")) - - (t (setq link nil))) - - ;; We're done setting link and desc, clean up - (if (consp link) (setq cpltxt (car link) link (cdr link))) - (setq link (or link cpltxt) - desc (or desc cpltxt)) - (cond ((equal desc "NONE") (setq desc nil)) - ((and desc (string-match org-bracket-link-analytic-regexp desc)) - (let ((d0 (match-string 3 desc)) - (p0 (match-string 5 desc))) - (setq desc - (replace-regexp-in-string - org-bracket-link-regexp - (concat (or p0 d0) - (if (equal (length (match-string 0 desc)) - (length desc)) "*" "")) desc))))) - - ;; Return the link - (if (not (and (or (org-called-interactively-p 'any) - executing-kbd-macro) - link)) - (or agenda-link (and link (org-make-link-string link desc))) - (push (list link desc) org-stored-links) - (message "Stored: %s" (or desc link)) - (when custom-id - (setq link (concat "file:" (abbreviate-file-name - (buffer-file-name)) "::#" custom-id)) - (push (list link desc) org-stored-links)) - (car org-stored-links)))))) + (when (string-match "::\\'" cpltxt) + (setq cpltxt (substring cpltxt 0 -2))) + (setq link cpltxt))))) + + ((buffer-file-name (buffer-base-buffer)) + ;; Just link to this file here. + (setq cpltxt (concat "file:" + (abbreviate-file-name + (buffer-file-name (buffer-base-buffer))))) + ;; Add a context string. + (when (org-xor org-context-in-file-links + (equal arg '(4))) + (setq txt (if (org-region-active-p) + (buffer-substring (region-beginning) (region-end)) + (buffer-substring (point-at-bol) (point-at-eol)))) + ;; Only use search option if there is some text. + (when (string-match "\\S-" txt) + (setq cpltxt + (concat cpltxt "::" (org-make-org-heading-search-string txt)) + desc "NONE"))) + (setq link cpltxt)) + + ((called-interactively-p 'interactive) + (user-error "No method for storing a link from this buffer")) + + (t (setq link nil))) + + ;; We're done setting link and desc, clean up + (when (consp link) (setq cpltxt (car link) link (cdr link))) + (setq link (or link cpltxt) + desc (or desc cpltxt)) + (cond ((not desc)) + ((equal desc "NONE") (setq desc nil)) + (t (setq desc + (replace-regexp-in-string + org-bracket-link-analytic-regexp + (lambda (m) (or (match-string 5 m) (match-string 3 m))) + desc)))) + ;; Return the link + (if (not (and (or (called-interactively-p 'any) + executing-kbd-macro) + link)) + (or agenda-link (and link (org-make-link-string link desc))) + (push (list link desc) org-stored-links) + (message "Stored: %s" (or desc link)) + (when custom-id + (setq link (concat "file:" (abbreviate-file-name + (buffer-file-name)) "::#" custom-id)) + (push (list link desc) org-stored-links)) + (car org-stored-links))))) (defun org-store-link-props (&rest plist) - "Store link properties, extract names and addresses." - (let (x adr) - (when (setq x (plist-get plist :from)) - (setq adr (mail-extract-address-components x)) - (setq plist (plist-put plist :fromname (car adr))) - (setq plist (plist-put plist :fromaddress (nth 1 adr)))) - (when (setq x (plist-get plist :to)) - (setq adr (mail-extract-address-components x)) - (setq plist (plist-put plist :toname (car adr))) - (setq plist (plist-put plist :toaddress (nth 1 adr))))) + "Store link properties, extract names, addresses and dates." + (let ((x (plist-get plist :from))) + (when x + (let ((adr (mail-extract-address-components x))) + (setq plist (plist-put plist :fromname (car adr))) + (setq plist (plist-put plist :fromaddress (nth 1 adr)))))) + (let ((x (plist-get plist :to))) + (when x + (let ((adr (mail-extract-address-components x))) + (setq plist (plist-put plist :toname (car adr))) + (setq plist (plist-put plist :toaddress (nth 1 adr)))))) + (let ((x (ignore-errors (date-to-time (plist-get plist :date))))) + (when x + (setq plist (plist-put plist :date-timestamp + (format-time-string + (org-time-stamp-format t) x))) + (setq plist (plist-put plist :date-timestamp-inactive + (format-time-string + (org-time-stamp-format t t) x))))) (let ((from (plist-get plist :from)) (to (plist-get plist :to))) (when (and from to org-from-is-user-regexp) @@ -9763,45 +10152,34 @@ according to FMT (default from `org-email-link-description-format')." (defun org-make-link-string (link &optional description) "Make a link with brackets, consisting of LINK and DESCRIPTION." - (unless (string-match "\\S-" link) - (error "Empty link")) - (when (and description - (stringp description) - (not (string-match "\\S-" description))) - (setq description nil)) - (when (stringp description) - ;; Remove brackets from the description, they are fatal. - (while (string-match "\\[" description) - (setq description (replace-match "{" t t description))) - (while (string-match "\\]" description) - (setq description (replace-match "}" t t description)))) - (when (equal link description) - ;; No description needed, it is identical - (setq description nil)) - (when (and (not description) - (not (string-match (org-image-file-name-regexp) link)) - (not (equal link (org-link-escape link)))) - (setq description (org-extract-attributes link))) - (setq link - (cond ((string-match (org-image-file-name-regexp) link) link) - ((string-match org-link-types-re link) - (concat (match-string 1 link) - (org-link-escape (substring link (match-end 1))))) - (t (org-link-escape link)))) - (concat "[[" link "]" - (if description (concat "[" description "]") "") - "]")) + (unless (org-string-nw-p link) (error "Empty link")) + (let ((uri (cond ((string-match org-link-types-re link) + (concat (match-string 1 link) + (org-link-escape (substring link (match-end 1))))) + ;; For readability, url-encode internal links only + ;; when absolutely needed (i.e, when they contain + ;; square brackets). File links however, are + ;; encoded since, e.g., spaces are significant. + ((or (file-name-absolute-p link) + (string-match-p "\\`\\.\\.?/\\|[][]" link)) + (org-link-escape link)) + (t link))) + (description + (and (org-string-nw-p description) + ;; Remove brackets from description, as they are fatal. + (replace-regexp-in-string + "[][]" (lambda (m) (if (equal "[" m) "{" "}")) + (org-trim description))))) + (format "[[%s]%s]" + uri + (if description (format "[%s]" description) "")))) (defconst org-link-escape-chars - '(?\ ?\[ ?\] ?\; ?\= ?\+) - "List of characters that should be escaped in link. + ;;%20 %5B %5D %25 + '(?\s ?\[ ?\] ?%) + "List of characters that should be escaped in a link when stored to Org. This is the list that is used for internal purposes.") -(defconst org-link-escape-chars-browser - '(?\ ?\") - "List of escapes for characters that are problematic in links. -This is the list that is used before handing over to the browser.") - (defun org-link-escape (text &optional table merge) "Return percent escaped representation of TEXT. TEXT is a string with the text to escape. @@ -9809,35 +10187,29 @@ Optional argument TABLE is a list with characters that should be escaped. When nil, `org-link-escape-chars' is used. If optional argument MERGE is set, merge TABLE into `org-link-escape-chars'." - (cond - ((and table merge) - (mapc (lambda (defchr) - (unless (member defchr table) - (setq table (cons defchr table)))) org-link-escape-chars)) - ((null table) - (setq table org-link-escape-chars))) - (mapconcat - (lambda (char) - (if (or (member char table) - (and (or (< char 32) (= char 37) (> char 126)) - org-url-hexify-p)) - (mapconcat (lambda (sequence-element) - (format "%%%.2X" sequence-element)) - (or (encode-coding-char char 'utf-8) - (error "Unable to percent escape character: %s" - (char-to-string char))) "") - (char-to-string char))) text "")) + (let ((characters-to-encode + (cond ((null table) org-link-escape-chars) + (merge (append org-link-escape-chars table)) + (t table)))) + (mapconcat + (lambda (c) + (if (or (memq c characters-to-encode) + (and org-url-hexify-p (or (< c 32) (> c 126)))) + (mapconcat (lambda (e) (format "%%%.2X" e)) + (or (encode-coding-char c 'utf-8) + (error "Unable to percent escape character: %c" c)) + "") + (char-to-string c))) + text ""))) (defun org-link-unescape (str) - "Unhex hexified Unicode strings as returned from the JavaScript function -encodeURIComponent. E.g. `%C3%B6' is the german o-Umlaut." - (unless (and (null str) (string= "" str)) - (let ((pos 0) (case-fold-search t) unhexed) - (while (setq pos (string-match "\\(%[0-9a-f][0-9a-f]\\)+" str pos)) - (setq unhexed (org-link-unescape-compound (match-string 0 str))) - (setq str (replace-match unhexed t t str)) - (setq pos (+ pos (length unhexed)))))) - str) + "Unhex hexified Unicode parts in string STR. +E.g. `%C3%B6' becomes the german o-Umlaut. This is the +reciprocal of `org-link-escape', which see." + (if (org-string-nw-p str) + (replace-regexp-in-string + "\\(%[0-9A-Za-z]\\{2\\}\\)+" #'org-link-unescape-compound str t t) + str)) (defun org-link-unescape-compound (hex) "Unhexify Unicode hex-chars. E.g. `%C3%B6' is the German o-Umlaut. @@ -9860,18 +10232,17 @@ Note: this function also decodes single byte encodings like ((>= val 192) (cons 2 192)) (t (cons 0 0))) (cons 6 128)))) - (if (>= val 192) (setq eat (car shift-xor))) + (when (>= val 192) (setq eat (car shift-xor))) (setq val (logxor val (cdr shift-xor))) (setq sum (+ (lsh sum (car shift-xor)) val)) - (if (> eat 0) (setq eat (- eat 1))) + (when (> eat 0) (setq eat (- eat 1))) (cond ((= 0 eat) ;multi byte - (setq ret (concat ret (org-char-to-string sum))) + (setq ret (concat ret (char-to-string sum))) (setq sum 0)) ((not bytes) ; single byte(s) - (setq ret (org-link-unescape-single-byte-sequence hex)))) - )) ;; end (while bytes - ret ))) + (setq ret (org-link-unescape-single-byte-sequence hex)))))) + ret))) (defun org-link-unescape-single-byte-sequence (hex) "Unhexify hex-encoded single byte character sequences." @@ -9901,28 +10272,47 @@ Note: this function also decodes single byte encodings like (defun org-link-prettify (link) "Return a human-readable representation of LINK. -The car of LINK must be a raw link the cdr of LINK must be either -a link description or nil." +The car of LINK must be a raw link. +The cdr of LINK must be either a link description or nil." (let ((desc (or (cadr link) ""))) (concat (format "%-45s" (substring desc 0 (min (length desc) 40))) "<" (car link) ">"))) ;;;###autoload (defun org-insert-link-global () - "Insert a link like Org-mode does. -This command can be called in any mode to insert a link in Org-mode syntax." + "Insert a link like Org mode does. +This command can be called in any mode to insert a link in Org syntax." (interactive) (org-load-modules-maybe) (org-run-like-in-org-mode 'org-insert-link)) -(defun org-insert-all-links (&optional keep) - "Insert all links in `org-stored-links'." +(defun org-insert-all-links (arg &optional pre post) + "Insert all links in `org-stored-links'. +When a universal prefix, do not delete the links from `org-stored-links'. +When `ARG' is a number, insert the last N link(s). +`PRE' and `POST' are optional arguments to define a string to +prepend or to append." (interactive "P") - (let ((links (copy-sequence org-stored-links)) l) - (while (setq l (if keep (pop links) (pop org-stored-links))) - (insert "- ") - (org-insert-link nil (car l) (or (cadr l) "")) - (insert "\n")))) + (let ((org-keep-stored-link-after-insertion (equal arg '(4))) + (links (copy-sequence org-stored-links)) + (pr (or pre "- ")) + (po (or post "\n")) + (cnt 1) l) + (if (null org-stored-links) + (message "No link to insert") + (while (and (or (listp arg) (>= arg cnt)) + (setq l (if (listp arg) + (pop links) + (pop org-stored-links)))) + (setq cnt (1+ cnt)) + (insert pr) + (org-insert-link nil (car l) (or (cadr l) "")) + (insert po))))) + +(defun org-insert-last-stored-link (arg) + "Insert the last link stored in `org-stored-links'." + (interactive "p") + (org-insert-all-links arg "" "\n")) (defun org-link-fontify-links-to-this-file () "Fontify links to the current file in `org-stored-links'." @@ -9946,73 +10336,73 @@ This command can be called in any mode to insert a link in Org-mode syntax." (put-text-property 0 (length l) 'face 'font-lock-comment-face l)) (delq nil (append a b))))) -(defvar org-link-links-in-this-file nil) +(defvar org--links-history nil) (defun org-insert-link (&optional complete-file link-location default-description) "Insert a link. At the prompt, enter the link. -Completion can be used to insert any of the link protocol prefixes like -http or ftp in use. +Completion can be used to insert any of the link protocol prefixes in use. The history can be used to select a link previously stored with `org-store-link'. When the empty string is entered (i.e. if you just -press RET at the prompt), the link defaults to the most recently -stored link. As SPC triggers completion in the minibuffer, you need to -use M-SPC or C-q SPC to force the insertion of a space character. +press `RET' at the prompt), the link defaults to the most recently +stored link. As `SPC' triggers completion in the minibuffer, you need to +use `M-SPC' or `C-q SPC' to force the insertion of a space character. You will also be prompted for a description, and if one is given, it will be displayed in the buffer instead of the link. -If there is already a link at point, this command will allow you to edit link -and description parts. +If there is already a link at point, this command will allow you to edit +link and description parts. -With a \\[universal-argument] prefix, prompts for a file to link to. The file name can -be selected using completion. The path to the file will be relative to the +With a `\\[universal-argument]' prefix, prompts for a file to link to. The \ +file name can be +selected using completion. The path to the file will be relative to the current directory if the file is in the current directory or a subdirectory. Otherwise, the link will be the absolute path as completed in the minibuffer \(i.e. normally ~/path/to/file). You can configure this behavior using the option `org-link-file-path-type'. -With two \\[universal-argument] prefixes, enforce an absolute path even if the file is in +With a `\\[universal-argument] \\[universal-argument]' prefix, enforce an \ +absolute path even if the file is in the current directory or below. -With three \\[universal-argument] prefixes, negate the meaning of -`org-keep-stored-link-after-insertion'. +A `\\[universal-argument] \\[universal-argument] \\[universal-argument]' \ +prefix negates `org-keep-stored-link-after-insertion'. If `org-make-link-description-function' is non-nil, this function will be called with the link target, and the result will be the default link description. -If the LINK-LOCATION parameter is non-nil, this value will be -used as the link location instead of reading one interactively. +If the LINK-LOCATION parameter is non-nil, this value will be used as +the link location instead of reading one interactively. -If the DEFAULT-DESCRIPTION parameter is non-nil, this value will -be used as the default description." +If the DEFAULT-DESCRIPTION parameter is non-nil, this value will be used +as the default description." (interactive "P") (let* ((wcf (current-window-configuration)) (origbuf (current-buffer)) - (region (if (org-region-active-p) - (buffer-substring (region-beginning) (region-end)))) + (region (when (org-region-active-p) + (buffer-substring (region-beginning) (region-end)))) (remove (and region (list (region-beginning) (region-end)))) (desc region) - tmphist ; byte-compile incorrectly complains about this (link link-location) (abbrevs org-link-abbrev-alist-local) - entry file all-prefixes auto-desc) + entry all-prefixes auto-desc) (cond - (link-location) ; specified by arg, just use it. + (link-location) ; specified by arg, just use it. ((org-in-regexp org-bracket-link-regexp 1) ;; We do have a link at point, and we are going to edit it. (setq remove (list (match-beginning 0) (match-end 0))) - (setq desc (if (match-end 3) (org-match-string-no-properties 3))) + (setq desc (when (match-end 3) (match-string-no-properties 3))) (setq link (read-string "Link: " (org-link-unescape - (org-match-string-no-properties 1))))) + (match-string-no-properties 1))))) ((or (org-in-regexp org-angle-link-re) (org-in-regexp org-plain-link-re)) ;; Convert to bracket link (setq remove (list (match-beginning 0) (match-end 0)) link (read-string "Link: " - (org-remove-angle-brackets (match-string 0))))) + (org-unbracket-string "<" ">" (match-string 0))))) ((member complete-file '((4) (16))) ;; Completing read for file names. (setq link (org-file-complete-link complete-file))) @@ -10035,92 +10425,91 @@ Use TAB to complete link prefixes, then RET for type-specific completion support (unless (pos-visible-in-window-p (point-max)) (org-fit-window-to-buffer)) (and (window-live-p cw) (select-window cw))) - ;; Fake a link history, containing the stored links. - (setq tmphist (append (mapcar 'car org-stored-links) - org-insert-link-history)) (setq all-prefixes (append (mapcar 'car abbrevs) (mapcar 'car org-link-abbrev-alist) - org-link-types)) + (org-link-types))) (unwind-protect - (progn + ;; Fake a link history, containing the stored links. + (let ((org--links-history + (append (mapcar #'car org-stored-links) + org-insert-link-history))) (setq link (org-completing-read "Link: " (append - (mapcar (lambda (x) (concat x ":")) - all-prefixes) - (mapcar 'car org-stored-links)) + (mapcar (lambda (x) (concat x ":")) all-prefixes) + (mapcar #'car org-stored-links)) nil nil nil - 'tmphist + 'org--links-history (caar org-stored-links))) - (if (not (string-match "\\S-" link)) - (user-error "No link selected")) - (mapc (lambda(l) - (when (equal link (cadr l)) (setq link (car l) auto-desc t))) - org-stored-links) - (if (or (member link all-prefixes) - (and (equal ":" (substring link -1)) - (member (substring link 0 -1) all-prefixes) - (setq link (substring link 0 -1)))) - (setq link (with-current-buffer origbuf - (org-link-try-special-completion link))))) + (unless (org-string-nw-p link) (user-error "No link selected")) + (dolist (l org-stored-links) + (when (equal link (cadr l)) + (setq link (car l)) + (setq auto-desc t))) + (when (or (member link all-prefixes) + (and (equal ":" (substring link -1)) + (member (substring link 0 -1) all-prefixes) + (setq link (substring link 0 -1)))) + (setq link (with-current-buffer origbuf + (org-link-try-special-completion link))))) (set-window-configuration wcf) (kill-buffer "*Org Links*")) (setq entry (assoc link org-stored-links)) (or entry (push link org-insert-link-history)) (setq desc (or desc (nth 1 entry))))) - (if (funcall (if (equal complete-file '(64)) 'not 'identity) - (not org-keep-stored-link-after-insertion)) - (setq org-stored-links (delq (assoc link org-stored-links) - org-stored-links))) + (when (funcall (if (equal complete-file '(64)) 'not 'identity) + (not org-keep-stored-link-after-insertion)) + (setq org-stored-links (delq (assoc link org-stored-links) + org-stored-links))) - (if (and (string-match org-plain-link-re link) - (not (string-match org-ts-regexp link))) - ;; URL-like link, normalize the use of angular brackets. - (setq link (org-remove-angle-brackets link))) + (when (and (string-match org-plain-link-re link) + (not (string-match org-ts-regexp link))) + ;; URL-like link, normalize the use of angular brackets. + (setq link (org-unbracket-string "<" ">" link))) ;; Check if we are linking to the current file with a search ;; option If yes, simplify the link by using only the search ;; option. (when (and buffer-file-name - (string-match "^file:\\(.+?\\)::\\(.+\\)" link)) - (let* ((path (match-string 1 link)) - (case-fold-search nil) - (search (match-string 2 link))) + (let ((case-fold-search nil)) + (string-match "\\`file:\\(.+?\\)::" link))) + (let ((path (match-string-no-properties 1 link)) + (search (substring-no-properties link (match-end 0)))) (save-match-data - (if (equal (file-truename buffer-file-name) (file-truename path)) - ;; We are linking to this same file, with a search option - (setq link search))))) + (when (equal (file-truename buffer-file-name) (file-truename path)) + ;; We are linking to this same file, with a search option + (setq link search))))) ;; Check if we can/should use a relative path. If yes, simplify the link - (when (string-match "^\\(file:\\|docview:\\)\\(.*\\)" link) - (let* ((type (match-string 1 link)) - (path (match-string 2 link)) - (origpath path) - (case-fold-search nil)) - (cond - ((or (eq org-link-file-path-type 'absolute) - (equal complete-file '(16))) - (setq path (abbreviate-file-name (expand-file-name path)))) - ((eq org-link-file-path-type 'noabbrev) - (setq path (expand-file-name path))) - ((eq org-link-file-path-type 'relative) - (setq path (file-relative-name path))) - (t - (save-match-data - (if (string-match (concat "^" (regexp-quote - (expand-file-name - (file-name-as-directory - default-directory)))) - (expand-file-name path)) - ;; We are linking a file with relative path name. - (setq path (substring (expand-file-name path) - (match-end 0))) - (setq path (abbreviate-file-name (expand-file-name path))))))) - (setq link (concat type path)) - (if (equal desc origpath) - (setq desc path)))) + (let ((case-fold-search nil)) + (when (string-match "\\`\\(file\\|docview\\):" link) + (let* ((type (match-string-no-properties 0 link)) + (path (substring-no-properties link (match-end 0))) + (origpath path)) + (cond + ((or (eq org-link-file-path-type 'absolute) + (equal complete-file '(16))) + (setq path (abbreviate-file-name (expand-file-name path)))) + ((eq org-link-file-path-type 'noabbrev) + (setq path (expand-file-name path))) + ((eq org-link-file-path-type 'relative) + (setq path (file-relative-name path))) + (t + (save-match-data + (if (string-match (concat "^" (regexp-quote + (expand-file-name + (file-name-as-directory + default-directory)))) + (expand-file-name path)) + ;; We are linking a file with relative path name. + (setq path (substring (expand-file-name path) + (match-end 0))) + (setq path (abbreviate-file-name (expand-file-name path))))))) + (setq link (concat type path)) + (when (equal desc origpath) + (setq desc path))))) (if org-make-link-description-function (setq desc @@ -10135,49 +10524,36 @@ Use TAB to complete link prefixes, then RET for type-specific completion support (read-string "Description: " desc))))) (unless (string-match "\\S-" desc) (setq desc nil)) - (if remove (apply 'delete-region remove)) - (insert (org-make-link-string link desc)))) + (when remove (apply 'delete-region remove)) + (insert (org-make-link-string link desc)) + ;; Redisplay so as the new link has proper invisible characters. + (sit-for 0))) (defun org-link-try-special-completion (type) "If there is completion support for link type TYPE, offer it." - (let ((fun (intern (concat "org-" type "-complete-link")))) + (let ((fun (org-link-get-parameter type :complete))) (if (functionp fun) (funcall fun) (read-string "Link (no completion support): " (concat type ":"))))) (defun org-file-complete-link (&optional arg) "Create a file link using completion." - (let (file link) - (setq file (org-iread-file-name "File: ")) - (let ((pwd (file-name-as-directory (expand-file-name "."))) - (pwd1 (file-name-as-directory (abbreviate-file-name - (expand-file-name "."))))) - (cond - ((equal arg '(16)) - (setq link (concat - "file:" - (abbreviate-file-name (expand-file-name file))))) - ((string-match (concat "^" (regexp-quote pwd1) "\\(.+\\)") file) - (setq link (concat "file:" (match-string 1 file)))) - ((string-match (concat "^" (regexp-quote pwd) "\\(.+\\)") - (expand-file-name file)) - (setq link (concat - "file:" (match-string 1 (expand-file-name file))))) - (t (setq link (concat "file:" file))))) - link)) - -(defun org-iread-file-name (&rest args) - "Read-file-name using `ido-mode' speedup if available. -ARGS are arguments that may be passed to `ido-read-file-name' or `read-file-name'. -See `read-file-name' for a description of parameters." - (org-without-partial-completion - (if (and org-completion-use-ido - (fboundp 'ido-read-file-name) - (boundp 'ido-mode) ido-mode - (listp (second args))) - (let ((ido-enter-matching-directory nil)) - (apply 'ido-read-file-name args)) - (apply 'read-file-name args)))) + (let ((file (read-file-name "File: ")) + (pwd (file-name-as-directory (expand-file-name "."))) + (pwd1 (file-name-as-directory (abbreviate-file-name + (expand-file-name "."))))) + (cond ((equal arg '(16)) + (concat "file:" + (abbreviate-file-name (expand-file-name file)))) + ((string-match + (concat "^" (regexp-quote pwd1) "\\(.+\\)") file) + (concat "file:" (match-string 1 file))) + ((string-match + (concat "^" (regexp-quote pwd) "\\(.+\\)") + (expand-file-name file)) + (concat "file:" + (match-string 1 (expand-file-name file)))) + (t (concat "file:" file))))) (defun org-completing-read (&rest args) "Completing-read with SPACE being a normal character." @@ -10186,58 +10562,9 @@ See `read-file-name' for a description of parameters." (copy-keymap minibuffer-local-completion-map))) (org-defkey minibuffer-local-completion-map " " 'self-insert-command) (org-defkey minibuffer-local-completion-map "?" 'self-insert-command) - (org-defkey minibuffer-local-completion-map (kbd "C-c !") 'org-time-stamp-inactive) - (apply 'org-icompleting-read args))) - -(defun org-completing-read-no-i (&rest args) - (let (org-completion-use-ido org-completion-use-iswitchb) - (apply 'org-completing-read args))) - -(defun org-iswitchb-completing-read (prompt choices &rest args) - "Use iswitch as a completing-read replacement to choose from choices. -PROMPT is a string to prompt with. CHOICES is a list of strings to choose -from." - (let* ((iswitchb-use-virtual-buffers nil) - (iswitchb-make-buflist-hook - (lambda () - (setq iswitchb-temp-buflist choices)))) - (iswitchb-read-buffer prompt))) - -(defun org-icompleting-read (&rest args) - "Completing-read using `ido-mode' or `iswitchb' speedups if available." - (org-without-partial-completion - (if (and org-completion-use-ido - (fboundp 'ido-completing-read) - (boundp 'ido-mode) ido-mode - (listp (second args))) - (let ((ido-enter-matching-directory nil)) - (apply 'ido-completing-read (concat (car args)) - (if (consp (car (nth 1 args))) - (mapcar 'car (nth 1 args)) - (nth 1 args)) - (cddr args))) - (if (and org-completion-use-iswitchb - (boundp 'iswitchb-mode) iswitchb-mode - (listp (second args))) - (apply 'org-iswitchb-completing-read (concat (car args)) - (if (consp (car (nth 1 args))) - (mapcar 'car (nth 1 args)) - (nth 1 args)) - (cddr args)) - (apply 'completing-read args))))) - -(defun org-extract-attributes (s) - "Extract the attributes cookie from a string and set as text property." - (let (a attr (start 0) key value) - (save-match-data - (when (string-match "{{\\([^}]+\\)}}$" s) - (setq a (match-string 1 s) s (substring s 0 (match-beginning 0))) - (while (string-match "\\([a-zA-Z]+\\)=\"\\([^\"]*\\)\"" a start) - (setq key (match-string 1 a) value (match-string 2 a) - start (match-end 0) - attr (plist-put attr (intern key) value)))) - (org-add-props s nil 'org-attr attr)) - s)) + (org-defkey minibuffer-local-completion-map (kbd "C-c !") + 'org-time-stamp-inactive) + (apply #'completing-read args))) ;;; Opening/following a link @@ -10257,8 +10584,8 @@ handle this as a special case. When the function does handle the link, it must return a non-nil value. If it decides that it is not responsible for this link, it must return -nil to indicate that that Org-mode can continue with other options -like exact and fuzzy text search.") +nil to indicate that that Org can continue with other options like +exact and fuzzy text search.") (defun org-next-link (&optional search-backward) "Move forward to the next link. @@ -10270,7 +10597,7 @@ If the link is in hidden text, expose it." (setq org-link-search-failed nil) (let* ((pos (point)) (ct (org-context)) - (a (assoc :link ct)) + (a (assq :link ct)) (srch-fun (if search-backward 're-search-backward 're-search-forward))) (cond (a (goto-char (nth (if search-backward 1 2) a))) ((looking-at org-any-link-re) @@ -10279,7 +10606,7 @@ If the link is in hidden text, expose it." (if (funcall srch-fun org-any-link-re nil t) (progn (goto-char (match-beginning 0)) - (if (outline-invisible-p) (org-show-context))) + (when (org-invisible-p) (org-show-context))) (goto-char pos) (setq org-link-search-failed t) (message "No further link found")))) @@ -10292,14 +10619,9 @@ If the link is in hidden text, expose it." (defun org-translate-link (s) "Translate a link string if a translation function has been defined." - (if (and org-link-translation-function - (fboundp org-link-translation-function) - (string-match "\\([a-zA-Z0-9]+\\):\\(.*\\)" s)) - (progn - (setq s (funcall org-link-translation-function - (match-string 1 s) (match-string 2 s))) - (concat (car s) ":" (cdr s))) - s)) + (with-temp-buffer + (insert (org-trim s)) + (org-trim (org-element-interpret-data (org-element-context))))) (defun org-translate-link-from-planner (type path) "Translate a link from Emacs Planner syntax so that Org can follow it. @@ -10319,7 +10641,7 @@ This is still an experimental function, your mileage may vary." ;; A typical message link. Planner has the id after the final slash, ;; we separate it with a hash mark (setq path (concat (match-string 1 path) "#" - (org-remove-angle-brackets (match-string 2 path)))))) + (org-unbracket-string "<" ">" (match-string 2 path)))))) (cons type path)) (defun org-find-file-at-mouse (ev) @@ -10333,28 +10655,32 @@ This is still an experimental function, your mileage may vary." See the docstring of `org-open-file' for details." (interactive "e") (mouse-set-point ev) - (if (eq major-mode 'org-agenda-mode) - (org-agenda-copy-local-variable 'org-link-abbrev-alist-local)) + (when (eq major-mode 'org-agenda-mode) + (org-agenda-copy-local-variable 'org-link-abbrev-alist-local)) (org-open-at-point)) (defvar org-window-config-before-follow-link nil "The window configuration before following a link. This is saved in case the need arises to restore it.") -(defvar org-open-link-marker (make-marker) - "Marker pointing to the location where `org-open-at-point' was called.") - ;;;###autoload (defun org-open-at-point-global () - "Follow a link like Org-mode does. -This command can be called in any mode to follow a link that has -Org-mode syntax." + "Follow a link or time-stamp like Org mode does. +This command can be called in any mode to follow an external link +or a time-stamp that has Org mode syntax. Its behavior is +undefined when called on internal links (e.g., fuzzy links). +Raise an error when there is nothing to follow. " (interactive) - (org-run-like-in-org-mode 'org-open-at-point)) + (cond ((org-in-regexp org-any-link-re) + (org-open-link-from-string (match-string-no-properties 0))) + ((or (org-in-regexp org-ts-regexp-both nil t) + (org-in-regexp org-tsr-regexp-both nil t)) + (org-follow-timestamp-link)) + (t (user-error "No link found")))) ;;;###autoload (defun org-open-link-from-string (s &optional arg reference-buffer) - "Open a link in the string S, as if it was in Org-mode." + "Open a link in the string S, as if it was in Org mode." (interactive "sLink: \nP") (let ((reference-buffer (or reference-buffer (current-buffer)))) (with-temp-buffer @@ -10375,267 +10701,240 @@ Functions in this hook must return t if they identify and follow a link at point. If they don't find anything interesting at point, they must return nil.") -(defvar org-link-search-inhibit-query nil) ;; dynamically scoped -(defvar clean-buffer-list-kill-buffer-names) ; Defined in midnight.el +(defvar org-link-search-inhibit-query nil) +(defvar clean-buffer-list-kill-buffer-names) ;Defined in midnight.el +(defun org--open-doi-link (path) + "Open a \"doi\" type link. +PATH is a the path to search for, as a string." + (browse-url (url-encode-url (concat org-doi-server-url path)))) + +(defun org--open-elisp-link (path) + "Open a \"elisp\" type link. +PATH is the sexp to evaluate, as a string." + (let ((cmd path)) + (if (or (and (org-string-nw-p + org-confirm-elisp-link-not-regexp) + (string-match-p org-confirm-elisp-link-not-regexp cmd)) + (not org-confirm-elisp-link-function) + (funcall org-confirm-elisp-link-function + (format "Execute \"%s\" as elisp? " + (org-add-props cmd nil 'face 'org-warning)))) + (message "%s => %s" cmd + (if (eq (string-to-char cmd) ?\() + (eval (read cmd)) + (call-interactively (read cmd)))) + (user-error "Abort")))) + +(defun org--open-help-link (path) + "Open a \"help\" type link. +PATH is a symbol name, as a string." + (pcase (intern path) + ((and (pred fboundp) variable) (describe-function variable)) + ((and (pred boundp) function) (describe-variable function)) + (name (user-error "Unknown function or variable: %s" name)))) + +(defun org--open-shell-link (path) + "Open a \"shell\" type link. +PATH is the command to execute, as a string." + (let ((buf (generate-new-buffer "*Org Shell Output*")) + (cmd path)) + (if (or (and (org-string-nw-p + org-confirm-shell-link-not-regexp) + (string-match + org-confirm-shell-link-not-regexp cmd)) + (not org-confirm-shell-link-function) + (funcall org-confirm-shell-link-function + (format "Execute \"%s\" in shell? " + (org-add-props cmd nil + 'face 'org-warning)))) + (progn + (message "Executing %s" cmd) + (shell-command cmd buf) + (when (featurep 'midnight) + (setq clean-buffer-list-kill-buffer-names + (cons (buffer-name buf) + clean-buffer-list-kill-buffer-names)))) + (user-error "Abort")))) + (defun org-open-at-point (&optional arg reference-buffer) - "Open link at or after point. -If there is no link at point, this function will search forward up to -the end of the current line. -Normally, files will be opened by an appropriate application. If the -optional prefix argument ARG is non-nil, Emacs will visit the file. -With a double prefix argument, try to open outside of Emacs, in the -application the system uses for this file type." - (interactive "P") - ;; if in a code block, then open the block's results - (unless (call-interactively #'org-babel-open-src-block-result) - (org-load-modules-maybe) - (move-marker org-open-link-marker (point)) - (setq org-window-config-before-follow-link (current-window-configuration)) - (org-remove-occur-highlights nil nil t) - (cond - ((and (org-at-heading-p) - (not (org-at-timestamp-p t)) - (not (org-in-regexp - (concat org-plain-link-re "\\|" - org-bracket-link-regexp "\\|" - org-angle-link-re "\\|" - "[ \t]:[^ \t\n]+:[ \t]*$"))) - (not (get-text-property (point) 'org-linked-text))) - (or (let* ((lkall (org-offer-links-in-entry (current-buffer) (point) arg)) - (lk0 (car lkall)) - (lk (if (stringp lk0) (list lk0) lk0)) - (lkend (cdr lkall))) - (mapcar (lambda(l) - (search-forward l nil lkend) - (goto-char (match-beginning 0)) - (org-open-at-point)) - lk)) - (progn (require 'org-attach) (org-attach-reveal 'if-exists)))) - ((run-hook-with-args-until-success 'org-open-at-point-functions)) - ((and (org-at-timestamp-p t) - (not (org-in-regexp org-bracket-link-regexp))) - (org-follow-timestamp-link)) - ((and (or (org-footnote-at-reference-p) (org-footnote-at-definition-p)) - (not (org-in-regexp org-any-link-re))) - (org-footnote-action)) - (t - (let (type path link line search (pos (point))) - (catch 'match - (save-excursion - (or (org-in-regexp org-plain-link-re) - (skip-chars-forward "^]\n\r")) - (when (org-in-regexp org-bracket-link-regexp 1) - (setq link (org-extract-attributes - (org-link-unescape (org-match-string-no-properties 1)))) - (while (string-match " *\n *" link) - (setq link (replace-match " " t t link))) - (setq link (org-link-expand-abbrev link)) - (cond - ((or (file-name-absolute-p link) - (string-match "^\\.\\.?/" link)) - (setq type "file" path link)) - ((string-match org-link-re-with-space3 link) - (setq type (match-string 1 link) path (match-string 2 link))) - ((string-match "^help:+\\(.+\\)" link) - (setq type "help" path (match-string 1 link))) - (t (setq type "thisfile" path link))) - (throw 'match t))) - - (when (get-text-property (point) 'org-linked-text) - (setq type "thisfile" - pos (if (get-text-property (1+ (point)) 'org-linked-text) - (1+ (point)) (point)) - path (buffer-substring - (or (previous-single-property-change pos 'org-linked-text) - (point-min)) - (or (next-single-property-change pos 'org-linked-text) - (point-max))) - ;; Ensure we will search for a <<>> link, not - ;; a simple reference like <> - path (concat "<" path)) - (throw 'match t)) + "Open link, timestamp, footnote or tags at point. - (save-excursion - (when (or (org-in-regexp org-angle-link-re) - (let ((match (org-in-regexp org-plain-link-re))) - ;; Check a plain link is not within a bracket link - (and match - (save-excursion - (save-match-data - (progn - (goto-char (car match)) - (not (org-in-regexp org-bracket-link-regexp))))))) - (let ((line_ending (save-excursion (end-of-line) (point)))) - ;; We are in a line before a plain or bracket link - (or (re-search-forward org-plain-link-re line_ending t) - (re-search-forward org-bracket-link-regexp line_ending t)))) - (setq type (match-string 1) - path (org-link-unescape (match-string 2))) - (throw 'match t))) - (save-excursion - (when (org-in-regexp (org-re "\\(:[[:alnum:]_@#%:]+\\):[ \t]*$")) - (setq type "tags" - path (match-string 1)) - (while (string-match ":" path) - (setq path (replace-match "+" t t path))) - (throw 'match t))) - (when (org-in-regexp "<\\([^><\n]+\\)>") - (setq type "tree-match" - path (match-string 1)) - (throw 'match t))) - (unless path - (user-error "No link found")) +When point is on a link, follow it. Normally, files will be +opened by an appropriate application. If the optional prefix +argument ARG is non-nil, Emacs will visit the file. With +a double prefix argument, try to open outside of Emacs, in the +application the system uses for this file type. - ;; switch back to reference buffer - ;; needed when if called in a temporary buffer through - ;; org-open-link-from-string - (with-current-buffer (or reference-buffer (current-buffer)) +When point is on a timestamp, open the agenda at the day +specified. - ;; Remove any trailing spaces in path - (if (string-match " +\\'" path) - (setq path (replace-match "" t t path))) - (if (and org-link-translation-function - (fboundp org-link-translation-function)) - ;; Check if we need to translate the link - (let ((tmp (funcall org-link-translation-function type path))) - (setq type (car tmp) path (cdr tmp)))) +When point is a footnote definition, move to the first reference +found. If it is on a reference, move to the associated +definition. - (cond +When point is on a headline, display a list of every link in the +entry, so it is possible to pick one, or all, of them. If point +is on a tag, call `org-tags-view' instead. - ((assoc type org-link-protocols) - (funcall (nth 1 (assoc type org-link-protocols)) path)) - - ((equal type "help") - (let ((f-or-v (intern path))) - (cond ((fboundp f-or-v) - (describe-function f-or-v)) - ((boundp f-or-v) - (describe-variable f-or-v)) - (t (error "Not a known function or variable"))))) - - ((equal type "mailto") - (let ((cmd (car org-link-mailto-program)) - (args (cdr org-link-mailto-program)) args1 - (address path) (subject "") a) - (if (string-match "\\(.*\\)::\\(.*\\)" path) - (setq address (match-string 1 path) - subject (org-link-escape (match-string 2 path)))) - (while args - (cond - ((not (stringp (car args))) (push (pop args) args1)) - (t (setq a (pop args)) - (if (string-match "%a" a) - (setq a (replace-match address t t a))) - (if (string-match "%s" a) - (setq a (replace-match subject t t a))) - (push a args1)))) - (apply cmd (nreverse args1)))) - - ((member type '("http" "https" "ftp" "news")) - (browse-url - (concat type ":" - (if (org-string-match-p - (concat "[[:nonascii:]" - org-link-escape-chars-browser "]") - path) - (org-link-escape path org-link-escape-chars-browser) - path)))) - - ((string= type "doi") - (browse-url - (concat org-doi-server-url - (if (org-string-match-p - (concat "[[:nonascii:]" - org-link-escape-chars-browser "]") - path) - (org-link-escape path org-link-escape-chars-browser) - path)))) - - ((member type '("message")) - (browse-url (concat type ":" path))) - - ((string= type "tags") - (org-tags-view arg path)) - - ((string= type "tree-match") - (org-occur (concat "\\[" (regexp-quote path) "\\]"))) - - ((string= type "file") - (if (string-match "::\\([0-9]+\\)\\'" path) - (setq line (string-to-number (match-string 1 path)) - path (substring path 0 (match-beginning 0))) - (if (string-match "::\\(.+\\)\\'" path) - (setq search (match-string 1 path) - path (substring path 0 (match-beginning 0))))) - (if (string-match "[*?{]" (file-name-nondirectory path)) - (dired path) - (org-open-file path arg line search))) - - ((string= type "shell") - (let ((buf (generate-new-buffer "*Org Shell Output")) - (cmd path)) - (if (or (and (not (string= org-confirm-shell-link-not-regexp "")) - (string-match org-confirm-shell-link-not-regexp cmd)) - (not org-confirm-shell-link-function) - (funcall org-confirm-shell-link-function - (format "Execute \"%s\" in shell? " - (org-add-props cmd nil - 'face 'org-warning)))) - (progn - (message "Executing %s" cmd) - (shell-command cmd buf) - (if (featurep 'midnight) - (setq clean-buffer-list-kill-buffer-names - (cons buf clean-buffer-list-kill-buffer-names)))) - (error "Abort")))) - - ((string= type "elisp") - (let ((cmd path)) - (if (or (and (not (string= org-confirm-elisp-link-not-regexp "")) - (string-match org-confirm-elisp-link-not-regexp cmd)) - (not org-confirm-elisp-link-function) - (funcall org-confirm-elisp-link-function - (format "Execute \"%s\" as elisp? " - (org-add-props cmd nil - 'face 'org-warning)))) - (message "%s => %s" cmd - (if (equal (string-to-char cmd) ?\() - (eval (read cmd)) - (call-interactively (read cmd)))) - (error "Abort")))) - - ((and (string= type "thisfile") - (or (run-hook-with-args-until-success - 'org-open-link-functions path) - (and link - (string-match "^id:" link) - (or (featurep 'org-id) (require 'org-id)) - (progn - (funcall (nth 1 (assoc "id" org-link-protocols)) - (substring path 3)) - t))))) - - ((string= type "thisfile") - (if arg - (switch-to-buffer-other-window - (org-get-buffer-for-internal-link (current-buffer))) - (org-mark-ring-push)) - (let ((cmd `(org-link-search - ,path - ,(cond ((equal arg '(4)) ''occur) - ((equal arg '(16)) ''org-occur)) - ,pos))) - (condition-case nil (let ((org-link-search-inhibit-query t)) - (eval cmd)) - (error (progn (widen) (eval cmd)))))) - - (t (browse-url-at-point))))))) - (move-marker org-open-link-marker nil) - (run-hook-with-args 'org-follow-link-hook))) +When optional argument REFERENCE-BUFFER is non-nil, it should +specify a buffer from where the link search should happen. This +is used internally by `org-open-link-from-string'. -(defsubst org-uniquify (list) - "Non-destructively remove duplicate elements from LIST." - (let ((res (copy-sequence list))) (delete-dups res))) +On top of syntactically correct links, this function will open +the link at point in comments or comment blocks and the first +link in a property drawer line." + (interactive "P") + ;; On a code block, open block's results. + (unless (call-interactively 'org-babel-open-src-block-result) + (org-load-modules-maybe) + (setq org-window-config-before-follow-link (current-window-configuration)) + (org-remove-occur-highlights nil nil t) + (unless (run-hook-with-args-until-success 'org-open-at-point-functions) + (let* ((context + ;; Only consider supported types, even if they are not + ;; the closest one. + (org-element-lineage + (org-element-context) + '(clock comment comment-block footnote-definition + footnote-reference headline inlinetask keyword link + node-property timestamp) + t)) + (type (org-element-type context)) + (value (org-element-property :value context))) + (cond + ((not context) (user-error "No link found")) + ;; Exception: open timestamps and links in properties + ;; drawers, keywords and comments. + ((memq type '(comment comment-block keyword node-property)) + (call-interactively #'org-open-at-point-global)) + ;; On a headline or an inlinetask, but not on a timestamp, + ;; a link, a footnote reference or on tags. + ((and (memq type '(headline inlinetask)) + ;; Not on tags. + (let ((case-fold-search nil)) + (save-excursion + (beginning-of-line) + (looking-at org-complex-heading-regexp)) + (or (not (match-beginning 5)) + (< (point) (match-beginning 5))))) + (let* ((data (org-offer-links-in-entry (current-buffer) (point) arg)) + (links (car data)) + (links-end (cdr data))) + (if links + (dolist (link (if (stringp links) (list links) links)) + (search-forward link nil links-end) + (goto-char (match-beginning 0)) + (org-open-at-point)) + (require 'org-attach) + (org-attach-reveal 'if-exists)))) + ;; On a clock line, make sure point is on the timestamp + ;; before opening it. + ((and (eq type 'clock) + value + (>= (point) (org-element-property :begin value)) + (<= (point) (org-element-property :end value))) + (org-follow-timestamp-link)) + ;; Do nothing on white spaces after an object. + ((>= (point) + (save-excursion + (goto-char (org-element-property :end context)) + (skip-chars-backward " \t") + (point))) + (user-error "No link found")) + ((eq type 'timestamp) (org-follow-timestamp-link)) + ;; On tags within a headline or an inlinetask. + ((and (memq type '(headline inlinetask)) + (let ((case-fold-search nil)) + (save-excursion (beginning-of-line) + (looking-at org-complex-heading-regexp)) + (and (match-beginning 5) + (>= (point) (match-beginning 5))))) + (org-tags-view arg (substring (match-string 5) 0 -1))) + ((eq type 'link) + ;; When link is located within the description of another + ;; link (e.g., an inline image), always open the parent + ;; link. + (let* ((link (let ((up (org-element-property :parent context))) + (if (eq (org-element-type up) 'link) up context))) + (type (org-element-property :type link)) + (path (org-link-unescape (org-element-property :path link)))) + ;; Switch back to REFERENCE-BUFFER needed when called in + ;; a temporary buffer through `org-open-link-from-string'. + (with-current-buffer (or reference-buffer (current-buffer)) + (cond + ((equal type "file") + (if (string-match "[*?{]" (file-name-nondirectory path)) + (dired path) + ;; Look into `org-link-parameters' in order to find + ;; a DEDICATED-FUNCTION to open file. The function + ;; will be applied on raw link instead of parsed + ;; link due to the limitation in `org-add-link-type' + ;; ("open" function called with a single argument). + ;; If no such function is found, fallback to + ;; `org-open-file'. + (let* ((option (org-element-property :search-option link)) + (app (org-element-property :application link)) + (dedicated-function + (org-link-get-parameter + (if app (concat type "+" app) type) + :follow))) + (if dedicated-function + (funcall dedicated-function + (concat path + (and option (concat "::" option)))) + (apply #'org-open-file + path + (cond (arg) + ((equal app "emacs") 'emacs) + ((equal app "sys") 'system)) + (cond ((not option) nil) + ((string-match-p "\\`[0-9]+\\'" option) + (list (string-to-number option))) + (t (list nil + (org-link-unescape option))))))))) + ((functionp (org-link-get-parameter type :follow)) + (funcall (org-link-get-parameter type :follow) path)) + ((member type '("coderef" "custom-id" "fuzzy" "radio")) + (unless (run-hook-with-args-until-success + 'org-open-link-functions path) + (if (not arg) (org-mark-ring-push) + (switch-to-buffer-other-window + (org-get-buffer-for-internal-link (current-buffer)))) + (let ((destination + (org-with-wide-buffer + (if (equal type "radio") + (org-search-radio-target + (org-element-property :path link)) + (org-link-search + (if (member type '("custom-id" "coderef")) + (org-element-property :raw-link link) + path) + ;; Prevent fuzzy links from matching + ;; themselves. + (and (equal type "fuzzy") + (+ 2 (org-element-property :begin link))))) + (point)))) + (unless (and (<= (point-min) destination) + (>= (point-max) destination)) + (widen)) + (goto-char destination)))) + (t (browse-url-at-point)))))) + ;; On a footnote reference or at a footnote definition's label. + ((or (eq type 'footnote-reference) + (and (eq type 'footnote-definition) + (save-excursion + ;; Do not validate action when point is on the + ;; spaces right after the footnote label, in + ;; order to be on par with behaviour on links. + (skip-chars-forward " \t") + (let ((begin + (org-element-property :contents-begin context))) + (if begin (< (point) begin) + (= (org-element-property :post-affiliated context) + (line-beginning-position))))))) + (org-footnote-action)) + (t (user-error "No link found"))))) + (run-hook-with-args 'org-follow-link-hook))) (defun org-offer-links-in-entry (buffer marker &optional nth zero) "Offer links in the current entry and return the selected link. @@ -10644,65 +10943,57 @@ If NTH is an integer, return the NTH link found. If ZERO is a string, check also this string for a link, and if there is one, return it." (with-current-buffer buffer - (save-excursion - (save-restriction - (widen) - (goto-char marker) - (let ((re (concat "\\(" org-bracket-link-regexp "\\)\\|" - "\\(" org-angle-link-re "\\)\\|" - "\\(" org-plain-link-re "\\)")) - (cnt ?0) - (in-emacs (if (integerp nth) nil nth)) - have-zero end links link c) - (when (and (stringp zero) (string-match org-bracket-link-regexp zero)) - (push (match-string 0 zero) links) - (setq cnt (1- cnt) have-zero t)) - (save-excursion - (org-back-to-heading t) - (setq end (save-excursion (outline-next-heading) (point))) - (while (re-search-forward re end t) - (push (match-string 0) links)) - (setq links (org-uniquify (reverse links)))) - (cond - ((null links) - (message "No links")) - ((equal (length links) 1) - (setq link (car links))) - ((and (integerp nth) (>= (length links) (if have-zero (1+ nth) nth))) - (setq link (nth (if have-zero nth (1- nth)) links))) - (t ; we have to select a link - (save-excursion - (save-window-excursion - (delete-other-windows) - (with-output-to-temp-buffer "*Select Link*" - (mapc (lambda (l) - (if (not (string-match org-bracket-link-regexp l)) - (princ (format "[%c] %s\n" (incf cnt) - (org-remove-angle-brackets l))) - (if (match-end 3) - (princ (format "[%c] %s (%s)\n" (incf cnt) - (match-string 3 l) (match-string 1 l))) - (princ (format "[%c] %s\n" (incf cnt) - (match-string 1 l)))))) - links)) - (org-fit-window-to-buffer (get-buffer-window "*Select Link*")) - (message "Select link to open, RET to open all:") - (setq c (read-char-exclusive)) - (and (get-buffer "*Select Link*") (kill-buffer "*Select Link*")))) - (when (equal c ?q) (error "Abort")) - (if (equal c ?\C-m) - (setq link links) - (setq nth (- c ?0)) - (if have-zero (setq nth (1+ nth))) - (unless (and (integerp nth) (>= (length links) nth)) - (user-error "Invalid link selection")) - (setq link (nth (1- nth) links))))) - (cons link end)))))) - -;; Add special file links that specify the way of opening - -(org-add-link-type "file+sys" 'org-open-file-with-system) -(org-add-link-type "file+emacs" 'org-open-file-with-emacs) + (org-with-wide-buffer + (goto-char marker) + (let ((cnt ?0) + have-zero end links link c) + (when (and (stringp zero) (string-match org-bracket-link-regexp zero)) + (push (match-string 0 zero) links) + (setq cnt (1- cnt) have-zero t)) + (save-excursion + (org-back-to-heading t) + (setq end (save-excursion (outline-next-heading) (point))) + (while (re-search-forward org-any-link-re end t) + (push (match-string 0) links)) + (setq links (org-uniquify (reverse links)))) + (cond + ((null links) + (message "No links")) + ((equal (length links) 1) + (setq link (car links))) + ((and (integerp nth) (>= (length links) (if have-zero (1+ nth) nth))) + (setq link (nth (if have-zero nth (1- nth)) links))) + (t ; we have to select a link + (save-excursion + (save-window-excursion + (delete-other-windows) + (with-output-to-temp-buffer "*Select Link*" + (dolist (l links) + (cond + ((not (string-match org-bracket-link-regexp l)) + (princ (format "[%c] %s\n" (cl-incf cnt) + (org-unbracket-string "<" ">" l)))) + ((match-end 3) + (princ (format "[%c] %s (%s)\n" (cl-incf cnt) + (match-string 3 l) (match-string 1 l)))) + (t (princ (format "[%c] %s\n" (cl-incf cnt) + (match-string 1 l))))))) + (org-fit-window-to-buffer (get-buffer-window "*Select Link*")) + (message "Select link to open, RET to open all:") + (setq c (read-char-exclusive)) + (and (get-buffer "*Select Link*") (kill-buffer "*Select Link*")))) + (when (equal c ?q) (user-error "Abort")) + (if (equal c ?\C-m) + (setq link links) + (setq nth (- c ?0)) + (when have-zero (setq nth (1+ nth))) + (unless (and (integerp nth) (>= (length links) nth)) + (user-error "Invalid link selection")) + (setq link (nth (1- nth) links))))) + (cons link end))))) + +;; TODO: These functions are deprecated since `org-open-at-point' +;; hard-codes behaviour for "file+emacs" and "file+sys" types. (defun org-open-file-with-system (path) "Open file at PATH using the system way of opening it." (org-open-file path 'system)) @@ -10732,8 +11023,8 @@ which see. A function in this hook may also use `setq' to set the variable `description' to provide a suggestion for the descriptive text to -be used for this link when it gets inserted into an Org-mode -buffer with \\[org-insert-link].") +be used for this link when it gets inserted into an Org buffer +with \\[org-insert-link].") (defvar org-execute-file-search-functions nil "List of functions to execute a file search triggered by a link. @@ -10757,179 +11048,201 @@ the window configuration before `org-open-at-point' was called using: (set-window-configuration org-window-config-before-follow-link)") -(defun org-link-search (s &optional type avoid-pos stealth) - "Search for a link search option. -If S is surrounded by forward slashes, it is interpreted as a -regular expression. In org-mode files, this will create an `org-occur' -sparse tree. In ordinary files, `occur' will be used to list matches. -If the current buffer is in `dired-mode', grep will be used to search -in all files. If AVOID-POS is given, ignore matches near that position. +(defun org-search-radio-target (target) + "Search a radio target matching TARGET in current buffer. +White spaces are not significant." + (let ((re (format "<<<%s>>>" + (mapconcat #'regexp-quote + (org-split-string target "[ \t\n]+") + "[ \t]+\\(?:\n[ \t]*\\)?"))) + (origin (point))) + (goto-char (point-min)) + (catch :radio-match + (while (re-search-forward re nil t) + (backward-char) + (let ((object (org-element-context))) + (when (eq (org-element-type object) 'radio-target) + (goto-char (org-element-property :begin object)) + (org-show-context 'link-search) + (throw :radio-match nil)))) + (goto-char origin) + (user-error "No match for radio target: %s" target)))) + +(defun org-link-search (s &optional avoid-pos stealth) + "Search for a search string S. + +If S starts with \"#\", it triggers a custom ID search. + +If S is enclosed within parenthesis, it initiates a coderef +search. + +If S is surrounded by forward slashes, it is interpreted as +a regular expression. In Org mode files, this will create an +`org-occur' sparse tree. In ordinary files, `occur' will be used +to list matches. If the current buffer is in `dired-mode', grep +will be used to search in all files. + +When AVOID-POS is given, ignore matches near that position. When optional argument STEALTH is non-nil, do not modify -visibility around point, thus ignoring -`org-show-hierarchy-above', `org-show-following-heading' and -`org-show-siblings' variables." - (let ((case-fold-search t) - (s0 (mapconcat 'identity (org-split-string s "[ \t\r\n]+") " ")) - (markers (concat "\\(?:" (mapconcat (lambda (x) (regexp-quote (car x))) - (append '(("") (" ") ("\t") ("\n")) - org-emphasis-alist) - "\\|") "\\)")) - (pos (point)) - (pre nil) (post nil) - words re0 re1 re2 re3 re4_ re4 re5 re2a re2a_ reall) +visibility around point, thus ignoring `org-show-context-detail' +variable. + +Search is case-insensitive and ignores white spaces. Return type +of matched result, which is either `dedicated' or `fuzzy'." + (unless (org-string-nw-p s) (error "Invalid search string \"%s\"" s)) + (let* ((case-fold-search t) + (origin (point)) + (normalized (replace-regexp-in-string "\n[ \t]*" " " s)) + (starred (eq (string-to-char normalized) ?*)) + (words (split-string (if starred (substring s 1) s))) + (s-multi-re (mapconcat #'regexp-quote words "\\(?:[ \t\n]+\\)")) + (s-single-re (mapconcat #'regexp-quote words "[ \t]+")) + type) (cond - ;; First check if there are any special search functions + ;; Check if there are any special search functions. ((run-hook-with-args-until-success 'org-execute-file-search-functions s)) - ;; Now try the builtin stuff - ((and (equal (string-to-char s0) ?#) - (> (length s0) 1) - (save-excursion - (goto-char (point-min)) - (and - (re-search-forward - (concat "^[ \t]*:CUSTOM_ID:[ \t]+" - (regexp-quote (substring s0 1)) "[ \t]*$") nil t) - (setq type 'dedicated - pos (match-beginning 0)))) - ;; There is an exact target for this - (goto-char pos) - (org-back-to-heading t))) - ((save-excursion + ((eq (string-to-char s) ?#) + ;; Look for a custom ID S if S starts with "#". + (let* ((id (substring normalized 1)) + (match (org-find-property "CUSTOM_ID" id))) + (if match (progn (goto-char match) (setf type 'dedicated)) + (error "No match for custom ID: %s" id)))) + ((string-match "\\`(\\(.*\\))\\'" normalized) + ;; Look for coderef targets if S is enclosed within parenthesis. + (let ((coderef (match-string-no-properties 1 normalized)) + (re (substring s-single-re 1 -1))) (goto-char (point-min)) - (and - (re-search-forward - (concat "<<" (regexp-quote s0) ">>") nil t) - (setq type 'dedicated - pos (match-beginning 0)))) - ;; There is an exact target for this - (goto-char pos)) - ((save-excursion - (goto-char (point-min)) - (and - (re-search-forward - (format "^[ \t]*#\\+NAME: %s" (regexp-quote s0)) nil t) - (setq type 'dedicated pos (match-beginning 0)))) - ;; Found an element with a matching #+name affiliated keyword. - (goto-char pos)) - ((and (string-match "^(\\(.*\\))$" s0) - (save-excursion + (catch :coderef-match + (while (re-search-forward re nil t) + (let ((element (org-element-at-point))) + (when (and (memq (org-element-type element) + '(example-block src-block)) + ;; Build proper regexp according to current + ;; block's label format. + (let ((label-fmt + (regexp-quote + (or (org-element-property :label-fmt element) + org-coderef-label-format)))) + (save-excursion + (beginning-of-line) + (looking-at (format ".*?\\(%s\\)[ \t]*$" + (format label-fmt coderef)))))) + (setq type 'dedicated) + (goto-char (match-beginning 1)) + (throw :coderef-match nil)))) + (goto-char origin) + (error "No match for coderef: %s" coderef)))) + ((string-match "\\`/\\(.*\\)/\\'" normalized) + ;; Look for a regular expression. + (funcall (if (derived-mode-p 'org-mode) #'org-occur #'org-do-occur) + (match-string 1 s))) + ;; From here, we handle fuzzy links. + ;; + ;; Look for targets, only if not in a headline search. + ((and (not starred) + (let ((target (format "<<%s>>" s-multi-re))) + (catch :target-match + (goto-char (point-min)) + (while (re-search-forward target nil t) + (backward-char) + (let ((context (org-element-context))) + (when (eq (org-element-type context) 'target) + (setq type 'dedicated) + (goto-char (org-element-property :begin context)) + (throw :target-match t)))) + nil)))) + ;; Look for elements named after S, only if not in a headline + ;; search. + ((and (not starred) + (let ((name (format "^[ \t]*#\\+NAME: +%s[ \t]*$" s-single-re))) + (catch :name-match + (goto-char (point-min)) + (while (re-search-forward name nil t) + (let ((element (org-element-at-point))) + (when (equal words + (split-string + (org-element-property :name element))) + (setq type 'dedicated) + (beginning-of-line) + (throw :name-match t)))) + nil)))) + ;; Regular text search. Prefer headlines in Org mode buffers. + ;; Ignore COMMENT keyword, TODO keywords, priority cookies, + ;; statistics cookies and tags. + ((and (derived-mode-p 'org-mode) + (let ((title-re + (format "%s.*\\(?:%s[ \t]\\)?.*%s" + org-outline-regexp-bol + org-comment-string + (mapconcat #'regexp-quote words ".+"))) + (cookie-re "\\[[0-9]*\\(?:%\\|/[0-9]*\\)\\]") + (comment-re (format "\\`%s[ \t]+" org-comment-string))) (goto-char (point-min)) - (and - (re-search-forward - (concat "[^[]" (regexp-quote - (format org-coderef-label-format - (match-string 1 s0)))) - nil t) - (setq type 'dedicated - pos (1+ (match-beginning 0)))))) - ;; There is a coderef target for this - (goto-char pos)) - ((string-match "^/\\(.*\\)/$" s) - ;; A regular expression - (cond - ((derived-mode-p 'org-mode) - (org-occur (match-string 1 s))) - (t (org-do-occur (match-string 1 s))))) - ((and (derived-mode-p 'org-mode) org-link-search-must-match-exact-headline) - (and (equal (string-to-char s) ?*) (setq s (substring s 1))) - (goto-char (point-min)) - (cond - ((let (case-fold-search) - (re-search-forward (format org-complex-heading-regexp-format - (regexp-quote s)) - nil t)) - ;; OK, found a match - (setq type 'dedicated) - (goto-char (match-beginning 0))) - ((and (not org-link-search-inhibit-query) - (eq org-link-search-must-match-exact-headline 'query-to-create) - (y-or-n-p "No match - create this as a new heading? ")) - (goto-char (point-max)) - (or (bolp) (newline)) - (insert "* " s "\n") - (beginning-of-line 0)) - (t - (goto-char pos) - (error "No match")))) - (t - ;; A normal search string - (when (equal (string-to-char s) ?*) - ;; Anchor on headlines, post may include tags. - (setq pre "^\\*+[ \t]+\\(?:\\sw+\\)?[ \t]*" - post (org-re "[ \t]*\\(?:[ \t]+:[[:alnum:]_@#%:+]:[ \t]*\\)?$") - s (substring s 1))) - (remove-text-properties - 0 (length s) - '(face nil mouse-face nil keymap nil fontified nil) s) - ;; Make a series of regular expressions to find a match - (setq words (org-split-string s "[ \n\r\t]+") - - re0 (concat "\\(<<" (regexp-quote s0) ">>\\)") - re2 (concat markers "\\(" (mapconcat 'downcase words "[ \t]+") - "\\)" markers) - re2a_ (concat "\\(" (mapconcat 'downcase words - "[ \t\r\n]+") "\\)[ \t\r\n]") - re2a (concat "[ \t\r\n]" re2a_) - re4_ (concat "\\(" (mapconcat 'downcase words - "[^a-zA-Z_\r\n]+") "\\)[^a-zA-Z_]") - re4 (concat "[^a-zA-Z_]" re4_) - - re1 (concat pre re2 post) - re3 (concat pre (if pre re4_ re4) post) - re5 (concat pre ".*" re4) - re2 (concat pre re2) - re2a (concat pre (if pre re2a_ re2a)) - re4 (concat pre (if pre re4_ re4)) - reall (concat "\\(" re0 "\\)\\|\\(" re1 "\\)\\|\\(" re2 - "\\)\\|\\(" re3 "\\)\\|\\(" re4 "\\)\\|\\(" - re5 "\\)")) - (cond - ((eq type 'org-occur) (org-occur reall)) - ((eq type 'occur) (org-do-occur (downcase reall) 'cleanup)) - (t (goto-char (point-min)) - (setq type 'fuzzy) - (if (or (and (org-search-not-self 1 re0 nil t) - (setq type 'dedicated)) - (org-search-not-self 1 re1 nil t) - (org-search-not-self 1 re2 nil t) - (org-search-not-self 1 re2a nil t) - (org-search-not-self 1 re3 nil t) - (org-search-not-self 1 re4 nil t) - (org-search-not-self 1 re5 nil t)) - (goto-char (match-beginning 1)) - (goto-char pos) - (error "No match")))))) - (and (derived-mode-p 'org-mode) - (not stealth) - (org-show-context 'link-search)) + (catch :found + (while (re-search-forward title-re nil t) + (when (equal words + (split-string + (replace-regexp-in-string + cookie-re "" + (replace-regexp-in-string + comment-re "" (org-get-heading t t))))) + (throw :found t))) + nil))) + (beginning-of-line) + (setq type 'dedicated)) + ;; Offer to create non-existent headline depending on + ;; `org-link-search-must-match-exact-headline'. + ((and (derived-mode-p 'org-mode) + (not org-link-search-inhibit-query) + (eq org-link-search-must-match-exact-headline 'query-to-create) + (yes-or-no-p "No match - create this as a new heading? ")) + (goto-char (point-max)) + (unless (bolp) (newline)) + (org-insert-heading nil t t) + (insert s "\n") + (beginning-of-line 0)) + ;; Only headlines are looked after. No need to process + ;; further: throw an error. + ((and (derived-mode-p 'org-mode) + (or starred org-link-search-must-match-exact-headline)) + (goto-char origin) + (error "No match for fuzzy expression: %s" normalized)) + ;; Regular text search. + ((catch :fuzzy-match + (goto-char (point-min)) + (while (re-search-forward s-multi-re nil t) + ;; Skip match if it contains AVOID-POS or it is included in + ;; a link with a description but outside the description. + (unless (or (and avoid-pos + (<= (match-beginning 0) avoid-pos) + (> (match-end 0) avoid-pos)) + (and (save-match-data + (org-in-regexp org-bracket-link-regexp)) + (match-beginning 3) + (or (> (match-beginning 3) (point)) + (<= (match-end 3) (point))) + (org-element-lineage + (save-match-data (org-element-context)) + '(link) t))) + (goto-char (match-beginning 0)) + (setq type 'fuzzy) + (throw :fuzzy-match t))) + nil)) + ;; All failed. Throw an error. + (t (goto-char origin) + (error "No match for fuzzy expression: %s" normalized))) + ;; Disclose surroundings of match, if appropriate. + (when (and (derived-mode-p 'org-mode) (not stealth)) + (org-show-context 'link-search)) type)) -(defun org-search-not-self (group &rest args) - "Execute `re-search-forward', but only accept matches that do not -enclose the position of `org-open-link-marker'." - (let ((m org-open-link-marker)) - (catch 'exit - (while (apply #'re-search-forward args) - (unless (get-text-property (match-end group) 'intangible) ; Emacs 21 - (goto-char (match-end group)) - (if (and (or (not (eq (marker-buffer m) (current-buffer))) - (> (match-beginning 0) (marker-position m)) - (< (match-end 0) (marker-position m))) - (save-match-data - (or (not (org-in-regexp - org-bracket-link-analytic-regexp 1)) - (not (match-end 4)) ; no description - (and (<= (match-beginning 4) (point)) - (>= (match-end 4) (point)))))) - (throw 'exit (point)))))))) - (defun org-get-buffer-for-internal-link (buffer) "Return a buffer to be used for displaying the link target of internal links." (cond ((not org-display-internal-link-with-indirect-buffer) buffer) - ((string-match "(Clone)$" (buffer-name buffer)) + ((string-suffix-p "(Clone)" (buffer-name buffer)) (message "Buffer is already a clone, not making another one") ;; we also do not modify visibility in this case buffer) @@ -10953,8 +11266,8 @@ to read." (goto-char (point-min)) (when (re-search-forward "match[a-z]+" nil t) (setq beg (match-end 0)) - (if (re-search-forward "^[ \t]*[0-9]+" nil t) - (setq end (1- (match-beginning 0))))) + (when (re-search-forward "^[ \t]*[0-9]+" nil t) + (setq end (1- (match-beginning 0))))) (and beg end (let ((inhibit-read-only t)) (delete-region beg end))) (goto-char (point-min)) (select-window cwin)))) @@ -10962,13 +11275,13 @@ to read." ;;; The mark ring for links jumps (defvar org-mark-ring nil - "Mark ring for positions before jumps in Org-mode.") + "Mark ring for positions before jumps in Org mode.") (defvar org-mark-ring-last-goto nil "Last position in the mark ring used to go back.") ;; Fill and close the ring (setq org-mark-ring nil org-mark-ring-last-goto nil) ;; in case file is reloaded -(loop for i from 1 to org-mark-ring-length do - (push (make-marker) org-mark-ring)) +(dotimes (_ org-mark-ring-length) + (push (make-marker) org-mark-ring)) (setcdr (nthcdr (1- org-mark-ring-length) org-mark-ring) org-mark-ring) @@ -10982,15 +11295,15 @@ to read." (or buffer (current-buffer))) (message "%s" (substitute-command-keys - "Position saved to mark ring, go back with \\[org-mark-ring-goto]."))) + "Position saved to mark ring, go back with \ +`\\[org-mark-ring-goto]'."))) (defun org-mark-ring-goto (&optional n) "Jump to the previous position in the mark ring. With prefix arg N, jump back that many stored positions. When called several times in succession, walk through the entire ring. -Org-mode commands jumping to a different position in the current file, -or to another Org-mode file, automatically push the old position -onto the ring." +Org mode commands jumping to a different position in the current file, +or to another Org file, automatically push the old position onto the ring." (interactive "p") (let (p m) (if (eq last-command this-command) @@ -10998,25 +11311,19 @@ onto the ring." (setq p org-mark-ring)) (setq org-mark-ring-last-goto p) (setq m (car p)) - (org-pop-to-buffer-same-window (marker-buffer m)) + (pop-to-buffer-same-window (marker-buffer m)) (goto-char m) - (if (or (outline-invisible-p) (org-invisible-p2)) (org-show-context 'mark-goto)))) + (when (or (org-invisible-p) (org-invisible-p2)) (org-show-context 'mark-goto)))) -(defun org-remove-angle-brackets (s) - (if (equal (substring s 0 1) "<") (setq s (substring s 1))) - (if (equal (substring s -1) ">") (setq s (substring s 0 -1))) - s) (defun org-add-angle-brackets (s) - (if (equal (substring s 0 1) "<") nil (setq s (concat "<" s))) - (if (equal (substring s -1) ">") nil (setq s (concat s ">"))) - s) -(defun org-remove-double-quotes (s) - (if (equal (substring s 0 1) "\"") (setq s (substring s 1))) - (if (equal (substring s -1) "\"") (setq s (substring s 0 -1))) + (unless (equal (substring s 0 1) "<") (setq s (concat "<" s))) + (unless (equal (substring s -1) ">") (setq s (concat s ">"))) s) ;;; Following specific links +(defvar org-agenda-buffer-tmp-name) +(defvar org-agenda-start-on-weekday) (defun org-follow-timestamp-link () "Open an agenda view for the time-stamp date/range at point." (cond @@ -11071,43 +11378,40 @@ If the file does not exist, an error is thrown." buffer-file-name (substitute-in-file-name (expand-file-name path)))) (file-apps (append org-file-apps (org-default-apps))) - (apps (org-remove-if + (apps (cl-remove-if 'org-file-apps-entry-match-against-dlink-p file-apps)) - (apps-dlink (org-remove-if-not + (apps-dlink (cl-remove-if-not 'org-file-apps-entry-match-against-dlink-p file-apps)) (remp (and (assq 'remote apps) (org-file-remote-p file))) - (dirp (if remp nil (file-directory-p file))) + (dirp (unless remp (file-directory-p file))) (file (if (and dirp org-open-directory-means-index-dot-org) (concat (file-name-as-directory file) "index.org") file)) (a-m-a-p (assq 'auto-mode apps)) (dfile (downcase file)) - ;; reconstruct the original file: link from the PATH, LINE and SEARCH args - (link (cond ((and (eq line nil) - (eq search nil)) - file) - (line - (concat file "::" (number-to-string line))) - (search - (concat file "::" search)))) + ;; Reconstruct the original link from the PATH, LINE and + ;; SEARCH args. + (link (cond (line (concat file "::" (number-to-string line))) + (search (concat file "::" search)) + (t file))) (dlink (downcase link)) (old-buffer (current-buffer)) (old-pos (point)) (old-mode major-mode) - ext cmd link-match-data) - (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\.gz\\)$" dfile) - (setq ext (match-string 1 dfile)) - (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\)$" dfile) - (setq ext (match-string 1 dfile)))) + (ext + (and (string-match "\\`.*?\\.\\([a-zA-Z0-9]+\\(\\.gz\\)?\\)\\'" dfile) + (match-string 1 dfile))) + cmd link-match-data) (cond ((member in-emacs '((16) system)) - (setq cmd (cdr (assoc 'system apps)))) + (setq cmd (cdr (assq 'system apps)))) (in-emacs (setq cmd 'emacs)) (t - (setq cmd (or (and remp (cdr (assoc 'remote apps))) - (and dirp (cdr (assoc 'directory apps))) - ; first, try matching against apps-dlink - ; if we get a match here, store the match data for later + (setq cmd (or (and remp (cdr (assq 'remote apps))) + (and dirp (cdr (assq 'directory apps))) + ;; First, try matching against apps-dlink if we + ;; get a match here, store the match data for + ;; later. (let ((match (assoc-default dlink apps-dlink 'string-match))) (if match @@ -11120,9 +11424,9 @@ If the file does not exist, an error is thrown." (assoc-default dfile (org-apps-regexp-alist apps a-m-a-p) 'string-match) (cdr (assoc ext apps)) - (cdr (assoc t apps)))))) + (cdr (assq t apps)))))) (when (eq cmd 'system) - (setq cmd (cdr (assoc 'system apps)))) + (setq cmd (cdr (assq 'system apps)))) (when (eq cmd 'default) (setq cmd (cdr (assoc t apps)))) (when (eq cmd 'mailcap) @@ -11133,21 +11437,20 @@ If the file does not exist, an error is thrown." (if (stringp command) (setq cmd command) (setq cmd 'emacs)))) - (if (and (not (eq cmd 'emacs)) ; Emacs has no problems with non-ex files - (not (file-exists-p file)) - (not org-open-non-existing-files)) - (user-error "No such file: %s" file)) + (when (and (not (eq cmd 'emacs)) ; Emacs has no problems with non-ex files + (not (file-exists-p file)) + (not org-open-non-existing-files)) + (user-error "No such file: %s" file)) (cond ((and (stringp cmd) (not (string-match "^\\s-*$" cmd))) ;; Remove quotes around the file name - we'll use shell-quote-argument. (while (string-match "['\"]%s['\"]" cmd) (setq cmd (replace-match "%s" t t cmd))) - (while (string-match "%s" cmd) - (setq cmd (replace-match - (save-match-data - (shell-quote-argument - (convert-standard-filename file))) - t t cmd))) + (setq cmd (replace-regexp-in-string + "%s" + (shell-quote-argument (convert-standard-filename file)) + cmd + nil t)) ;; Replace "%1", "%2" etc. in command with group matches from regex (save-match-data @@ -11169,17 +11472,33 @@ If the file does not exist, an error is thrown." (eq cmd 'emacs)) (funcall (cdr (assq 'file org-link-frame-setup)) file) (widen) - (if line (org-goto-line line) - (if search (org-link-search search)))) + (cond (line (org-goto-line line) + (when (derived-mode-p 'org-mode) (org-reveal))) + (search (org-link-search search)))) + ((functionp cmd) + (save-match-data + (set-match-data link-match-data) + (condition-case nil + (funcall cmd file link) + ;; FIXME: Remove this check when most default installations + ;; of Emacs have at least Org 9.0. + ((debug wrong-number-of-arguments wrong-type-argument + invalid-function) + (user-error "Please see Org News for version 9.0 about \ +`org-file-apps'--Lisp error: %S" cmd))))) ((consp cmd) - (let ((file (convert-standard-filename file))) - (save-match-data - (set-match-data link-match-data) - (eval cmd)))) + ;; FIXME: Remove this check when most default installations of + ;; Emacs have at least Org 9.0. + ;; Heads-up instead of silently fall back to + ;; `org-link-frame-setup' for an old usage of `org-file-apps' + ;; with sexp instead of a function for `cmd'. + (user-error "Please see Org News for version 9.0 about \ +`org-file-apps'--Error: Deprecated usage of %S" cmd)) (t (funcall (cdr (assq 'file org-link-frame-setup)) file))) - (and (derived-mode-p 'org-mode) (eq old-mode 'org-mode) - (or (not (equal old-buffer (current-buffer))) - (not (equal old-pos (point)))) + (and (derived-mode-p 'org-mode) + (eq old-mode 'org-mode) + (or (not (eq old-buffer (current-buffer))) + (not (eq old-pos (point)))) (org-mark-ring-push old-pos old-buffer)))) (defun org-file-apps-entry-match-against-dlink-p (entry) @@ -11220,16 +11539,15 @@ be opened in Emacs." (append (delq nil (mapcar (lambda (x) - (if (not (stringp (car x))) - nil + (unless (not (stringp (car x))) (if (string-match "\\W" (car x)) x (cons (concat "\\." (car x) "\\'") (cdr x))))) list)) - (if add-auto-mode - (mapcar (lambda (x) (cons (car x) 'emacs)) auto-mode-alist)))) + (when add-auto-mode + (mapcar (lambda (x) (cons (car x) 'emacs)) auto-mode-alist)))) -(defvar ange-ftp-name-format) ; to silence the XEmacs compiler. +(defvar ange-ftp-name-format) (defun org-file-remote-p (file) "Test whether FILE specifies a location on a remote system. Return non-nil if the location is indeed remote. @@ -11262,8 +11580,8 @@ on the system \"/user@host:\"." ((not (listp org-reverse-note-order)) nil) (t (catch 'exit (dolist (entry org-reverse-note-order) - (if (string-match (car entry) buffer-file-name) - (throw 'exit (cdr entry)))))))) + (when (string-match (car entry) buffer-file-name) + (throw 'exit (cdr entry)))))))) (defvar org-refile-target-table nil "The list of refile targets, created by `org-refile'.") @@ -11288,7 +11606,7 @@ on the system \"/user@host:\"." (defun org-refile-cache-clear () "Clear the refile cache and disable all the markers." - (mapc (lambda (m) (move-marker m nil)) org-refile-markers) + (dolist (m org-refile-markers) (move-marker m nil)) (setq org-refile-markers nil) (setq org-refile-cache nil) (message "Refile cache has been cleared")) @@ -11323,17 +11641,23 @@ on the system \"/user@host:\"." org-refile-cache)))) (and set (org-refile-cache-check-set set) set))))) -(defun org-refile-get-targets (&optional default-buffer excluded-entries) +(defvar org-outline-path-cache nil + "Alist between buffer positions and outline paths. +It value is an alist (POSITION . PATH) where POSITION is the +buffer position at the beginning of an entry and PATH is a list +of strings describing the outline path for that entry, in reverse +order.") + +(defun org-refile-get-targets (&optional default-buffer) "Produce a table with refile targets." (let ((case-fold-search nil) ;; otherwise org confuses "TODO" as a kw and "Todo" as a word (entries (or org-refile-targets '((nil . (:level . 1))))) - targets tgs txt re files desc descre fast-path-p level pos0) + targets tgs files desc descre) (message "Getting targets...") (with-current-buffer (or default-buffer (current-buffer)) (dolist (entry entries) (setq files (car entry) desc (cdr entry)) - (setq fast-path-p nil) (cond ((null files) (setq files (list (current-buffer)))) ((eq files 'org-agenda-files) @@ -11342,7 +11666,7 @@ on the system \"/user@host:\"." (setq files (funcall files))) ((and (symbolp files) (boundp files)) (setq files (symbol-value files)))) - (if (stringp files) (setq files (list files))) + (when (stringp files) (setq files (list files))) (cond ((eq (car desc) :tag) (setq descre (concat "^\\*+[ \t]+.*?:" (regexp-quote (cdr desc)) ":"))) @@ -11357,7 +11681,6 @@ on the system \"/user@host:\"." (cdr desc))) "\\}[ \t]"))) ((eq (car desc) :maxlevel) - (setq fast-path-p t) (setq descre (concat "^\\*\\{1," (number-to-string (if org-odd-levels-only (1- (* 2 (cdr desc))) @@ -11365,99 +11688,113 @@ on the system \"/user@host:\"." "\\}[ \t]"))) (t (error "Bad refiling target description %s" desc))) (dolist (f files) - (with-current-buffer - (if (bufferp f) f (org-get-agenda-file-buffer f)) + (with-current-buffer (if (bufferp f) f (org-get-agenda-file-buffer f)) (or (setq tgs (org-refile-cache-get (buffer-file-name) descre)) (progn - (if (bufferp f) (setq f (buffer-file-name - (buffer-base-buffer f)))) + (when (bufferp f) + (setq f (buffer-file-name (buffer-base-buffer f)))) (setq f (and f (expand-file-name f))) - (if (eq org-refile-use-outline-path 'file) - (push (list (file-name-nondirectory f) f nil nil) tgs)) - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (while (re-search-forward descre nil t) - (goto-char (setq pos0 (point-at-bol))) - (catch 'next - (when org-refile-target-verify-function - (save-match-data - (or (funcall org-refile-target-verify-function) - (throw 'next t)))) - (when (and (looking-at org-complex-heading-regexp) - (not (member (match-string 4) excluded-entries)) - (match-string 4)) - (setq level (org-reduced-level - (- (match-end 1) (match-beginning 1))) - txt (org-link-display-format (match-string 4)) - txt (replace-regexp-in-string "\\( *[[0-9]+/?[0-9]*%?]\\)+$" "" txt) - re (format org-complex-heading-regexp-format - (regexp-quote (match-string 4)))) - (when org-refile-use-outline-path - (setq txt (mapconcat - 'org-protect-slash - (append - (if (eq org-refile-use-outline-path - 'file) - (list (file-name-nondirectory - (buffer-file-name - (buffer-base-buffer)))) - (if (eq org-refile-use-outline-path - 'full-file-path) - (list (buffer-file-name - (buffer-base-buffer))))) - (org-get-outline-path fast-path-p - level txt) - (list txt)) - "/"))) - (push (list txt f re (org-refile-marker (point))) - tgs))) - (when (= (point) pos0) - ;; verification function has not moved point - (goto-char (point-at-eol)))))))) + (when (eq org-refile-use-outline-path 'file) + (push (list (file-name-nondirectory f) f nil nil) tgs)) + (org-with-wide-buffer + (goto-char (point-min)) + (setq org-outline-path-cache nil) + (while (re-search-forward descre nil t) + (beginning-of-line) + (let ((case-fold-search nil)) + (looking-at org-complex-heading-regexp)) + (let ((begin (point)) + (heading (match-string-no-properties 4))) + (unless (or (and + org-refile-target-verify-function + (not + (funcall org-refile-target-verify-function))) + (not heading)) + (let ((re (format org-complex-heading-regexp-format + (regexp-quote heading))) + (target + (if (not org-refile-use-outline-path) heading + (mapconcat + #'org-protect-slash + (append + (pcase org-refile-use-outline-path + (`file (list (file-name-nondirectory + (buffer-file-name + (buffer-base-buffer))))) + (`full-file-path + (list (buffer-file-name + (buffer-base-buffer)))) + (_ nil)) + (org-get-outline-path t t)) + "/")))) + (push (list target f re (org-refile-marker (point))) + tgs))) + (when (= (point) begin) + ;; Verification function has not moved point. + (end-of-line))))))) (when org-refile-use-cache (org-refile-cache-put tgs (buffer-file-name) descre)) (setq targets (append tgs targets)))))) (message "Getting targets...done") - (nreverse targets))) + (delete-dups (nreverse targets)))) (defun org-protect-slash (s) - (while (string-match "/" s) - (setq s (replace-match "\\" t t s))) - s) - -(defvar org-olpa (make-vector 20 nil)) - -(defun org-get-outline-path (&optional fastp level heading) - "Return the outline path to the current entry, as a list. - -The parameters FASTP, LEVEL, and HEADING are for use by a scanner -routine which makes outline path derivations for an entire file, -avoiding backtracing. Refile target collection makes use of that." - (if fastp - (progn - (if (> level 19) - (error "Outline path failure, more than 19 levels")) - (loop for i from level upto 19 do - (aset org-olpa i nil)) - (prog1 - (delq nil (append org-olpa nil)) - (aset org-olpa level heading))) - (let (rtn case-fold-search) - (save-excursion - (save-restriction - (widen) - (while (org-up-heading-safe) - (when (looking-at org-complex-heading-regexp) - (push (org-trim - (replace-regexp-in-string - ;; Remove statistical/checkboxes cookies - "\\[[0-9]+%\\]\\|\\[[0-9]+/[0-9]+\\]" "" - (org-match-string-no-properties 4))) - rtn))) - rtn))))) + (replace-regexp-in-string "/" "\\/" s nil t)) + +(defun org--get-outline-path-1 (&optional use-cache) + "Return outline path to current headline. + +Outline path is a list of strings, in reverse order. When +optional argument USE-CACHE is non-nil, make use of a cache. See +`org-get-outline-path' for details. + +Assume buffer is widened and point is on a headline." + (or (and use-cache (cdr (assq (point) org-outline-path-cache))) + (let ((p (point)) + (heading (let ((case-fold-search nil)) + (looking-at org-complex-heading-regexp) + (if (not (match-end 4)) "" + ;; Remove statistics cookies. + (org-trim + (org-link-display-format + (replace-regexp-in-string + "\\[[0-9]+%\\]\\|\\[[0-9]+/[0-9]+\\]" "" + (match-string-no-properties 4)))))))) + (if (org-up-heading-safe) + (let ((path (cons heading (org--get-outline-path-1 use-cache)))) + (when use-cache + (push (cons p path) org-outline-path-cache)) + path) + ;; This is a new root node. Since we assume we are moving + ;; forward, we can drop previous cache so as to limit number + ;; of associations there. + (let ((path (list heading))) + (when use-cache (setq org-outline-path-cache (list (cons p path)))) + path))))) + +(defun org-get-outline-path (&optional with-self use-cache) + "Return the outline path to the current entry. + +An outline path is a list of ancestors for current headline, as +a list of strings. Statistics cookies are removed and links are +replaced with their description, if any, or their path otherwise. + +When optional argument WITH-SELF is non-nil, the path also +includes the current headline. + +When optional argument USE-CACHE is non-nil, cache outline paths +between calls to this function so as to avoid backtracking. This +argument is useful when planning to find more than one outline +path in the same document. In that case, there are two +conditions to satisfy: + - `org-outline-path-cache' is set to nil before starting the + process; + - outline paths are computed by increasing buffer positions." + (org-with-wide-buffer + (and (or (and with-self (org-back-to-heading t)) + (org-up-heading-safe)) + (reverse (org--get-outline-path-1 use-cache))))) (defun org-format-outline-path (path &optional width prefix separator) "Format the outline path PATH for display. @@ -11467,38 +11804,28 @@ such as the file name. SEPARATOR is inserted between the different parts of the path, the default is \"/\"." (setq width (or width 79)) - (if prefix (setq width (- width (length prefix)))) - (if (not path) - (or prefix "") - (let* ((nsteps (length path)) - (total-width (+ nsteps (apply '+ (mapcar 'length path)))) - (maxwidth (if (<= total-width width) - 10000 ;; everything fits - ;; we need to shorten the level headings - (/ (- width nsteps) nsteps))) - (org-odd-levels-only nil) - (n 0) - (total (1+ (length prefix)))) - (setq maxwidth (max maxwidth 10)) - (concat prefix - (if prefix (or separator "/")) - (mapconcat - (lambda (h) - (setq n (1+ n)) - (if (and (= n nsteps) (< maxwidth 10000)) - (setq maxwidth (- total-width total))) - (if (< (length h) maxwidth) - (progn (setq total (+ total (length h) 1)) h) - (setq h (substring h 0 (- maxwidth 2)) - total (+ total maxwidth 1)) - (if (string-match "[ \t]+\\'" h) - (setq h (substring h 0 (match-beginning 0)))) - (setq h (concat h ".."))) - (org-add-props h nil 'face - (nth (% (1- n) org-n-level-faces) - org-level-faces)) - h) - path (or separator "/")))))) + (setq path (delq nil path)) + (unless (> width 0) + (user-error "Argument `width' must be positive")) + (setq separator (or separator "/")) + (let* ((org-odd-levels-only nil) + (fpath (concat + prefix (and prefix path separator) + (mapconcat + (lambda (s) (replace-regexp-in-string "[ \t]+\\'" "" s)) + (cl-loop for head in path + for n from 0 + collect (org-add-props + head nil 'face + (nth (% n org-n-level-faces) org-level-faces))) + separator)))) + (when (> (length fpath) width) + (if (< width 7) + ;; It's unlikely that `width' will be this small, but don't + ;; waste characters by adding ".." if it is. + (setq fpath (substring fpath 0 width)) + (setf (substring fpath (- width 2)) ".."))) + fpath)) (defun org-display-outline-path (&optional file current separator just-return-string) "Display the current outline path in the echo area. @@ -11513,10 +11840,10 @@ If JUST-RETURN-STRING is non-nil, return a string, don't display a message." (bfn (buffer-file-name (buffer-base-buffer))) (path (and (derived-mode-p 'org-mode) (org-get-outline-path))) res) - (if current (setq path (append path - (save-excursion - (org-back-to-heading t) - (if (looking-at org-complex-heading-regexp) + (when current (setq path (append path + (save-excursion + (org-back-to-heading t) + (when (looking-at org-complex-heading-regexp) (list (match-string 4))))))) (setq res (org-format-outline-path @@ -11546,25 +11873,27 @@ the *old* location.") (let ((org-refile-keep t)) (funcall 'org-refile nil nil nil "Copy"))) -(defun org-refile (&optional goto default-buffer rfloc msg) +(defun org-refile (&optional arg default-buffer rfloc msg) "Move the entry or entries at point to another heading. + The list of target headings is compiled using the information in `org-refile-targets', which see. -At the target location, the entry is filed as a subitem of the target -heading. Depending on `org-reverse-note-order', the new subitem will -either be the first or the last subitem. +At the target location, the entry is filed as a subitem of the +target heading. Depending on `org-reverse-note-order', the new +subitem will either be the first or the last subitem. -If there is an active region, all entries in that region will be moved. -However, the region must fulfill the requirement that the first heading -is the first one sets the top-level of the moved text - at most siblings -below it are allowed. +If there is an active region, all entries in that region will be +refiled. However, the region must fulfill the requirement that +the first heading sets the top-level of the moved text. -With prefix arg GOTO, the command will only visit the target location +With a `\\[universal-argument]' ARG, the command will only visit the target \ +location and not actually move anything. -With a double prefix arg \\[universal-argument] \\[universal-argument], \ -go to the location where the last refiling operation has put the subtree. +With a prefix `\\[universal-argument] \\[universal-argument]', go to the \ +location where the last +refiling operation has put the subtree. With a numeric prefix argument of `2', refile to the running clock. @@ -11578,26 +11907,23 @@ RFLOC can be a refile location obtained in a different way. MSG is a string to replace \"Refile\" in the default prompt with another verb. E.g. `org-copy' sets this parameter to \"Copy\". -See also `org-refile-use-outline-path' and `org-completion-use-ido'. +See also `org-refile-use-outline-path'. -If you are using target caching (see `org-refile-use-cache'), -you have to clear the target cache in order to find new targets. -This can be done with a 0 prefix (`C-0 C-c C-w') or a triple +If you are using target caching (see `org-refile-use-cache'), you +have to clear the target cache in order to find new targets. +This can be done with a `0' prefix (`C-0 C-c C-w') or a triple prefix argument (`C-u C-u C-u C-c C-w')." - (interactive "P") - (if (member goto '(0 (64))) + (if (member arg '(0 (64))) (org-refile-cache-clear) (let* ((actionmsg (cond (msg msg) - ((equal goto 3) "Refile (and keep)") + ((equal arg 3) "Refile (and keep)") (t "Refile"))) - (cbuf (current-buffer)) (regionp (org-region-active-p)) (region-start (and regionp (region-beginning))) (region-end (and regionp (region-end))) - (filename (buffer-file-name (buffer-base-buffer cbuf))) - (org-refile-keep (if (equal goto 3) t org-refile-keep)) - pos it nbuf file re level reversed) + (org-refile-keep (if (equal arg 3) t org-refile-keep)) + pos it nbuf file level reversed) (setq last-command nil) (when regionp (goto-char region-start) @@ -11610,10 +11936,10 @@ prefix argument (`C-u C-u C-u C-c C-w')." (org-toggle-heading) (setq region-end (+ (- (point-at-eol) s) region-end))))) (user-error "The region is not a (sequence of) subtree(s)"))) - (if (equal goto '(16)) + (if (equal arg '(16)) (org-refile-goto-last-stored) (when (or - (and (equal goto 2) + (and (equal arg 2) org-clock-hd-marker (marker-buffer org-clock-hd-marker) (prog1 (setq it (list (or org-clock-heading "running clock") @@ -11621,43 +11947,44 @@ prefix argument (`C-u C-u C-u C-c C-w')." (marker-buffer org-clock-hd-marker)) "" (marker-position org-clock-hd-marker))) - (setq goto nil))) - (setq it (or rfloc - (let (heading-text) - (save-excursion - (unless (and goto (listp goto)) - (org-back-to-heading t) - (setq heading-text - (nth 4 (org-heading-components)))) - - (org-refile-get-location - (cond ((and goto (listp goto)) "Goto") - (regionp (concat actionmsg " region to")) - (t (concat actionmsg " subtree \"" - heading-text "\" to"))) - default-buffer - (and (not (equal '(4) goto)) - org-refile-allow-creating-parent-nodes) - goto)))))) + (setq arg nil))) + (setq it + (or rfloc + (let (heading-text) + (save-excursion + (unless (and arg (listp arg)) + (org-back-to-heading t) + (setq heading-text + (replace-regexp-in-string + org-bracket-link-regexp + "\\3" + (or (nth 4 (org-heading-components)) + "")))) + (org-refile-get-location + (cond ((and arg (listp arg)) "Goto") + (regionp (concat actionmsg " region to")) + (t (concat actionmsg " subtree \"" + heading-text "\" to"))) + default-buffer + (and (not (equal '(4) arg)) + org-refile-allow-creating-parent-nodes))))))) (setq file (nth 1 it) - re (nth 2 it) pos (nth 3 it)) - (if (and (not goto) - pos - (equal (buffer-file-name) file) - (if regionp - (and (>= pos region-start) - (<= pos region-end)) - (and (>= pos (point)) - (< pos (save-excursion - (org-end-of-subtree t t)))))) - (error "Cannot refile to position inside the tree or region")) - + (when (and (not arg) + pos + (equal (buffer-file-name) file) + (if regionp + (and (>= pos region-start) + (<= pos region-end)) + (and (>= pos (point)) + (< pos (save-excursion + (org-end-of-subtree t t)))))) + (error "Cannot refile to position inside the tree or region")) (setq nbuf (or (find-buffer-visiting file) (find-file-noselect file))) - (if (and goto (not (equal goto 3))) + (if (and arg (not (equal arg 3))) (progn - (org-pop-to-buffer-same-window nbuf) + (pop-to-buffer-same-window nbuf) (goto-char pos) (org-show-context 'org-goto)) (if regionp @@ -11668,50 +11995,48 @@ prefix argument (`C-u C-u C-u C-c C-w')." (with-current-buffer (setq nbuf (or (find-buffer-visiting file) (find-file-noselect file))) (setq reversed (org-notes-order-reversed-p)) - (save-excursion - (save-restriction - (widen) - (if pos - (progn - (goto-char pos) - (looking-at org-outline-regexp) - (setq level (org-get-valid-level (funcall outline-level) 1)) - (goto-char - (if reversed - (or (outline-next-heading) (point-max)) - (or (save-excursion (org-get-next-sibling)) - (org-end-of-subtree t t) - (point-max))))) - (setq level 1) - (if (not reversed) - (goto-char (point-max)) - (goto-char (point-min)) - (or (outline-next-heading) (goto-char (point-max))))) - (if (not (bolp)) (newline)) - (org-paste-subtree level) - (when org-log-refile - (org-add-log-setup 'refile nil nil 'findpos org-log-refile) - (unless (eq org-log-refile 'note) - (save-excursion (org-add-log-note)))) - (and org-auto-align-tags - (let ((org-loop-over-headlines-in-active-region nil)) - (org-set-tags nil t))) - (let ((bookmark-name (plist-get org-bookmark-names-plist - :last-refile))) - (when bookmark-name - (with-demoted-errors - (bookmark-set bookmark-name)))) - ;; If we are refiling for capture, make sure that the - ;; last-capture pointers point here - (when (org-bound-and-true-p org-refile-for-capture) - (let ((bookmark-name (plist-get org-bookmark-names-plist - :last-capture-marker))) - (when bookmark-name - (with-demoted-errors - (bookmark-set bookmark-name)))) - (move-marker org-capture-last-stored-marker (point))) - (if (fboundp 'deactivate-mark) (deactivate-mark)) - (run-hooks 'org-after-refile-insert-hook)))) + (org-with-wide-buffer + (if pos + (progn + (goto-char pos) + (looking-at org-outline-regexp) + (setq level (org-get-valid-level (funcall outline-level) 1)) + (goto-char + (if reversed + (or (outline-next-heading) (point-max)) + (or (save-excursion (org-get-next-sibling)) + (org-end-of-subtree t t) + (point-max))))) + (setq level 1) + (if (not reversed) + (goto-char (point-max)) + (goto-char (point-min)) + (or (outline-next-heading) (goto-char (point-max))))) + (unless (bolp) (newline)) + (org-paste-subtree level nil nil t) + (when org-log-refile + (org-add-log-setup 'refile nil nil org-log-refile) + (unless (eq org-log-refile 'note) + (save-excursion (org-add-log-note)))) + (and org-auto-align-tags + (let ((org-loop-over-headlines-in-active-region nil)) + (org-set-tags nil t))) + (let ((bookmark-name (plist-get org-bookmark-names-plist + :last-refile))) + (when bookmark-name + (with-demoted-errors + (bookmark-set bookmark-name)))) + ;; If we are refiling for capture, make sure that the + ;; last-capture pointers point here + (when (bound-and-true-p org-capture-is-refiling) + (let ((bookmark-name (plist-get org-bookmark-names-plist + :last-capture-marker))) + (when bookmark-name + (with-demoted-errors + (bookmark-set bookmark-name)))) + (move-marker org-capture-last-stored-marker (point))) + (when (fboundp 'deactivate-mark) (deactivate-mark)) + (run-hooks 'org-after-refile-insert-hook))) (unless org-refile-keep (if regionp (delete-region (point) (+ (point) (- region-end region-start))) @@ -11726,7 +12051,7 @@ prefix argument (`C-u C-u C-u C-c C-w')." (defun org-refile-goto-last-stored () "Go to the location where the last refile was stored." (interactive) - (bookmark-jump "org-refile-last-stored") + (bookmark-jump (plist-get org-bookmark-names-plist :last-refile)) (message "This is the location of the last refile")) (defun org-refile--get-location (refloc tbl) @@ -11740,35 +12065,22 @@ Also check `org-refile-target-table'." (list (replace-regexp-in-string "/$" "" refloc) (replace-regexp-in-string "\\([^/]\\)$" "\\1/" refloc)))))) -(defun org-refile-get-location (&optional prompt default-buffer new-nodes - no-exclude) +(defun org-refile-get-location (&optional prompt default-buffer new-nodes) "Prompt the user for a refile location, using PROMPT. PROMPT should not be suffixed with a colon and a space, because this function appends the default value from -`org-refile-history' automatically, if that is not empty. -When NO-EXCLUDE is set, do not exclude headlines in the current subtree, -this is used for the GOTO interface." +`org-refile-history' automatically, if that is not empty." (let ((org-refile-targets org-refile-targets) - (org-refile-use-outline-path org-refile-use-outline-path) - excluded-entries) - (when (and (derived-mode-p 'org-mode) - (not org-refile-use-cache) - (not no-exclude)) - (org-map-tree - (lambda() - (setq excluded-entries - (append excluded-entries (list (org-get-heading t t))))))) - (setq org-refile-target-table - (org-refile-get-targets default-buffer excluded-entries))) + (org-refile-use-outline-path org-refile-use-outline-path)) + (setq org-refile-target-table (org-refile-get-targets default-buffer))) (unless org-refile-target-table (user-error "No refile targets")) (let* ((cbuf (current-buffer)) - (partial-completion-mode nil) (cfn (buffer-file-name (buffer-base-buffer cbuf))) (cfunc (if (and org-refile-use-outline-path org-outline-path-complete-in-steps) - 'org-olpath-completing-read - 'org-icompleting-read)) + #'org-olpath-completing-read + #'completing-read)) (extra (if org-refile-use-outline-path "/" "")) (cbnex (concat (buffer-name) extra)) (filename (and cfn (expand-file-name cfn))) @@ -11803,8 +12115,8 @@ this is used for the GOTO interface." (cons (car pa) (if (assoc (car org-refile-history) tbl) org-refile-history (cdr org-refile-history)))) - (if (equal (car org-refile-history) (nth 1 org-refile-history)) - (pop org-refile-history))) + (when (equal (car org-refile-history) (nth 1 org-refile-history)) + (pop org-refile-history))) pa) (if (string-match "\\`\\(.*\\)/\\([^/]+\\)\\'" answ) (progn @@ -11827,20 +12139,18 @@ this is used for the GOTO interface." (pos (nth 3 refile-pointer)) buffer) (if (and (not (markerp pos)) (not file)) - (user-error "Please save the buffer to a file before refiling") + (user-error "Please indicate a target file in the refile path") (when (org-string-nw-p re) (setq buffer (if (markerp pos) (marker-buffer pos) (or (find-buffer-visiting file) (find-file-noselect file)))) (with-current-buffer buffer - (save-excursion - (save-restriction - (widen) - (goto-char pos) - (beginning-of-line 1) - (unless (org-looking-at-p re) - (user-error "Invalid refile position, please clear the cache with `C-0 C-c C-w' before refiling"))))))))) + (org-with-wide-buffer + (goto-char pos) + (beginning-of-line 1) + (unless (looking-at-p re) + (user-error "Invalid refile position, please clear the cache with `C-0 C-c C-w' before refiling")))))))) (defun org-refile-new-child (parent-target child) "Use refile target PARENT-TARGET to add new CHILD below it." @@ -11851,53 +12161,43 @@ this is used for the GOTO interface." level) (with-current-buffer (or (find-buffer-visiting file) (find-file-noselect file)) - (save-excursion - (save-restriction - (widen) - (if pos - (goto-char pos) - (goto-char (point-max)) - (if (not (bolp)) (newline))) - (when (looking-at org-outline-regexp) - (setq level (funcall outline-level)) - (org-end-of-subtree t t)) - (org-back-over-empty-lines) - (insert "\n" (make-string - (if pos (org-get-valid-level level 1) 1) ?*) - " " child "\n") - (beginning-of-line 0) - (list (concat (car parent-target) "/" child) file "" (point))))))) + (org-with-wide-buffer + (if pos + (goto-char pos) + (goto-char (point-max)) + (unless (bolp) (newline))) + (when (looking-at org-outline-regexp) + (setq level (funcall outline-level)) + (org-end-of-subtree t t)) + (org-back-over-empty-lines) + (insert "\n" (make-string + (if pos (org-get-valid-level level 1) 1) ?*) + " " child "\n") + (beginning-of-line 0) + (list (concat (car parent-target) "/" child) file "" (point)))))) (defun org-olpath-completing-read (prompt collection &rest args) "Read an outline path like a file name." - (let ((thetable collection) - (org-completion-use-ido nil) ; does not work with ido. - (org-completion-use-iswitchb nil)) ; or iswitchb - (apply - 'org-icompleting-read prompt - (lambda (string predicate &optional flag) - (let (rtn r f (l (length string))) - (cond - ((eq flag nil) - ;; try completion - (try-completion string thetable)) - ((eq flag t) - ;; all-completions - (setq rtn (all-completions string thetable predicate)) - (mapcar - (lambda (x) - (setq r (substring x l)) - (if (string-match " ([^)]*)$" x) - (setq f (match-string 0 x)) - (setq f "")) - (if (string-match "/" r) - (concat string (substring r 0 (match-end 0)) f) - x)) - rtn)) - ((eq flag 'lambda) - ;; exact match? - (assoc string thetable))))) - args))) + (let ((thetable collection)) + (apply #'completing-read + prompt + (lambda (string predicate &optional flag) + (cond + ((eq flag nil) (try-completion string thetable)) + ((eq flag t) + (let ((l (length string))) + (mapcar (lambda (x) + (let ((r (substring x l)) + (f (if (string-match " ([^)]*)$" x) + (match-string 0 x) + ""))) + (if (string-match "/" r) + (concat string (substring r 0 (match-end 0)) f) + x))) + (all-completions string thetable predicate)))) + ;; Exact match? + ((eq flag 'lambda) (assoc string thetable)))) + args))) ;;;; Dynamic blocks @@ -11910,19 +12210,12 @@ If not found, stay at current position and return nil." (setq pos (and (re-search-forward (concat "^[ \t]*#\\+\\(?:BEGIN\\|begin\\):[ \t]+" name "\\>") nil t) (match-beginning 0)))) - (if pos (goto-char pos)) + (when pos (goto-char pos)) pos)) -(defconst org-dblock-start-re - "^[ \t]*#\\+\\(?:BEGIN\\|begin\\):[ \t]+\\(\\S-+\\)\\([ \t]+\\(.*\\)\\)?" - "Matches the start line of a dynamic block, with parameters.") - -(defconst org-dblock-end-re "^[ \t]*#\\+\\(?:END\\|end\\)\\([: \t\r\n]\\|$\\)" - "Matches the end of a dynamic block.") - (defun org-create-dblock (plist) "Create a dynamic block section, with parameters taken from PLIST. -PLIST must contain a :name entry which is used as name of the block." +PLIST must contain a :name entry which is used as the name of the block." (when (string-match "\\S-" (buffer-substring (point-at-bol) (point-at-eol))) (end-of-line 1) (newline)) @@ -12042,13 +12335,14 @@ This function can be used in a hook." ;;;; Completion +(declare-function org-export-backend-options "ox" (cl-x) t) (defun org-get-export-keywords () "Return a list of all currently understood export keywords. Export keywords include options, block names, attributes and keywords relative to each registered export back-end." (let (keywords) (dolist (backend - (org-bound-and-true-p org-export--registered-backends) + (bound-and-true-p org-export-registered-backends) (delq nil keywords)) ;; Back-end name (for keywords, like #+LATEX:) (push (upcase (symbol-name (org-export-backend-name backend))) keywords) @@ -12064,27 +12358,24 @@ keywords relative to each registered export back-end." "TITLE:" "TODO:" "TYP_TODO:" "SELECT_TAGS:" "EXCLUDE_TAGS:")) (defcustom org-structure-template-alist - '(("s" "#+BEGIN_SRC ?\n\n#+END_SRC" "\n\n") - ("e" "#+BEGIN_EXAMPLE\n?\n#+END_EXAMPLE" "\n?\n") - ("q" "#+BEGIN_QUOTE\n?\n#+END_QUOTE" "\n?\n") - ("v" "#+BEGIN_VERSE\n?\n#+END_VERSE" "\n?\n") - ("V" "#+BEGIN_VERBATIM\n?\n#+END_VERBATIM" "\n?\n") - ("c" "#+BEGIN_CENTER\n?\n#+END_CENTER" "
\n?\n
") - ("l" "#+BEGIN_LaTeX\n?\n#+END_LaTeX" - "\n?\n") - ("L" "#+LaTeX: " "?") - ("h" "#+BEGIN_HTML\n?\n#+END_HTML" - "\n?\n") - ("H" "#+HTML: " "?") - ("a" "#+BEGIN_ASCII\n?\n#+END_ASCII" "") - ("A" "#+ASCII: " "") - ("i" "#+INDEX: ?" "#+INDEX: ?") - ("I" "#+INCLUDE: %file ?" - "")) + '(("s" "#+BEGIN_SRC ?\n\n#+END_SRC") + ("e" "#+BEGIN_EXAMPLE\n?\n#+END_EXAMPLE") + ("q" "#+BEGIN_QUOTE\n?\n#+END_QUOTE") + ("v" "#+BEGIN_VERSE\n?\n#+END_VERSE") + ("V" "#+BEGIN_VERBATIM\n?\n#+END_VERBATIM") + ("c" "#+BEGIN_CENTER\n?\n#+END_CENTER") + ("l" "#+BEGIN_EXPORT latex\n?\n#+END_EXPORT") + ("L" "#+LaTeX: ") + ("h" "#+BEGIN_EXPORT html\n?\n#+END_EXPORT") + ("H" "#+HTML: ") + ("a" "#+BEGIN_EXPORT ascii\n?\n#+END_EXPORT") + ("A" "#+ASCII: ") + ("i" "#+INDEX: ?") + ("I" "#+INCLUDE: %file ?")) "Structure completion elements. This is a list of abbreviation keys and values. The value gets inserted if you type `<' followed by the key and then press the completion key, -usually `M-TAB'. %file will be replaced by a file name after prompting +usually `TAB'. %file will be replaced by a file name after prompting for the file using completion. The cursor will be placed at the position of the `?' in the template. There are two templates for each key, the first uses the original Org syntax, @@ -12095,8 +12386,9 @@ variable `org-mtags-prefer-muse-templates'." :type '(repeat (list (string :tag "Key") - (string :tag "Template") - (string :tag "Muse Template")))) + (string :tag "Template"))) + :version "26.1" + :package-version '(Org . "8.3")) (defun org-try-structure-completion () "Try to complete a structure template before point. @@ -12113,29 +12405,28 @@ expands them." (defun org-complete-expand-structure-template (start cell) "Expand a structure template." - (let* ((musep (org-bound-and-true-p org-mtags-prefer-muse-templates)) - (rpl (nth (if musep 2 1) cell)) - (ind "")) + (let ((rpl (nth 1 cell)) + (ind "")) (delete-region start (point)) - (when (string-match "\\`#\\+" rpl) + (when (string-match "\\`[ \t]*#\\+" rpl) (cond ((bolp)) ((not (string-match "\\S-" (buffer-substring (point-at-bol) (point)))) (setq ind (buffer-substring (point-at-bol) (point)))) (t (newline)))) (setq start (point)) - (if (string-match "%file" rpl) - (setq rpl (replace-match - (concat - "\"" - (save-match-data - (abbreviate-file-name (read-file-name "Include file: "))) - "\"") - t t rpl))) + (when (string-match "%file" rpl) + (setq rpl (replace-match + (concat + "\"" + (save-match-data + (abbreviate-file-name (read-file-name "Include file: "))) + "\"") + t t rpl))) (setq rpl (mapconcat 'identity (split-string rpl "\n") (concat "\n" ind))) (insert rpl) - (if (re-search-backward "\\?" start t) (delete-char 1)))) + (when (re-search-backward "\\?" start t) (delete-char 1)))) ;;;; TODO, DEADLINE, Comments @@ -12144,17 +12435,18 @@ expands them." (interactive) (save-excursion (org-back-to-heading) - (let (case-fold-search) - (cond - ((looking-at (format org-heading-keyword-regexp-format - org-comment-string)) - (goto-char (match-end 1)) - (looking-at (concat " +" org-comment-string)) - (replace-match "" t t) - (when (eolp) (insert " "))) - ((looking-at org-outline-regexp) - (goto-char (match-end 0)) - (insert org-comment-string " ")))))) + (let ((case-fold-search nil)) + (looking-at org-complex-heading-regexp)) + (goto-char (or (match-end 3) (match-end 2) (match-end 1))) + (skip-chars-forward " \t") + (unless (memq (char-before) '(?\s ?\t)) (insert " ")) + (if (org-in-commented-heading-p t) + (delete-region (point) + (progn (search-forward " " (line-end-position) 'move) + (skip-chars-forward " \t") + (point))) + (insert org-comment-string) + (unless (eolp) (insert " "))))) (defvar org-last-todo-state-is-todo nil "This is non-nil when the last TODO state change led to a TODO state. @@ -12193,43 +12485,65 @@ nil or a string to be used for the todo mark." ) (interactive "P") (if (eq major-mode 'org-agenda-mode) (apply 'org-agenda-todo-yesterday arg) - (let* ((hour (third (decode-time - (org-current-time)))) + (let* ((org-use-effective-time t) + (hour (nth 2 (decode-time (org-current-time)))) (org-extend-today-until (1+ hour))) (org-todo arg)))) (defvar org-block-entry-blocking "" "First entry preventing the TODO state change.") +(defun org-cancel-repeater () + "Cancel a repeater by setting its numeric value to zero." + (interactive) + (save-excursion + (org-back-to-heading t) + (let ((bound1 (point)) + (bound0 (save-excursion (outline-next-heading) (point)))) + (when (and (re-search-forward + (concat "\\(" org-scheduled-time-regexp "\\)\\|\\(" + org-deadline-time-regexp "\\)\\|\\(" + org-ts-regexp "\\)") + bound0 t) + (re-search-backward "[ \t]+\\(?:[.+]\\)?\\+\\([0-9]+\\)[hdwmy]" + bound1 t)) + (replace-match "0" t nil nil 1))))) + +(defvar org-state) +(defvar org-blocked-by-checkboxes) (defun org-todo (&optional arg) "Change the TODO state of an item. + The state of an item is given by a keyword at the start of the heading, like *** TODO Write paper *** DONE Call mom The different keywords are specified in the variable `org-todo-keywords'. -By default the available states are \"TODO\" and \"DONE\". -So for this example: when the item starts with TODO, it is changed to DONE. +By default the available states are \"TODO\" and \"DONE\". So, for this +example: when the item starts with TODO, it is changed to DONE. When it starts with DONE, the DONE is removed. And when neither TODO nor DONE are present, add TODO at the beginning of the heading. -With \\[universal-argument] prefix arg, use completion to determine the new \ +With `\\[universal-argument]' prefix ARG, use completion to determine the new \ state. -With numeric prefix arg, switch to that state. -With a double \\[universal-argument] prefix, switch to the next set of TODO \ +With numeric prefix ARG, switch to that state. +With a `\\[universal-argument] \\[universal-argument]' prefix, switch to the \ +next set of TODO \ keywords (nextset). -With a triple \\[universal-argument] prefix, circumvent any state blocking. +With a `\\[universal-argument] \\[universal-argument] \\[universal-argument]' \ +prefix, circumvent any state blocking. With a numeric prefix arg of 0, inhibit note taking for the change. - -For calling through lisp, arg is also interpreted in the following way: -`none' -> empty state -\"\" (empty string) -> switch to empty state -`done' -> switch to DONE -`nextset' -> switch to the next set of keywords -`previousset' -> switch to the previous set of keywords -\"WAITING\" -> switch to the specified keyword, but only if it - really is a member of `org-todo-keywords'." +With a numeric prefix arg of -1, cancel repeater to allow marking as DONE. + +When called through ELisp, arg is also interpreted in the following way: +`none' -> empty state +\"\" -> switch to empty state +`done' -> switch to DONE +`nextset' -> switch to the next set of keywords +`previousset' -> switch to the previous set of keywords +\"WAITING\" -> switch to the specified keyword, but only if it + really is a member of `org-todo-keywords'." (interactive "P") (if (and (org-region-active-p) org-loop-over-headlines-in-active-region) (let ((cl (if (eq org-loop-over-headlines-in-active-region 'start-level) @@ -12238,8 +12552,9 @@ For calling through lisp, arg is also interpreted in the following way: (org-map-entries `(org-todo ,arg) org-loop-over-headlines-in-active-region - cl (if (outline-invisible-p) (org-end-of-subtree nil t)))) - (if (equal arg '(16)) (setq arg 'nextset)) + cl (when (org-invisible-p) (org-end-of-subtree nil t)))) + (when (equal arg '(16)) (setq arg 'nextset)) + (when (equal arg -1) (org-cancel-repeater) (setq arg nil)) (let ((org-blocker-hook org-blocker-hook) commentp case-fold-search) @@ -12252,10 +12567,10 @@ For calling through lisp, arg is also interpreted in the following way: (save-excursion (catch 'exit (org-back-to-heading t) - (when (looking-at (concat "^\\*+ " org-comment-string)) + (when (org-in-commented-heading-p t) (org-toggle-comment) (setq commentp t)) - (if (looking-at org-outline-regexp) (goto-char (1- (match-end 0)))) + (when (looking-at org-outline-regexp) (goto-char (1- (match-end 0)))) (or (looking-at (concat " +" org-todo-regexp "\\( +\\|[ \t]*$\\)")) (looking-at "\\(?: *\\|[ \t]*$\\)")) (let* ((match-data (match-data)) @@ -12285,31 +12600,30 @@ For calling through lisp, arg is also interpreted in the following way: (and (not arg) org-use-fast-todo-selection (not (eq org-use-fast-todo-selection 'prefix))))) - ;; Use fast selection + ;; Use fast selection. (org-fast-todo-selection)) ((and (equal arg '(4)) (or (not org-use-fast-todo-selection) (not org-todo-key-trigger))) - ;; Read a state with completion - (org-icompleting-read - "State: " (mapcar 'list org-todo-keywords-1) + ;; Read a state with completion. + (completing-read + "State: " (mapcar #'list org-todo-keywords-1) nil t)) ((eq arg 'right) (if this (if tail (car tail) nil) (car org-todo-keywords-1))) ((eq arg 'left) - (if (equal member org-todo-keywords-1) - nil + (unless (equal member org-todo-keywords-1) (if this (nth (- (length org-todo-keywords-1) (length tail) 2) org-todo-keywords-1) (org-last org-todo-keywords-1)))) ((and (eq org-use-fast-todo-selection t) (equal arg '(4)) - (setq arg nil))) ; hack to fall back to cycling + (setq arg nil))) ;hack to fall back to cycling (arg - ;; user or caller requests a specific state + ;; User or caller requests a specific state. (cond ((equal arg "") nil) ((eq arg 'none) nil) @@ -12327,8 +12641,8 @@ For calling through lisp, arg is also interpreted in the following way: ((nth (1- (prefix-numeric-value arg)) org-todo-keywords-1)))) ((null member) (or head (car org-todo-keywords-1))) - ((equal this final-done-word) nil) ;; -> make empty - ((null tail) nil) ;; -> first entry + ((equal this final-done-word) nil) ;-> make empty + ((null tail) nil) ;-> first entry ((memq interpret '(type priority)) (if (eq this-command last-command) (car tail) @@ -12346,24 +12660,30 @@ For calling through lisp, arg is also interpreted in the following way: :position startpos)) dolog now-done-p) (when org-blocker-hook - (setq org-last-todo-state-is-todo - (not (member this org-done-keywords))) - (unless (save-excursion - (save-match-data - (org-with-wide-buffer - (run-hook-with-args-until-failure - 'org-blocker-hook change-plist)))) - (if (org-called-interactively-p 'interactive) - (user-error "TODO state change from %s to %s blocked (by \"%s\")" - this org-state org-block-entry-blocking) - ;; fail silently - (message "TODO state change from %s to %s blocked (by \"%s\")" - this org-state org-block-entry-blocking) - (throw 'exit nil)))) + (let (org-blocked-by-checkboxes block-reason) + (setq org-last-todo-state-is-todo + (not (member this org-done-keywords))) + (unless (save-excursion + (save-match-data + (org-with-wide-buffer + (run-hook-with-args-until-failure + 'org-blocker-hook change-plist)))) + (setq block-reason (if org-blocked-by-checkboxes + "contained checkboxes" + (format "\"%s\"" org-block-entry-blocking))) + (if (called-interactively-p 'interactive) + (user-error "TODO state change from %s to %s blocked (by %s)" + this org-state block-reason) + ;; Fail silently. + (message "TODO state change from %s to %s blocked (by %s)" + this org-state block-reason) + (throw 'exit nil))))) (store-match-data match-data) (replace-match next t t) - (unless (pos-visible-in-window-p hl-pos) - (message "TODO state changed to %s" (org-trim next))) + (cond ((equal this org-state) + (message "TODO state was already %s" (org-trim next))) + ((pos-visible-in-window-p hl-pos) + (message "TODO state changed to %s" (org-trim next)))) (unless head (setq head (org-get-todo-sequence-head org-state) ass (assoc head org-todo-kwd-alist) @@ -12384,11 +12704,11 @@ For calling through lisp, arg is also interpreted in the following way: (when (and (or org-todo-log-states org-log-done) (not (eq org-inhibit-logging t)) (not (memq arg '(nextset previousset)))) - ;; we need to look at recording a time and note + ;; We need to look at recording a time and note. (setq dolog (or (nth 1 (assoc org-state org-todo-log-states)) (nth 2 (assoc this org-todo-log-states)))) - (if (and (eq dolog 'note) (eq org-inhibit-logging 'note)) - (setq dolog 'time)) + (when (and (eq dolog 'note) (eq org-inhibit-logging 'note)) + (setq dolog 'time)) (when (or (and (not org-state) (not org-closed-keep-when-no-todo)) (and org-state (member org-state org-not-done-keywords) @@ -12397,21 +12717,21 @@ For calling through lisp, arg is also interpreted in the following way: ;; If there was a CLOSED time stamp, get rid of it. (org-add-planning-info nil nil 'closed)) (when (and now-done-p org-log-done) - ;; It is now done, and it was not done before + ;; It is now done, and it was not done before. (org-add-planning-info 'closed (org-current-effective-time)) - (if (and (not dolog) (eq 'note org-log-done)) - (org-add-log-setup 'done org-state this 'findpos 'note))) + (when (and (not dolog) (eq 'note org-log-done)) + (org-add-log-setup 'done org-state this 'note))) (when (and org-state dolog) - ;; This is a non-nil state, and we need to log it - (org-add-log-setup 'state org-state this 'findpos dolog))) - ;; Fixup tag positioning + ;; This is a non-nil state, and we need to log it. + (org-add-log-setup 'state org-state this dolog))) + ;; Fixup tag positioning. (org-todo-trigger-tag-changes org-state) (and org-auto-align-tags (not org-setting-tags) (org-set-tags nil t)) (when org-provide-todo-statistics (org-update-parent-todo-statistics)) (run-hooks 'org-after-todo-state-change-hook) - (if (and arg (not (member org-state org-done-keywords))) - (setq head (org-get-todo-sequence-head org-state))) + (when (and arg (not (member org-state org-done-keywords))) + (setq head (org-get-todo-sequence-head org-state))) (put-text-property (point-at-bol) (point-at-eol) 'org-todo-head head) ;; Do we need to trigger a repeat? (when now-done-p @@ -12421,15 +12741,14 @@ For calling through lisp, arg is also interpreted in the following way: (setq org-agenda-headline-snapshot-before-repeat (org-get-heading)))) (org-auto-repeat-maybe org-state)) - ;; Fixup cursor location if close to the keyword - (if (and (outline-on-heading-p) - (not (bolp)) - (save-excursion (beginning-of-line 1) - (looking-at org-todo-line-regexp)) - (< (point) (+ 2 (or (match-end 2) (match-end 1))))) - (progn - (goto-char (or (match-end 2) (match-end 1))) - (and (looking-at " ") (just-one-space)))) + ;; Fixup cursor location if close to the keyword. + (when (and (outline-on-heading-p) + (not (bolp)) + (save-excursion (beginning-of-line 1) + (looking-at org-todo-line-regexp)) + (< (point) (+ 2 (or (match-end 2) (match-end 1))))) + (goto-char (or (match-end 2) (match-end 1))) + (and (looking-at " ") (just-one-space))) (when org-trigger-hook (save-excursion (run-hook-with-args 'org-trigger-hook change-plist))) @@ -12471,10 +12790,10 @@ changes. Such blocking occurs when: (> child-level this-level)) ;; this todo has children, check whether they are all ;; completed - (if (and (not (org-entry-is-done-p)) - (org-entry-is-todo-p)) - (progn (setq org-block-entry-blocking (org-get-heading)) - (throw 'dont-block nil))) + (when (and (not (org-entry-is-done-p)) + (org-entry-is-todo-p)) + (setq org-block-entry-blocking (org-get-heading)) + (throw 'dont-block nil)) (outline-next-heading) (setq child-level (funcall outline-level)))))) ;; Otherwise, if the task's parent has the :ORDERED: property, and @@ -12482,8 +12801,9 @@ changes. Such blocking occurs when: (save-excursion (org-back-to-heading t) (let* ((pos (point)) - (parent-pos (and (org-up-heading-safe) (point)))) - (if (not parent-pos) (throw 'dont-block t)) ; no parent + (parent-pos (and (org-up-heading-safe) (point))) + (case-fold-search nil)) + (unless parent-pos (throw 'dont-block t)) ; no parent (when (and (org-not-nil (org-entry-get (point) "ORDERED")) (forward-line 1) (re-search-forward org-not-done-heading-regexp pos t)) @@ -12492,11 +12812,11 @@ changes. Such blocking occurs when: ;; Search further up the hierarchy, to see if an ancestor is blocked (while t (goto-char parent-pos) - (if (not (looking-at org-not-done-heading-regexp)) - (throw 'dont-block t)) ; do not block, parent is not a TODO + (unless (looking-at org-not-done-heading-regexp) + (throw 'dont-block t)) ; do not block, parent is not a TODO (setq pos (point)) (setq parent-pos (and (org-up-heading-safe) (point))) - (if (not parent-pos) (throw 'dont-block t)) ; no parent + (unless parent-pos (throw 'dont-block t)) ; no parent (when (and (org-not-nil (org-entry-get (point) "ORDERED")) (forward-line 1) (re-search-forward org-not-done-heading-regexp pos t) @@ -12533,14 +12853,13 @@ See variable `org-track-ordered-property-with-tag'." (org-back-to-heading) (if (org-entry-get nil "ORDERED") (progn - (org-delete-property "ORDERED" "PROPERTIES") + (org-delete-property "ORDERED") (and tag (org-toggle-tag tag 'off)) (message "Subtasks can be completed in arbitrary order")) (org-entry-put nil "ORDERED" "t") (and tag (org-toggle-tag tag 'on)) (message "Subtasks must be completed in sequence"))))) -(defvar org-blocked-by-checkboxes) ; dynamically scoped (defun org-block-todo-from-checkboxes (change-plist) "Block turning an entry into a TODO, using checkboxes. This checks whether the current task should be blocked from state @@ -12564,32 +12883,32 @@ changes because there are unchecked boxes in this entry." (outline-next-heading) (setq end (point)) (goto-char beg) - (if (org-list-search-forward - (concat (org-item-beginning-re) - "\\(?:\\[@\\(?:start:\\)?\\([0-9]+\\|[A-Za-z]\\)\\][ \t]*\\)?" - "\\[[- ]\\]") - end t) - (progn - (if (boundp 'org-blocked-by-checkboxes) - (setq org-blocked-by-checkboxes t)) - (throw 'dont-block nil))))) + (when (org-list-search-forward + (concat (org-item-beginning-re) + "\\(?:\\[@\\(?:start:\\)?\\([0-9]+\\|[A-Za-z]\\)\\][ \t]*\\)?" + "\\[[- ]\\]") + end t) + (when (boundp 'org-blocked-by-checkboxes) + (setq org-blocked-by-checkboxes t)) + (throw 'dont-block nil)))) t))) ; do not block (defun org-entry-blocked-p () - "Is the current entry blocked?" - (org-with-silent-modifications - (if (org-entry-get nil "NOBLOCKING") - nil ;; Never block this entry - (not (run-hook-with-args-until-failure - 'org-blocker-hook - (list :type 'todo-state-change - :position (point) - :from 'todo - :to 'done)))))) + "Non-nil if entry at point is blocked." + (and (not (org-entry-get nil "NOBLOCKING")) + (member (org-entry-get nil "TODO") org-not-done-keywords) + (not (run-hook-with-args-until-failure + 'org-blocker-hook + (list :type 'todo-state-change + :position (point) + :from 'todo + :to 'done))))) (defun org-update-statistics-cookies (all) "Update the statistics cookie, either from TODO or from checkboxes. -This should be called with the cursor in a line with a statistics cookie." +This should be called with the cursor in a line with a statistics +cookie. When called with a \\[universal-argument] prefix, update +all statistics cookies in the buffer." (interactive "P") (if all (progn @@ -12605,7 +12924,7 @@ This should be called with the cursor in a line with a statistics cookie." (setq l1 (org-outline-level)) (setq end (save-excursion (outline-next-heading) - (if (org-at-heading-p) (setq l2 (org-outline-level))) + (when (org-at-heading-p) (setq l2 (org-outline-level))) (point))) (if (and (save-excursion (re-search-forward @@ -12642,7 +12961,7 @@ statistics everywhere." (box-re "\\(\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)\\)") level ltoggle l1 new ndel (cnt-all 0) (cnt-done 0) is-percent kwd - checkbox-beg ov ovs ove cookie-present) + checkbox-beg cookie-present) (catch 'exit (save-excursion (beginning-of-line 1) @@ -12677,14 +12996,31 @@ statistics everywhere." (setq kwd (and (or recursive (= l1 ltoggle)) (match-string 2))) (if (or (eq org-provide-todo-statistics 'all-headlines) + (and (eq org-provide-todo-statistics t) + (or (member kwd org-done-keywords))) (and (listp org-provide-todo-statistics) + (stringp (car org-provide-todo-statistics)) (or (member kwd org-provide-todo-statistics) - (member kwd org-done-keywords)))) + (member kwd org-done-keywords))) + (and (listp org-provide-todo-statistics) + (listp (car org-provide-todo-statistics)) + (or (member kwd (car org-provide-todo-statistics)) + (and (member kwd org-done-keywords) + (member kwd (cadr org-provide-todo-statistics)))))) (setq cnt-all (1+ cnt-all)) - (if (eq org-provide-todo-statistics t) - (and kwd (setq cnt-all (1+ cnt-all))))) - (and (member kwd org-done-keywords) - (setq cnt-done (1+ cnt-done))) + (and (eq org-provide-todo-statistics t) + kwd + (setq cnt-all (1+ cnt-all)))) + (when (or (and (member org-provide-todo-statistics '(t all-headlines)) + (member kwd org-done-keywords)) + (and (listp org-provide-todo-statistics) + (listp (car org-provide-todo-statistics)) + (member kwd org-done-keywords) + (member kwd (cadr org-provide-todo-statistics))) + (and (listp org-provide-todo-statistics) + (stringp (car org-provide-todo-statistics)) + (member kwd org-done-keywords))) + (setq cnt-done (1+ cnt-done))) (outline-next-heading))) (setq new (if is-percent @@ -12692,15 +13028,10 @@ statistics everywhere." (max 1 cnt-all))) (format "[%d/%d]" cnt-done cnt-all)) ndel (- (match-end 0) checkbox-beg)) - ;; handle overlays when updating cookie from column view - (when (setq ov (car (overlays-at checkbox-beg))) - (setq ovs (overlay-start ov) ove (overlay-end ov)) - (delete-overlay ov)) (goto-char checkbox-beg) (insert new) (delete-region (point) (+ (point) ndel)) - (when org-auto-align-tags (org-fix-tags-on-the-fly)) - (when ov (move-overlay ov ovs ove))) + (when org-auto-align-tags (org-fix-tags-on-the-fly))) (when cookie-present (run-hook-with-args 'org-after-todo-statistics-hook cnt-done (- cnt-all cnt-done)))))) @@ -12736,9 +13067,9 @@ This hook runs even if there is no statistics cookie present, in which case (when (and (stringp state) (> (length state) 0)) (setq changes (append changes (cdr (assoc state l))))) (when (member state org-not-done-keywords) - (setq changes (append changes (cdr (assoc 'todo l))))) + (setq changes (append changes (cdr (assq 'todo l))))) (when (member state org-done-keywords) - (setq changes (append changes (cdr (assoc 'done l))))) + (setq changes (append changes (cdr (assq 'done l))))) (dolist (c changes) (org-toggle-tag (car c) (if (cdr c) 'on 'off))))) @@ -12749,7 +13080,7 @@ This hook runs even if there is no statistics cookie present, in which case org-log-repeat nil org-todo-log-states nil) (dolist (w (org-split-string value)) - (let* (a) + (let (a) (cond ((setq a (assoc w org-startup-options)) (and (member (nth 1 a) '(org-log-done org-log-repeat)) @@ -12786,7 +13117,7 @@ Returns the new TODO keyword, or nil if no state change should occur." (expert nil) (fwidth (+ maxlen 3 1 3)) (ncol (/ (- (window-width) 4) fwidth)) - tg cnt c tbl + tg cnt e c tbl groups ingroup) (save-excursion (save-window-excursion @@ -12794,13 +13125,13 @@ Returns the new TODO keyword, or nil if no state change should occur." (set-buffer (get-buffer-create " *Org todo*")) (org-switch-to-buffer-other-window (get-buffer-create " *Org todo*"))) (erase-buffer) - (org-set-local 'org-done-keywords done-keywords) + (setq-local org-done-keywords done-keywords) (setq tbl fulltable cnt 0) - (dolist (e tbl) + (while (setq e (pop tbl)) (cond ((equal e '(:startgroup)) (push '() groups) (setq ingroup t) - (when (not (= cnt 0)) + (unless (= cnt 0) (setq cnt 0) (insert "\n")) (insert "{ ")) @@ -12808,7 +13139,7 @@ Returns the new TODO keyword, or nil if no state change should occur." (setq ingroup nil cnt 0) (insert "}\n")) ((equal e '(:newline)) - (when (not (= cnt 0)) + (unless (= cnt 0) (setq cnt 0) (insert "\n") (setq e (car tbl)) @@ -12817,19 +13148,19 @@ Returns the new TODO keyword, or nil if no state change should occur." (setq tbl (cdr tbl))))) (t (setq tg (car e) c (cdr e)) - (if ingroup (push tg (car groups))) + (when ingroup (push tg (car groups))) (setq tg (org-add-props tg nil 'face (org-get-todo-face tg))) - (if (and (= cnt 0) (not ingroup)) (insert " ")) + (when (and (= cnt 0) (not ingroup)) (insert " ")) (insert "[" c "] " tg (make-string (- fwidth 4 (length tg)) ?\ )) (when (= (setq cnt (1+ cnt)) ncol) (insert "\n") - (if ingroup (insert " ")) + (when ingroup (insert " ")) (setq cnt 0))))) (insert "\n") (goto-char (point-min)) - (if (not expert) (org-fit-window-to-buffer)) + (unless expert (org-fit-window-to-buffer)) (message "[a-z..]:Set [SPC]:clear") (setq c (let ((inhibit-quit t)) (read-char-exclusive))) (cond @@ -12851,12 +13182,19 @@ Returns the new TODO keyword, or nil if no state change should occur." "Return the TODO keyword of the current subtree." (save-excursion (org-back-to-heading t) - (and (looking-at org-todo-line-regexp) + (and (let ((case-fold-search nil)) (looking-at org-todo-line-regexp)) (match-end 2) (match-string 2)))) (defun org-at-date-range-p (&optional inactive-ok) - "Is the cursor inside a date range?" + "Non-nil if point is inside a date range. + +When optional argument INACTIVE-OK is non-nil, also consider +inactive time ranges. + +When this function returns a non-nil value, match data is set +according to `org-tr-regexp-both' or `org-tr-regexp', depending +on INACTIVE-OK." (interactive) (save-excursion (catch 'exit @@ -12888,14 +13226,15 @@ Returns the new TODO keyword, or nil if no state change should occur." (defvar org-last-inserted-timestamp) (defvar org-log-post-message) (defvar org-log-note-purpose) -(defvar org-log-note-how) +(defvar org-log-note-how nil) (defvar org-log-note-extra) (defun org-auto-repeat-maybe (done-word) - "Check if the current headline contains a repeated deadline/schedule. + "Check if the current headline contains a repeated time-stamp. + If yes, set TODO state back to what it was and change the base date of repeating deadline/scheduled time stamps to new date. + This function is run automatically after each state change to a DONE state." - ;; last-state is dynamically scoped into this function (let* ((repeat (org-get-repeat)) (aa (assoc org-last-state org-todo-kwd-alist)) (interpret (nth 1 aa)) @@ -12903,73 +13242,108 @@ This function is run automatically after each state change to a DONE state." (whata '(("h" . hour) ("d" . day) ("m" . month) ("y" . year))) (msg "Entry repeats: ") (org-log-done nil) - (org-todo-log-states nil) - re type n what ts time to-state) - (when repeat - (if (eq org-log-repeat t) (setq org-log-repeat 'state)) - (setq to-state (or (org-entry-get nil "REPEAT_TO_STATE") - org-todo-repeat-to-state)) - (unless (and to-state (member to-state org-todo-keywords-1)) - (setq to-state (if (eq interpret 'type) org-last-state head))) - (org-todo to-state) + (org-todo-log-states nil)) + (when (and repeat (not (zerop (string-to-number (substring repeat 1))))) + (when (eq org-log-repeat t) (setq org-log-repeat 'state)) + (let ((to-state (or (org-entry-get nil "REPEAT_TO_STATE" 'selective) + org-todo-repeat-to-state))) + (org-todo (cond ((and to-state (member to-state org-todo-keywords-1)) + to-state) + ((eq interpret 'type) org-last-state) + (head) + (t 'none)))) (when (or org-log-repeat (org-entry-get nil "CLOCK")) (org-entry-put nil "LAST_REPEAT" (format-time-string (org-time-stamp-format t t)))) (when org-log-repeat (if (or (memq 'org-add-log-note (default-value 'post-command-hook)) (memq 'org-add-log-note post-command-hook)) - ;; OK, we are already setup for some record - (if (eq org-log-repeat 'note) - ;; make sure we take a note, not only a time stamp - (setq org-log-note-how 'note)) - ;; Set up for taking a record - (org-add-log-setup 'state (or done-word (car org-done-keywords)) + ;; We are already setup for some record. + (when (eq org-log-repeat 'note) + ;; Make sure we take a note, not only a time stamp. + (setq org-log-note-how 'note)) + ;; Set up for taking a record. + (org-add-log-setup 'state + (or done-word (car org-done-keywords)) org-last-state - 'findpos org-log-repeat))) + org-log-repeat))) (org-back-to-heading t) (org-add-planning-info nil nil 'closed) - (setq re (concat "\\(" org-scheduled-time-regexp "\\)\\|\\(" - org-deadline-time-regexp "\\)\\|\\(" - org-ts-regexp "\\)")) - (while (re-search-forward - re (save-excursion (outline-next-heading) (point)) t) - (setq type (if (match-end 1) org-scheduled-string - (if (match-end 3) org-deadline-string "Plain:")) - ts (match-string (if (match-end 2) 2 (if (match-end 4) 4 0)))) - (when (string-match "\\([.+]\\)?\\(\\+[0-9]+\\)\\([hdwmy]\\)" ts) - (setq n (string-to-number (match-string 2 ts)) - what (match-string 3 ts)) - (if (equal what "w") (setq n (* n 7) what "d")) - (if (and (equal what "h") (not (string-match "[0-9]\\{1,2\\}:[0-9]\\{2\\}" ts))) - (user-error "Cannot repeat in Repeat in %d hour(s) because no hour has been set" n)) - ;; Preparation, see if we need to modify the start date for the change - (when (match-end 1) - (setq time (save-match-data (org-time-string-to-time ts))) + (let ((end (save-excursion (outline-next-heading) (point))) + (planning-re (regexp-opt + (list org-scheduled-string org-deadline-string)))) + (while (re-search-forward org-ts-regexp end t) + (let* ((ts (match-string 0)) + (planning? (org-at-planning-p)) + (type (if (not planning?) "Plain:" + (save-excursion + (re-search-backward + planning-re (line-beginning-position) t) + (match-string 0))))) (cond - ((equal (match-string 1 ts) ".") - ;; Shift starting date to today - (org-timestamp-change - (- (org-today) (time-to-days time)) - 'day)) - ((equal (match-string 1 ts) "+") - (let ((nshiftmax 10) (nshift 0)) - (while (or (= nshift 0) - (<= (time-to-days time) - (time-to-days (current-time)))) - (when (= (incf nshift) nshiftmax) - (or (y-or-n-p (message "%d repeater intervals were not enough to shift date past today. Continue? " nshift)) - (error "Abort"))) - (org-timestamp-change n (cdr (assoc what whata))) - (org-at-timestamp-p t) - (setq ts (match-string 1)) - (setq time (save-match-data (org-time-string-to-time ts))))) - (org-timestamp-change (- n) (cdr (assoc what whata))) - ;; rematch, so that we have everything in place for the real shift - (org-at-timestamp-p t) - (setq ts (match-string 1)) - (string-match "\\([.+]\\)?\\(\\+[0-9]+\\)\\([hdwmy]\\)" ts)))) - (save-excursion (org-timestamp-change n (cdr (assoc what whata)) nil t)) - (setq msg (concat msg type " " org-last-changed-timestamp " ")))) + ;; Ignore fake time-stamps (e.g., within comments). + ((and (not planning?) + (not (org-at-property-p)) + (not (eq 'timestamp + (org-element-type (save-excursion + (backward-char) + (org-element-context))))))) + ;; Time-stamps without a repeater are usually skipped. + ;; However, a SCHEDULED time-stamp without one is + ;; removed, as it is considered as no longer relevant. + ((not (string-match "\\([.+]\\)?\\(\\+[0-9]+\\)\\([hdwmy]\\)" ts)) + (when (equal type org-scheduled-string) + (org-remove-timestamp-with-keyword type))) + (t + (let ((n (string-to-number (match-string 2 ts))) + (what (match-string 3 ts))) + (when (equal what "w") (setq n (* n 7) what "d")) + (when (and (equal what "h") + (not (string-match-p "[0-9]\\{1,2\\}:[0-9]\\{2\\}" + ts))) + (user-error + "Cannot repeat in Repeat in %d hour(s) because no hour \ +has been set" + n)) + ;; Preparation, see if we need to modify the start + ;; date for the change. + (when (match-end 1) + (let ((time (save-match-data (org-time-string-to-time ts)))) + (cond + ((equal (match-string 1 ts) ".") + ;; Shift starting date to today + (org-timestamp-change + (- (org-today) (time-to-days time)) + 'day)) + ((equal (match-string 1 ts) "+") + (let ((nshiftmax 10) + (nshift 0)) + (while (or (= nshift 0) + (not (time-less-p (current-time) time))) + (when (= (cl-incf nshift) nshiftmax) + (or (y-or-n-p + (format "%d repeater intervals were not \ +enough to shift date past today. Continue? " + nshift)) + (user-error "Abort"))) + (org-timestamp-change n (cdr (assoc what whata))) + (org-at-timestamp-p t) + (setq ts (match-string 1)) + (setq time + (save-match-data + (org-time-string-to-time ts))))) + (org-timestamp-change (- n) (cdr (assoc what whata))) + ;; Rematch, so that we have everything in place + ;; for the real shift. + (org-at-timestamp-p t) + (setq ts (match-string 1)) + (string-match "\\([.+]\\)?\\(\\+[0-9]+\\)\\([hdwmy]\\)" + ts))))) + (save-excursion + (org-timestamp-change n (cdr (assoc what whata)) nil t)) + (setq msg + (concat + msg type " " org-last-changed-timestamp " ")))))))) (setq org-log-post-message msg) (message "%s" msg)))) @@ -12977,7 +13351,7 @@ This function is run automatically after each state change to a DONE state." "Make a compact tree which shows all headlines marked with TODO. The tree will show the lines where the regexp matches, and all higher headlines above the match. -With a \\[universal-argument] prefix, prompt for a regexp to match. +With a `\\[universal-argument]' prefix, prompt for a regexp to match. With a numeric prefix N, construct a sparse tree for the Nth element of `org-todo-keywords-1'." (interactive "P") @@ -12985,8 +13359,9 @@ of `org-todo-keywords-1'." (kwd-re (cond ((null arg) org-not-done-regexp) ((equal arg '(4)) - (let ((kwd (org-icompleting-read "Keyword (or KWD1|KWD2|...): " - (mapcar 'list org-todo-keywords-1)))) + (let ((kwd + (completing-read "Keyword (or KWD1|KWD2|...): " + (mapcar #'list org-todo-keywords-1)))) (concat "\\(" (mapconcat 'identity (org-split-string kwd "|") "\\|") "\\)\\>"))) @@ -12997,75 +13372,99 @@ of `org-todo-keywords-1'." (message "%d TODO entries found" (org-occur (concat "^" org-outline-regexp " *" kwd-re ))))) +(defun org--deadline-or-schedule (arg type time) + "Insert DEADLINE or SCHEDULE information in current entry. +TYPE is either `deadline' or `scheduled'. See `org-deadline' or +`org-schedule' for information about ARG and TIME arguments." + (let* ((deadline? (eq type 'deadline)) + (keyword (if deadline? org-deadline-string org-scheduled-string)) + (log (if deadline? org-log-redeadline org-log-reschedule)) + (old-date (org-entry-get nil (if deadline? "DEADLINE" "SCHEDULED"))) + (old-date-time (and old-date (org-time-string-to-time old-date))) + ;; Save repeater cookie from either TIME or current scheduled + ;; time stamp. We are going to insert it back at the end of + ;; the process. + (repeater (or (and (org-string-nw-p time) + ;; We use `org-repeat-re' because we need + ;; to tell the difference between a real + ;; repeater and a time delta, e.g. "+2d". + (string-match org-repeat-re time) + (match-string 1 time)) + (and (org-string-nw-p old-date) + (string-match "\\([.+-]+[0-9]+[hdwmy]\ +\\(?:[/ ][-+]?[0-9]+[hdwmy]\\)?\\)" + old-date) + (match-string 1 old-date))))) + (pcase arg + (`(4) + (when (and old-date log) + (org-add-log-setup (if deadline? 'deldeadline 'delschedule) + nil old-date log)) + (org-remove-timestamp-with-keyword keyword) + (message (if deadline? "Item no longer has a deadline." + "Item is no longer scheduled."))) + (`(16) + (save-excursion + (org-back-to-heading t) + (let ((regexp (if deadline? org-deadline-time-regexp + org-scheduled-time-regexp))) + (if (not (re-search-forward regexp (line-end-position 2) t)) + (user-error (if deadline? "No deadline information to update" + "No scheduled information to update")) + (let* ((rpl0 (match-string 1)) + (rpl (replace-regexp-in-string " -[0-9]+[hdwmy]" "" rpl0)) + (msg (if deadline? "Warn starting from" "Delay until"))) + (replace-match + (concat keyword + " <" rpl + (format " -%dd" + (abs (- (time-to-days + (save-match-data + (org-read-date + nil t nil msg old-date-time))) + (time-to-days old-date-time)))) + ">") t t)))))) + (_ + (org-add-planning-info type time 'closed) + (when (and old-date + log + (not (equal old-date org-last-inserted-timestamp))) + (org-add-log-setup (if deadline? 'redeadline 'reschedule) + org-last-inserted-timestamp + old-date + log)) + (when repeater + (save-excursion + (org-back-to-heading t) + (when (re-search-forward + (concat keyword " " org-last-inserted-timestamp) + (line-end-position 2) + t) + (goto-char (1- (match-end 0))) + (insert " " repeater) + (setq org-last-inserted-timestamp + (concat (substring org-last-inserted-timestamp 0 -1) + " " repeater + (substring org-last-inserted-timestamp -1)))))) + (message (if deadline? "Deadline on %s" "Scheduled to %s") + org-last-inserted-timestamp))))) + (defun org-deadline (arg &optional time) "Insert the \"DEADLINE:\" string with a timestamp to make a deadline. With one universal prefix argument, remove any deadline from the item. With two universal prefix arguments, prompt for a warning delay. With argument TIME, set the deadline at the corresponding date. TIME -can either be an Org date like \"2011-07-24\" or a delta like \"+2d\"." - (interactive "P") - (if (and (org-region-active-p) org-loop-over-headlines-in-active-region) - (let ((cl (if (eq org-loop-over-headlines-in-active-region 'start-level) - 'region-start-level 'region)) - org-loop-over-headlines-in-active-region) - (org-map-entries - `(org-deadline ',arg ,time) - org-loop-over-headlines-in-active-region - cl (if (outline-invisible-p) (org-end-of-subtree nil t)))) - (let* ((old-date (org-entry-get nil "DEADLINE")) - (old-date-time (if old-date (org-time-string-to-time old-date))) - (repeater (and old-date - (string-match - "\\([.+-]+[0-9]+[hdwmy]\\(?:[/ ][-+]?[0-9]+[hdwmy]\\)?\\) ?" - old-date) - (match-string 1 old-date)))) - (cond - ((equal arg '(4)) - (when (and old-date org-log-redeadline) - (org-add-log-setup 'deldeadline nil old-date 'findpos - org-log-redeadline)) - (org-remove-timestamp-with-keyword org-deadline-string) - (message "Item no longer has a deadline.")) - ((equal arg '(16)) - (save-excursion - (org-back-to-heading t) - (if (re-search-forward - org-deadline-time-regexp - (save-excursion (outline-next-heading) (point)) t) - (let* ((rpl0 (match-string 1)) - (rpl (replace-regexp-in-string " -[0-9]+[hdwmy]" "" rpl0))) - (replace-match - (concat org-deadline-string - " <" rpl - (format " -%dd" - (abs - (- (time-to-days - (save-match-data - (org-read-date nil t nil "Warn starting from" old-date-time))) - (time-to-days old-date-time)))) - ">") t t)) - (user-error "No deadline information to update")))) - (t - (org-add-planning-info 'deadline time 'closed) - (when (and old-date org-log-redeadline - (not (equal old-date - (substring org-last-inserted-timestamp 1 -1)))) - (org-add-log-setup 'redeadline nil old-date 'findpos - org-log-redeadline)) - (when repeater - (save-excursion - (org-back-to-heading t) - (when (re-search-forward (concat org-deadline-string " " - org-last-inserted-timestamp) - (save-excursion - (outline-next-heading) (point)) t) - (goto-char (1- (match-end 0))) - (insert " " repeater) - (setq org-last-inserted-timestamp - (concat (substring org-last-inserted-timestamp 0 -1) - " " repeater - (substring org-last-inserted-timestamp -1)))))) - (message "Deadline on %s" org-last-inserted-timestamp)))))) +can either be an Org date like \"2011-07-24\" or a delta like \"+2d\"." + (interactive "P") + (if (and (org-region-active-p) org-loop-over-headlines-in-active-region) + (org-map-entries + (lambda () (org--deadline-or-schedule arg 'deadline time)) + nil + (if (eq org-loop-over-headlines-in-active-region 'start-level) + 'region-start-level + 'region) + (lambda () (when (org-invisible-p) (org-end-of-subtree nil t)))) + (org--deadline-or-schedule arg 'deadline time))) (defun org-schedule (arg &optional time) "Insert the SCHEDULED: string with a timestamp to schedule a TODO item. @@ -13075,68 +13474,14 @@ With argument TIME, scheduled at the corresponding date. TIME can either be an Org date like \"2011-07-24\" or a delta like \"+2d\"." (interactive "P") (if (and (org-region-active-p) org-loop-over-headlines-in-active-region) - (let ((cl (if (eq org-loop-over-headlines-in-active-region 'start-level) - 'region-start-level 'region)) - org-loop-over-headlines-in-active-region) - (org-map-entries - `(org-schedule ',arg ,time) - org-loop-over-headlines-in-active-region - cl (if (outline-invisible-p) (org-end-of-subtree nil t)))) - (let* ((old-date (org-entry-get nil "SCHEDULED")) - (old-date-time (if old-date (org-time-string-to-time old-date))) - (repeater (and old-date - (string-match - "\\([.+-]+[0-9]+[hdwmy]\\(?:[/ ][-+]?[0-9]+[hdwmy]\\)?\\) ?" - old-date) - (match-string 1 old-date)))) - (cond - ((equal arg '(4)) - (progn - (when (and old-date org-log-reschedule) - (org-add-log-setup 'delschedule nil old-date 'findpos - org-log-reschedule)) - (org-remove-timestamp-with-keyword org-scheduled-string) - (message "Item is no longer scheduled."))) - ((equal arg '(16)) - (save-excursion - (org-back-to-heading t) - (if (re-search-forward - org-scheduled-time-regexp - (save-excursion (outline-next-heading) (point)) t) - (let* ((rpl0 (match-string 1)) - (rpl (replace-regexp-in-string " -[0-9]+[hdwmy]" "" rpl0))) - (replace-match - (concat org-scheduled-string - " <" rpl - (format " -%dd" - (abs - (- (time-to-days - (save-match-data - (org-read-date nil t nil "Delay until" old-date-time))) - (time-to-days old-date-time)))) - ">") t t)) - (user-error "No scheduled information to update")))) - (t - (org-add-planning-info 'scheduled time 'closed) - (when (and old-date org-log-reschedule - (not (equal old-date - (substring org-last-inserted-timestamp 1 -1)))) - (org-add-log-setup 'reschedule nil old-date 'findpos - org-log-reschedule)) - (when repeater - (save-excursion - (org-back-to-heading t) - (when (re-search-forward (concat org-scheduled-string " " - org-last-inserted-timestamp) - (save-excursion - (outline-next-heading) (point)) t) - (goto-char (1- (match-end 0))) - (insert " " repeater) - (setq org-last-inserted-timestamp - (concat (substring org-last-inserted-timestamp 0 -1) - " " repeater - (substring org-last-inserted-timestamp -1)))))) - (message "Scheduled to %s" org-last-inserted-timestamp)))))) + (org-map-entries + (lambda () (org--deadline-or-schedule arg 'scheduled time)) + nil + (if (eq org-loop-over-headlines-in-active-region 'start-level) + 'region-start-level + 'region) + (lambda () (when (org-invisible-p) (org-end-of-subtree nil t)))) + (org--deadline-or-schedule arg 'scheduled time))) (defun org-get-scheduled-time (pom &optional inherit) "Get the scheduled time as a time tuple, of a format suitable @@ -13167,24 +13512,36 @@ nil." (if (and (string-match "\\S-" (buffer-substring (point-at-bol) (point))) (equal (char-before) ?\ )) (backward-delete-char 1) - (if (string-match "^[ \t]*$" (buffer-substring - (point-at-bol) (point-at-eol))) - (delete-region (point-at-bol) - (min (point-max) (1+ (point-at-eol)))))))))) + (when (string-match "^[ \t]*$" (buffer-substring + (point-at-bol) (point-at-eol))) + (delete-region (point-at-bol) + (min (point-max) (1+ (point-at-eol)))))))))) (defvar org-time-was-given) ; dynamically scoped parameter (defvar org-end-time-was-given) ; dynamically scoped parameter -(defun org-add-planning-info (what &optional time &rest remove) - "Insert new timestamp with keyword in the line directly after the headline. -WHAT indicates what kind of time stamp to add. TIME indicates the time to use. -If non is given, the user is prompted for a date. -REMOVE indicates what kind of entries to remove. An old WHAT entry will also -be removed." - (interactive) - (let (org-time-was-given org-end-time-was-given ts - end default-time default-input) +(defun org-at-planning-p () + "Non-nil when point is on a planning info line." + ;; This is as accurate and faster than `org-element-at-point' since + ;; planning info location is fixed in the section. + (org-with-wide-buffer + (beginning-of-line) + (and (looking-at-p org-planning-line-re) + (eq (point) + (ignore-errors + (if (and (featurep 'org-inlinetask) (org-inlinetask-in-task-p)) + (org-back-to-heading t) + (org-with-limited-levels (org-back-to-heading t))) + (line-beginning-position 2)))))) +(defun org-add-planning-info (what &optional time &rest remove) + "Insert new timestamp with keyword in the planning line. +WHAT indicates what kind of time stamp to add. It is a symbol +among `closed', `deadline', `scheduled' and nil. TIME indicates +the time to use. If none is given, the user is prompted for +a date. REMOVE indicates what kind of entries to remove. An old +WHAT entry will also be removed." + (let (org-time-was-given org-end-time-was-given default-time default-input) (catch 'exit (when (and (memq what '(scheduled deadline)) (or (not time) @@ -13193,108 +13550,98 @@ be removed." ;; Try to get a default date/time from existing timestamp (save-excursion (org-back-to-heading t) - (setq end (save-excursion (outline-next-heading) (point))) - (when (re-search-forward (if (eq what 'scheduled) - org-scheduled-time-regexp - org-deadline-time-regexp) - end t) - (setq ts (match-string 1) - default-time - (apply 'encode-time (org-parse-time-string ts)) - default-input (and ts (org-get-compact-tod ts)))))) + (let ((end (save-excursion (outline-next-heading) (point))) ts) + (when (re-search-forward (if (eq what 'scheduled) + org-scheduled-time-regexp + org-deadline-time-regexp) + end t) + (setq ts (match-string 1) + default-time (apply 'encode-time (org-parse-time-string ts)) + default-input (and ts (org-get-compact-tod ts))))))) (when what (setq time (if (stringp time) - ;; This is a string (relative or absolute), set proper date - (apply 'encode-time + ;; This is a string (relative or absolute), set + ;; proper date. + (apply #'encode-time (org-read-date-analyze time default-time (decode-time default-time))) ;; If necessary, get the time from the user (or time (org-read-date nil 'to-time nil nil default-time default-input))))) - (when (and org-insert-labeled-timestamps-at-point - (member what '(scheduled deadline))) - (insert - (if (eq what 'scheduled) org-scheduled-string org-deadline-string) " ") - (org-insert-time-stamp time org-time-was-given - nil nil nil (list org-end-time-was-given)) - (setq what nil)) - (save-excursion - (save-restriction - (let (col list elt ts buffer-invisibility-spec) - (org-back-to-heading t) - (looking-at (concat org-outline-regexp "\\( *\\)[^\r\n]*")) - (goto-char (match-end 1)) - (setq col (current-column)) - (goto-char (match-end 0)) - (if (eobp) (insert "\n") (forward-char 1)) - (when (and (not what) - (not (looking-at - (concat "[ \t]*" - org-keyword-time-not-clock-regexp)))) - ;; Nothing to add, nothing to remove...... :-) - (throw 'exit nil)) - (if (and (not (looking-at org-outline-regexp)) - (looking-at (concat "[^\r\n]*?" org-keyword-time-regexp - "[^\r\n]*")) - (not (equal (match-string 1) org-clock-string))) - (narrow-to-region (match-beginning 0) (match-end 0)) - (insert-before-markers "\n") - (backward-char 1) - (narrow-to-region (point) (point)) - (and org-adapt-indentation (org-indent-to-column col))) - ;; Check if we have to remove something. - (setq list (cons what remove)) - (while list - (setq elt (pop list)) - (when (or (and (eq elt 'scheduled) - (re-search-forward org-scheduled-time-regexp nil t)) - (and (eq elt 'deadline) - (re-search-forward org-deadline-time-regexp nil t)) - (and (eq elt 'closed) - (re-search-forward org-closed-time-regexp nil t))) - (replace-match "") - (if (looking-at "--+<[^>]+>") (replace-match "")))) - (and (looking-at "[ \t]+") (replace-match "")) - (and org-adapt-indentation (bolp) (org-indent-to-column col)) - (when what - (insert - (if (not (or (bolp) (eq (char-before) ?\ ))) " " "") - (cond ((eq what 'scheduled) org-scheduled-string) - ((eq what 'deadline) org-deadline-string) - ((eq what 'closed) org-closed-string)) - " ") - (setq ts (org-insert-time-stamp - time - (or org-time-was-given - (and (eq what 'closed) org-log-done-with-time)) - (eq what 'closed) - nil nil (list org-end-time-was-given))) - (insert - (if (not (or (bolp) (eq (char-before) ?\ ) - (memq (char-after) '(32 10)) - (eobp))) " " "")) - (end-of-line 1)) - (goto-char (point-min)) - (widen) - (if (and (looking-at "[ \t]*\n") - (equal (char-before) ?\n)) - (delete-region (1- (point)) (point-at-eol))) - ts)))))) - -(defvar org-log-note-marker (make-marker)) + (org-with-wide-buffer + (org-back-to-heading t) + (forward-line) + (unless (bolp) (insert "\n")) + (cond ((looking-at-p org-planning-line-re) + ;; Move to current indentation. + (skip-chars-forward " \t") + ;; Check if we have to remove something. + (dolist (type (if what (cons what remove) remove)) + (save-excursion + (when (re-search-forward + (cl-case type + (closed org-closed-time-regexp) + (deadline org-deadline-time-regexp) + (scheduled org-scheduled-time-regexp) + (otherwise + (error "Invalid planning type: %s" type))) + (line-end-position) t) + ;; Delete until next keyword or end of line. + (delete-region + (match-beginning 0) + (if (re-search-forward org-keyword-time-not-clock-regexp + (line-end-position) + t) + (match-beginning 0) + (line-end-position)))))) + ;; If there is nothing more to add and no more keyword + ;; is left, remove the line completely. + (if (and (looking-at-p "[ \t]*$") (not what)) + (delete-region (line-beginning-position) + (line-beginning-position 2)) + ;; If we removed last keyword, do not leave trailing + ;; white space at the end of line. + (let ((p (point))) + (save-excursion + (end-of-line) + (unless (= (skip-chars-backward " \t" p) 0) + (delete-region (point) (line-end-position))))))) + ((not what) (throw 'exit nil)) ; Nothing to do. + (t (insert-before-markers "\n") + (backward-char 1) + (when org-adapt-indentation + (indent-to-column (1+ (org-outline-level)))))) + (when what + ;; Insert planning keyword. + (insert (cl-case what + (closed org-closed-string) + (deadline org-deadline-string) + (scheduled org-scheduled-string) + (otherwise (error "Invalid planning type: %s" what))) + " ") + ;; Insert associated timestamp. + (let ((ts (org-insert-time-stamp + time + (or org-time-was-given + (and (eq what 'closed) org-log-done-with-time)) + (eq what 'closed) + nil nil (list org-end-time-was-given)))) + (unless (eolp) (insert " ")) + ts)))))) + +(defvar org-log-note-marker (make-marker) + "Marker pointing at the entry where the note is to be inserted.") (defvar org-log-note-purpose nil) (defvar org-log-note-state nil) (defvar org-log-note-previous-state nil) -(defvar org-log-note-how nil) (defvar org-log-note-extra nil) (defvar org-log-note-window-configuration nil) (defvar org-log-note-return-to (make-marker)) (defvar org-log-note-effective-time nil "Remembered current time so that dynamically scoped -`org-extend-today-until' affects tha timestamps in state change -log") +`org-extend-today-until' affects timestamps in state change log") (defvar org-log-post-message nil "Message to be displayed after a log note has been stored. @@ -13304,85 +13651,92 @@ The auto-repeater uses this.") "Add a note to the current entry. This is done in the same way as adding a state change note." (interactive) - (org-add-log-setup 'note nil nil 'findpos nil)) + (org-add-log-setup 'note)) -(defvar org-property-end-re) -(defun org-add-log-setup (&optional purpose state prev-state - findpos how extra) +(defun org-log-beginning (&optional create) + "Return expected start of log notes in current entry. +When optional argument CREATE is non-nil, the function creates +a drawer to store notes, if necessary. Returned position ignores +narrowing." + (org-with-wide-buffer + (let ((drawer (org-log-into-drawer))) + (cond + (drawer + (org-end-of-meta-data) + (let ((regexp (concat "^[ \t]*:" (regexp-quote drawer) ":[ \t]*$")) + (end (if (org-at-heading-p) (point) + (save-excursion (outline-next-heading) (point)))) + (case-fold-search t)) + (catch 'exit + ;; Try to find existing drawer. + (while (re-search-forward regexp end t) + (let ((element (org-element-at-point))) + (when (eq (org-element-type element) 'drawer) + (let ((cend (org-element-property :contents-end element))) + (when (and (not org-log-states-order-reversed) cend) + (goto-char cend))) + (throw 'exit nil)))) + ;; No drawer found. Create one, if permitted. + (when create + (unless (bolp) (insert "\n")) + (let ((beg (point))) + (insert ":" drawer ":\n:END:\n") + (org-indent-region beg (point))) + (end-of-line -1))))) + (t + (org-end-of-meta-data org-log-state-notes-insert-after-drawers) + (skip-chars-forward " \t\n") + (beginning-of-line) + (unless org-log-states-order-reversed + (org-skip-over-state-notes) + (skip-chars-backward " \t\n") + (forward-line))))) + (if (bolp) (point) (line-beginning-position 2)))) + +(defun org-add-log-setup (&optional purpose state prev-state how extra) "Set up the post command hook to take a note. If this is about to TODO state change, the new state is expected in STATE. -When FINDPOS is non-nil, find the correct position for the note in -the current entry. If not, assume that it can be inserted at point. HOW is an indicator what kind of note should be created. EXTRA is additional text that will be inserted into the notes buffer." - (let* ((org-log-into-drawer (org-log-into-drawer)) - (drawer (cond ((stringp org-log-into-drawer) - org-log-into-drawer) - (org-log-into-drawer "LOGBOOK")))) - (save-restriction - (save-excursion - (when findpos - (org-back-to-heading t) - (narrow-to-region (point) (save-excursion - (outline-next-heading) (point))) - (looking-at (concat org-outline-regexp "\\( *\\)[^\r\n]*" - "\\(\n[^\r\n]*?" org-keyword-time-not-clock-regexp - "[^\r\n]*\\)?")) - (goto-char (match-end 0)) - (cond - (drawer - (if (re-search-forward (concat "^[ \t]*:" drawer ":[ \t]*$") - nil t) - (progn - (goto-char (match-end 0)) - (or org-log-states-order-reversed - (and (re-search-forward org-property-end-re nil t) - (goto-char (1- (match-beginning 0)))))) - (insert "\n:" drawer ":\n:END:") - (beginning-of-line 0) - (org-indent-line) - (beginning-of-line 2) - (org-indent-line) - (end-of-line 0))) - ((and org-log-state-notes-insert-after-drawers - (save-excursion - (forward-line) (looking-at org-drawer-regexp))) - (forward-line) - (while (looking-at org-drawer-regexp) - (goto-char (match-end 0)) - (re-search-forward org-property-end-re (point-max) t) - (forward-line)) - (forward-line -1))) - (unless org-log-states-order-reversed - (and (= (char-after) ?\n) (forward-char 1)) - (org-skip-over-state-notes) - (skip-chars-backward " \t\n\r"))) - (move-marker org-log-note-marker (point)) - (setq org-log-note-purpose purpose - org-log-note-state state - org-log-note-previous-state prev-state - org-log-note-how how - org-log-note-extra extra - org-log-note-effective-time (org-current-effective-time)) - (add-hook 'post-command-hook 'org-add-log-note 'append))))) + (move-marker org-log-note-marker (point)) + (setq org-log-note-purpose purpose + org-log-note-state state + org-log-note-previous-state prev-state + org-log-note-how how + org-log-note-extra extra + org-log-note-effective-time (org-current-effective-time)) + (add-hook 'post-command-hook 'org-add-log-note 'append)) (defun org-skip-over-state-notes () "Skip past the list of State notes in an entry." - (if (looking-at "\n[ \t]*- State") (forward-char 1)) (when (ignore-errors (goto-char (org-in-item-p))) (let* ((struct (org-list-struct)) - (prevs (org-list-prevs-alist struct))) - (while (looking-at "[ \t]*- State") + (prevs (org-list-prevs-alist struct)) + (regexp + (concat "[ \t]*- +" + (replace-regexp-in-string + " +" " +" + (org-replace-escapes + (regexp-quote (cdr (assq 'state org-log-note-headings))) + `(("%d" . ,org-ts-regexp-inactive) + ("%D" . ,org-ts-regexp) + ("%s" . "\"\\S-+\"") + ("%S" . "\"\\S-+\"") + ("%t" . ,org-ts-regexp-inactive) + ("%T" . ,org-ts-regexp) + ("%u" . ".*?") + ("%U" . ".*?"))))))) + (while (looking-at-p regexp) (goto-char (or (org-list-get-next-item (point) struct prevs) (org-list-get-item-end (point) struct))))))) -(defun org-add-log-note (&optional purpose) - "Pop up a window for taking a note, and add this note later at point." +(defun org-add-log-note (&optional _purpose) + "Pop up a window for taking a note, and add this note later." (remove-hook 'post-command-hook 'org-add-log-note) (setq org-log-note-window-configuration (current-window-configuration)) (delete-other-windows) (move-marker org-log-note-return-to (point)) - (org-pop-to-buffer-same-window (marker-buffer org-log-note-marker)) + (pop-to-buffer-same-window (marker-buffer org-log-note-marker)) (goto-char org-log-note-marker) (org-switch-to-buffer-other-window "*Org Note*") (erase-buffer) @@ -13411,23 +13765,23 @@ EXTRA is additional text that will be inserted into the notes buffer." ((eq org-log-note-purpose 'note) "this entry") (t (error "This should not happen"))))) - (if org-log-note-extra (insert org-log-note-extra)) - (org-set-local 'org-finish-function 'org-store-log-note) + (when org-log-note-extra (insert org-log-note-extra)) + (setq-local org-finish-function 'org-store-log-note) (run-hooks 'org-log-buffer-setup-hook))) (defvar org-note-abort nil) ; dynamically scoped (defun org-store-log-note () "Finish taking a log note, and insert it to where it belongs." - (let ((txt (buffer-string))) - (kill-buffer (current-buffer)) - (let ((note (cdr (assq org-log-note-purpose org-log-note-headings))) - lines ind bul) + (let ((txt (prog1 (buffer-string) + (kill-buffer))) + (note (cdr (assq org-log-note-purpose org-log-note-headings))) + lines) (while (string-match "\\`# .*\n[ \t\n]*" txt) (setq txt (replace-match "" t t txt))) - (if (string-match "\\s-+\\'" txt) - (setq txt (replace-match "" t t txt))) + (when (string-match "\\s-+\\'" txt) + (setq txt (replace-match "" t t txt))) (setq lines (org-split-string txt "\n")) - (when (and note (string-match "\\S-" note)) + (when (org-string-nw-p note) (setq note (org-replace-escapes note @@ -13445,74 +13799,83 @@ EXTRA is additional text that will be inserted into the notes buffer." (cons "%D" (format-time-string (org-time-stamp-format nil nil) org-log-note-effective-time)) - (cons "%s" (if org-log-note-state - (concat "\"" org-log-note-state "\"") - "")) - (cons "%S" (if org-log-note-previous-state - (concat "\"" org-log-note-previous-state "\"") - "\"\""))))) - (if lines (setq note (concat note " \\\\"))) + (cons "%s" (cond + ((not org-log-note-state) "") + ((string-match-p org-ts-regexp + org-log-note-state) + (format "\"[%s]\"" + (substring org-log-note-state 1 -1))) + (t (format "\"%s\"" org-log-note-state)))) + (cons "%S" + (cond + ((not org-log-note-previous-state) "") + ((string-match-p org-ts-regexp + org-log-note-previous-state) + (format "\"[%s]\"" + (substring + org-log-note-previous-state 1 -1))) + (t (format "\"%s\"" + org-log-note-previous-state))))))) + (when lines (setq note (concat note " \\\\"))) (push note lines)) - (when (or current-prefix-arg org-note-abort) - (when org-log-into-drawer - (org-remove-empty-drawer-at - (if (stringp org-log-into-drawer) org-log-into-drawer "LOGBOOK") - org-log-note-marker)) - (setq lines nil)) - (when lines + (when (and lines (not (or current-prefix-arg org-note-abort))) (with-current-buffer (marker-buffer org-log-note-marker) - (save-excursion - (goto-char org-log-note-marker) - (move-marker org-log-note-marker nil) - (end-of-line 1) - (if (not (bolp)) (let ((inhibit-read-only t)) (insert "\n"))) - (setq ind (save-excursion - (if (ignore-errors (goto-char (org-in-item-p))) - (let ((struct (org-list-struct))) - (org-list-get-ind - (org-list-get-top-point struct) struct)) - (skip-chars-backward " \r\t\n") - (cond - ((and (org-at-heading-p) - org-adapt-indentation) - (1+ (org-current-level))) - ((org-at-heading-p) 0) - (t (org-get-indentation)))))) - (setq bul (org-list-bullet-string "-")) - (org-indent-line-to ind) - (insert bul (pop lines)) - (let ((ind-body (+ (length bul) ind))) - (while lines - (insert "\n") - (org-indent-line-to ind-body) - (insert (pop lines)))) - (message "Note stored") - (org-back-to-heading t) - (org-cycle-hide-drawers 'children)) + (org-with-wide-buffer + ;; Find location for the new note. + (goto-char org-log-note-marker) + (set-marker org-log-note-marker nil) + ;; Note associated to a clock is to be located right after + ;; the clock. Do not move point. + (unless (eq org-log-note-purpose 'clock-out) + (goto-char (org-log-beginning t))) + ;; Make sure point is at the beginning of an empty line. + (cond ((not (bolp)) (let ((inhibit-read-only t)) (insert "\n"))) + ((looking-at "[ \t]*\\S-") (save-excursion (insert "\n")))) + ;; In an existing list, add a new item at the top level. + ;; Otherwise, indent line like a regular one. + (let ((itemp (org-in-item-p))) + (if itemp + (indent-line-to + (let ((struct (save-excursion + (goto-char itemp) (org-list-struct)))) + (org-list-get-ind (org-list-get-top-point struct) struct))) + (org-indent-line))) + (insert (org-list-bullet-string "-") (pop lines)) + (let ((ind (org-list-item-body-column (line-beginning-position)))) + (dolist (line lines) + (insert "\n") + (indent-line-to ind) + (insert line))) + (message "Note stored") + (org-back-to-heading t) + (org-cycle-hide-drawers 'children)) ;; Fix `buffer-undo-list' when `org-store-log-note' is called ;; from within `org-add-log-note' because `buffer-undo-list' ;; is then modified outside of `org-with-remote-undo'. (when (eq this-command 'org-agenda-todo) - (setcdr buffer-undo-list (cddr buffer-undo-list))))))) - ;; Don't add undo information when called from `org-agenda-todo' + (setcdr buffer-undo-list (cddr buffer-undo-list)))))) + ;; Don't add undo information when called from `org-agenda-todo'. (let ((buffer-undo-list (eq this-command 'org-agenda-todo))) (set-window-configuration org-log-note-window-configuration) (with-current-buffer (marker-buffer org-log-note-return-to) (goto-char org-log-note-return-to)) (move-marker org-log-note-return-to nil) - (and org-log-post-message (message "%s" org-log-post-message)))) + (when org-log-post-message (message "%s" org-log-post-message)))) -(defun org-remove-empty-drawer-at (drawer pos) - "Remove an empty drawer DRAWER at position POS. +(defun org-remove-empty-drawer-at (pos) + "Remove an empty drawer at position POS. POS may also be a marker." (with-current-buffer (if (markerp pos) (marker-buffer pos) (current-buffer)) - (save-excursion - (save-restriction - (widen) - (goto-char pos) - (if (org-in-regexp - (concat "^[ \t]*:" drawer ":[ \t]*\n[ \t]*:END:[ \t]*\n?") 2) - (replace-match "")))))) + (org-with-wide-buffer + (goto-char pos) + (let ((drawer (org-element-at-point))) + (when (and (memq (org-element-type drawer) '(drawer property-drawer)) + (not (org-element-property :contents-begin drawer))) + (delete-region (org-element-property :begin drawer) + (progn (goto-char (org-element-property :end drawer)) + (skip-chars-backward " \r\t\n") + (forward-line) + (point)))))))) (defvar org-ts-type nil) (defun org-sparse-tree (&optional arg type) @@ -13533,47 +13896,45 @@ D Show deadlines and scheduled items between a date range." (interactive "P") (setq type (or type org-sparse-tree-default-date-type)) (setq org-ts-type type) - (message "Sparse tree: [/]regexp [t]odo [T]odo-kwd [m]atch [p]roperty - [d]eadlines [b]efore-date [a]fter-date [D]ates range - [c]ycle through date types: %s" - (case type + (message "Sparse tree: [r]egexp [t]odo [T]odo-kwd [m]atch [p]roperty + \[d]eadlines [b]efore-date [a]fter-date [D]ates range + \[c]ycle through date types: %s" + (cl-case type (all "all timestamps") (scheduled "only scheduled") (deadline "only deadline") (active "only active timestamps") (inactive "only inactive timestamps") - (scheduled-or-deadline "scheduled/deadline") (closed "with a closed time-stamp") (otherwise "scheduled/deadline"))) (let ((answer (read-char-exclusive))) - (case answer + (cl-case answer (?c (org-sparse-tree arg - (cadr (memq type '(scheduled-or-deadline all scheduled deadline active - inactive closed))))) - (?d (call-interactively #'org-check-deadlines)) - (?b (call-interactively #'org-check-before-date)) - (?a (call-interactively #'org-check-after-date)) - (?D (call-interactively #'org-check-dates-range)) - (?t (call-interactively #'org-show-todo-tree)) + (cadr + (memq type '(nil all scheduled deadline active inactive closed))))) + (?d (call-interactively 'org-check-deadlines)) + (?b (call-interactively 'org-check-before-date)) + (?a (call-interactively 'org-check-after-date)) + (?D (call-interactively 'org-check-dates-range)) + (?t (call-interactively 'org-show-todo-tree)) (?T (org-show-todo-tree '(4))) - (?m (call-interactively #'org-match-sparse-tree)) + (?m (call-interactively 'org-match-sparse-tree)) ((?p ?P) - (let* ((kwd (org-icompleting-read + (let* ((kwd (completing-read "Property: " (mapcar #'list (org-buffer-property-keys)))) - (value (org-icompleting-read + (value (completing-read "Value: " (mapcar #'list (org-property-values kwd))))) (unless (string-match "\\`{.*}\\'" value) (setq value (concat "\"" value "\""))) (org-match-sparse-tree arg (concat kwd "=" value)))) - ((?r ?R ?/) (call-interactively #'org-occur)) + ((?r ?R ?/) (call-interactively 'org-occur)) (otherwise (user-error "No such sparse tree command \"%c\"" answer))))) -(defvar org-occur-highlights nil +(defvar-local org-occur-highlights nil "List of overlays used for occur matches.") -(make-variable-buffer-local 'org-occur-highlights) -(defvar org-occur-parameters nil +(defvar-local org-occur-parameters nil "Parameters of the active org-occur calls. This is a list, each call to org-occur pushes as cons cell, containing the regular expression and the callback, onto the list. @@ -13583,18 +13944,21 @@ will only contain one set of parameters. When the highlights are removed (for example with `C-c C-c', or with the next edit (depending on `org-remove-highlights-with-change'), this variable is emptied as well.") -(make-variable-buffer-local 'org-occur-parameters) (defun org-occur (regexp &optional keep-previous callback) "Make a compact tree which shows all matches of REGEXP. -The tree will show the lines where the regexp matches, and all higher -headlines above the match. It will also show the heading after the match, -to make sure editing the matching entry is easy. -If KEEP-PREVIOUS is non-nil, highlighting and exposing done by a previous -call to `org-occur' will be kept, to allow stacking of calls to this -command. -If CALLBACK is non-nil, it is a function which is called to confirm -that the match should indeed be shown." + +The tree will show the lines where the regexp matches, and any other context +defined in `org-show-context-detail', which see. + +When optional argument KEEP-PREVIOUS is non-nil, highlighting and exposing +done by a previous call to `org-occur' will be kept, to allow stacking of +calls to this command. + +Optional argument CALLBACK can be a function of no argument. In this case, +it is called with point at the end of the match, match data being set +accordingly. Current match is shown only if the return value is non-nil. +The function must neither move point nor alter narrowing." (interactive "sRegexp: \nP") (when (equal regexp "") (user-error "Regexp cannot be empty")) @@ -13604,32 +13968,35 @@ that the match should indeed be shown." (let ((cnt 0)) (save-excursion (goto-char (point-min)) - (if (or (not keep-previous) ; do not want to keep - (not org-occur-highlights)) ; no previous matches - ;; hide everything - (org-overview)) - (while (re-search-forward regexp nil t) - (when (or (not callback) - (save-match-data (funcall callback))) - (setq cnt (1+ cnt)) - (when org-highlight-sparse-tree-matches - (org-highlight-new-match (match-beginning 0) (match-end 0))) - (org-show-context 'occur-tree)))) + (when (or (not keep-previous) ; do not want to keep + (not org-occur-highlights)) ; no previous matches + ;; hide everything + (org-overview)) + (let ((case-fold-search (if (eq org-occur-case-fold-search 'smart) + (isearch-no-upper-case-p regexp t) + org-occur-case-fold-search))) + (while (re-search-forward regexp nil t) + (when (or (not callback) + (save-match-data (funcall callback))) + (setq cnt (1+ cnt)) + (when org-highlight-sparse-tree-matches + (org-highlight-new-match (match-beginning 0) (match-end 0))) + (org-show-context 'occur-tree))))) (when org-remove-highlights-with-change - (org-add-hook 'before-change-functions 'org-remove-occur-highlights - nil 'local)) + (add-hook 'before-change-functions 'org-remove-occur-highlights + nil 'local)) (unless org-sparse-tree-open-archived-trees (org-hide-archived-subtrees (point-min) (point-max))) (run-hooks 'org-occur-hook) - (if (org-called-interactively-p 'interactive) - (message "%d match(es) for regexp %s" cnt regexp)) + (when (called-interactively-p 'interactive) + (message "%d match(es) for regexp %s" cnt regexp)) cnt)) -(defun org-occur-next-match (&optional n reset) +(defun org-occur-next-match (&optional n _reset) "Function for `next-error-function' to find sparse tree matches. N is the number of matches to move, when negative move backwards. -RESET is entirely ignored - this function always goes back to the -starting point when no match is found." +This function always goes back to the starting point when no +match is found." (let* ((limit (if (< n 0) (point-min) (point-max))) (search-func (if (< n 0) 'previous-single-char-property-change @@ -13641,7 +14008,7 @@ starting point when no match is found." (while (setq p1 (funcall search-func (point) 'org-type)) (when (equal p1 limit) (goto-char pos) - (error "No more matches")) + (user-error "No more matches")) (when (equal (get-char-property p1 'org-type) 'org-occur) (setq n (1- n)) (when (= n 0) @@ -13649,65 +14016,75 @@ starting point when no match is found." (throw 'exit (point)))) (goto-char p1)) (goto-char p1) - (error "No more matches")))) + (user-error "No more matches")))) (defun org-show-context (&optional key) "Make sure point and context are visible. -How much context is shown depends upon the variables -`org-show-hierarchy-above', `org-show-following-heading', -`org-show-entry-below' and `org-show-siblings'." - (let ((heading-p (org-at-heading-p t)) - (hierarchy-p (org-get-alist-option org-show-hierarchy-above key)) - (following-p (org-get-alist-option org-show-following-heading key)) - (entry-p (org-get-alist-option org-show-entry-below key)) - (siblings-p (org-get-alist-option org-show-siblings key))) - ;; Show heading or entry text - (if (and heading-p (not entry-p)) - (org-flag-heading nil) ; only show the heading - (and (or entry-p (outline-invisible-p) (org-invisible-p2)) - (org-show-hidden-entry))) ; show entire entry - (when following-p - ;; Show next sibling, or heading below text - (save-excursion - (and (if heading-p (org-goto-sibling) (outline-next-heading)) - (org-flag-heading nil)))) - (when siblings-p (org-show-siblings)) - (when hierarchy-p - ;; show all higher headings, possibly with siblings - (save-excursion - (while (and (condition-case nil - (progn (org-up-heading-all 1) t) - (error nil)) - (not (bobp))) - (org-flag-heading nil) - (when siblings-p (org-show-siblings))))))) +Optional argument KEY, when non-nil, is a symbol. See +`org-show-context-detail' for allowed values and how much is to +be shown." + (org-show-set-visibility + (cond ((symbolp org-show-context-detail) org-show-context-detail) + ((cdr (assq key org-show-context-detail))) + (t (cdr (assq 'default org-show-context-detail)))))) + +(defun org-show-set-visibility (detail) + "Set visibility around point according to DETAIL. +DETAIL is either nil, `minimal', `local', `ancestors', `lineage', +`tree', `canonical' or t. See `org-show-context-detail' for more +information." + ;; Show current heading and possibly its entry, following headline + ;; or all children. + (if (and (org-at-heading-p) (not (eq detail 'local))) + (org-flag-heading nil) + (org-show-entry) + ;; If point is hidden within a drawer or a block, make sure to + ;; expose it. + (dolist (o (overlays-at (point))) + (when (memq (overlay-get o 'invisible) '(org-hide-block outline)) + (delete-overlay o))) + (unless (org-before-first-heading-p) + (org-with-limited-levels + (cl-case detail + ((tree canonical t) (org-show-children)) + ((nil minimal ancestors)) + (t (save-excursion + (outline-next-heading) + (org-flag-heading nil))))))) + ;; Show all siblings. + (when (eq detail 'lineage) (org-show-siblings)) + ;; Show ancestors, possibly with their children. + (when (memq detail '(ancestors lineage tree canonical t)) + (save-excursion + (while (org-up-heading-safe) + (org-flag-heading nil) + (when (memq detail '(canonical t)) (org-show-entry)) + (when (memq detail '(tree canonical t)) (org-show-children)))))) (defvar org-reveal-start-hook nil "Hook run before revealing a location.") (defun org-reveal (&optional siblings) "Show current entry, hierarchy above it, and the following headline. -This can be used to show a consistent set of context around locations -exposed with `org-show-hierarchy-above' or `org-show-following-heading' -not t for the search context. + +This can be used to show a consistent set of context around +locations exposed with `org-show-context'. With optional argument SIBLINGS, on each level of the hierarchy all siblings are shown. This repairs the tree structure to what it would look like when opened with hierarchical calls to `org-cycle'. -With double optional argument \\[universal-argument] \\[universal-argument], \ -go to the parent and show the -entire tree." + +With a \\[universal-argument] \\[universal-argument] prefix, \ +go to the parent and show the entire tree." (interactive "P") (run-hooks 'org-reveal-start-hook) - (let ((org-show-hierarchy-above t) - (org-show-following-heading t) - (org-show-siblings (if siblings t org-show-siblings))) - (org-show-context nil)) - (when (equal siblings '(16)) - (save-excursion - (when (org-up-heading-safe) - (org-show-subtree) - (run-hook-with-args 'org-cycle-hook 'subtree))))) + (cond ((equal siblings '(4)) (org-show-set-visibility 'canonical)) + ((equal siblings '(16)) + (save-excursion + (when (org-up-heading-safe) + (org-show-subtree) + (run-hook-with-args 'org-cycle-hook 'subtree)))) + (t (org-show-set-visibility 'lineage)))) (defun org-highlight-new-match (beg end) "Highlight from BEG to END and mark the highlight is an occur headline." @@ -13716,13 +14093,13 @@ entire tree." (overlay-put ov 'org-type 'org-occur) (push ov org-occur-highlights))) -(defun org-remove-occur-highlights (&optional beg end noremove) +(defun org-remove-occur-highlights (&optional _beg _end noremove) "Remove the occur highlights from the buffer. BEG and END are ignored. If NOREMOVE is nil, remove this function from the `before-change-functions' in the current buffer." (interactive) (unless org-inhibit-highlight-removal - (mapc 'delete-overlay org-occur-highlights) + (mapc #'delete-overlay org-occur-highlights) (setq org-occur-highlights nil) (setq org-occur-parameters nil) (unless noremove @@ -13746,89 +14123,88 @@ from the `before-change-functions' in the current buffer." (interactive) (org-priority 'down)) -(defun org-priority (&optional action show) +(defun org-priority (&optional action _show) "Change the priority of an item. ACTION can be `set', `up', `down', or a character." (interactive "P") (if (equal action '(4)) (org-show-priority) - (unless org-enable-priority-commands - (user-error "Priority commands are disabled")) - (setq action (or action 'set)) - (let (current new news have remove) - (save-excursion - (org-back-to-heading t) - (if (looking-at org-priority-regexp) + (unless org-enable-priority-commands + (user-error "Priority commands are disabled")) + (setq action (or action 'set)) + (let (current new news have remove) + (save-excursion + (org-back-to-heading t) + (when (looking-at org-priority-regexp) (setq current (string-to-char (match-string 2)) have t)) - (cond - ((eq action 'remove) - (setq remove t new ?\ )) - ((or (eq action 'set) - (if (featurep 'xemacs) (characterp action) (integerp action))) - (if (not (eq action 'set)) - (setq new action) - (message "Priority %c-%c, SPC to remove: " - org-highest-priority org-lowest-priority) - (save-match-data - (setq new (read-char-exclusive)))) - (if (and (= (upcase org-highest-priority) org-highest-priority) - (= (upcase org-lowest-priority) org-lowest-priority)) + (cond + ((eq action 'remove) + (setq remove t new ?\ )) + ((or (eq action 'set) + (integerp action)) + (if (not (eq action 'set)) + (setq new action) + (message "Priority %c-%c, SPC to remove: " + org-highest-priority org-lowest-priority) + (save-match-data + (setq new (read-char-exclusive)))) + (when (and (= (upcase org-highest-priority) org-highest-priority) + (= (upcase org-lowest-priority) org-lowest-priority)) (setq new (upcase new))) - (cond ((equal new ?\ ) (setq remove t)) - ((or (< (upcase new) org-highest-priority) (> (upcase new) org-lowest-priority)) - (user-error "Priority must be between `%c' and `%c'" - org-highest-priority org-lowest-priority)))) - ((eq action 'up) - (setq new (if have - (1- current) ; normal cycling - ;; last priority was empty - (if (eq last-command this-command) - org-lowest-priority ; wrap around empty to lowest - ;; default - (if org-priority-start-cycle-with-default - org-default-priority - (1- org-default-priority)))))) - ((eq action 'down) - (setq new (if have - (1+ current) ; normal cycling - ;; last priority was empty - (if (eq last-command this-command) - org-highest-priority ; wrap around empty to highest - ;; default - (if org-priority-start-cycle-with-default - org-default-priority - (1+ org-default-priority)))))) - (t (user-error "Invalid action"))) - (if (or (< (upcase new) org-highest-priority) - (> (upcase new) org-lowest-priority)) + (cond ((equal new ?\ ) (setq remove t)) + ((or (< (upcase new) org-highest-priority) (> (upcase new) org-lowest-priority)) + (user-error "Priority must be between `%c' and `%c'" + org-highest-priority org-lowest-priority)))) + ((eq action 'up) + (setq new (if have + (1- current) ; normal cycling + ;; last priority was empty + (if (eq last-command this-command) + org-lowest-priority ; wrap around empty to lowest + ;; default + (if org-priority-start-cycle-with-default + org-default-priority + (1- org-default-priority)))))) + ((eq action 'down) + (setq new (if have + (1+ current) ; normal cycling + ;; last priority was empty + (if (eq last-command this-command) + org-highest-priority ; wrap around empty to highest + ;; default + (if org-priority-start-cycle-with-default + org-default-priority + (1+ org-default-priority)))))) + (t (user-error "Invalid action"))) + (when (or (< (upcase new) org-highest-priority) + (> (upcase new) org-lowest-priority)) (if (and (memq action '(up down)) (not have) (not (eq last-command this-command))) - ;; `new' is from default priority + ;; `new' is from default priority (error "The default can not be set, see `org-default-priority' why") - ;; normal cycling: `new' is beyond highest/lowest priority - ;; and is wrapped around to the empty priority + ;; normal cycling: `new' is beyond highest/lowest priority + ;; and is wrapped around to the empty priority (setq remove t))) - (setq news (format "%c" new)) - (if have + (setq news (format "%c" new)) + (if have + (if remove + (replace-match "" t t nil 1) + (replace-match news t t nil 2)) (if remove - (replace-match "" t t nil 1) - (replace-match news t t nil 2)) - (if remove - (user-error "No priority cookie found in line") - (let ((case-fold-search nil)) - (looking-at org-todo-line-regexp)) - (if (match-end 2) - (progn - (goto-char (match-end 2)) - (insert " [#" news "]")) - (goto-char (match-beginning 3)) - (insert "[#" news "] ")))) - (org-preserve-lc (org-set-tags nil 'align))) - (if remove - (message "Priority removed") - (message "Priority of current item set to %s" news))))) + (user-error "No priority cookie found in line") + (let ((case-fold-search nil)) (looking-at org-todo-line-regexp)) + (if (match-end 2) + (progn + (goto-char (match-end 2)) + (insert " [#" news "]")) + (goto-char (match-beginning 3)) + (insert "[#" news "] ")))) + (org-set-tags nil 'align)) + (if remove + (message "Priority removed") + (message "Priority of current item set to %s" news))))) (defun org-show-priority () "Show the priority of the current item. @@ -13863,6 +14239,7 @@ Can be set by the action argument to `org-scan-tags' and `org-map-entries'.") (defvar org-scanner-tags nil "The current tag list while the tags scanner is running.") + (defvar org-trust-scanner-tags nil "Should `org-get-tags-at' use the tags for the scanner. This is for internal dynamical scoping only. @@ -13874,6 +14251,8 @@ obtain a list of properties. Building the tags list for each entry in such a file becomes an N^2 operation - but with this variable set, it scales as N.") +(defvar org--matcher-tags-todo-only nil) + (defun org-scan-tags (action matcher todo-only &optional start-level) "Scan headline tags with inheritance and produce output ACTION. @@ -13882,11 +14261,14 @@ or `agenda' to produce an entry list for an agenda view. It can also be a Lisp form or a function that should be called at each matched headline, in this case the return value is a list of all return values from these calls. -MATCHER is a Lisp form to be evaluated, testing if a given set of tags -qualifies a headline for inclusion. When TODO-ONLY is non-nil, -only lines with a not-done TODO keyword are included in the output. -This should be the same variable that was scoped into -and set by `org-make-tags-matcher' when it constructed MATCHER. +MATCHER is a function accepting three arguments, returning +a non-nil value whenever a given set of tags qualifies a headline +for inclusion. See `org-make-tags-matcher' for more information. +As a special case, it can also be set to t (respectively nil) in +order to match all (respectively none) headline. + +When TODO-ONLY is non-nil, only lines with a not-done TODO +keyword are included in the output. START-LEVEL can be a string with asterisks, reducing the scope to headlines matching this string." @@ -13897,8 +14279,8 @@ headlines matching this string." (concat "\\*\\{" (number-to-string start-level) "\\} ") org-outline-regexp) " *\\(\\<\\(" - (mapconcat 'regexp-quote org-todo-keywords-1 "\\|") - (org-re "\\)\\>\\)? *\\(.*?\\)\\(:[[:alnum:]_@#%:]+:\\)?[ \t]*$"))) + (mapconcat #'regexp-quote org-todo-keywords-1 "\\|") + "\\)\\>\\)? *\\(.*?\\)\\(:[[:alnum:]_@#%:]+:\\)?[ \t]*$")) (props (list 'face 'default 'done-face 'org-agenda-done 'undone-face 'default @@ -13915,8 +14297,9 @@ headlines matching this string." lspos tags tags-list (tags-alist (list (cons 0 org-file-tags))) (llast 0) rtn rtn1 level category i txt - todo marker entry priority) - (when (not (or (member action '(agenda sparse-tree)) (functionp action))) + todo marker entry priority + ts-date ts-date-type ts-date-pair) + (unless (or (member action '(agenda sparse-tree)) (functionp action)) (setq action (list 'lambda nil action))) (save-excursion (goto-char (point-min)) @@ -13927,11 +14310,17 @@ headlines matching this string." (re-search-forward re nil t)) (setq org-map-continue-from nil) (catch :skip - (setq todo (if (match-end 1) (org-match-string-no-properties 2)) - tags (if (match-end 4) (org-match-string-no-properties 4))) + (setq todo + ;; TODO: is the 1-2 difference a bug? + (when (match-end 1) (match-string-no-properties 2)) + tags (when (match-end 4) (match-string-no-properties 4))) (goto-char (setq lspos (match-beginning 0))) (setq level (org-reduced-level (org-outline-level)) category (org-get-category)) + (when (eq action 'agenda) + (setq ts-date-pair (org-agenda-entry-get-agenda-timestamp (point)) + ts-date (car ts-date-pair) + ts-date-type (cdr ts-date-pair))) (setq i llast llast level) ;; remove tag lists from same and sublevels (while (>= i level) @@ -13958,18 +14347,20 @@ headlines matching this string." (when (and tags org-use-tag-inheritance (or (not (eq t org-use-tag-inheritance)) org-tags-exclude-from-inheritance)) - ;; selective inheritance, remove uninherited ones + ;; Selective inheritance, remove uninherited ones. (setcdr (car tags-alist) (org-remove-uninherited-tags (cdar tags-alist)))) (when (and ;; eval matcher only when the todo condition is OK (and (or (not todo-only) (member todo org-not-done-keywords)) - (let ((case-fold-search t) (org-trust-scanner-tags t)) - (eval matcher))) + (if (functionp matcher) + (let ((case-fold-search t) (org-trust-scanner-tags t)) + (funcall matcher todo tags-list level)) + matcher)) - ;; Call the skipper, but return t if it does not skip, - ;; so that the `and' form continues evaluating + ;; Call the skipper, but return t if it does not + ;; skip, so that the `and' form continues evaluating. (progn (unless (eq action 'sparse-tree) (org-agenda-skip)) t) @@ -13995,7 +14386,8 @@ headlines matching this string." (if (eq org-tags-match-list-sublevels 'indented) (make-string (1- level) ?.) "") (org-get-heading)) - level category + (make-string level ?\s) + category tags-list) priority (org-get-priority txt)) (goto-char lspos) @@ -14003,7 +14395,9 @@ headlines matching this string." (org-add-props txt props 'org-marker marker 'org-hd-marker marker 'org-category category 'todo-state todo - 'priority priority 'type "tagsmatch") + 'ts-date ts-date + 'priority priority + 'type (concat "tagsmatch" ts-date-type)) (push txt rtn)) ((functionp action) (setq org-map-continue-from nil) @@ -14048,13 +14442,19 @@ headlines matching this string." (defun org-match-sparse-tree (&optional todo-only match) "Create a sparse tree according to tags string MATCH. -MATCH can contain positive and negative selection of tags, like -\"+WORK+URGENT-WITHBOSS\". -If optional argument TODO-ONLY is non-nil, only select lines that are -also TODO lines." + +MATCH is a string with match syntax. It can contain a selection +of tags (\"+work+urgent-boss\"), properties (\"LEVEL>3\"), and +TODO keywords (\"TODO=\\\"WAITING\\\"\") or a combination of +those. See the manual for details. + +If optional argument TODO-ONLY is non-nil, only select lines that +are also TODO tasks." (interactive "P") (org-agenda-prepare-buffers (list (current-buffer))) - (org-scan-tags 'sparse-tree (cdr (org-make-tags-matcher match)) todo-only)) + (let ((org--matcher-tags-todo-only todo-only)) + (org-scan-tags 'sparse-tree (cdr (org-make-tags-matcher match)) + org--matcher-tags-todo-only))) (defalias 'org-tags-sparse-tree 'org-match-sparse-tree) @@ -14062,15 +14462,17 @@ also TODO lines." (defun org-cached-entry-get (pom property) (if (or (eq t org-use-property-inheritance) (and (stringp org-use-property-inheritance) - (string-match org-use-property-inheritance property)) + (let ((case-fold-search t)) + (string-match-p org-use-property-inheritance property))) (and (listp org-use-property-inheritance) - (member property org-use-property-inheritance))) - ;; Caching is not possible, check it directly + (member-ignore-case property org-use-property-inheritance))) + ;; Caching is not possible, check it directly. (org-entry-get pom property 'inherit) - ;; Get all properties, so that we can do complicated checks easily - (cdr (assoc property (or org-cached-props - (setq org-cached-props - (org-entry-properties pom))))))) + ;; Get all properties, so we can do complicated checks easily. + (cdr (assoc-string property + (or org-cached-props + (setq org-cached-props (org-entry-properties pom))) + t)))) (defun org-global-tags-completion-table (&optional files) "Return the list of all tags in all agenda buffer/files. @@ -14079,186 +14481,173 @@ instead of the agenda files." (save-excursion (org-uniquify (delq nil - (apply 'append + (apply #'append (mapcar (lambda (file) (set-buffer (find-file-noselect file)) - (append (org-get-buffer-tags) - (mapcar (lambda (x) (if (stringp (car-safe x)) - (list (car-safe x)) nil)) - org-tag-alist))) - (if (and files (car files)) - files + (mapcar (lambda (x) + (and (stringp (car-safe x)) + (list (car-safe x)))) + (or org-current-tag-alist (org-get-buffer-tags)))) + (if (car-safe files) files (org-agenda-files)))))))) (defun org-make-tags-matcher (match) "Create the TAGS/TODO matcher form for the selection string MATCH. -The variable `todo-only' is scoped dynamically into this function. -It will be set to t if the matcher restricts matching to TODO entries, -otherwise will not be touched. - -Returns a cons of the selection string MATCH and the constructed -lisp form implementing the matcher. The matcher is to be evaluated -at an Org entry, with point on the headline, and returns t if the -entry matches the selection string MATCH. The returned lisp form -references two variables with information about the entry, which -must be bound around the form's evaluation: todo, the TODO keyword -at the entry (or nil of none); and tags-list, the list of all tags -at the entry including inherited ones. Additionally, the category -of the entry (if any) must be specified as the text property -'org-category on the headline. - -See also `org-scan-tags'. -" - (declare (special todo-only)) - (unless (boundp 'todo-only) - (error "`org-make-tags-matcher' expects todo-only to be scoped in")) +Returns a cons of the selection string MATCH and a function +implementing the matcher. + +The matcher is to be called at an Org entry, with point on the +headline, and returns non-nil if the entry matches the selection +string MATCH. It must be called with three arguments: the TODO +keyword at the entry (or nil if none), the list of all tags at +the entry including inherited ones and the reduced level of the +headline. Additionally, the category of the entry, if any, must +be specified as the text property `org-category' on the headline. + +This function sets the variable `org--matcher-tags-todo-only' to +a non-nil value if the matcher restricts matching to TODO +entries, otherwise it is not touched. + +See also `org-scan-tags'." (unless match ;; Get a new match request, with completion against the global - ;; tags table and the local tags in current buffer + ;; tags table and the local tags in current buffer. (let ((org-last-tags-completion-table (org-uniquify (delq nil (append (org-get-buffer-tags) (org-global-tags-completion-table)))))) - (setq match (org-completing-read-no-i - "Match: " 'org-tags-completion-function nil nil nil - 'org-tags-history)))) + (setq match + (completing-read + "Match: " + 'org-tags-completion-function nil nil nil 'org-tags-history)))) - ;; Parse the string and create a lisp form (let ((match0 match) - (re (org-re "^&?\\([-+:]\\)?\\({[^}]+}\\|LEVEL\\([<=>]\\{1,2\\}\\)\\([0-9]+\\)\\|\\(\\(?:[[:alnum:]_]+\\(?:\\\\-\\)*\\)+\\)\\([<>=]\\{1,2\\}\\)\\({[^}]+}\\|\"[^\"]*\"\\|-?[.0-9]+\\(?:[eE][-+]?[0-9]+\\)?\\)\\|[[:alnum:]_@#%]+\\)")) - minus tag mm - tagsmatch todomatch tagsmatcher todomatcher kwd matcher - orterms orlist re-p str-p level-p level-op time-p - prop-p pn pv po gv rest (start 0) (ss 0)) - ;; Expand group tags + (re "^&?\\([-+:]\\)?\\({[^}]+}\\|LEVEL\\([<=>]\\{1,2\\}\\)\\([0-9]+\\)\\|\\(\\(?:[[:alnum:]_]+\\(?:\\\\-\\)*\\)+\\)\\([<>=]\\{1,2\\}\\)\\({[^}]+}\\|\"[^\"]*\"\\|-?[.0-9]+\\(?:[eE][-+]?[0-9]+\\)?\\)\\|[[:alnum:]_@#%]+\\)") + (start 0) + tagsmatch todomatch tagsmatcher todomatcher) + + ;; Expand group tags. (setq match (org-tags-expand match)) ;; Check if there is a TODO part of this match, which would be the - ;; part after a "/". TO make sure that this slash is not part of - ;; a property value to be matched against, we also check that there - ;; is no " after that slash. - ;; First, find the last slash - (while (string-match "/+" match ss) - (setq start (match-beginning 0) ss (match-end 0))) + ;; part after a "/". To make sure that this slash is not part of + ;; a property value to be matched against, we also check that + ;; there is no / after that slash. First, find the last slash. + (let ((s 0)) + (while (string-match "/+" match s) + (setq start (match-beginning 0)) + (setq s (match-end 0)))) (if (and (string-match "/+" match start) - (not (save-match-data (string-match "\"" match start)))) - ;; match contains also a todo-matching request + (not (string-match-p "\"" match start))) + ;; Match contains also a TODO-matching request. (progn - (setq tagsmatch (substring match 0 (match-beginning 0)) - todomatch (substring match (match-end 0))) - (if (string-match "^!" todomatch) - (setq todo-only t todomatch (substring todomatch 1))) - (if (string-match "^\\s-*$" todomatch) - (setq todomatch nil))) - ;; only matching tags - (setq tagsmatch match todomatch nil)) - - ;; Make the tags matcher - (if (or (not tagsmatch) (not (string-match "\\S-" tagsmatch))) - (setq tagsmatcher t) - (setq orterms (org-split-string tagsmatch "|") orlist nil) - (dolist (term orterms) - (while (and (equal (substring term -1) "\\") orterms) - (setq term (concat term "|" (pop orterms)))) ; repair bad split - (while (string-match re term) - (setq rest (substring term (match-end 0)) - minus (and (match-end 1) - (equal (match-string 1 term) "-")) - tag (save-match-data (replace-regexp-in-string - "\\\\-" "-" - (match-string 2 term))) - re-p (equal (string-to-char tag) ?{) - level-p (match-end 4) - prop-p (match-end 5) - mm (cond - (re-p `(org-match-any-p ,(substring tag 1 -1) tags-list)) - (level-p - (setq level-op (org-op-to-function (match-string 3 term))) - `(,level-op level ,(string-to-number - (match-string 4 term)))) - (prop-p - (setq pn (match-string 5 term) - po (match-string 6 term) - pv (match-string 7 term) - re-p (equal (string-to-char pv) ?{) - str-p (equal (string-to-char pv) ?\") - time-p (save-match-data - (string-match "^\"[[<].*[]>]\"$" pv)) - pv (if (or re-p str-p) (substring pv 1 -1) pv)) - (if time-p (setq pv (org-matcher-time pv))) - (setq po (org-op-to-function po (if time-p 'time str-p))) - (cond - ((equal pn "CATEGORY") - (setq gv '(get-text-property (point) 'org-category))) - ((equal pn "TODO") - (setq gv 'todo)) - (t - (setq gv `(org-cached-entry-get nil ,pn)))) - (if re-p - (if (eq po 'org<>) - `(not (string-match ,pv (or ,gv ""))) - `(string-match ,pv (or ,gv ""))) - (if str-p - `(,po (or ,gv "") ,pv) - `(,po (string-to-number (or ,gv "")) - ,(string-to-number pv) )))) - (t `(member ,tag tags-list))) - mm (if minus (list 'not mm) mm) - term rest) - (push mm tagsmatcher)) - (push (if (> (length tagsmatcher) 1) - (cons 'and tagsmatcher) - (car tagsmatcher)) - orlist) - (setq tagsmatcher nil)) - (setq tagsmatcher (if (> (length orlist) 1) (cons 'or orlist) (car orlist))) - (setq tagsmatcher - (list 'progn '(setq org-cached-props nil) tagsmatcher))) - ;; Make the todo matcher - (if (or (not todomatch) (not (string-match "\\S-" todomatch))) - (setq todomatcher t) - (setq orterms (org-split-string todomatch "|") orlist nil) - (dolist (term orterms) - (while (string-match re term) - (setq minus (and (match-end 1) - (equal (match-string 1 term) "-")) - kwd (match-string 2 term) - re-p (equal (string-to-char kwd) ?{) - term (substring term (match-end 0)) - mm (if re-p - `(string-match ,(substring kwd 1 -1) todo) - (list 'equal 'todo kwd)) - mm (if minus (list 'not mm) mm)) - (push mm todomatcher)) - (push (if (> (length todomatcher) 1) - (cons 'and todomatcher) - (car todomatcher)) - orlist) - (setq todomatcher nil)) - (setq todomatcher (if (> (length orlist) 1) - (cons 'or orlist) (car orlist)))) - - ;; Return the string and lisp forms of the matcher - (setq matcher (if todomatcher - (list 'and tagsmatcher todomatcher) - tagsmatcher)) - (when todo-only - (setq matcher (list 'and '(member todo org-not-done-keywords) - matcher))) - (cons match0 matcher))) - -(defun org-tags-expand (match &optional single-as-list downcased) + (setq tagsmatch (substring match 0 (match-beginning 0))) + (setq todomatch (substring match (match-end 0))) + (when (string-prefix-p "!" todomatch) + (setq org--matcher-tags-todo-only t) + (setq todomatch (substring todomatch 1))) + (when (string-match "\\`\\s-*\\'" todomatch) + (setq todomatch nil))) + ;; Only matching tags. + (setq tagsmatch match) + (setq todomatch nil)) + + ;; Make the tags matcher. + (when (org-string-nw-p tagsmatch) + (let ((orlist nil) + (orterms (org-split-string tagsmatch "|")) + term) + (while (setq term (pop orterms)) + (while (and (equal (substring term -1) "\\") orterms) + (setq term (concat term "|" (pop orterms)))) ;repair bad split. + (while (string-match re term) + (let* ((rest (substring term (match-end 0))) + (minus (and (match-end 1) + (equal (match-string 1 term) "-"))) + (tag (save-match-data + (replace-regexp-in-string + "\\\\-" "-" (match-string 2 term)))) + (regexp (eq (string-to-char tag) ?{)) + (levelp (match-end 4)) + (propp (match-end 5)) + (mm + (cond + (regexp `(org-match-any-p ,(substring tag 1 -1) tags-list)) + (levelp + `(,(org-op-to-function (match-string 3 term)) + level + ,(string-to-number (match-string 4 term)))) + (propp + (let* ((gv (pcase (upcase (match-string 5 term)) + ("CATEGORY" + '(get-text-property (point) 'org-category)) + ("TODO" 'todo) + (p `(org-cached-entry-get nil ,p)))) + (pv (match-string 7 term)) + (regexp (eq (string-to-char pv) ?{)) + (strp (eq (string-to-char pv) ?\")) + (timep (string-match-p "^\"[[<].*[]>]\"$" pv)) + (po (org-op-to-function (match-string 6 term) + (if timep 'time strp)))) + (setq pv (if (or regexp strp) (substring pv 1 -1) pv)) + (when timep (setq pv (org-matcher-time pv))) + (cond ((and regexp (eq po 'org<>)) + `(not (string-match ,pv (or ,gv "")))) + (regexp `(string-match ,pv (or ,gv ""))) + (strp `(,po (or ,gv "") ,pv)) + (t + `(,po + (string-to-number (or ,gv "")) + ,(string-to-number pv)))))) + (t `(member ,tag tags-list))))) + (push (if minus `(not ,mm) mm) tagsmatcher) + (setq term rest))) + (push `(and ,@tagsmatcher) orlist) + (setq tagsmatcher nil)) + (setq tagsmatcher `(progn (setq org-cached-props nil) (or ,@orlist))))) + + ;; Make the TODO matcher. + (when (org-string-nw-p todomatch) + (let ((orlist nil)) + (dolist (term (org-split-string todomatch "|")) + (while (string-match re term) + (let* ((minus (and (match-end 1) + (equal (match-string 1 term) "-"))) + (kwd (match-string 2 term)) + (regexp (eq (string-to-char kwd) ?{)) + (mm (if regexp `(string-match ,(substring kwd 1 -1) todo) + `(equal todo ,kwd)))) + (push (if minus `(not ,mm) mm) todomatcher)) + (setq term (substring term (match-end 0)))) + (push (if (> (length todomatcher) 1) + (cons 'and todomatcher) + (car todomatcher)) + orlist) + (setq todomatcher nil)) + (setq todomatcher (cons 'or orlist)))) + + ;; Return the string and function of the matcher. If no + ;; tags-specific or todo-specific matcher exists, match + ;; everything. + (let ((matcher (if (and tagsmatcher todomatcher) + `(and ,tagsmatcher ,todomatcher) + (or tagsmatcher todomatcher t)))) + (when org--matcher-tags-todo-only + (setq matcher `(and (member todo org-not-done-keywords) ,matcher))) + (cons match0 `(lambda (todo tags-list level) ,matcher))))) + +(defun org-tags-expand (match &optional single-as-list downcased tags-already-expanded) "Expand group tags in MATCH. This replaces every group tag in MATCH with a regexp tag search. For example, a group tag \"Work\" defined as { Work : Lab Conf } will be replaced like this: - Work => {\\(?:Work\\|Lab\\|Conf\\)} - +Work => +{\\(?:Work\\|Lab\\|Conf\\)} - -Work => -{\\(?:Work\\|Lab\\|Conf\\)} + Work => {\\<\\(?:Work\\|Lab\\|Conf\\)\\>} + +Work => +{\\<\\(?:Work\\|Lab\\|Conf\\)\\>} + -Work => -{\\<\\(?:Work\\|Lab\\|Conf\\)\\>} Replacing by a regexp preserves the structure of the match. E.g., this expansion @@ -14268,6 +14657,12 @@ E.g., this expansion will match anything tagged with \"Lab\" and \"Home\", or tagged with \"Conf\" and \"Home\" or tagged with \"Work\" and \"home\". +A group tag in MATCH can contain regular expressions of its own. +For example, a group tag \"Proj\" defined as { Proj : {P@.+} } +will be replaced like this: + + Proj => {\\<\\(?:Proj\\)\\>\\|P@.+} + When the optional argument SINGLE-AS-LIST is non-nil, MATCH is assumed to be a single group tag, and the function will return the list of tags in this group. @@ -14276,34 +14671,113 @@ When DOWNCASE is non-nil, expand downcased TAGS." (if org-group-tags (let* ((case-fold-search t) (stable org-mode-syntax-table) - (tal (or org-tag-groups-alist-for-agenda - org-tag-groups-alist)) - (tal (if downcased - (mapcar (lambda(tg) (mapcar 'downcase tg)) tal) tal)) - (tml (mapcar 'car tal)) - (rtnmatch match) rpl) - ;; @ and _ are allowed as word-components in tags + (taggroups (or org-tag-groups-alist-for-agenda org-tag-groups-alist)) + (taggroups (if downcased + (mapcar (lambda (tg) (mapcar #'downcase tg)) + taggroups) + taggroups)) + (taggroups-keys (mapcar #'car taggroups)) + (return-match (if downcased (downcase match) match)) + (count 0) + (work-already-expanded tags-already-expanded) + regexps-in-match tags-in-group regexp-in-group regexp-in-group-escaped) + ;; @ and _ are allowed as word-components in tags. (modify-syntax-entry ?@ "w" stable) (modify-syntax-entry ?_ "w" stable) - (while (and tml + ;; Temporarily replace regexp-expressions in the match-expression. + (while (string-match "{.+?}" return-match) + (cl-incf count) + (push (match-string 0 return-match) regexps-in-match) + (setq return-match (replace-match (format "<%d>" count) t nil return-match))) + (while (and taggroups-keys (with-syntax-table stable (string-match (concat "\\(?1:[+-]?\\)\\(?2:\\<" - (regexp-opt tml) "\\>\\)") - rtnmatch))) - (let* ((dir (match-string 1 rtnmatch)) - (tag (match-string 2 rtnmatch)) + (regexp-opt taggroups-keys) "\\>\\)") + return-match))) + (let* ((dir (match-string 1 return-match)) + (tag (match-string 2 return-match)) (tag (if downcased (downcase tag) tag))) - (setq tml (delete tag tml)) - (when (not (get-text-property 0 'grouptag (match-string 2 rtnmatch))) - (setq rpl (append (org-uniquify rpl) (assoc tag tal))) - (setq rpl (concat dir "{\\<" (regexp-opt rpl) "\\>}")) - (if (stringp rpl) (org-add-props rpl '(grouptag t))) - (setq rtnmatch (replace-match rpl t t rtnmatch))))) + (unless (or (get-text-property 0 'grouptag (match-string 2 return-match)) + (member tag work-already-expanded)) + (setq tags-in-group (assoc tag taggroups)) + (push tag work-already-expanded) + ;; Recursively expand each tag in the group, if the tag hasn't + ;; already been expanded. Restore the match-data after all recursive calls. + (save-match-data + (let (tags-expanded) + (dolist (x (cdr tags-in-group)) + (if (and (member x taggroups-keys) + (not (member x work-already-expanded))) + (setq tags-expanded + (delete-dups + (append + (org-tags-expand x t downcased + work-already-expanded) + tags-expanded))) + (setq tags-expanded + (append (list x) tags-expanded))) + (setq work-already-expanded + (delete-dups + (append tags-expanded + work-already-expanded)))) + (setq tags-in-group + (delete-dups (cons (car tags-in-group) + tags-expanded))))) + ;; Filter tag-regexps from tags. + (setq regexp-in-group-escaped + (delq nil (mapcar (lambda (x) + (if (stringp x) + (and (equal "{" (substring x 0 1)) + (equal "}" (substring x -1)) + x) + x)) + tags-in-group)) + regexp-in-group + (mapcar (lambda (x) + (substring x 1 -1)) + regexp-in-group-escaped) + tags-in-group + (delq nil (mapcar (lambda (x) + (if (stringp x) + (and (not (equal "{" (substring x 0 1))) + (not (equal "}" (substring x -1))) + x) + x)) + tags-in-group))) + ;; If single-as-list, do no more in the while-loop. + (if (not single-as-list) + (progn + (when regexp-in-group + (setq regexp-in-group + (concat "\\|" + (mapconcat 'identity regexp-in-group + "\\|")))) + (setq tags-in-group + (concat dir + "{\\<" + (regexp-opt tags-in-group) + "\\>" + regexp-in-group + "}")) + (when (stringp tags-in-group) + (org-add-props tags-in-group '(grouptag t))) + (setq return-match + (replace-match tags-in-group t t return-match))) + (setq tags-in-group + (append regexp-in-group-escaped tags-in-group)))) + (setq taggroups-keys (delete tag taggroups-keys)))) + ;; Add the regular expressions back into the match-expression again. + (while regexps-in-match + (setq return-match (replace-regexp-in-string (format "<%d>" count) + (pop regexps-in-match) + return-match t t)) + (cl-decf count)) (if single-as-list - (or (reverse rpl) (list rtnmatch)) - rtnmatch)) - (if single-as-list (list (if downcased (downcase match) match)) + (if tags-in-group tags-in-group (list return-match)) + return-match)) + (if single-as-list + (list (if downcased (downcase match) match)) match))) (defun org-op-to-function (op &optional stringp) @@ -14371,7 +14845,7 @@ epoch to the beginning of today (00:00)." (defvar org-add-colon-after-tag-completion nil) ;; dynamically scoped param (defvar org-tags-overlay (make-overlay 1 1)) -(org-detach-overlay org-tags-overlay) +(delete-overlay org-tags-overlay) (defun org-get-local-tags-at (&optional pos) "Get a list of tags defined in the current headline." @@ -14405,10 +14879,9 @@ ignore inherited ones." (org-back-to-heading t) (while (not (equal lastpos (point))) (setq lastpos (point)) - (when (looking-at - (org-re "[^\r\n]+?:\\([[:alnum:]_@#%:]+\\):[ \t]*$")) + (when (looking-at ".+?:\\([[:alnum:]_@#%:]+\\):[ \t]*$") (setq ltags (org-split-string - (org-match-string-no-properties 1) ":")) + (match-string-no-properties 1) ":")) (when parent (setq ltags (mapcar 'org-add-prop-inherited ltags))) (setq tags (append @@ -14417,7 +14890,7 @@ ignore inherited ones." ltags) tags))) (or org-use-tag-inheritance (throw 'done t)) - (if local (throw 'done t)) + (when local (throw 'done t)) (or (org-up-heading-safe) (error nil)) (setq parent t))) (error nil))))) @@ -14439,7 +14912,7 @@ If ONOFF is `on' or `off', don't toggle but set to this state." (let (res current) (save-excursion (org-back-to-heading t) - (if (re-search-forward (org-re "[ \t]:\\([[:alnum:]_@#%:]+\\):[ \t]*$") + (if (re-search-forward "[ \t]:\\([[:alnum:]_@#%:]+\\):[ \t]*$" (point-at-eol) t) (progn (setq current (match-string 1)) @@ -14465,29 +14938,24 @@ If ONOFF is `on' or `off', don't toggle but set to this state." (run-hooks 'org-after-tags-change-hook)) res)) -(defun org-align-tags-here (to-col) - ;; Assumes that this is a headline - "Align tags on the current headline to TO-COL." - (let ((pos (point)) (col (current-column)) ncol tags-l p) - (beginning-of-line 1) - (if (and (looking-at (org-re ".*?\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$")) - (< pos (match-beginning 2))) - (progn - (setq tags-l (- (match-end 2) (match-beginning 2))) - (goto-char (match-beginning 1)) - (insert " ") - (delete-region (point) (1+ (match-beginning 2))) - (setq ncol (max (current-column) - (1+ col) - (if (> to-col 0) - to-col - (- (abs to-col) tags-l)))) - (setq p (point)) - (insert (make-string (- ncol (current-column)) ?\ )) - (setq ncol (current-column)) - (when indent-tabs-mode (tabify p (point-at-eol))) - (org-move-to-column (min ncol col))) - (goto-char pos)))) +(defun org--align-tags-here (to-col) + "Align tags on the current headline to TO-COL. +Assume point is on a headline." + (let ((pos (point))) + (beginning-of-line) + (if (or (not (looking-at ".*?\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$")) + (>= pos (match-beginning 2))) + ;; No tags or point within tags: do not align. + (goto-char pos) + (goto-char (match-beginning 1)) + (let ((shift (max (- (if (>= to-col 0) to-col + (- (abs to-col) (string-width (match-string 2)))) + (current-column)) + 1))) + (replace-match (make-string shift ?\s) nil nil nil 1) + ;; Preserve initial position, if possible. In any case, stop + ;; before tags. + (when (< pos (point)) (goto-char pos)))))) (defun org-set-tags-command (&optional arg just-align) "Call the set-tags command for the current entry." @@ -14517,7 +14985,8 @@ If DATA is nil or the empty string, any tags will be removed." (when data (save-excursion (org-back-to-heading t) - (when (looking-at org-complex-heading-regexp) + (when (let ((case-fold-search nil)) + (looking-at org-complex-heading-regexp)) (if (match-end 5) (progn (goto-char (match-beginning 5)) @@ -14528,11 +14997,11 @@ If DATA is nil or the empty string, any tags will be removed." (insert " " data) (org-set-tags nil 'align))) (beginning-of-line 1) - (if (looking-at ".*?\\([ \t]+\\)$") - (delete-region (match-beginning 1) (match-end 1)))))) + (when (looking-at ".*?\\([ \t]+\\)$") + (delete-region (match-beginning 1) (match-end 1)))))) (defun org-align-all-tags () - "Align the tags i all headings." + "Align the tags in all headings." (interactive) (save-excursion (or (ignore-errors (org-back-to-heading t)) @@ -14549,106 +15018,124 @@ When JUST-ALIGN is non-nil, only align tags." (interactive "P") (if (and (org-region-active-p) org-loop-over-headlines-in-active-region) (let ((cl (if (eq org-loop-over-headlines-in-active-region 'start-level) - 'region-start-level 'region)) - org-loop-over-headlines-in-active-region) - (org-map-entries - ;; We don't use ARG and JUST-ALIGN here because these args - ;; are not useful when looping over headlines. - `(org-set-tags) - org-loop-over-headlines-in-active-region - cl (if (outline-invisible-p) (org-end-of-subtree nil t)))) - (let* ((re org-outline-regexp-bol) - (current (unless arg (org-get-tags-string))) - (col (current-column)) - (org-setting-tags t) - table current-tags inherited-tags ; computed below when needed - tags p0 c0 c1 rpl di tc level) + 'region-start-level + 'region)) + org-loop-over-headlines-in-active-region) + (org-map-entries + ;; We don't use ARG and JUST-ALIGN here because these args + ;; are not useful when looping over headlines. + #'org-set-tags + org-loop-over-headlines-in-active-region + cl + '(when (org-invisible-p) (org-end-of-subtree nil t)))) + (let ((org-setting-tags t)) (if arg - (save-excursion - (goto-char (point-min)) - (let ((buffer-invisibility-spec (org-inhibit-invisibility))) - (while (re-search-forward re nil t) - (org-set-tags nil t) - (end-of-line 1))) - (message "All tags realigned to column %d" org-tags-column)) - (if just-align - (setq tags current) - ;; Get a new set of tags from the user - (save-excursion - (setq table (append org-tag-persistent-alist - (or org-tag-alist (org-get-buffer-tags)) - (and - org-complete-tags-always-offer-all-agenda-tags - (org-global-tags-completion-table - (org-agenda-files)))) - org-last-tags-completion-table table - current-tags (org-split-string current ":") - inherited-tags (nreverse - (nthcdr (length current-tags) - (nreverse (org-get-tags-at)))) - tags - (if (or (eq t org-use-fast-tag-selection) - (and org-use-fast-tag-selection - (delq nil (mapcar 'cdr table)))) - (org-fast-tag-selection - current-tags inherited-tags table - (if org-fast-tag-selection-include-todo - org-todo-key-alist)) - (let ((org-add-colon-after-tag-completion (< 1 (length table)))) - (org-trim - (org-icompleting-read "Tags: " - 'org-tags-completion-function - nil nil current 'org-tags-history)))))) - (while (string-match "[-+&]+" tags) - ;; No boolean logic, just a list - (setq tags (replace-match ":" t t tags)))) - - (setq tags (replace-regexp-in-string "[,]" ":" tags)) - - (if org-tags-sort-function - (setq tags (mapconcat 'identity - (sort (org-split-string - tags (org-re "[^[:alnum:]_@#%]+")) - org-tags-sort-function) ":"))) - - (if (string-match "\\`[\t ]*\\'" tags) - (setq tags "") - (unless (string-match ":$" tags) (setq tags (concat tags ":"))) - (unless (string-match "^:" tags) (setq tags (concat ":" tags)))) - - ;; Insert new tags at the correct column - (beginning-of-line 1) - (setq level (or (and (looking-at org-outline-regexp) - (- (match-end 0) (point) 1)) - 1)) - (cond - ((and (equal current "") (equal tags ""))) - ((re-search-forward - (concat "\\([ \t]*" (regexp-quote current) "\\)[ \t]*$") - (point-at-eol) t) - (if (equal tags "") - (setq rpl "") - (goto-char (match-beginning 0)) - (setq c0 (current-column) - ;; compute offset for the case of org-indent-mode active - di (if (org-bound-and-true-p org-indent-mode) - (* (1- org-indent-indentation-per-level) (1- level)) - 0) - p0 (if (equal (char-before) ?*) (1+ (point)) (point)) - tc (+ org-tags-column (if (> org-tags-column 0) (- di) di)) - c1 (max (1+ c0) (if (> tc 0) tc (- (- tc) (length tags)))) - rpl (concat (make-string (max 0 (- c1 c0)) ?\ ) tags))) - (replace-match rpl t t) - (and (not (featurep 'xemacs)) c0 indent-tabs-mode (tabify p0 (point))) - tags) - (t (error "Tags alignment failed"))) - (org-move-to-column col) - (unless just-align - (run-hooks 'org-after-tags-change-hook)))))) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward org-outline-regexp-bol nil t) + (org-set-tags nil t) + (end-of-line)) + (message "All tags realigned to column %d" org-tags-column)) + (let* ((current (org-get-tags-string)) + (tags + (if just-align current + ;; Get a new set of tags from the user. + (save-excursion + (let* ((seen) + (table + (setq + org-last-tags-completion-table + ;; Uniquify tags in alists, yet preserve + ;; structure (i.e., keywords). + (delq nil + (mapcar + (lambda (pair) + (let ((head (car pair))) + (cond ((symbolp head) pair) + ((member head seen) nil) + (t (push head seen) + pair)))) + (append + (or org-current-tag-alist + (org-get-buffer-tags)) + (and + org-complete-tags-always-offer-all-agenda-tags + (org-global-tags-completion-table + (org-agenda-files)))))))) + (current-tags (org-split-string current ":")) + (inherited-tags + (nreverse (nthcdr (length current-tags) + (nreverse (org-get-tags-at)))))) + (replace-regexp-in-string + "\\([-+&]+\\|,\\)" + ":" + (if (or (eq t org-use-fast-tag-selection) + (and org-use-fast-tag-selection + (delq nil (mapcar #'cdr table)))) + (org-fast-tag-selection + current-tags inherited-tags table + (and org-fast-tag-selection-include-todo + org-todo-key-alist)) + (let ((org-add-colon-after-tag-completion + (< 1 (length table)))) + (org-trim + (completing-read + "Tags: " + #'org-tags-completion-function + nil nil current 'org-tags-history)))))))))) + + (when org-tags-sort-function + (setq tags + (mapconcat + #'identity + (sort (org-split-string tags "[^[:alnum:]_@#%]+") + org-tags-sort-function) + ":"))) + + (if (or (string= ":" tags) + (string= "::" tags)) + (setq tags "")) + (if (not (org-string-nw-p tags)) (setq tags "") + (unless (string-suffix-p ":" tags) (setq tags (concat tags ":"))) + (unless (string-prefix-p ":" tags) (setq tags (concat ":" tags)))) + + ;; Insert new tags at the correct column. + (unless (equal current tags) + (save-excursion + (beginning-of-line) + (let ((case-fold-search nil)) + (looking-at org-complex-heading-regexp)) + ;; Remove current tags, if any. + (when (match-end 5) (replace-match "" nil nil nil 5)) + ;; Insert new tags, if any. Otherwise, remove trailing + ;; white spaces. + (end-of-line) + (if (not (equal tags "")) + ;; When text is being inserted on an invisible + ;; region boundary, it can be inadvertently sucked + ;; into invisibility. + (outline-flag-region (point) (progn (insert " " tags) (point)) nil) + (skip-chars-backward " \t") + (delete-region (point) (line-end-position))))) + ;; Align tags, if any. Fix tags column if `org-indent-mode' + ;; is on. + (unless (equal tags "") + (let* ((level (save-excursion + (beginning-of-line) + (skip-chars-forward "\\*"))) + (offset (if (bound-and-true-p org-indent-mode) + (* (1- org-indent-indentation-per-level) + (1- level)) + 0)) + (tags-column + (+ org-tags-column + (if (> org-tags-column 0) (- offset) offset)))) + (org--align-tags-here tags-column)))) + (unless just-align (run-hooks 'org-after-tags-change-hook)))))) (defun org-change-tag-in-region (beg end tag off) "Add or remove TAG for each entry in the region. -This works in the agenda, and also in an org-mode buffer." +This works in the agenda, and also in an Org buffer." (interactive (list (region-beginning) (region-end) (let ((org-last-tags-completion-table @@ -14657,37 +15144,37 @@ This works in the agenda, and also in an org-mode buffer." (delq nil (append (org-get-buffer-tags) (org-global-tags-completion-table)))) (org-global-tags-completion-table)))) - (org-icompleting-read + (completing-read "Tag: " 'org-tags-completion-function nil nil nil 'org-tags-history)) (progn (message "[s]et or [r]emove? ") (equal (read-char-exclusive) ?r)))) - (if (fboundp 'deactivate-mark) (deactivate-mark)) + (when (fboundp 'deactivate-mark) (deactivate-mark)) (let ((agendap (equal major-mode 'org-agenda-mode)) l1 l2 m buf pos newhead (cnt 0)) (goto-char end) (setq l2 (1- (org-current-line))) (goto-char beg) (setq l1 (org-current-line)) - (loop for l from l1 to l2 do - (org-goto-line l) - (setq m (get-text-property (point) 'org-hd-marker)) - (when (or (and (derived-mode-p 'org-mode) (org-at-heading-p)) - (and agendap m)) - (setq buf (if agendap (marker-buffer m) (current-buffer)) - pos (if agendap m (point))) - (with-current-buffer buf - (save-excursion - (save-restriction - (goto-char pos) - (setq cnt (1+ cnt)) - (org-toggle-tag tag (if off 'off 'on)) - (setq newhead (org-get-heading))))) - (and agendap (org-agenda-change-all-lines newhead m)))) + (cl-loop for l from l1 to l2 do + (org-goto-line l) + (setq m (get-text-property (point) 'org-hd-marker)) + (when (or (and (derived-mode-p 'org-mode) (org-at-heading-p)) + (and agendap m)) + (setq buf (if agendap (marker-buffer m) (current-buffer)) + pos (if agendap m (point))) + (with-current-buffer buf + (save-excursion + (save-restriction + (goto-char pos) + (setq cnt (1+ cnt)) + (org-toggle-tag tag (if off 'off 'on)) + (setq newhead (org-get-heading))))) + (and agendap (org-agenda-change-all-lines newhead m)))) (message "Tag :%s: %s in %d headings" tag (if off "removed" "set") cnt))) -(defun org-tags-completion-function (string predicate &optional flag) +(defun org-tags-completion-function (string _predicate &optional flag) (let (s1 s2 rtn (ctable org-last-tags-completion-table) (confirm (lambda (x) (stringp (car x))))) (if (string-match "^\\(.*[-+:&,|]\\)\\([^-+:&,|]*\\)$" string) @@ -14698,12 +15185,12 @@ This works in the agenda, and also in an org-mode buffer." ((eq flag nil) ;; try completion (setq rtn (try-completion s2 ctable confirm)) - (if (stringp rtn) - (setq rtn - (concat s1 s2 (substring rtn (length s2)) - (if (and org-add-colon-after-tag-completion - (assoc rtn ctable)) - ":" "")))) + (when (stringp rtn) + (setq rtn + (concat s1 s2 (substring rtn (length s2)) + (if (and org-add-colon-after-tag-completion + (assoc rtn ctable)) + ":" "")))) rtn) ((eq flag t) ;; all-completions @@ -14722,8 +15209,8 @@ Also insert END." (defun org-fast-tag-show-exit (flag) (save-excursion (org-goto-line 3) - (if (re-search-forward "[ \t]+Next change exits" (point-at-eol) t) - (replace-match "")) + (when (re-search-forward "[ \t]+Next change exits" (point-at-eol) t) + (replace-match "")) (when flag (end-of-line 1) (org-move-to-column (- (window-width) 19) t) @@ -14732,11 +15219,8 @@ Also insert END." (defun org-set-current-tags-overlay (current prefix) "Add an overlay to CURRENT tag with PREFIX." (let ((s (concat ":" (mapconcat 'identity current ":") ":"))) - (if (featurep 'xemacs) - (org-overlay-display org-tags-overlay (concat prefix s) - 'secondary-selection) - (put-text-property 0 (length s) 'face '(secondary-selection org-tag) s) - (org-overlay-display org-tags-overlay (concat prefix s))))) + (put-text-property 0 (length s) 'face '(secondary-selection org-tag) s) + (org-overlay-display org-tags-overlay (concat prefix s)))) (defvar org-last-tag-selection-key nil) (defun org-fast-tag-selection (current inherited table &optional todo-table) @@ -14759,15 +15243,14 @@ Returns the new tags string, or nil to not change the current settings." (ncol (/ (- (window-width) 4) fwidth)) (i-face 'org-done) (c-face 'org-todo) - tg cnt c char c1 c2 ntable tbl rtn + tg cnt e c char c1 c2 ntable tbl rtn ov-start ov-end ov-prefix (exit-after-next org-fast-tag-selection-single-key) (done-keywords org-done-keywords) - groups ingroup) + groups ingroup intaggroup) (save-excursion (beginning-of-line 1) - (if (looking-at - (org-re ".*[ \t]\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$")) + (if (looking-at ".*[ \t]\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$") (setq ov-start (match-beginning 1) ov-end (match-end 1) ov-prefix "") @@ -14788,32 +15271,41 @@ Returns the new tags string, or nil to not change the current settings." (set-window-buffer (split-window-vertically) (get-buffer-create " *Org tags*")) (org-switch-to-buffer-other-window " *Org tags*")) (erase-buffer) - (org-set-local 'org-done-keywords done-keywords) + (setq-local org-done-keywords done-keywords) (org-fast-tag-insert "Inherited" inherited i-face "\n") (org-fast-tag-insert "Current" current c-face "\n\n") (org-fast-tag-show-exit exit-after-next) (org-set-current-tags-overlay current ov-prefix) (setq tbl fulltable char ?a cnt 0) - (dolist (e tbl) + (while (setq e (pop tbl)) (cond - ((equal (car e) :startgroup) + ((eq (car e) :startgroup) (push '() groups) (setq ingroup t) - (when (not (= cnt 0)) + (unless (zerop cnt) (setq cnt 0) (insert "\n")) (insert (if (cdr e) (format "%s: " (cdr e)) "") "{ ")) - ((equal (car e) :endgroup) + ((eq (car e) :endgroup) (setq ingroup nil cnt 0) (insert "}" (if (cdr e) (format " (%s) " (cdr e)) "") "\n")) + ((eq (car e) :startgrouptag) + (setq intaggroup t) + (unless (zerop cnt) + (setq cnt 0) + (insert "\n")) + (insert "[ ")) + ((eq (car e) :endgrouptag) + (setq intaggroup nil cnt 0) + (insert "]\n")) ((equal e '(:newline)) - (when (not (= cnt 0)) + (unless (zerop cnt) (setq cnt 0) (insert "\n") (setq e (car tbl)) (while (equal (car tbl) '(:newline)) (insert "\n") (setq tbl (cdr tbl))))) - ((equal e '(:grouptags)) nil) + ((equal e '(:grouptags)) (insert " : ")) (t (setq tg (copy-sequence (car e)) c2 nil) (if (cdr e) @@ -14827,27 +15319,27 @@ Returns the new tags string, or nil to not change the current settings." (setq char (1+ char))) (setq c2 c1)) (setq c (or c2 char))) - (if ingroup (push tg (car groups))) + (when ingroup (push tg (car groups))) (setq tg (org-add-props tg nil 'face (cond ((not (assoc tg table)) (org-get-todo-face tg)) ((member tg current) c-face) ((member tg inherited) i-face)))) - (if (equal (caar tbl) :grouptags) - (org-add-props tg nil 'face 'org-tag-group)) - (if (and (= cnt 0) (not ingroup)) (insert " ")) + (when (equal (caar tbl) :grouptags) + (org-add-props tg nil 'face 'org-tag-group)) + (when (and (zerop cnt) (not ingroup) (not intaggroup)) (insert " ")) (insert "[" c "] " tg (make-string (- fwidth 4 (length tg)) ?\ )) (push (cons tg c) ntable) - (when (= (setq cnt (1+ cnt)) ncol) + (when (= (cl-incf cnt) ncol) (insert "\n") - (if ingroup (insert " ")) + (when (or ingroup intaggroup) (insert " ")) (setq cnt 0))))) (setq ntable (nreverse ntable)) (insert "\n") (goto-char (point-min)) - (if (not expert) (org-fit-window-to-buffer)) + (unless expert (org-fit-window-to-buffer)) (setq rtn (catch 'exit (while t @@ -14873,53 +15365,51 @@ Returns the new tags string, or nil to not change the current settings." (org-fit-window-to-buffer))) ((or (= c ?\C-g) (and (= c ?q) (not (rassoc c ntable)))) - (org-detach-overlay org-tags-overlay) + (delete-overlay org-tags-overlay) (setq quit-flag t)) ((= c ?\ ) (setq current nil) - (if exit-after-next (setq exit-after-next 'now))) + (when exit-after-next (setq exit-after-next 'now))) ((= c ?\t) (condition-case nil - (setq tg (org-icompleting-read + (setq tg (completing-read "Tag: " (or buffer-tags (with-current-buffer buf - (org-get-buffer-tags))))) + (setq buffer-tags + (org-get-buffer-tags)))))) (quit (setq tg ""))) (when (string-match "\\S-" tg) - (add-to-list 'buffer-tags (list tg)) + (cl-pushnew (list tg) buffer-tags :test #'equal) (if (member tg current) (setq current (delete tg current)) (push tg current))) - (if exit-after-next (setq exit-after-next 'now))) + (when exit-after-next (setq exit-after-next 'now))) ((setq e (rassoc c todo-table) tg (car e)) (with-current-buffer buf (save-excursion (org-todo tg))) - (if exit-after-next (setq exit-after-next 'now))) + (when exit-after-next (setq exit-after-next 'now))) ((setq e (rassoc c ntable) tg (car e)) (if (member tg current) (setq current (delete tg current)) - (loop for g in groups do - (if (member tg g) - (mapc (lambda (x) - (setq current (delete x current))) - g))) + (cl-loop for g in groups do + (when (member tg g) + (dolist (x g) (setq current (delete x current))))) (push tg current)) - (if exit-after-next (setq exit-after-next 'now)))) + (when exit-after-next (setq exit-after-next 'now)))) ;; Create a sorted list (setq current (sort current (lambda (a b) (assoc b (cdr (memq (assoc a ntable) ntable)))))) - (if (eq exit-after-next 'now) (throw 'exit t)) + (when (eq exit-after-next 'now) (throw 'exit t)) (goto-char (point-min)) (beginning-of-line 2) (delete-region (point) (point-at-eol)) (org-fast-tag-insert "Current" current c-face) (org-set-current-tags-overlay current ov-prefix) - (while (re-search-forward - (org-re "\\[.\\] \\([[:alnum:]_@#%]+\\)") nil t) + (while (re-search-forward "\\[.\\] \\([[:alnum:]_@#%]+\\)" nil t) (setq tg (match-string 1)) (add-text-properties (match-beginning 1) (match-end 1) @@ -14929,7 +15419,7 @@ Returns the new tags string, or nil to not change the current settings." ((member tg inherited) i-face) (t (get-text-property (match-beginning 1) 'face)))))) (goto-char (point-min))))) - (org-detach-overlay org-tags-overlay) + (delete-overlay org-tags-overlay) (if rtn (mapconcat 'identity current ":") nil)))) @@ -14940,8 +15430,8 @@ Returns the new tags string, or nil to not change the current settings." (user-error "Not on a heading")) (save-excursion (beginning-of-line 1) - (if (looking-at (org-re ".*[ \t]\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$")) - (org-match-string-no-properties 1) + (if (looking-at ".*[ \t]\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$") + (match-string-no-properties 1) ""))) (defun org-get-tags () @@ -14950,19 +15440,20 @@ Returns the new tags string, or nil to not change the current settings." (defun org-get-buffer-tags () "Get a table of all tags used in the buffer, for completion." - (let (tags) - (save-excursion - (goto-char (point-min)) - (while (re-search-forward - (org-re "[ \t]:\\([[:alnum:]_@#%:]+\\):[ \t\r\n]") nil t) - (when (equal (char-after (point-at-bol 0)) ?*) - (mapc (lambda (x) (add-to-list 'tags x)) - (org-split-string (org-match-string-no-properties 1) ":"))))) - (mapc (lambda (s) (add-to-list 'tags s)) org-file-tags) - (mapcar 'list tags))) + (org-with-wide-buffer + (goto-char (point-min)) + (let ((tag-re (concat org-outline-regexp-bol + "\\(?:.*?[ \t]\\)?:\\([[:alnum:]_@#%:]+\\):[ \t]*$")) + tags) + (while (re-search-forward tag-re nil t) + (dolist (tag (org-split-string (match-string-no-properties 1) ":")) + (push tag tags))) + (mapcar #'list (append org-file-tags (org-uniquify tags)))))) ;;;; The mapping API +(defvar org-agenda-skip-comment-trees) +(defvar org-agenda-skip-function) (defun org-map-entries (func &optional match scope &rest skip) "Call FUNC at each headline selected by MATCH in SCOPE. @@ -15032,13 +15523,12 @@ a *different* entry, you cannot use these techniques." (car (org-delete-all '(comment archive) skip))) (org-tags-match-list-sublevels t) (start-level (eq scope 'region-start-level)) - matcher file res + matcher res org-todo-keywords-for-agenda org-done-keywords-for-agenda org-todo-keyword-alist-for-agenda - org-drawers-for-agenda org-tag-alist-for-agenda - todo-only) + org--matcher-tags-todo-only) (cond ((eq match t) (setq matcher t)) @@ -15071,7 +15561,9 @@ a *different* entry, you cannot use these techniques." (progn (org-agenda-prepare-buffers (and buffer-file-name (list buffer-file-name))) - (setq res (org-scan-tags func matcher todo-only start-level))) + (setq res + (org-scan-tags + func matcher org--matcher-tags-todo-only start-level))) ;; Get the right scope (cond ((and scope (listp scope) (symbolp (car scope))) @@ -15088,22 +15580,21 @@ a *different* entry, you cannot use these techniques." (org-agenda-prepare-buffers scope) (dolist (file scope) (with-current-buffer (org-find-base-buffer-visiting file) - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (setq res (append res (org-scan-tags func matcher todo-only)))))))))) + (org-with-wide-buffer + (goto-char (point-min)) + (setq res + (append + res + (org-scan-tags + func matcher org--matcher-tags-todo-only))))))))) res))) -;;;; Properties - -;;; Setting and retrieving properties +;;; Properties API (defconst org-special-properties - '("TODO" "TAGS" "ALLTAGS" "DEADLINE" "SCHEDULED" "CLOCK" "CLOSED" "PRIORITY" - "TIMESTAMP" "TIMESTAMP_IA" "BLOCKED" "FILE" "CLOCKSUM" "CLOCKSUM_T") - "The special properties valid in Org-mode. - + '("ALLTAGS" "BLOCKED" "CLOCKSUM" "CLOCKSUM_T" "CLOSED" "DEADLINE" "FILE" + "ITEM" "PRIORITY" "SCHEDULED" "TAGS" "TIMESTAMP" "TIMESTAMP_IA" "TODO") + "The special properties valid in Org mode. These are properties that are not defined in the property drawer, but in some other way.") @@ -15112,59 +15603,86 @@ but in some other way.") "LOCATION" "LOGGING" "COLUMNS" "VISIBILITY" "TABLE_EXPORT_FORMAT" "TABLE_EXPORT_FILE" "EXPORT_OPTIONS" "EXPORT_TEXT" "EXPORT_FILE_NAME" - "EXPORT_TITLE" "EXPORT_AUTHOR" "EXPORT_DATE" + "EXPORT_TITLE" "EXPORT_AUTHOR" "EXPORT_DATE" "UNNUMBERED" "ORDERED" "NOBLOCKING" "COOKIE_DATA" "LOG_INTO_DRAWER" "REPEAT_TO_STATE" "CLOCK_MODELINE_TOTAL" "STYLE" "HTML_CONTAINER_CLASS") - "Some properties that are used by Org-mode for various purposes. + "Some properties that are used by Org mode for various purposes. Being in this list makes sure that they are offered for completion.") -(defconst org-property-start-re "^[ \t]*:PROPERTIES:[ \t]*$" - "Regular expression matching the first line of a property drawer.") - -(defconst org-property-end-re "^[ \t]*:END:[ \t]*$" - "Regular expression matching the last line of a property drawer.") - -(defconst org-clock-drawer-start-re "^[ \t]*:CLOCK:[ \t]*$" - "Regular expression matching the first line of a property drawer.") - -(defconst org-clock-drawer-end-re "^[ \t]*:END:[ \t]*$" - "Regular expression matching the first line of a property drawer.") - -(defconst org-property-drawer-re - (concat "\\(" org-property-start-re "\\)[^\000]*\\(" - org-property-end-re "\\)\n?") - "Matches an entire property drawer.") +(defun org--valid-property-p (property) + "Non nil when string PROPERTY is a valid property name." + (not + (or (equal property "") + (string-match-p "\\s-" property)))) + +(defun org--update-property-plist (key val props) + "Associate KEY to VAL in alist PROPS. +Modifications are made by side-effect. Return new alist." + (let* ((appending (string= (substring key -1) "+")) + (key (if appending (substring key 0 -1) key)) + (old (assoc-string key props t))) + (if (not old) (cons (cons key val) props) + (setcdr old (if appending (concat (cdr old) " " val) val)) + props))) + +(defun org-get-property-block (&optional beg force) + "Return the (beg . end) range of the body of the property drawer. +BEG is the beginning of the current subtree, or of the part +before the first headline. If it is not given, it will be found. +If the drawer does not exist, create it if FORCE is non-nil, or +return nil." + (org-with-wide-buffer + (when beg (goto-char beg)) + (unless (org-before-first-heading-p) + (let ((beg (cond (beg) + ((or (not (featurep 'org-inlinetask)) + (org-inlinetask-in-task-p)) + (org-back-to-heading t)) + (t (org-with-limited-levels (org-back-to-heading t)))))) + (forward-line) + (when (looking-at-p org-planning-line-re) (forward-line)) + (cond ((looking-at org-property-drawer-re) + (forward-line) + (cons (point) (progn (goto-char (match-end 0)) + (line-beginning-position)))) + (force + (goto-char beg) + (org-insert-property-drawer) + (let ((pos (save-excursion (search-forward ":END:") + (line-beginning-position)))) + (cons pos pos)))))))) -(defconst org-clock-drawer-re - (concat "\\(" org-clock-drawer-start-re "\\)[^\000]*\\(" - org-property-end-re "\\)\n?") - "Matches an entire clock drawer.") +(defun org-at-property-p () + "Non-nil when point is inside a property drawer. +See `org-property-re' for match data, if applicable." + (save-excursion + (beginning-of-line) + (and (looking-at org-property-re) + (let ((property-drawer (save-match-data (org-get-property-block)))) + (and property-drawer + (>= (point) (car property-drawer)) + (< (point) (cdr property-drawer))))))) (defun org-property-action () "Do an action on properties." (interactive) - (let (c) - (org-at-property-p) - (message "Property Action: [s]et [d]elete [D]elete globally [c]ompute") - (setq c (read-char-exclusive)) - (cond - ((equal c ?s) - (call-interactively 'org-set-property)) - ((equal c ?d) - (call-interactively 'org-delete-property)) - ((equal c ?D) - (call-interactively 'org-delete-property-globally)) - ((equal c ?c) - (call-interactively 'org-compute-property-at-point)) - (t (user-error "No such property action %c" c))))) + (unless (org-at-property-p) (user-error "Not at a property")) + (message "Property Action: [s]et [d]elete [D]elete globally [c]ompute") + (let ((c (read-char-exclusive))) + (cl-case c + (?s (call-interactively #'org-set-property)) + (?d (call-interactively #'org-delete-property)) + (?D (call-interactively #'org-delete-property-globally)) + (?c (call-interactively #'org-compute-property-at-point)) + (otherwise (user-error "No such property action %c" c))))) (defun org-inc-effort () "Increment the value of the effort property in the current entry." (interactive) (org-set-effort nil t)) -(defvar org-clock-effort) ;; Defined in org-clock.el -(defvar org-clock-current-task) ;; Defined in org-clock.el +(defvar org-clock-effort) ; Defined in org-clock.el. +(defvar org-clock-current-task) ; Defined in org-clock.el. (defun org-set-effort (&optional value increment) "Set the effort property of the current entry. With numerical prefix arg, use the nth allowed value, 0 stands for the @@ -15172,7 +15690,7 @@ With numerical prefix arg, use the nth allowed value, 0 stands for the When INCREMENT is non-nil, set the property to the next allowed value." (interactive "P") - (if (equal value 0) (setq value 10)) + (when (equal value 0) (setq value 10)) (let* ((completion-ignore-case t) (prop org-effort-property) (cur (org-entry-get nil prop)) @@ -15186,7 +15704,7 @@ When INCREMENT is non-nil, set the property to the next allowed value." (or (car (nth (1- value) allowed)) (car (org-last allowed)))) ((and allowed increment) - (or (caadr (member (list cur) allowed)) + (or (cl-caadr (member (list cur) allowed)) (user-error "Allowed effort values are not set"))) (allowed (message "Select 1-9,0, [RET%s]: %s" @@ -15196,231 +15714,295 @@ When INCREMENT is non-nil, set the property to the next allowed value." (if (equal rpl ?\r) cur (setq rpl (- rpl ?0)) - (if (equal rpl 0) (setq rpl 10)) + (when (equal rpl 0) (setq rpl 10)) (if (and (> rpl 0) (<= rpl (length allowed))) (car (nth (1- rpl) allowed)) (org-completing-read "Effort: " allowed nil)))) (t - (let (org-completion-use-ido org-completion-use-iswitchb) - (org-completing-read - (concat "Effort " (if (and cur (string-match "\\S-" cur)) - (concat "[" cur "]") "") - ": ") - existing nil nil "" nil cur)))))) + (org-completing-read + (concat "Effort" (and cur (string-match "\\S-" cur) + (concat " [" cur "]")) + ": ") + existing nil nil "" nil cur))))) (unless (equal (org-entry-get nil prop) val) (org-entry-put nil prop val)) - (save-excursion - (org-back-to-heading t) - (put-text-property (point-at-bol) (point-at-eol) 'org-effort val)) - (when (string= heading org-clock-current-task) - (setq org-clock-effort (get-text-property (point-at-bol) 'org-effort)) + (org-refresh-property + '((effort . identity) + (effort-minutes . org-duration-string-to-minutes)) + val) + (when (equal heading (bound-and-true-p org-clock-current-task)) + (setq org-clock-effort (get-text-property (point-at-bol) 'effort)) (org-clock-update-mode-line)) (message "%s is now %s" prop val))) -(defun org-at-property-p () - "Is cursor inside a property drawer?" - (save-excursion - (when (equal 'node-property (car (org-element-at-point))) - (beginning-of-line 1) - (looking-at org-property-re)))) +(defun org-entry-properties (&optional pom which) + "Get all properties of the current entry. + +When POM is a buffer position, get all properties from the entry +there instead. + +This includes the TODO keyword, the tags, time strings for +deadline, scheduled, and clocking, and any additional properties +defined in the entry. -(defun org-get-property-block (&optional beg end force) - "Return the (beg . end) range of the body of the property drawer. -BEG and END are the beginning and end of the current subtree, or of -the part before the first headline. If they are not given, they will -be found. If the drawer does not exist and FORCE is non-nil, create -the drawer." - (catch 'exit - (save-excursion - (let* ((beg (or beg (and (org-before-first-heading-p) (point-min)) - (progn (org-back-to-heading t) (point)))) - (end (or end (and (not (outline-next-heading)) (point-max)) - (point)))) - (goto-char beg) - (if (re-search-forward org-property-start-re end t) - (setq beg (1+ (match-end 0))) - (if force - (save-excursion - (org-insert-property-drawer) - (setq end (progn (outline-next-heading) (point)))) - (throw 'exit nil)) - (goto-char beg) - (if (re-search-forward org-property-start-re end t) - (setq beg (1+ (match-end 0))))) - (if (re-search-forward org-property-end-re end t) - (setq end (match-beginning 0)) - (or force (throw 'exit nil)) - (goto-char beg) - (setq end beg) - (org-indent-line) - (insert ":END:\n")) - (cons beg end))))) - -(defun org-entry-properties (&optional pom which specific) - "Get all properties of the entry at point-or-marker POM. -This includes the TODO keyword, the tags, time strings for deadline, -scheduled, and clocking, and any additional properties defined in the -entry. The return value is an alist, keys may occur multiple times -if the property key was used several times. -POM may also be nil, in which case the current entry is used. If WHICH is nil or `all', get all properties. If WHICH is -`special' or `standard', only get that subclass. If WHICH -is a string only get exactly this property. SPECIFIC can be a string, the -specific property we are interested in. Specifying it can speed -things up because then unnecessary parsing is avoided." - (setq which (or which 'all)) - (org-with-wide-buffer - (org-with-point-at pom - (let ((clockstr (substring org-clock-string 0 -1)) - (excluded '("TODO" "TAGS" "ALLTAGS" "PRIORITY" "BLOCKED")) - (case-fold-search nil) - beg end range props sum-props key key1 value string clocksum clocksumt) - (when (and (derived-mode-p 'org-mode) - (ignore-errors (org-back-to-heading t))) - (setq beg (point)) - (setq sum-props (get-text-property (point) 'org-summaries)) - (setq clocksum (get-text-property (point) :org-clock-minutes) - clocksumt (get-text-property (point) :org-clock-minutes-today)) - (outline-next-heading) - (setq end (point)) - (when (memq which '(all special)) - ;; Get the special properties, like TODO and tags - (goto-char beg) - (when (and (or (not specific) (string= specific "TODO")) - (looking-at org-todo-line-regexp) (match-end 2)) - (push (cons "TODO" (org-match-string-no-properties 2)) props)) - (when (and (or (not specific) (string= specific "PRIORITY")) - (looking-at org-priority-regexp)) - (push (cons "PRIORITY" (org-match-string-no-properties 2)) props)) - (when (or (not specific) (string= specific "FILE")) - (push (cons "FILE" buffer-file-name) props)) - (when (and (or (not specific) (string= specific "TAGS")) - (setq value (org-get-tags-string)) - (string-match "\\S-" value)) - (push (cons "TAGS" value) props)) - (when (and (or (not specific) (string= specific "ALLTAGS")) - (setq value (org-get-tags-at))) - (push (cons "ALLTAGS" (concat ":" (mapconcat 'identity value ":") - ":")) - props)) - (when (or (not specific) (string= specific "BLOCKED")) - (push (cons "BLOCKED" (if (org-entry-blocked-p) "t" "")) props)) - (when (or (not specific) - (member specific - '("SCHEDULED" "DEADLINE" "CLOCK" "CLOSED" - "TIMESTAMP" "TIMESTAMP_IA"))) - (catch 'match - (while (and (re-search-forward org-maybe-keyword-time-regexp end t) - (not (text-property-any 0 (length (match-string 0)) - 'face 'font-lock-comment-face - (match-string 0)))) - (setq key (if (match-end 1) - (substring (org-match-string-no-properties 1) - 0 -1)) - string (if (equal key clockstr) - (org-trim - (buffer-substring-no-properties - (match-beginning 3) (goto-char - (point-at-eol)))) - (substring (org-match-string-no-properties 3) - 1 -1))) - ;; Get the correct property name from the key. This is - ;; necessary if the user has configured time keywords. - (setq key1 (concat key ":")) - (cond - ((not key) - (setq key - (if (= (char-after (match-beginning 3)) ?\[) - "TIMESTAMP_IA" "TIMESTAMP"))) - ((equal key1 org-scheduled-string) (setq key "SCHEDULED")) - ((equal key1 org-deadline-string) (setq key "DEADLINE")) - ((equal key1 org-closed-string) (setq key "CLOSED")) - ((equal key1 org-clock-string) (setq key "CLOCK"))) - (if (and specific (equal key specific) (not (equal key "CLOCK"))) - (progn - (push (cons key string) props) - ;; no need to search further if match is found - (throw 'match t)) - (when (or (equal key "CLOCK") (not (assoc key props))) - (push (cons key string) props))))))) - - (when (memq which '(all standard)) - ;; Get the standard properties, like :PROP: ... - (setq range (org-get-property-block beg end)) - (when range - (goto-char (car range)) - (while (re-search-forward org-property-re - (cdr range) t) - (setq key (org-match-string-no-properties 2) - value (org-trim (or (org-match-string-no-properties 3) ""))) - (unless (member key excluded) - (push (cons key (or value "")) props))))) - (if clocksum - (push (cons "CLOCKSUM" - (org-columns-number-to-string (/ (float clocksum) 60.) - 'add_times)) - props)) - (if clocksumt - (push (cons "CLOCKSUM_T" - (org-columns-number-to-string (/ (float clocksumt) 60.) - 'add_times)) - props)) - (unless (assoc "CATEGORY" props) - (push (cons "CATEGORY" (org-get-category)) props)) - (append sum-props (nreverse props))))))) +`special' or `standard', only get that subclass. If WHICH is +a string, only get that property. + +Return value is an alist. Keys are properties, as upcased +strings." + (org-with-point-at pom + (when (and (derived-mode-p 'org-mode) + (ignore-errors (org-back-to-heading t))) + (catch 'exit + (let* ((beg (point)) + (specific (and (stringp which) (upcase which))) + (which (cond ((not specific) which) + ((member specific org-special-properties) 'special) + (t 'standard))) + props) + ;; Get the special properties, like TODO and TAGS. + (when (memq which '(nil all special)) + (when (or (not specific) (string= specific "CLOCKSUM")) + (let ((clocksum (get-text-property (point) :org-clock-minutes))) + (when clocksum + (push (cons "CLOCKSUM" + (org-minutes-to-clocksum-string clocksum)) + props))) + (when specific (throw 'exit props))) + (when (or (not specific) (string= specific "CLOCKSUM_T")) + (let ((clocksumt (get-text-property (point) + :org-clock-minutes-today))) + (when clocksumt + (push (cons "CLOCKSUM_T" + (org-minutes-to-clocksum-string clocksumt)) + props))) + (when specific (throw 'exit props))) + (when (or (not specific) (string= specific "ITEM")) + (let ((case-fold-search nil)) + (when (looking-at org-complex-heading-regexp) + (push (cons "ITEM" + (let ((title (match-string-no-properties 4))) + (if (org-string-nw-p title) + (org-remove-tabs title) + ""))) + props))) + (when specific (throw 'exit props))) + (when (or (not specific) (string= specific "TODO")) + (let ((case-fold-search nil)) + (when (and (looking-at org-todo-line-regexp) (match-end 2)) + (push (cons "TODO" (match-string-no-properties 2)) props))) + (when specific (throw 'exit props))) + (when (or (not specific) (string= specific "PRIORITY")) + (push (cons "PRIORITY" + (if (looking-at org-priority-regexp) + (match-string-no-properties 2) + (char-to-string org-default-priority))) + props) + (when specific (throw 'exit props))) + (when (or (not specific) (string= specific "FILE")) + (push (cons "FILE" (buffer-file-name (buffer-base-buffer))) + props) + (when specific (throw 'exit props))) + (when (or (not specific) (string= specific "TAGS")) + (let ((value (org-string-nw-p (org-get-tags-string)))) + (when value (push (cons "TAGS" value) props))) + (when specific (throw 'exit props))) + (when (or (not specific) (string= specific "ALLTAGS")) + (let ((value (org-get-tags-at))) + (when value + (push (cons "ALLTAGS" + (format ":%s:" (mapconcat #'identity value ":"))) + props))) + (when specific (throw 'exit props))) + (when (or (not specific) (string= specific "BLOCKED")) + (push (cons "BLOCKED" (if (org-entry-blocked-p) "t" "")) props) + (when specific (throw 'exit props))) + (when (or (not specific) + (member specific '("CLOSED" "DEADLINE" "SCHEDULED"))) + (forward-line) + (when (looking-at-p org-planning-line-re) + (end-of-line) + (let ((bol (line-beginning-position)) + ;; Backward compatibility: time keywords used to + ;; be configurable (before 8.3). Make sure we + ;; get the correct keyword. + (key-assoc `(("CLOSED" . ,org-closed-string) + ("DEADLINE" . ,org-deadline-string) + ("SCHEDULED" . ,org-scheduled-string)))) + (dolist (pair (if specific (list (assoc specific key-assoc)) + key-assoc)) + (save-excursion + (when (search-backward (cdr pair) bol t) + (goto-char (match-end 0)) + (skip-chars-forward " \t") + (and (looking-at org-ts-regexp-both) + (push (cons (car pair) + (match-string-no-properties 0)) + props))))))) + (when specific (throw 'exit props))) + (when (or (not specific) + (member specific '("TIMESTAMP" "TIMESTAMP_IA"))) + (let ((find-ts + (lambda (end ts) + ;; Fix next time-stamp before END. TS is the + ;; list of time-stamps found so far. + (let ((ts ts) + (regexp (cond + ((string= specific "TIMESTAMP") + org-ts-regexp) + ((string= specific "TIMESTAMP_IA") + org-ts-regexp-inactive) + ((assoc "TIMESTAMP_IA" ts) + org-ts-regexp) + ((assoc "TIMESTAMP" ts) + org-ts-regexp-inactive) + (t org-ts-regexp-both)))) + (catch 'next + (while (re-search-forward regexp end t) + (backward-char) + (let ((object (org-element-context))) + ;; Accept to match timestamps in node + ;; properties, too. + (when (memq (org-element-type object) + '(node-property timestamp)) + (let ((type + (org-element-property :type object))) + (cond + ((and (memq type '(active active-range)) + (not (equal specific "TIMESTAMP_IA"))) + (unless (assoc "TIMESTAMP" ts) + (push (cons "TIMESTAMP" + (org-element-property + :raw-value object)) + ts) + (when specific (throw 'exit ts)))) + ((and (memq type '(inactive inactive-range)) + (not (string= specific "TIMESTAMP"))) + (unless (assoc "TIMESTAMP_IA" ts) + (push (cons "TIMESTAMP_IA" + (org-element-property + :raw-value object)) + ts) + (when specific (throw 'exit ts)))))) + ;; Both timestamp types are found, + ;; move to next part. + (when (= (length ts) 2) (throw 'next ts))))) + ts))))) + (goto-char beg) + ;; First look for timestamps within headline. + (let ((ts (funcall find-ts (line-end-position) nil))) + (if (= (length ts) 2) (setq props (nconc ts props)) + ;; Then find timestamps in the section, skipping + ;; planning line. + (let ((end (save-excursion (outline-next-heading)))) + (forward-line) + (when (looking-at-p org-planning-line-re) (forward-line)) + (setq props (nconc (funcall find-ts end ts) props)))))))) + ;; Get the standard properties, like :PROP:. + (when (memq which '(nil all standard)) + ;; If we are looking after a specific property, delegate + ;; to `org-entry-get', which is faster. However, make an + ;; exception for "CATEGORY", since it can be also set + ;; through keywords (i.e. #+CATEGORY). + (if (and specific (not (equal specific "CATEGORY"))) + (let ((value (org-entry-get beg specific nil t))) + (throw 'exit (and value (list (cons specific value))))) + (let ((range (org-get-property-block beg))) + (when range + (let ((end (cdr range)) seen-base) + (goto-char (car range)) + ;; Unlike to `org--update-property-plist', we + ;; handle the case where base values is found + ;; after its extension. We also forbid standard + ;; properties to be named as special properties. + (while (re-search-forward org-property-re end t) + (let* ((key (upcase (match-string-no-properties 2))) + (extendp (string-match-p "\\+\\'" key)) + (key-base (if extendp (substring key 0 -1) key)) + (value (match-string-no-properties 3))) + (cond + ((member-ignore-case key-base org-special-properties)) + (extendp + (setq props + (org--update-property-plist key value props))) + ((member key seen-base)) + (t (push key seen-base) + (let ((p (assoc-string key props t))) + (if p (setcdr p (concat value " " (cdr p))) + (push (cons key value) props)))))))))))) + (unless (assoc "CATEGORY" props) + (push (cons "CATEGORY" (org-get-category beg)) props) + (when (string= specific "CATEGORY") (throw 'exit props))) + ;; Return value. + props))))) + +(defun org--property-local-values (property literal-nil) + "Return value for PROPERTY in current entry. +Value is a list whose car is the base value for PROPERTY and cdr +a list of accumulated values. Return nil if neither is found in +the entry. Also return nil when PROPERTY is set to \"nil\", +unless LITERAL-NIL is non-nil." + (let ((range (org-get-property-block))) + (when range + (goto-char (car range)) + (let* ((case-fold-search t) + (end (cdr range)) + (value + ;; Base value. + (save-excursion + (let ((v (and (re-search-forward + (org-re-property property nil t) end t) + (match-string-no-properties 3)))) + (list (if literal-nil v (org-not-nil v))))))) + ;; Find additional values. + (let* ((property+ (org-re-property (concat property "+") nil t))) + (while (re-search-forward property+ end t) + (push (match-string-no-properties 3) value))) + ;; Return final values. + (and (not (equal value '(nil))) (nreverse value)))))) + +(defun org--property-global-value (property literal-nil) + "Return value for PROPERTY in current buffer. +Return value is a string. Return nil if property is not set +globally. Also return nil when PROPERTY is set to \"nil\", +unless LITERAL-NIL is non-nil." + (let ((global + (cdr (or (assoc-string property org-file-properties t) + (assoc-string property org-global-properties t) + (assoc-string property org-global-properties-fixed t))))) + (if literal-nil global (org-not-nil global)))) (defun org-entry-get (pom property &optional inherit literal-nil) "Get value of PROPERTY for entry or content at point-or-marker POM. -If INHERIT is non-nil and the entry does not have the property, -then also check higher levels of the hierarchy. -If INHERIT is the symbol `selective', use inheritance only if the setting -in `org-use-property-inheritance' selects PROPERTY for inheritance. -If the property is present but empty, the return value is the empty string. -If the property is not present at all, nil is returned. - -Return the value as a string. -If LITERAL-NIL is set, return the string value \"nil\" as a string, -do not interpret it as the list atom nil. This is used for inheritance -when a \"nil\" value can supersede a non-nil value higher up the hierarchy." +If INHERIT is non-nil and the entry does not have the property, +then also check higher levels of the hierarchy. If INHERIT is +the symbol `selective', use inheritance only if the setting in +`org-use-property-inheritance' selects PROPERTY for inheritance. + +If the property is present but empty, the return value is the +empty string. If the property is not present at all, nil is +returned. In any other case, return the value as a string. +Search is case-insensitive. + +If LITERAL-NIL is set, return the string value \"nil\" as +a string, do not interpret it as the list atom nil. This is used +for inheritance when a \"nil\" value can supersede a non-nil +value higher up the hierarchy." (org-with-point-at pom - (if (and inherit (if (eq inherit 'selective) - (org-property-inherit-p property) - t)) - (org-entry-get-with-inheritance property literal-nil) - (if (member property org-special-properties) - ;; We need a special property. Use `org-entry-properties' - ;; to retrieve it, but specify the wanted property - (cdr (assoc property (org-entry-properties nil 'special property))) - (org-with-wide-buffer - (let ((range (org-get-property-block))) - (when (and range (not (eq (car range) (cdr range))) - (save-excursion - (goto-char (car range)) - (re-search-forward - (concat (org-re-property property) "\\|" - (org-re-property (concat property "+"))) - (cdr range) t))) - (let* ((props - (list (or (assoc property org-file-properties) - (assoc property org-global-properties) - (assoc property org-global-properties-fixed)))) - (ap (lambda (key) - (when (re-search-forward - (org-re-property key) (cdr range) t) - (setq props - (org-update-property-plist - key - (if (match-end 3) - (org-match-string-no-properties 3) "") - props))))) - val) - (goto-char (car range)) - (funcall ap property) - (goto-char (car range)) - (while (funcall ap (concat property "+"))) - (setq val (cdr (assoc property props))) - (when val (if literal-nil val (org-not-nil val))))))))))) + (cond + ((member-ignore-case property (cons "CATEGORY" org-special-properties)) + ;; We need a special property. Use `org-entry-properties' to + ;; retrieve it, but specify the wanted property. + (cdr (assoc-string property (org-entry-properties nil property)))) + ((and inherit + (or (not (eq inherit 'selective)) (org-property-inherit-p property))) + (org-entry-get-with-inheritance property literal-nil)) + (t + (let* ((local (org--property-local-values property literal-nil)) + (value (and local (mapconcat #'identity (delq nil local) " ")))) + (if literal-nil value (org-not-nil value))))))) (defun org-property-or-variable-value (var &optional inherit) "Check if there is a property fixing the value of VAR. @@ -15430,26 +16012,26 @@ If yes, return this value. If not, return the current value of the variable." (read prop) (symbol-value var)))) -(defun org-entry-delete (pom property &optional delete-empty-drawer) - "Delete the property PROPERTY from entry at point-or-marker POM. -When optional argument DELETE-EMPTY-DRAWER is a string, it defines -an empty drawer to delete." +(defun org-entry-delete (pom property) + "Delete PROPERTY from entry at point-or-marker POM. +Accumulated properties, i.e. PROPERTY+, are also removed. Return +non-nil when a property was removed." (org-with-point-at pom - (if (member property org-special-properties) - nil ; cannot delete these properties. - (let ((range (org-get-property-block))) - (if (and range - (goto-char (car range)) - (re-search-forward - (org-re-property property nil t) - (cdr range) t)) - (progn - (delete-region (match-beginning 0) (1+ (point-at-eol))) - (and delete-empty-drawer - (org-remove-empty-drawer-at - delete-empty-drawer (car range))) - t) - nil))))) + (pcase (org-get-property-block) + (`(,begin . ,origin) + (let* ((end (copy-marker origin)) + (re (org-re-property + (concat (regexp-quote property) "\\+?") t t))) + (goto-char begin) + (while (re-search-forward re end t) + (delete-region (match-beginning 0) (line-beginning-position 2))) + ;; If drawer is empty, remove it altogether. + (when (= begin end) + (delete-region (line-beginning-position 0) + (line-beginning-position 2))) + ;; Return non-nil if some property was removed. + (prog1 (/= end origin) (set-marker end nil)))) + (_ nil)))) ;; Multi-values properties are properties that contain multiple values ;; These values are assumed to be single words, separated by whitespace. @@ -15526,24 +16108,29 @@ If the value found is \"nil\", return nil to show that the property should be considered as undefined (this is the meaning of nil here). However, if LITERAL-NIL is set, return the string value \"nil\" instead." (move-marker org-entry-property-inherited-from nil) - (let (tmp) - (save-excursion - (save-restriction - (widen) - (catch 'ex - (while t - (when (setq tmp (org-entry-get nil property nil literal-nil)) - (or (ignore-errors (org-back-to-heading t)) - (goto-char (point-min))) - (move-marker org-entry-property-inherited-from (point)) - (throw 'ex tmp)) - (or (ignore-errors (org-up-heading-safe)) - (throw 'ex nil)))))) - (setq tmp (or tmp - (cdr (assoc property org-file-properties)) - (cdr (assoc property org-global-properties)) - (cdr (assoc property org-global-properties-fixed)))) - (if literal-nil tmp (org-not-nil tmp)))) + (org-with-wide-buffer + (let (value) + (catch 'exit + (while t + (let ((v (org--property-local-values property literal-nil))) + (when v + (setq value + (concat (mapconcat #'identity (delq nil v) " ") + (and value " ") + value))) + (cond + ((car v) + (org-back-to-heading t) + (move-marker org-entry-property-inherited-from (point)) + (throw 'exit nil)) + ((org-up-heading-safe)) + (t + (let ((global (org--property-global-value property literal-nil))) + (cond ((not global)) + (value (setq value (concat global " " value))) + (t (setq value global)))) + (throw 'exit nil)))))) + (if literal-nil value (org-not-nil value))))) (defvar org-property-changed-functions nil "Hook called when the value of a property has changed. @@ -15552,177 +16139,188 @@ and the new value.") (defun org-entry-put (pom property value) "Set PROPERTY to VALUE for entry at point-or-marker POM. -If the value is nil, it is converted to the empty string. -If it is not a string, an error is raised." + +If the value is nil, it is converted to the empty string. If it +is not a string, an error is raised. Also raise an error on +invalid property names. + +PROPERTY can be any regular property (see +`org-special-properties'). It can also be \"TODO\", +\"PRIORITY\", \"SCHEDULED\" and \"DEADLINE\". + +For the last two properties, VALUE may have any of the special +values \"earlier\" and \"later\". The function then increases or +decreases scheduled or deadline date by one day." (cond ((null value) (setq value "")) - ((not (stringp value)) - (error "Properties values should be strings."))) + ((not (stringp value)) (error "Properties values should be strings")) + ((not (org--valid-property-p property)) + (user-error "Invalid property name: \"%s\"" property))) (org-with-point-at pom - (org-back-to-heading t) - (let ((beg (point)) (end (save-excursion (outline-next-heading) (point))) - range) + (if (or (not (featurep 'org-inlinetask)) (org-inlinetask-in-task-p)) + (org-back-to-heading t) + (org-with-limited-levels (org-back-to-heading t))) + (let ((beg (point))) (cond ((equal property "TODO") - (when (and (string-match "\\S-" value) - (not (member value org-todo-keywords-1))) - (user-error "\"%s\" is not a valid TODO state" value)) - (if (or (not value) - (not (string-match "\\S-" value))) - (setq value 'none)) + (cond ((not (org-string-nw-p value)) (setq value 'none)) + ((not (member value org-todo-keywords-1)) + (user-error "\"%s\" is not a valid TODO state" value))) (org-todo value) (org-set-tags nil 'align)) ((equal property "PRIORITY") - (org-priority (if (and value (string-match "\\S-" value)) - (string-to-char value) ?\ )) + (org-priority (if (org-string-nw-p value) (string-to-char value) ?\s)) (org-set-tags nil 'align)) - ((equal property "CLOCKSUM") - (if (not (re-search-forward - (concat org-clock-string ".*\\]--\\(\\[[^]]+\\]\\)") nil t)) - (error "Cannot find a clock log") - (goto-char (- (match-end 1) 2)) - (cond - ((eq value 'earlier) (org-timestamp-down)) - ((eq value 'later) (org-timestamp-up))) - (org-clock-sum-current-item))) ((equal property "SCHEDULED") - (if (re-search-forward org-scheduled-time-regexp end t) - (cond - ((eq value 'earlier) (org-timestamp-change -1 'day)) - ((eq value 'later) (org-timestamp-change 1 'day)) - (t (call-interactively 'org-schedule))) - (call-interactively 'org-schedule))) + (forward-line) + (if (and (looking-at-p org-planning-line-re) + (re-search-forward + org-scheduled-time-regexp (line-end-position) t)) + (cond ((string= value "earlier") (org-timestamp-change -1 'day)) + ((string= value "later") (org-timestamp-change 1 'day)) + ((string= value "") (org-schedule '(4))) + (t (org-schedule nil value))) + (if (member value '("earlier" "later" "")) + (call-interactively #'org-schedule) + (org-schedule nil value)))) ((equal property "DEADLINE") - (if (re-search-forward org-deadline-time-regexp end t) - (cond - ((eq value 'earlier) (org-timestamp-change -1 'day)) - ((eq value 'later) (org-timestamp-change 1 'day)) - (t (call-interactively 'org-deadline))) - (call-interactively 'org-deadline))) + (forward-line) + (if (and (looking-at-p org-planning-line-re) + (re-search-forward + org-deadline-time-regexp (line-end-position) t)) + (cond ((string= value "earlier") (org-timestamp-change -1 'day)) + ((string= value "later") (org-timestamp-change 1 'day)) + ((string= value "") (org-deadline '(4))) + (t (org-deadline nil value))) + (if (member value '("earlier" "later" "")) + (call-interactively #'org-deadline) + (org-deadline nil value)))) ((member property org-special-properties) - (error "The %s property can not yet be set with `org-entry-put'" - property)) - (t ; a non-special property - (let ((buffer-invisibility-spec (org-inhibit-invisibility))) ; Emacs 21 - (setq range (org-get-property-block beg end 'force)) + (error "The %s property cannot be set with `org-entry-put'" property)) + (t + (let* ((range (org-get-property-block beg 'force)) + (end (cdr range)) + (case-fold-search t)) (goto-char (car range)) - (if (re-search-forward - (org-re-property property nil t) (cdr range) t) - (progn - (delete-region (match-beginning 0) (match-end 0)) - (goto-char (match-beginning 0))) - (goto-char (cdr range)) + (if (re-search-forward (org-re-property property nil t) end t) + (progn (delete-region (match-beginning 0) (match-end 0)) + (goto-char (match-beginning 0))) + (goto-char end) (insert "\n") - (backward-char 1) - (org-indent-line)) + (backward-char)) (insert ":" property ":") - (and value (insert " " value)) + (when value (insert " " value)) (org-indent-line))))) (run-hook-with-args 'org-property-changed-functions property value))) -(defun org-buffer-property-keys (&optional include-specials include-defaults include-columns) +(defun org-buffer-property-keys + (&optional specials defaults columns ignore-malformed) "Get all property keys in the current buffer. -With INCLUDE-SPECIALS, also list the special properties that reflect things -like tags and TODO state. -With INCLUDE-DEFAULTS, also include properties that has special meaning -internally: ARCHIVE, CATEGORY, SUMMARY, DESCRIPTION, LOCATION, and LOGGING -and others. -With INCLUDE-COLUMNS, also include property names given in COLUMN -formats in the current buffer." - (let (rtn range cfmt s p) - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (while (re-search-forward org-property-start-re nil t) - (setq range (org-get-property-block)) - (goto-char (car range)) - (while (re-search-forward org-property-re - (cdr range) t) - (add-to-list 'rtn (org-match-string-no-properties 2))) - (outline-next-heading)))) - (when include-specials - (setq rtn (append org-special-properties rtn))) +When SPECIALS is non-nil, also list the special properties that +reflect things like tags and TODO state. - (when include-defaults - (mapc (lambda (x) (add-to-list 'rtn x)) org-default-properties) - (add-to-list 'rtn org-effort-property)) +When DEFAULTS is non-nil, also include properties that has +special meaning internally: ARCHIVE, CATEGORY, SUMMARY, +DESCRIPTION, LOCATION, and LOGGING and others. - (when include-columns - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (while (re-search-forward - "^\\(#\\+COLUMNS:\\|[ \t]*:COLUMNS:\\)[ \t]*\\(.*\\)" - nil t) - (setq cfmt (match-string 2) s 0) - (while (string-match (org-re "%[0-9]*\\([-[:alnum:]_]+\\)") - cfmt s) - (setq s (match-end 0) - p (match-string 1 cfmt)) - (unless (or (equal p "ITEM") - (member p org-special-properties)) - (add-to-list 'rtn (match-string 1 cfmt)))))))) - - (sort rtn (lambda (a b) (string< (upcase a) (upcase b)))))) +When COLUMNS in non-nil, also include property names given in +COLUMN formats in the current buffer. + +When IGNORE-MALFORMED is non-nil, malformed drawer repair will not be +automatically performed, such drawers will be silently ignored." + (let ((case-fold-search t) + (props (append + (and specials org-special-properties) + (and defaults (cons org-effort-property org-default-properties)) + nil))) + (org-with-wide-buffer + (goto-char (point-min)) + (while (re-search-forward org-property-start-re nil t) + (let ((range (org-get-property-block))) + (catch 'skip + (unless range + (when (and (not ignore-malformed) + (not (org-before-first-heading-p)) + (y-or-n-p (format "Malformed drawer at %d, repair?" + (line-beginning-position)))) + (org-get-property-block nil t)) + (throw 'skip nil)) + (goto-char (car range)) + (let ((begin (car range)) + (end (cdr range))) + ;; Make sure that found property block is not located + ;; before current point, as it would generate an infloop. + ;; It can happen, for example, in the following + ;; situation: + ;; + ;; * Headline + ;; :PROPERTIES: + ;; ... + ;; :END: + ;; *************** Inlinetask + ;; #+BEGIN_EXAMPLE + ;; :PROPERTIES: + ;; #+END_EXAMPLE + ;; + (if (< begin (point)) (throw 'skip nil) (goto-char begin)) + (while (< (point) end) + (let ((p (progn (looking-at org-property-re) + (match-string-no-properties 2)))) + ;; Only add true property name, not extension symbol. + (push (if (not (string-match-p "\\+\\'" p)) p + (substring p 0 -1)) + props)) + (forward-line)))) + (outline-next-heading))) + (when columns + (goto-char (point-min)) + (while (re-search-forward "^[ \t]*\\(?:#\\+\\|:\\)COLUMNS:" nil t) + (let ((element (org-element-at-point))) + (when (memq (org-element-type element) '(keyword node-property)) + (let ((value (org-element-property :value element)) + (start 0)) + (while (string-match "%[0-9]*\\(\\S-+\\)" value start) + (setq start (match-end 0)) + (let ((p (match-string-no-properties 1 value))) + (unless (member-ignore-case p org-special-properties) + (push p props)))))))))) + (sort (delete-dups props) (lambda (a b) (string< (upcase a) (upcase b)))))) (defun org-property-values (key) - "Return a list of all values of property KEY in the current buffer." - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (let ((re (org-re-property key)) - values) - (while (re-search-forward re nil t) - (add-to-list 'values (org-trim (match-string 3)))) - (delete "" values))))) + "List all non-nil values of property KEY in current buffer." + (org-with-wide-buffer + (goto-char (point-min)) + (let ((case-fold-search t) + (re (org-re-property key)) + values) + (while (re-search-forward re nil t) + (push (org-entry-get (point) key) values)) + (delete-dups values)))) (defun org-insert-property-drawer () "Insert a property drawer into the current entry." - (org-back-to-heading t) - (looking-at org-outline-regexp) - (let ((indent (if org-adapt-indentation - (- (match-end 0) (match-beginning 0)) - 0)) - (beg (point)) - (re (concat "^[ \t]*" org-keyword-time-regexp)) - end hiddenp) - (outline-next-heading) - (setq end (point)) - (goto-char beg) - (while (re-search-forward re end t)) - (setq hiddenp (outline-invisible-p)) - (end-of-line 1) - (and (equal (char-after) ?\n) (forward-char 1)) - (while (looking-at "^[ \t]*\\(:CLOCK:\\|:LOGBOOK:\\|CLOCK:\\|:END:\\)") - (if (member (match-string 1) '("CLOCK:" ":END:")) - ;; just skip this line - (beginning-of-line 2) - ;; Drawer start, find the end - (re-search-forward "^\\*+ \\|^[ \t]*:END:" nil t) - (beginning-of-line 1))) - (org-skip-over-state-notes) - (skip-chars-backward " \t\n\r") - (if (and (eq (char-before) ?*) (not (eq (char-after) ?\n))) - (forward-char 1)) - (goto-char (point-at-eol)) - (let ((inhibit-read-only t)) (insert "\n:PROPERTIES:\n:END:")) - (beginning-of-line 0) - (org-indent-to-column indent) - (beginning-of-line 2) - (org-indent-to-column indent) - (beginning-of-line 0) - (if hiddenp - (save-excursion - (org-back-to-heading t) - (hide-entry)) - (org-flag-drawer t)))) + (org-with-wide-buffer + (if (or (not (featurep 'org-inlinetask)) (org-inlinetask-in-task-p)) + (org-back-to-heading t) + (org-with-limited-levels (org-back-to-heading t))) + (forward-line) + (when (looking-at-p org-planning-line-re) (forward-line)) + (unless (looking-at-p org-property-drawer-re) + ;; Make sure we start editing a line from current entry, not from + ;; next one. It prevents extending text properties or overlays + ;; belonging to the latter. + (when (bolp) (backward-char)) + (let ((begin (1+ (point))) + (inhibit-read-only t)) + (insert "\n:PROPERTIES:\n:END:") + (when (eobp) (insert "\n")) + (org-indent-region begin (point)))))) (defun org-insert-drawer (&optional arg drawer) "Insert a drawer at point. +When optional argument ARG is non-nil, insert a property drawer. + Optional argument DRAWER, when non-nil, is a string representing drawer's name. Otherwise, the user is prompted for a name. @@ -15731,23 +16329,14 @@ instead. Point is left between drawer's boundaries." (interactive "P") - (let* ((logbook (if (stringp org-log-into-drawer) org-log-into-drawer - "LOGBOOK")) - ;; SYSTEM-DRAWERS is a list of drawer names that are used - ;; internally by Org. They are meant to be inserted - ;; automatically. - (system-drawers `("CLOCK" ,logbook "PROPERTIES")) - ;; Remove system drawers from list. Note: For some reason, - ;; `org-completing-read' ignores the predicate while - ;; `completing-read' handles it fine. - (drawer (if arg "PROPERTIES" - (or drawer - (completing-read - "Drawer: " org-drawers - (lambda (d) (not (member d system-drawers)))))))) + (let* ((drawer (if arg "PROPERTIES" + (or drawer (read-from-minibuffer "Drawer: "))))) (cond ;; With C-u, fall back on `org-insert-property-drawer' (arg (org-insert-property-drawer)) + ;; Check validity of suggested drawer's name. + ((not (string-match-p org-drawer-regexp (format ":%s:" drawer))) + (user-error "Invalid drawer name")) ;; With an active region, insert a drawer at point. ((not (org-region-active-p)) (progn @@ -15813,38 +16402,25 @@ This is computed according to `org-property-set-functions-alist'." (funcall set-function prompt allowed nil (not (get-text-property 0 'org-unrestricted (caar allowed)))) - (let (org-completion-use-ido org-completion-use-iswitchb) - (funcall set-function prompt - (mapcar 'list (org-property-values property)) - nil nil "" nil cur))))) + (funcall set-function prompt + (mapcar 'list (org-property-values property)) + nil nil "" nil cur)))) (org-trim val))) (defvar org-last-set-property nil) (defvar org-last-set-property-value nil) (defun org-read-property-name () "Read a property name." - (let* ((completion-ignore-case t) - (keys (org-buffer-property-keys nil t t)) - (default-prop (or (save-excursion - (save-match-data - (beginning-of-line) - (and (looking-at "^\\s-*:\\([^:\n]+\\):") - (null (string= (match-string 1) "END")) - (match-string 1)))) - org-last-set-property)) - (property (org-icompleting-read - (concat "Property" - (if default-prop (concat " [" default-prop "]") "") - ": ") - (mapcar 'list keys) - nil nil nil nil - default-prop))) - (if (member property keys) - property - (or (cdr (assoc (downcase property) - (mapcar (lambda (x) (cons (downcase x) x)) - keys))) - property)))) + (let ((completion-ignore-case t) + (default-prop (or (and (org-at-property-p) + (match-string-no-properties 2)) + org-last-set-property))) + (org-completing-read + (concat "Property" + (if default-prop (concat " [" default-prop "]") "") + ": ") + (mapcar #'list (org-buffer-property-keys nil t t)) + nil nil nil nil default-prop))) (defun org-set-property-and-value (use-last) "Allow to set [PROPERTY]: [value] direction from prompt. @@ -15865,26 +16441,52 @@ When use-default, don't even ask, just use the last (defun org-set-property (property value) "In the current entry, set PROPERTY to VALUE. + When called interactively, this will prompt for a property name, offering completion on existing and default properties. And then it will prompt for a value, offering completion either on allowed values (via an inherited xxx_ALL property) or on existing values in other instances of this property -in the current file." +in the current file. + +Throw an error when trying to set a property with an invalid name." (interactive (list nil nil)) - (let* ((property (or property (org-read-property-name))) - (value (or value (org-read-property-value property))) - (fn (cdr (assoc property org-properties-postprocess-alist)))) - (setq org-last-set-property property) - (setq org-last-set-property-value (concat property ": " value)) - ;; Possibly postprocess the inserted value: - (when fn (setq value (funcall fn value))) - (unless (equal (org-entry-get nil property) value) - (org-entry-put nil property value)))) - -(defun org-delete-property (property &optional delete-empty-drawer) - "In the current entry, delete PROPERTY. -When optional argument DELETE-EMPTY-DRAWER is a string, it defines -an empty drawer to delete." + (let ((property (or property (org-read-property-name)))) + ;; `org-entry-put' also makes the following check, but this one + ;; avoids polluting `org-last-set-property' and + ;; `org-last-set-property-value' needlessly. + (unless (org--valid-property-p property) + (user-error "Invalid property name: \"%s\"" property)) + (let ((value (or value (org-read-property-value property))) + (fn (cdr (assoc-string property org-properties-postprocess-alist t)))) + (setq org-last-set-property property) + (setq org-last-set-property-value (concat property ": " value)) + ;; Possibly postprocess the inserted value: + (when fn (setq value (funcall fn value))) + (unless (equal (org-entry-get nil property) value) + (org-entry-put nil property value))))) + +(defun org-find-property (property &optional value) + "Find first entry in buffer that sets PROPERTY. + +When optional argument VALUE is non-nil, only consider an entry +if it contains PROPERTY set to this value. If PROPERTY should be +explicitly set to nil, use string \"nil\" for VALUE. + +Return position where the entry begins, or nil if there is no +such entry. If narrowing is in effect, only search the visible +part of the buffer." + (save-excursion + (goto-char (point-min)) + (let ((case-fold-search t) + (re (org-re-property property nil (not value) value))) + (catch 'exit + (while (re-search-forward re nil t) + (when (if value (org-at-property-p) + (org-entry-get (point) property nil t)) + (throw 'exit (progn (org-back-to-heading t) (point))))))))) + +(defun org-delete-property (property) + "In the current entry, delete PROPERTY." (interactive (let* ((completion-ignore-case t) (cat (org-entry-get (point) "CATEGORY")) @@ -15892,33 +16494,30 @@ an empty drawer to delete." (props (if cat props0 (delete `("CATEGORY" . ,(org-get-category)) props0))) (prop (if (< 1 (length props)) - (org-icompleting-read "Property: " props nil t) + (completing-read "Property: " props nil t) (caar props)))) (list prop))) (if (not property) (message "No property to delete in this entry") - (org-entry-delete nil property delete-empty-drawer) + (org-entry-delete nil property) (message "Property \"%s\" deleted" property))) (defun org-delete-property-globally (property) - "Remove PROPERTY globally, from all entries." + "Remove PROPERTY globally, from all entries. +This function ignores narrowing, if any." (interactive (let* ((completion-ignore-case t) - (prop (org-icompleting-read + (prop (completing-read "Globally remove property: " - (mapcar 'list (org-buffer-property-keys))))) + (mapcar #'list (org-buffer-property-keys))))) (list prop))) - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (let ((cnt 0)) - (while (re-search-forward - (org-re-property property) - nil t) - (setq cnt (1+ cnt)) - (delete-region (match-beginning 0) (1+ (point-at-eol)))) - (message "Property \"%s\" removed from %d entries" property cnt))))) + (org-with-wide-buffer + (goto-char (point-min)) + (let ((count 0) + (re (org-re-property (concat (regexp-quote property) "\\+?") t t))) + (while (re-search-forward re nil t) + (when (org-entry-delete (point) property) (cl-incf count))) + (message "Property \"%s\" removed from %d entries" property count)))) (defvar org-columns-current-fmt-compiled) ; defined in org-colview.el @@ -15929,9 +16528,9 @@ then applies it to the property in the column format's scope." (interactive) (unless (org-at-property-p) (user-error "Not at a property")) - (let ((prop (org-match-string-no-properties 2))) + (let ((prop (match-string-no-properties 2))) (org-columns-get-format-and-top-level) - (unless (nth 3 (assoc prop org-columns-current-fmt-compiled)) + (unless (nth 3 (assoc-string prop org-columns-current-fmt-compiled t)) (user-error "No operator defined for property %s" prop)) (org-columns-compute prop))) @@ -15958,6 +16557,7 @@ completion." (while (>= n org-highest-priority) (push (char-to-string n) vals) (setq n (1- n))))) + ((equal property "CATEGORY")) ((member property org-special-properties)) ((setq vals (run-hook-with-args-until-success 'org-property-allowed-value-functions property))) @@ -15976,7 +16576,7 @@ completion." (org-add-props (car vals) '(org-unrestricted t))) (if table (mapcar 'list vals) vals))) -(defun org-property-previous-allowed-value (&optional previous) +(defun org-property-previous-allowed-value (&optional _previous) "Switch to the next allowed value for this property." (interactive) (org-property-next-allowed-value t)) @@ -15996,21 +16596,22 @@ completion." nval) (unless allowed (user-error "Allowed values for this property have not been defined")) - (if previous (setq allowed (reverse allowed))) - (if (member value allowed) - (setq nval (car (cdr (member value allowed))))) + (when previous (setq allowed (reverse allowed))) + (when (member value allowed) + (setq nval (car (cdr (member value allowed))))) (setq nval (or nval (car allowed))) - (if (equal nval value) - (user-error "Only one allowed value for this property")) + (when (equal nval value) + (user-error "Only one allowed value for this property")) (org-at-property-p) (replace-match (concat " :" key ": " nval) t t) (org-indent-line) (beginning-of-line 1) (skip-chars-forward " \t") (when (equal prop org-effort-property) - (save-excursion - (org-back-to-heading t) - (put-text-property (point-at-bol) (point-at-eol) 'org-effort nval)) + (org-refresh-property + '((effort . identity) + (effort-minutes . org-duration-string-to-minutes)) + nval) (when (string= org-clock-current-task heading) (setq org-clock-effort nval) (org-clock-update-mode-line))) @@ -16035,31 +16636,28 @@ only headings." (level 1) (lmin 1) (lmax 1) - limit re end found pos heading cnt flevel) + end found flevel) (unless buffer (error "File not found :%s" file)) (with-current-buffer buffer - (save-excursion - (save-restriction - (widen) - (setq limit (point-max)) - (goto-char (point-min)) - (dolist (heading path) - (setq re (format org-complex-heading-regexp-format - (regexp-quote heading))) - (setq cnt 0 pos (point)) - (while (re-search-forward re end t) - (setq level (- (match-end 1) (match-beginning 1))) - (if (and (>= level lmin) (<= level lmax)) - (setq found (match-beginning 0) flevel level cnt (1+ cnt)))) - (when (= cnt 0) (error "Heading not found on level %d: %s" - lmax heading)) - (when (> cnt 1) (error "Heading not unique on level %d: %s" - lmax heading)) - (goto-char found) - (setq lmin (1+ flevel) lmax (+ lmin (if org-odd-levels-only 1 0))) - (setq end (save-excursion (org-end-of-subtree t t)))) - (when (org-at-heading-p) - (point-marker))))))) + (org-with-wide-buffer + (goto-char (point-min)) + (dolist (heading path) + (let ((re (format org-complex-heading-regexp-format + (regexp-quote heading))) + (cnt 0)) + (while (re-search-forward re end t) + (setq level (- (match-end 1) (match-beginning 1))) + (when (and (>= level lmin) (<= level lmax)) + (setq found (match-beginning 0) flevel level cnt (1+ cnt)))) + (when (= cnt 0) + (error "Heading not found on level %d: %s" lmax heading)) + (when (> cnt 1) + (error "Heading not unique on level %d: %s" lmax heading)) + (goto-char found) + (setq lmin (1+ flevel) lmax (+ lmin (if org-odd-levels-only 1 0))) + (setq end (save-excursion (org-end-of-subtree t t))))) + (when (org-at-heading-p) + (point-marker)))))) (defun org-find-exact-headline-in-buffer (heading &optional buffer pos-only) "Find node HEADING in BUFFER. @@ -16069,24 +16667,22 @@ If POS-ONLY is set, return just the position instead of a marker. The heading text must match exact, but it may have a TODO keyword, a priority cookie and tags in the standard locations." (with-current-buffer (or buffer (current-buffer)) - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (let (case-fold-search) - (if (re-search-forward - (format org-complex-heading-regexp-format - (regexp-quote heading)) nil t) - (if pos-only - (match-beginning 0) - (move-marker (make-marker) (match-beginning 0))))))))) + (org-with-wide-buffer + (goto-char (point-min)) + (let (case-fold-search) + (when (re-search-forward + (format org-complex-heading-regexp-format + (regexp-quote heading)) nil t) + (if pos-only + (match-beginning 0) + (move-marker (make-marker) (match-beginning 0)))))))) (defun org-find-exact-heading-in-directory (heading &optional dir) "Find Org node headline HEADING in all .org files in directory DIR. When the target headline is found, return a marker to this location." (let ((files (directory-files (or dir default-directory) - nil "\\`[^.#].*\\.org\\'")) - file visiting m buffer) + t "\\`[^.#].*\\.org\\'")) + visiting m buffer) (catch 'found (dolist (file files) (message "trying %s" file) @@ -16105,19 +16701,10 @@ Return the position where this entry starts, or nil if there is no such entry." (interactive "sID: ") (let ((id (cond ((stringp ident) ident) - ((symbol-name ident) (symbol-name ident)) + ((symbolp ident) (symbol-name ident)) ((numberp ident) (number-to-string ident)) - (t (error "IDENT %s must be a string, symbol or number" ident)))) - (case-fold-search nil)) - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (when (re-search-forward - (concat "^[ \t]*:ID:[ \t]+" (regexp-quote id) "[ \t]*$") - nil t) - (org-back-to-heading t) - (point)))))) + (t (error "IDENT %s must be a string, symbol or number" ident))))) + (org-with-wide-buffer (org-find-property "ID" id)))) ;;;; Timestamps @@ -16128,17 +16715,16 @@ Return the position where this entry starts, or nil if there is no such entry." (defun org-time-stamp (arg &optional inactive) "Prompt for a date/time and insert a time stamp. + If the user specifies a time like HH:MM or if this command is called with at least one prefix argument, the time stamp contains -the date and the time. Otherwise, only the date is be included. +the date and the time. Otherwise, only the date is included. -All parts of a date not specified by the user is filled in from -the current date/time. So if you just press return without -typing anything, the time stamp will represent the current -date/time. +All parts of a date not specified by the user are filled in from +the timestamp at point, if any, or the current date/time +otherwise. -If there is already a timestamp at the cursor, it will be -modified. +If there is already a timestamp at the cursor, it is replaced. With two universal prefix arguments, insert an active timestamp with the current time without prompting the user. @@ -16146,57 +16732,56 @@ with the current time without prompting the user. When called from lisp, the timestamp is inactive if INACTIVE is non-nil." (interactive "P") - (let* ((ts nil) - (default-time - ;; Default time is either today, or, when entering a range, - ;; the range start. - (if (or (and (org-at-timestamp-p t) (setq ts (match-string 0))) - (save-excursion - (re-search-backward - (concat org-ts-regexp "--?-?\\=") ; 1-3 minuses - (- (point) 20) t))) - (apply 'encode-time (org-parse-time-string (match-string 1))) - (current-time))) - (default-input (and ts (org-get-compact-tod ts))) - (repeater (save-excursion - (save-match-data - (beginning-of-line) - (when (re-search-forward - "\\([.+-]+[0-9]+[hdwmy] ?\\)+" ;;\\(?:[/ ][-+]?[0-9]+[hdwmy]\\)?\\) ?" - (save-excursion (progn (end-of-line) (point))) t) - (match-string 0))))) - org-time-was-given org-end-time-was-given time) + (let* ((ts (cond + ((org-at-date-range-p t) + (match-string (if (< (point) (- (match-beginning 2) 2)) 1 2))) + ((org-at-timestamp-p t) (match-string 0)))) + ;; Default time is either the timestamp at point or today. + ;; When entering a range, only the range start is considered. + (default-time (if (not ts) (current-time) + (apply #'encode-time (org-parse-time-string ts)))) + (default-input (and ts (org-get-compact-tod ts))) + (repeater (and ts + (string-match "\\([.+-]+[0-9]+[hdwmy] ?\\)+" ts) + (match-string 0 ts))) + org-time-was-given + org-end-time-was-given + (time + (and (if (equal arg '(16)) (current-time) + ;; Preserve `this-command' and `last-command'. + (let ((this-command this-command) + (last-command last-command)) + (org-read-date + arg 'totime nil nil default-time default-input + inactive)))))) (cond - ((and (org-at-timestamp-p t) - (memq last-command '(org-time-stamp org-time-stamp-inactive)) - (memq this-command '(org-time-stamp org-time-stamp-inactive))) + ((and ts + (memq last-command '(org-time-stamp org-time-stamp-inactive)) + (memq this-command '(org-time-stamp org-time-stamp-inactive))) (insert "--") - (setq time (let ((this-command this-command)) - (org-read-date arg 'totime nil nil - default-time default-input inactive))) (org-insert-time-stamp time (or org-time-was-given arg) inactive)) - ((org-at-timestamp-p t) - (setq time (let ((this-command this-command)) - (org-read-date arg 'totime nil nil default-time default-input inactive))) - (when (org-at-timestamp-p t) ; just to get the match data - ; (setq inactive (eq (char-after (match-beginning 0)) ?\[)) - (replace-match "") + (ts + ;; Make sure we're on a timestamp. When in the middle of a date + ;; range, move arbitrarily to range end. + (unless (org-at-timestamp-p t) + (skip-chars-forward "-") + (org-at-timestamp-p t)) + (replace-match "") + (setq org-last-changed-timestamp + (org-insert-time-stamp + time (or org-time-was-given arg) + inactive nil nil (list org-end-time-was-given))) + (when repeater + (backward-char) + (insert " " repeater) (setq org-last-changed-timestamp - (org-insert-time-stamp - time (or org-time-was-given arg) - inactive nil nil (list org-end-time-was-given))) - (when repeater (goto-char (1- (point))) (insert " " repeater) - (setq org-last-changed-timestamp - (concat (substring org-last-inserted-timestamp 0 -1) - " " repeater ">")))) + (concat (substring org-last-inserted-timestamp 0 -1) + " " repeater ">"))) (message "Timestamp updated")) - ((equal arg '(16)) - (org-insert-time-stamp (current-time) t inactive)) - (t - (setq time (let ((this-command this-command)) - (org-read-date arg 'totime nil nil default-time default-input inactive))) - (org-insert-time-stamp time (or org-time-was-given arg) inactive - nil nil (list org-end-time-was-given)))))) + ((equal arg '(16)) (org-insert-time-stamp time t inactive)) + (t (org-insert-time-stamp + time (or org-time-was-given arg) inactive nil nil + (list org-end-time-was-given)))))) ;; FIXME: can we use this for something else, like computing time differences? (defun org-get-compact-tod (s) @@ -16211,7 +16796,7 @@ non-nil." (if (not t2) t1 (setq dh (- h2 h1) dm (- m2 m1)) - (if (< dm 0) (setq dm (+ dm 60) dh (1- dh))) + (when (< dm 0) (setq dm (+ dm 60) dh (1- dh))) (concat t1 "+" (number-to-string dh) (and (/= 0 dm) (format ":%02d" dm))))))) @@ -16226,7 +16811,7 @@ So these are more for recording a certain time/date." (defvar org-date-ovl (make-overlay 1 1)) (overlay-put org-date-ovl 'face 'org-date-selected) -(org-detach-overlay org-date-ovl) +(delete-overlay org-date-ovl) (defvar org-ans1) ; dynamically scoped parameter (defvar org-ans2) ; dynamically scoped parameter @@ -16243,13 +16828,14 @@ So these are more for recording a certain time/date." (defvar org-read-date-inactive) (defvar org-read-date-minibuffer-local-map - (let* ((org-replace-disputed-keys nil) - (map (make-sparse-keymap))) + (let* ((map (make-sparse-keymap))) (set-keymap-parent map minibuffer-local-map) (org-defkey map (kbd ".") (lambda () (interactive) ;; Are we at the beginning of the prompt? - (if (looking-back "^[^:]+: ") + (if (looking-back "^[^:]+: " + (let ((inhibit-field-text-motion t)) + (line-beginning-position))) (org-eval-in-calendar '(calendar-goto-today)) (insert ".")))) (org-defkey map (kbd "C-.") @@ -16316,7 +16902,8 @@ So these are more for recording a certain time/date." (defvar org-defdecode) (defvar org-with-time) -(defun org-read-date (&optional org-with-time to-time from-string prompt +(defvar calendar-setup) ; Dynamically scoped. +(defun org-read-date (&optional with-time to-time from-string prompt default-time default-input inactive) "Read a date, possibly a time, and make things smooth for the user. The prompt will suggest to enter an ISO date, but you can also enter anything @@ -16360,8 +16947,8 @@ If you don't like the calendar, turn it off with With optional argument TO-TIME, the date will immediately be converted to an internal time. -With an optional argument ORG-WITH-TIME, the prompt will suggest to -also insert a time. Note that when ORG-WITH-TIME is not set, you can +With an optional argument WITH-TIME, the prompt will suggest to +also insert a time. Note that when WITH-TIME is not set, you can still enter a time, and this function will inform the calling routine about this change. The calling routine may then choose to change the format used to insert the time stamp into the buffer to include the time. @@ -16370,75 +16957,90 @@ the user. PROMPT can overwrite the default prompt. DEFAULT-TIME is the time/date that is used for everything that is not specified by the user." (require 'parse-time) - (let* ((org-time-stamp-rounding-minutes - (if (equal org-with-time '(16)) '(0 0) org-time-stamp-rounding-minutes)) + (let* ((org-with-time with-time) + (org-time-stamp-rounding-minutes + (if (equal org-with-time '(16)) + '(0 0) + org-time-stamp-rounding-minutes)) (org-dcst org-display-custom-times) (ct (org-current-time)) (org-def (or org-overriding-default-time default-time ct)) (org-defdecode (decode-time org-def)) - (dummy (progn - (when (< (nth 2 org-defdecode) org-extend-today-until) - (setcar (nthcdr 2 org-defdecode) -1) - (setcar (nthcdr 1 org-defdecode) 59) - (setq org-def (apply 'encode-time org-defdecode) - org-defdecode (decode-time org-def))))) - (mouse-autoselect-window nil) ; Don't let the mouse jump - (calendar-frame-setup nil) - (calendar-setup nil) + (cur-frame (selected-frame)) + (mouse-autoselect-window nil) ; Don't let the mouse jump + (calendar-setup + (and (eq calendar-setup 'calendar-only) 'calendar-only)) (calendar-move-hook nil) (calendar-view-diary-initially-flag nil) (calendar-view-holidays-initially-flag nil) - (timestr (format-time-string - (if org-with-time "%Y-%m-%d %H:%M" "%Y-%m-%d") org-def)) - (prompt (concat (if prompt (concat prompt " ") "") - (format "Date+time [%s]: " timestr))) - ans (org-ans0 "") org-ans1 org-ans2 final) - - (cond - (from-string (setq ans from-string)) - (org-read-date-popup-calendar - (save-excursion - (save-window-excursion - (calendar) - (org-eval-in-calendar '(setq cursor-type nil) t) - (unwind-protect - (progn - (calendar-forward-day (- (time-to-days org-def) - (calendar-absolute-from-gregorian - (calendar-current-date)))) - (org-eval-in-calendar nil t) - (let* ((old-map (current-local-map)) - (map (copy-keymap calendar-mode-map)) - (minibuffer-local-map - (copy-keymap org-read-date-minibuffer-local-map))) - (org-defkey map (kbd "RET") 'org-calendar-select) - (org-defkey map [mouse-1] 'org-calendar-select-mouse) - (org-defkey map [mouse-2] 'org-calendar-select-mouse) - (unwind-protect - (progn - (use-local-map map) - (setq org-read-date-inactive inactive) - (add-hook 'post-command-hook 'org-read-date-display) - (setq org-ans0 (read-string prompt default-input - 'org-read-date-history nil)) - ;; org-ans0: from prompt - ;; org-ans1: from mouse click - ;; org-ans2: from calendar motion - (setq ans (concat org-ans0 " " (or org-ans1 org-ans2)))) - (remove-hook 'post-command-hook 'org-read-date-display) - (use-local-map old-map) - (when org-read-date-overlay - (delete-overlay org-read-date-overlay) - (setq org-read-date-overlay nil))))) - (bury-buffer "*Calendar*"))))) - - (t ; Naked prompt only - (unwind-protect - (setq ans (read-string prompt default-input - 'org-read-date-history timestr)) - (when org-read-date-overlay - (delete-overlay org-read-date-overlay) - (setq org-read-date-overlay nil))))) + ans (org-ans0 "") org-ans1 org-ans2 final cal-frame) + ;; Rationalize `org-def' and `org-defdecode', if required. + (when (< (nth 2 org-defdecode) org-extend-today-until) + (setf (nth 2 org-defdecode) -1) + (setf (nth 1 org-defdecode) 59) + (setq org-def (apply #'encode-time org-defdecode)) + (setq org-defdecode (decode-time org-def))) + (let* ((timestr (format-time-string + (if org-with-time "%Y-%m-%d %H:%M" "%Y-%m-%d") + org-def)) + (prompt (concat (if prompt (concat prompt " ") "") + (format "Date+time [%s]: " timestr)))) + (cond + (from-string (setq ans from-string)) + (org-read-date-popup-calendar + (save-excursion + (save-window-excursion + (calendar) + (when (eq calendar-setup 'calendar-only) + (setq cal-frame + (window-frame (get-buffer-window "*Calendar*" 'visible))) + (select-frame cal-frame)) + (org-eval-in-calendar '(setq cursor-type nil) t) + (unwind-protect + (progn + (calendar-forward-day (- (time-to-days org-def) + (calendar-absolute-from-gregorian + (calendar-current-date)))) + (org-eval-in-calendar nil t) + (let* ((old-map (current-local-map)) + (map (copy-keymap calendar-mode-map)) + (minibuffer-local-map + (copy-keymap org-read-date-minibuffer-local-map))) + (org-defkey map (kbd "RET") 'org-calendar-select) + (org-defkey map [mouse-1] 'org-calendar-select-mouse) + (org-defkey map [mouse-2] 'org-calendar-select-mouse) + (unwind-protect + (progn + (use-local-map map) + (setq org-read-date-inactive inactive) + (add-hook 'post-command-hook 'org-read-date-display) + (setq org-ans0 + (read-string prompt + default-input + 'org-read-date-history + nil)) + ;; org-ans0: from prompt + ;; org-ans1: from mouse click + ;; org-ans2: from calendar motion + (setq ans + (concat org-ans0 " " (or org-ans1 org-ans2)))) + (remove-hook 'post-command-hook 'org-read-date-display) + (use-local-map old-map) + (when org-read-date-overlay + (delete-overlay org-read-date-overlay) + (setq org-read-date-overlay nil))))) + (bury-buffer "*Calendar*") + (when cal-frame + (delete-frame cal-frame) + (select-frame-set-input-focus cur-frame)))))) + + (t ; Naked prompt only + (unwind-protect + (setq ans (read-string prompt default-input + 'org-read-date-history timestr)) + (when org-read-date-overlay + (delete-overlay org-read-date-overlay) + (setq org-read-date-overlay nil)))))) (setq final (org-read-date-analyze ans org-def org-defdecode)) @@ -16499,13 +17101,18 @@ user." (make-overlay (1- (point-at-eol)) (point-at-eol))) (org-overlay-display org-read-date-overlay txt 'secondary-selection))))) -(defun org-read-date-analyze (ans org-def org-defdecode) +(defun org-read-date-analyze (ans def defdecode) "Analyze the combined answer of the date prompt." ;; FIXME: cleanup and comment - (let ((nowdecode (decode-time)) + ;; Pass `current-time' result to `decode-time' (instead of calling + ;; without arguments) so that only `current-time' has to be + ;; overridden in tests. + (let ((org-def def) + (org-defdecode defdecode) + (nowdecode (decode-time (current-time))) delta deltan deltaw deltadef year month day hour minute second wday pm h2 m2 tl wday1 - iso-year iso-weekday iso-week iso-year iso-date futurep kill-year) + iso-year iso-weekday iso-week iso-date futurep kill-year) (setq org-read-date-analyze-futurep nil org-read-date-analyze-forced-year nil) (when (string-match "\\`[ \t]*\\.[ \t]*\\'" ans) @@ -16521,11 +17128,11 @@ user." ;; info and postpone interpreting it until the rest of the parsing ;; is done. (when (string-match "\\<\\(?:\\([0-9]+\\)-\\)?[wW]\\([0-9]\\{1,2\\}\\)\\(?:-\\([0-6]\\)\\)?\\([ \t]\\|$\\)" ans) - (setq iso-year (if (match-end 1) - (org-small-year-to-year - (string-to-number (match-string 1 ans)))) - iso-weekday (if (match-end 3) - (string-to-number (match-string 3 ans))) + (setq iso-year (when (match-end 1) + (org-small-year-to-year + (string-to-number (match-string 1 ans)))) + iso-weekday (when (match-end 3) + (string-to-number (match-string 3 ans))) iso-week (string-to-number (match-string 2 ans))) (setq ans (replace-match "" t t ans))) @@ -16538,7 +17145,7 @@ user." (string-to-number (format-time-string "%Y")))) month (string-to-number (match-string 3 ans)) day (string-to-number (match-string 4 ans))) - (if (< year 100) (setq year (+ 2000 year))) + (setq year (org-small-year-to-year year)) (setq ans (replace-match (format "%04d-%02d-%02d\\5" year month day) t nil ans))) @@ -16562,26 +17169,26 @@ user." (string-to-number (format-time-string "%Y")))) month (string-to-number (match-string 1 ans)) day (string-to-number (match-string 2 ans))) - (if (< year 100) (setq year (+ 2000 year))) + (setq year (org-small-year-to-year year)) (setq ans (replace-match (format "%04d-%02d-%02d\\5" year month day) t nil ans))) ;; Help matching am/pm times, because `parse-time-string' does not do that. ;; If there is a time with am/pm, and *no* time without it, we convert ;; so that matching will be successful. - (loop for i from 1 to 2 do ; twice, for end time as well - (when (and (not (string-match "\\(\\`\\|[^+]\\)[012]?[0-9]:[0-9][0-9]\\([ \t\n]\\|$\\)" ans)) - (string-match "\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?\\(am\\|AM\\|pm\\|PM\\)\\>" ans)) - (setq hour (string-to-number (match-string 1 ans)) - minute (if (match-end 3) - (string-to-number (match-string 3 ans)) - 0) - pm (equal ?p - (string-to-char (downcase (match-string 4 ans))))) - (if (and (= hour 12) (not pm)) - (setq hour 0) - (if (and pm (< hour 12)) (setq hour (+ 12 hour)))) - (setq ans (replace-match (format "%02d:%02d" hour minute) - t t ans)))) + (cl-loop for i from 1 to 2 do ; twice, for end time as well + (when (and (not (string-match "\\(\\`\\|[^+]\\)[012]?[0-9]:[0-9][0-9]\\([ \t\n]\\|$\\)" ans)) + (string-match "\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?\\(am\\|AM\\|pm\\|PM\\)\\>" ans)) + (setq hour (string-to-number (match-string 1 ans)) + minute (if (match-end 3) + (string-to-number (match-string 3 ans)) + 0) + pm (equal ?p + (string-to-char (downcase (match-string 4 ans))))) + (if (and (= hour 12) (not pm)) + (setq hour 0) + (when (and pm (< hour 12)) (setq hour (+ 12 hour)))) + (setq ans (replace-match (format "%02d:%02d" hour minute) + t t ans)))) ;; Check if a time range is given as a duration (when (string-match "\\([012]?[0-9]\\):\\([0-6][0-9]\\)\\+\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?" ans) @@ -16590,7 +17197,7 @@ user." minute (string-to-number (match-string 2 ans)) m2 (+ minute (if (match-end 5) (string-to-number (match-string 5 ans))0))) - (if (>= m2 60) (setq h2 (1+ h2) m2 (- m2 60))) + (when (>= m2 60) (setq h2 (1+ h2) m2 (- m2 60))) (setq ans (replace-match (format "%02d:%02d-%02d:%02d" hour minute h2 m2) t t ans))) @@ -16605,16 +17212,35 @@ user." (setq tl (parse-time-string ans) day (or (nth 3 tl) (nth 3 org-defdecode)) - month (or (nth 4 tl) - (if (and org-read-date-prefer-future - (nth 3 tl) (< (nth 3 tl) (nth 3 nowdecode))) - (prog1 (1+ (nth 4 nowdecode)) (setq futurep t)) - (nth 4 org-defdecode))) - year (or (and (not kill-year) (nth 5 tl)) - (if (and org-read-date-prefer-future - (nth 4 tl) (< (nth 4 tl) (nth 4 nowdecode))) - (prog1 (1+ (nth 5 nowdecode)) (setq futurep t)) - (nth 5 org-defdecode))) + month + (cond ((nth 4 tl)) + ((not org-read-date-prefer-future) (nth 4 org-defdecode)) + ;; Day was specified. Make sure DAY+MONTH + ;; combination happens in the future. + ((nth 3 tl) + (setq futurep t) + (if (< day (nth 3 nowdecode)) (1+ (nth 4 nowdecode)) + (nth 4 nowdecode))) + (t (nth 4 org-defdecode))) + year + (cond ((and (not kill-year) (nth 5 tl))) + ((not org-read-date-prefer-future) (nth 5 org-defdecode)) + ;; Month was guessed in the future and is at least + ;; equal to NOWDECODE's. Fix year accordingly. + (futurep + (if (or (> month (nth 4 nowdecode)) + (>= day (nth 3 nowdecode))) + (nth 5 nowdecode) + (1+ (nth 5 nowdecode)))) + ;; Month was specified. Make sure MONTH+YEAR + ;; combination happens in the future. + ((nth 4 tl) + (setq futurep t) + (cond ((> month (nth 4 nowdecode)) (nth 5 nowdecode)) + ((< month (nth 4 nowdecode)) (1+ (nth 5 nowdecode))) + ((< day (nth 3 nowdecode)) (1+ (nth 5 nowdecode))) + (t (nth 5 nowdecode)))) + (t (nth 5 org-defdecode))) hour (or (nth 2 tl) (nth 2 org-defdecode)) minute (or (nth 1 tl) (nth 1 org-defdecode)) second (or (nth 0 tl) 0) @@ -16643,7 +17269,7 @@ user." day (or iso-weekday wday 1) wday nil ; to make sure that the trigger below does not match iso-date (calendar-gregorian-from-absolute - (calendar-absolute-from-iso + (calendar-iso-to-absolute (list iso-week day year)))) ; FIXME: Should we also push ISO weeks into the future? ; (when (and org-read-date-prefer-future @@ -16652,7 +17278,7 @@ user." ; (time-to-days (current-time)))) ; (setq year (1+ year) ; iso-date (calendar-gregorian-from-absolute - ; (calendar-absolute-from-iso + ; (calendar-iso-to-absolute ; (list iso-week day year))))) (setq month (car iso-date) year (nth 2 iso-date) @@ -16660,7 +17286,10 @@ user." (deltan (setq futurep nil) (unless deltadef - (let ((now (decode-time))) + ;; Pass `current-time' result to `decode-time' (instead of + ;; calling without arguments) so that only `current-time' has + ;; to be overridden in tests. + (let ((now (decode-time (current-time)))) (setq day (nth 3 now) month (nth 4 now) year (nth 5 now)))) (cond ((member deltaw '("d" "")) (setq day (+ day deltan))) ((equal deltaw "w") (setq day (+ day (* 7 deltan)))) @@ -16672,17 +17301,17 @@ user." (setq wday1 (nth 6 (decode-time (encode-time 0 0 0 day month year)))) (unless (equal wday wday1) (setq day (+ day (% (- wday wday1 -7) 7)))))) - (if (and (boundp 'org-time-was-given) - (nth 2 tl)) - (setq org-time-was-given t)) - (if (< year 100) (setq year (+ 2000 year))) + (when (and (boundp 'org-time-was-given) + (nth 2 tl)) + (setq org-time-was-given t)) + (when (< year 100) (setq year (+ 2000 year))) ;; Check of the date is representable (if org-read-date-force-compatible-dates (progn - (if (< year 1970) - (setq year 1970 org-read-date-analyze-forced-year t)) - (if (> year 2037) - (setq year 2037 org-read-date-analyze-forced-year t))) + (when (< year 1970) + (setq year 1970 org-read-date-analyze-forced-year t)) + (when (> year 2037) + (setq year 2037 org-read-date-analyze-forced-year t))) (condition-case nil (ignore (encode-time second minute hour day month year)) (error @@ -16722,12 +17351,11 @@ DEF-FLAG is t when a double ++ or -- indicates shift relative to (if wday1 (progn (setq delta (mod (+ 7 (- wday1 wday)) 7)) - (if (= delta 0) (setq delta 7)) - (if (= dir ?-) - (progn - (setq delta (- delta 7)) - (if (= delta 0) (setq delta -7)))) - (if (> n 1) (setq delta (+ delta (* (1- n) (if (= dir ?-) -7 7))))) + (when (= delta 0) (setq delta 7)) + (when (= dir ?-) + (setq delta (- delta 7)) + (when (= delta 0) (setq delta -7))) + (when (> n 1) (setq delta (+ delta (* (1- n) (if (= dir ?-) -7 7))))) (list delta "d" rel)) (list (* n (if (= dir ?-) -1 1)) what rel))))) @@ -16736,23 +17364,14 @@ DEF-FLAG is t when a double ++ or -- indicates shift relative to The internal representation needed by the calendar is (month day year). This is a wrapper to handle the brain-dead convention in calendar that user function argument order change dependent on argument order." - (if (boundp 'calendar-date-style) - (cond - ((eq calendar-date-style 'american) - (list arg1 arg2 arg3)) - ((eq calendar-date-style 'european) - (list arg2 arg1 arg3)) - ((eq calendar-date-style 'iso) - (list arg2 arg3 arg1))) - (org-no-warnings ;; european-calendar-style is obsolete as of version 23.1 - (if (org-bound-and-true-p european-calendar-style) - (list arg2 arg1 arg3) - (list arg1 arg2 arg3))))) + (pcase calendar-date-style + (`american (list arg1 arg2 arg3)) + (`european (list arg2 arg1 arg3)) + (`iso (list arg2 arg3 arg1)))) (defun org-eval-in-calendar (form &optional keepdate) "Eval FORM in the calendar window and return to current window. -When KEEPDATE is non-nil, update `org-ans2' from the cursor date, -otherwise stick to the current value of `org-ans2'." +Unless KEEPDATE is non-nil, update `org-ans2' to the cursor date." (let ((sf (selected-frame)) (sw (selected-window))) (select-window (get-buffer-window "*Calendar*" t)) @@ -16763,7 +17382,7 @@ otherwise stick to the current value of `org-ans2'." (setq org-ans2 (format-time-string "%Y-%m-%d" time)))) (move-overlay org-date-ovl (1- (point)) (1+ (point)) (current-buffer)) (select-window sw) - (org-select-frame-set-input-focus sf))) + (select-frame-set-input-focus sf))) (defun org-calendar-select () "Return to `org-read-date' with the date currently selected. @@ -16773,10 +17392,11 @@ This is used by `org-read-date' in a temporary keymap for the calendar buffer." (let* ((date (calendar-cursor-to-date)) (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date)))) (setq org-ans1 (format-time-string "%Y-%m-%d" time))) - (if (active-minibuffer-window) (exit-minibuffer)))) + (when (active-minibuffer-window) (exit-minibuffer)))) (defun org-insert-time-stamp (time &optional with-hm inactive pre post extra) "Insert a date stamp for the date given by the internal TIME. +See `format-time-string' for the format of TIME. WITH-HM means use the stamp format that includes the time of the day. INACTIVE means use square brackets instead of angular ones, so that the stamp will not contribute to the agenda. @@ -16785,7 +17405,7 @@ stamp. The command returns the inserted time stamp." (let ((fmt (funcall (if with-hm 'cdr 'car) org-time-stamp-formats)) stamp) - (if inactive (setq fmt (concat "[" (substring fmt 1 -1) "]"))) + (when inactive (setq fmt (concat "[" (substring fmt 1 -1) "]"))) (insert-before-markers (or pre "")) (when (listp extra) (setq extra (car extra)) @@ -16808,14 +17428,12 @@ The command returns the inserted time stamp." (unless org-display-custom-times (let ((p (point-min)) (bmp (buffer-modified-p))) (while (setq p (next-single-property-change p 'display)) - (if (and (get-text-property p 'display) - (eq (get-text-property p 'face) 'org-date)) - (remove-text-properties - p (setq p (next-single-property-change p 'display)) - '(display t)))) + (when (and (get-text-property p 'display) + (eq (get-text-property p 'face) 'org-date)) + (remove-text-properties + p (setq p (next-single-property-change p 'display)) + '(display t)))) (set-buffer-modified-p bmp))) - (if (featurep 'xemacs) - (remove-text-properties (point-min) (point-max) '(end-glyph t))) (org-restart-font-lock) (setq org-table-may-need-update t) (if org-display-custom-times @@ -16828,8 +17446,8 @@ The command returns the inserted time stamp." t1 w1 with-hm tf time str w2 (off 0)) (save-match-data (setq t1 (org-parse-time-string ts t)) - (if (string-match "\\(-[0-9]+:[0-9]+\\)?\\( [.+]?\\+[0-9]+[hdwmy]\\(/[0-9]+[hdwmy]\\)?\\)?\\'" ts) - (setq off (- (match-end 0) (match-beginning 0))))) + (when (string-match "\\(-[0-9]+:[0-9]+\\)?\\( [.+]?\\+[0-9]+[hdwmy]\\(/[0-9]+[hdwmy]\\)?\\)?\\'" ts) + (setq off (- (match-end 0) (match-beginning 0))))) (setq end (- end off)) (setq w1 (- end beg) with-hm (and (nth 1 t1) (nth 2 t1)) @@ -16840,41 +17458,10 @@ The command returns the inserted time stamp." (substring tf 1 -1) (apply 'encode-time time)) nil 'mouse-face 'highlight) w2 (length str)) - (if (not (= w2 w1)) - (add-text-properties (1+ beg) (+ 2 beg) - (list 'org-dwidth t 'org-dwidth-n (- w1 w2)))) - (if (featurep 'xemacs) - (progn - (put-text-property beg end 'invisible t) - (put-text-property beg end 'end-glyph (make-glyph str))) - (put-text-property beg end 'display str)))) - -(defun org-translate-time (string) - "Translate all timestamps in STRING to custom format. -But do this only if the variable `org-display-custom-times' is set." - (when org-display-custom-times - (save-match-data - (let* ((start 0) - (re org-ts-regexp-both) - t1 with-hm inactive tf time str beg end) - (while (setq start (string-match re string start)) - (setq beg (match-beginning 0) - end (match-end 0) - t1 (save-match-data - (org-parse-time-string (substring string beg end) t)) - with-hm (and (nth 1 t1) (nth 2 t1)) - inactive (equal (substring string beg (1+ beg)) "[") - tf (funcall (if with-hm 'cdr 'car) - org-time-stamp-custom-formats) - time (org-fix-decoded-time t1) - str (format-time-string - (concat - (if inactive "[" "<") (substring tf 1 -1) - (if inactive "]" ">")) - (apply 'encode-time time)) - string (replace-match str t t string) - start (+ start (length str))))))) - string) + (unless (= w2 w1) + (add-text-properties (1+ beg) (+ 2 beg) + (list 'org-dwidth t 'org-dwidth-n (- w1 w2)))) + (put-text-property beg end 'display str))) (defun org-fix-decoded-time (time) "Set 0 instead of nil for the first 6 elements of time. @@ -16882,19 +17469,17 @@ Don't touch the rest." (let ((n 0)) (mapcar (lambda (x) (if (< (setq n (1+ n)) 7) (or x 0) x)) time))) -(define-obsolete-function-alias 'org-days-to-time 'org-time-stamp-to-now "24.4") - (defun org-time-stamp-to-now (timestamp-string &optional seconds) "Difference between TIMESTAMP-STRING and now in days. If SECONDS is non-nil, return the difference in seconds." - (let ((fdiff (if seconds 'float-time 'time-to-days))) + (let ((fdiff (if seconds #'float-time #'time-to-days))) (- (funcall fdiff (org-time-string-to-time timestamp-string)) (funcall fdiff (current-time))))) -(defun org-deadline-close (timestamp-string &optional ndays) +(defun org-deadline-close-p (timestamp-string &optional ndays) "Is the time in TIMESTAMP-STRING close to the current date?" (setq ndays (or ndays (org-get-wdays timestamp-string))) - (and (< (org-time-stamp-to-now timestamp-string) ndays) + (and (<= (org-time-stamp-to-now timestamp-string) ndays) (not (org-entry-is-done-p)))) (defun org-get-wdays (ts &optional delay zero-delay) @@ -16930,14 +17515,15 @@ This is used by `org-read-date' in a temporary keymap for the calendar buffer." (let* ((date (calendar-cursor-to-date)) (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date)))) (setq org-ans1 (format-time-string "%Y-%m-%d" time))) - (if (active-minibuffer-window) (exit-minibuffer)))) + (when (active-minibuffer-window) (exit-minibuffer)))) (defun org-check-deadlines (ndays) "Check if there are any deadlines due or past due. A deadline is considered due if it happens within `org-deadline-warning-days' days from today's date. If the deadline appears in an entry marked DONE, -it is not shown. The prefix arg NDAYS can be used to test that many -days. If the prefix is a raw \\[universal-argument] prefix, all deadlines are shown." +it is not shown. A numeric prefix argument NDAYS can be used to test that +many days. If the prefix is a raw `\\[universal-argument]', all deadlines \ +are shown." (interactive "P") (let* ((org-warn-days (cond @@ -16947,8 +17533,7 @@ days. If the prefix is a raw \\[universal-argument] prefix, all deadlines are s (case-fold-search nil) (regexp (concat "\\<" org-deadline-string " *<\\([^>]+\\)>")) (callback - (lambda () (org-deadline-close (match-string 1) org-warn-days)))) - + (lambda () (org-deadline-close-p (match-string 1) org-warn-days)))) (message "%d deadlines past-due or due within %d days" (org-occur regexp nil callback) org-warn-days))) @@ -16966,39 +17551,61 @@ Allowed values for TYPE are: When TYPE is nil, fall back on returning a regexp that matches both scheduled and deadline timestamps." - (cond ((eq type 'all) "\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\(?: +[^]+0-9>\r\n -]+\\)?\\(?: +[0-9]\\{1,2\\}:[0-9]\\{2\\}\\)?\\)") - ((eq type 'active) org-ts-regexp) - ((eq type 'inactive) "\\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^\r\n>]*?\\)\\]") - ((eq type 'scheduled) (concat "\\<" org-scheduled-string " *<\\([^>]+\\)>")) - ((eq type 'deadline) (concat "\\<" org-deadline-string " *<\\([^>]+\\)>")) - ((eq type 'closed) (concat org-closed-string " \\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^\r\n>]*?\\)\\]")) - ((eq type 'scheduled-or-deadline) - (concat "\\<\\(?:" org-deadline-string "\\|" org-scheduled-string "\\) *<\\([^>]+\\)>")))) - -(defun org-check-before-date (date) - "Check if there are deadlines or scheduled entries before DATE." + (cl-case type + (all org-ts-regexp-both) + (active org-ts-regexp) + (inactive org-ts-regexp-inactive) + (scheduled org-scheduled-time-regexp) + (deadline org-deadline-time-regexp) + (closed org-closed-time-regexp) + (otherwise + (concat "\\<" + (regexp-opt (list org-deadline-string org-scheduled-string)) + " *<\\([^>]+\\)>")))) + +(defun org-check-before-date (d) + "Check if there are deadlines or scheduled entries before date D." (interactive (list (org-read-date))) - (let ((case-fold-search nil) - (regexp (org-re-timestamp org-ts-type)) - (callback - (lambda () (time-less-p - (org-time-string-to-time (match-string 1)) - (org-time-string-to-time date))))) + (let* ((case-fold-search nil) + (regexp (org-re-timestamp org-ts-type)) + (ts-type org-ts-type) + (callback + (lambda () + (let ((match (match-string 1))) + (and (if (memq ts-type '(active inactive all)) + (eq (org-element-type (save-excursion + (backward-char) + (org-element-context))) + 'timestamp) + (org-at-planning-p)) + (time-less-p + (org-time-string-to-time match) + (org-time-string-to-time d))))))) (message "%d entries before %s" - (org-occur regexp nil callback) date))) + (org-occur regexp nil callback) + d))) -(defun org-check-after-date (date) - "Check if there are deadlines or scheduled entries after DATE." +(defun org-check-after-date (d) + "Check if there are deadlines or scheduled entries after date D." (interactive (list (org-read-date))) - (let ((case-fold-search nil) - (regexp (org-re-timestamp org-ts-type)) - (callback - (lambda () (not - (time-less-p - (org-time-string-to-time (match-string 1)) - (org-time-string-to-time date)))))) + (let* ((case-fold-search nil) + (regexp (org-re-timestamp org-ts-type)) + (ts-type org-ts-type) + (callback + (lambda () + (let ((match (match-string 1))) + (and (if (memq ts-type '(active inactive all)) + (eq (org-element-type (save-excursion + (backward-char) + (org-element-context))) + 'timestamp) + (org-at-planning-p)) + (not (time-less-p + (org-time-string-to-time match) + (org-time-string-to-time d)))))))) (message "%d entries after %s" - (org-occur regexp nil callback) date))) + (org-occur regexp nil callback) + d))) (defun org-check-dates-range (start-date end-date) "Check for deadlines/scheduled entries between START-DATE and END-DATE." @@ -17007,15 +17614,22 @@ both scheduled and deadline timestamps." (let ((case-fold-search nil) (regexp (org-re-timestamp org-ts-type)) (callback - (lambda () - (let ((match (match-string 1))) - (and - (not (time-less-p - (org-time-string-to-time match) - (org-time-string-to-time start-date))) - (time-less-p - (org-time-string-to-time match) - (org-time-string-to-time end-date))))))) + (let ((type org-ts-type)) + (lambda () + (let ((match (match-string 1))) + (and + (if (memq type '(active inactive all)) + (eq (org-element-type (save-excursion + (backward-char) + (org-element-context))) + 'timestamp) + (org-at-planning-p)) + (not (time-less-p + (org-time-string-to-time match) + (org-time-string-to-time start-date))) + (time-less-p + (org-time-string-to-time match) + (org-time-string-to-time end-date)))))))) (message "%d entries between %s and %s" (org-occur regexp nil callback) start-date end-date))) @@ -17034,8 +17648,8 @@ days in order to avoid rounding problems." (unless (org-at-date-range-p t) (goto-char (point-at-bol)) (re-search-forward org-tr-regexp-both (point-at-eol) t)) - (if (not (org-at-date-range-p t)) - (user-error "Not at a time-stamp range, and none found in current line"))) + (unless (org-at-date-range-p t) + (user-error "Not at a time-stamp range, and none found in current line"))) (let* ((ts1 (match-string 1)) (ts2 (match-string 2)) (havetime (or (> (length ts1) 15) (> (length ts2) 15))) @@ -17073,27 +17687,31 @@ days in order to avoid rounding problems." (setq align t) (and (looking-at " *|") (goto-char (match-end 0)))) (goto-char match-end)) - (if (looking-at - "\\( *-? *[0-9]+y\\)?\\( *[0-9]+d\\)? *[0-9][0-9]:[0-9][0-9]") - (replace-match "")) - (if negative (insert " -")) + (when (looking-at + "\\( *-? *[0-9]+y\\)?\\( *[0-9]+d\\)? *[0-9][0-9]:[0-9][0-9]") + (replace-match "")) + (when negative (insert " -")) (if (> y 0) (insert " " (format (if havetime fy fy1) y d h m)) (if (> d 0) (insert " " (format (if havetime fd fd1) d h m)) (insert " " (format fh h m)))) - (if align (org-table-align)) + (when align (org-table-align)) (message "Time difference inserted"))))) (defun org-make-tdiff-string (y d h m) (let ((fmt "") (l nil)) - (if (> y 0) (setq fmt (concat fmt "%d year" (if (> y 1) "s" "") " ") - l (push y l))) - (if (> d 0) (setq fmt (concat fmt "%d day" (if (> d 1) "s" "") " ") - l (push d l))) - (if (> h 0) (setq fmt (concat fmt "%d hour" (if (> h 1) "s" "") " ") - l (push h l))) - (if (> m 0) (setq fmt (concat fmt "%d minute" (if (> m 1) "s" "") " ") - l (push m l))) + (when (> y 0) + (setq fmt (concat fmt "%d year" (if (> y 1) "s" "") " ")) + (push y l)) + (when (> d 0) + (setq fmt (concat fmt "%d day" (if (> d 1) "s" "") " ")) + (push d l)) + (when (> h 0) + (setq fmt (concat fmt "%d hour" (if (> h 1) "s" "") " ")) + (push h l)) + (when (> m 0) + (setq fmt (concat fmt "%d minute" (if (> m 1) "s" "") " ")) + (push m l)) (apply 'format fmt (nreverse l)))) (defun org-time-string-to-time (s &optional buffer pos) @@ -17110,28 +17728,40 @@ days in order to avoid rounding problems." "Convert a timestamp string to a number of seconds." (float-time (org-time-string-to-time s))) -(defun org-time-string-to-absolute (s &optional daynr prefer show-all buffer pos) - "Convert a time stamp to an absolute day number. -If there is a specifier for a cyclic time stamp, get the closest -date to DAYNR. -PREFER and SHOW-ALL are passed through to `org-closest-date'. -The variable `date' is bound by the calendar when this is called." +(org-define-error 'org-diary-sexp-no-match "Unable to match diary sexp") + +(defun org-time-string-to-absolute (s &optional daynr prefer buffer pos) + "Convert time stamp S to an absolute day number. + +If DAYNR in non-nil, and there is a specifier for a cyclic time +stamp, get the closest date to DAYNR. If PREFER is +`past' (respectively `future') return a date past (respectively +after) or equal to DAYNR. + +POS is the location of time stamp S, as a buffer position in +BUFFER. + +Diary sexp timestamps are matched against DAYNR, when non-nil. +If matching fails or DAYNR is nil, `org-diary-sexp-no-match' is +signaled." (cond - ((and daynr (string-match "\\`%%\\((.*)\\)" s)) - (if (org-diary-sexp-entry (match-string 1 s) "" date) + ((string-match "\\`%%\\((.*)\\)" s) + ;; Sexp timestamp: try to match DAYNR, if available, since we're + ;; only able to match individual dates. If it fails, raise an + ;; error. + (if (and daynr + (org-diary-sexp-entry + (match-string 1 s) "" (calendar-gregorian-from-absolute daynr))) daynr - (+ daynr 1000))) - ((and daynr (string-match "\\+[0-9]+[hdwmy]" s)) - (org-closest-date s (if (and (boundp 'daynr) (integerp daynr)) daynr - (time-to-days (current-time))) (match-string 0 s) - prefer show-all)) + (signal 'org-diary-sexp-no-match (list s)))) + (daynr (org-closest-date s daynr prefer)) (t (time-to-days (condition-case errdata - (apply 'encode-time (org-parse-time-string s)) + (apply #'encode-time (org-parse-time-string s)) (error (error "Bad timestamp `%s'%s\nError was: %s" - s (if (not (and buffer pos)) - "" - (format-message " at %d in buffer `%s'" pos buffer)) + s + (if (not (and buffer pos)) "" + (format-message " at %d in buffer `%s'" pos buffer)) (cdr errdata)))))))) (defun org-days-to-iso-week (days) @@ -17141,43 +17771,46 @@ The variable `date' is bound by the calendar when this is called." (defun org-small-year-to-year (year) "Convert 2-digit years into 4-digit years. -38-99 are mapped into 1938-1999. 1-37 are mapped into 2001-2037. -The year 2000 cannot be abbreviated. Any year larger than 99 -is returned unchanged." - (if (< year 38) - (setq year (+ 2000 year)) - (if (< year 100) - (setq year (+ 1900 year)))) - year) +YEAR is expanded into one of the 30 next years, if possible, or +into a past one. Any year larger than 99 is returned unchanged." + (if (>= year 100) year + (let* ((current (string-to-number (format-time-string "%Y" (current-time)))) + (century (/ current 100)) + (offset (- year (% current 100)))) + (cond ((> offset 30) (+ (* (1- century) 100) year)) + ((> offset -70) (+ (* century 100) year)) + (t (+ (* (1+ century) 100) year)))))) (defun org-time-from-absolute (d) "Return the time corresponding to date D. D may be an absolute day number, or a calendar-type list (month day year)." - (if (numberp d) (setq d (calendar-gregorian-from-absolute d))) + (when (numberp d) (setq d (calendar-gregorian-from-absolute d))) (encode-time 0 0 0 (nth 1 d) (car d) (nth 2 d))) +(defvar org-agenda-current-date) (defun org-calendar-holiday () - "List of holidays, for Diary display in Org-mode." + "List of holidays, for Diary display in Org mode." (require 'holidays) - (let ((hl (funcall - (if (fboundp 'calendar-check-holidays) - 'calendar-check-holidays 'check-calendar-holidays) date))) - (if hl (mapconcat 'identity hl "; ")))) + (let ((hl (calendar-check-holidays org-agenda-current-date))) + (and hl (mapconcat #'identity hl "; ")))) -(defun org-diary-sexp-entry (sexp entry date) - "Process a SEXP diary ENTRY for DATE." +(defun org-diary-sexp-entry (sexp entry d) + "Process a SEXP diary ENTRY for date D." (require 'diary-lib) - (let ((result (if calendar-debug-sexp - (let ((stack-trace-on-error t)) - (eval (car (read-from-string sexp)))) - (condition-case nil - (eval (car (read-from-string sexp))) - (error - (beep) - (message "Bad sexp at line %d in %s: %s" - (org-current-line) - (buffer-file-name) sexp) - (sleep-for 2)))))) + ;; `org-anniversary' and alike expect ENTRY and DATE to be bound + ;; dynamically. + (let* ((sexp `(let ((entry ,entry) + (date ',d)) + ,(car (read-from-string sexp)))) + (result (if calendar-debug-sexp (eval sexp) + (condition-case nil + (eval sexp) + (error + (beep) + (message "Bad sexp at line %d in %s: %s" + (org-current-line) + (buffer-file-name) sexp) + (sleep-for 2)))))) (cond ((stringp result) (split-string result "; ")) ((and (consp result) (not (consp (cdr result))) @@ -17189,9 +17822,7 @@ D may be an absolute day number, or a calendar-type list (month day year)." (defun org-diary-to-ical-string (frombuf) "Get iCalendar entries from diary entries in buffer FROMBUF. This uses the icalendar.el library." - (let* ((tmpdir (if (featurep 'xemacs) - (temp-directory) - temporary-file-directory)) + (let* ((tmpdir temporary-file-directory) (tmpfile (make-temp-name (expand-file-name "orgics" tmpdir))) buf rtn b e) @@ -17200,125 +17831,146 @@ This uses the icalendar.el library." (setq buf (find-buffer-visiting tmpfile)) (set-buffer buf) (goto-char (point-min)) - (if (re-search-forward "^BEGIN:VEVENT" nil t) - (setq b (match-beginning 0))) + (when (re-search-forward "^BEGIN:VEVENT" nil t) + (setq b (match-beginning 0))) (goto-char (point-max)) - (if (re-search-backward "^END:VEVENT" nil t) - (setq e (match-end 0))) + (when (re-search-backward "^END:VEVENT" nil t) + (setq e (match-end 0))) (setq rtn (if (and b e) (concat (buffer-substring b e) "\n") ""))) (kill-buffer buf) (delete-file tmpfile) rtn)) -(defun org-closest-date (start current change prefer show-all) - "Find the date closest to CURRENT that is consistent with START and CHANGE. -When PREFER is `past', return a date that is either CURRENT or past. -When PREFER is `future', return a date that is either CURRENT or future. -When SHOW-ALL is nil, only return the current occurrence of a time stamp." - ;; Make the proper lists from the dates - (catch 'exit - (let ((a1 '(("h" . hour) - ("d" . day) - ("w" . week) - ("m" . month) - ("y" . year))) - (shour (nth 2 (org-parse-time-string start))) - dn dw sday cday n1 n2 n0 - d m y y1 y2 date1 date2 nmonths nm ny m2) - - (setq start (org-date-to-gregorian start) - current (org-date-to-gregorian - (if show-all - current - (time-to-days (current-time)))) - sday (calendar-absolute-from-gregorian start) - cday (calendar-absolute-from-gregorian current)) - - (if (<= cday sday) (throw 'exit sday)) - - (if (string-match "\\(\\+[0-9]+\\)\\([hdwmy]\\)" change) - (setq dn (string-to-number (match-string 1 change)) - dw (cdr (assoc (match-string 2 change) a1))) - (user-error "Invalid change specifier: %s" change)) - (if (eq dw 'week) (setq dw 'day dn (* 7 dn))) - (cond - ((eq dw 'hour) - (let ((missing-hours - (mod (+ (- (* 24 (- cday sday)) shour) org-extend-today-until) - dn))) - (setq n1 (if (zerop missing-hours) cday - (- cday (1+ (floor (/ missing-hours 24))))) - n2 (+ cday (floor (/ (- dn missing-hours) 24)))))) - ((eq dw 'day) - (setq n1 (+ sday (* dn (floor (/ (- cday sday) dn)))) - n2 (+ n1 dn))) - ((eq dw 'year) - (setq d (nth 1 start) m (car start) y1 (nth 2 start) y2 (nth 2 current)) - (setq y1 (+ (* (floor (/ (- y2 y1) dn)) dn) y1)) - (setq date1 (list m d y1) - n1 (calendar-absolute-from-gregorian date1) - date2 (list m d (+ y1 (* (if (< n1 cday) 1 -1) dn))) - n2 (calendar-absolute-from-gregorian date2))) - ((eq dw 'month) - ;; approx number of month between the two dates - (setq nmonths (floor (/ (- cday sday) 30.436875))) - ;; How often does dn fit in there? - (setq d (nth 1 start) m (car start) y (nth 2 start) - nm (* dn (max 0 (1- (floor (/ nmonths dn))))) - m (+ m nm) - ny (floor (/ m 12)) - y (+ y ny) - m (- m (* ny 12))) - (while (> m 12) (setq m (- m 12) y (1+ y))) - (setq n1 (calendar-absolute-from-gregorian (list m d y))) - (setq m2 (+ m dn) y2 y) - (if (> m2 12) (setq y2 (1+ y2) m2 (- m2 12))) - (setq n2 (calendar-absolute-from-gregorian (list m2 d y2))) - (while (<= n2 cday) - (setq n1 n2 m m2 y y2) - (setq m2 (+ m dn) y2 y) - (if (> m2 12) (setq y2 (1+ y2) m2 (- m2 12))) - (setq n2 (calendar-absolute-from-gregorian (list m2 d y2)))))) - ;; Make sure n1 is the earlier date - (setq n0 n1 n1 (min n1 n2) n2 (max n0 n2)) - (if show-all - (cond - ((eq prefer 'past) (if (= cday n2) n2 n1)) - ((eq prefer 'future) (if (= cday n1) n1 n2)) - (t (if (> (abs (- cday n1)) (abs (- cday n2))) n2 n1))) - (cond - ((eq prefer 'past) (if (= cday n2) n2 n1)) - ((eq prefer 'future) (if (= cday n1) n1 n2)) - (t (if (= cday n1) n1 n2))))))) - -(defun org-date-to-gregorian (date) - "Turn any specification of DATE into a Gregorian date for the calendar." - (cond ((integerp date) (calendar-gregorian-from-absolute date)) - ((and (listp date) (= (length date) 3)) date) - ((stringp date) - (setq date (org-parse-time-string date)) - (list (nth 4 date) (nth 3 date) (nth 5 date))) - ((listp date) - (list (nth 4 date) (nth 3 date) (nth 5 date))))) - -(defun org-parse-time-string (s &optional nodefault) - "Parse the standard Org-mode time string. +(defun org-closest-date (start current prefer) + "Return closest date to CURRENT starting from START. + +CURRENT and START are both time stamps. + +When PREFER is `past', return a date that is either CURRENT or +past. When PREFER is `future', return a date that is either +CURRENT or future. + +Only time stamps with a repeater are modified. Any other time +stamp stay unchanged. In any case, return value is an absolute +day number." + (if (not (string-match "\\+\\([0-9]+\\)\\([hdwmy]\\)" start)) + ;; No repeater. Do not shift time stamp. + (time-to-days (apply #'encode-time (org-parse-time-string start))) + (let ((value (string-to-number (match-string 1 start))) + (type (match-string 2 start))) + (if (= 0 value) + ;; Repeater with a 0-value is considered as void. + (time-to-days (apply #'encode-time (org-parse-time-string start))) + (let* ((base (org-date-to-gregorian start)) + (target (org-date-to-gregorian current)) + (sday (calendar-absolute-from-gregorian base)) + (cday (calendar-absolute-from-gregorian target)) + n1 n2) + ;; If START is already past CURRENT, just return START. + (if (<= cday sday) sday + ;; Compute closest date before (N1) and closest date past + ;; (N2) CURRENT. + (pcase type + ("h" + (let ((missing-hours + (mod (+ (- (* 24 (- cday sday)) + (nth 2 (org-parse-time-string start))) + org-extend-today-until) + value))) + (setf n1 (if (= missing-hours 0) cday + (- cday (1+ (/ missing-hours 24))))) + (setf n2 (+ cday (/ (- value missing-hours) 24))))) + ((or "d" "w") + (let ((value (if (equal type "w") (* 7 value) value))) + (setf n1 (+ sday (* value (/ (- cday sday) value)))) + (setf n2 (+ n1 value)))) + ("m" + (let* ((add-months + (lambda (d n) + ;; Add N months to gregorian date D, i.e., + ;; a list (MONTH DAY YEAR). Return a valid + ;; gregorian date. + (let ((m (+ (nth 0 d) n))) + (list (mod m 12) + (nth 1 d) + (+ (/ m 12) (nth 2 d)))))) + (months ; Complete months to TARGET. + (* (/ (+ (* 12 (- (nth 2 target) (nth 2 base))) + (- (nth 0 target) (nth 0 base)) + ;; If START's day is greater than + ;; TARGET's, remove incomplete month. + (if (> (nth 1 target) (nth 1 base)) 0 -1)) + value) + value)) + (before (funcall add-months base months))) + (setf n1 (calendar-absolute-from-gregorian before)) + (setf n2 + (calendar-absolute-from-gregorian + (funcall add-months before value))))) + (_ + (let* ((d (nth 1 base)) + (m (nth 0 base)) + (y (nth 2 base)) + (years ; Complete years to TARGET. + (* (/ (- (nth 2 target) + y + ;; If START's month and day are + ;; greater than TARGET's, remove + ;; incomplete year. + (if (or (> (nth 0 target) m) + (and (= (nth 0 target) m) + (> (nth 1 target) d))) + 0 + 1)) + value) + value)) + (before (list m d (+ y years)))) + (setf n1 (calendar-absolute-from-gregorian before)) + (setf n2 (calendar-absolute-from-gregorian + (list m d (+ (nth 2 before) value))))))) + ;; Handle PREFER parameter, if any. + (cond + ((eq prefer 'past) (if (= cday n2) n2 n1)) + ((eq prefer 'future) (if (= cday n1) n1 n2)) + (t (if (> (abs (- cday n1)) (abs (- cday n2))) n2 n1))))))))) + +(defun org-date-to-gregorian (d) + "Turn any specification of date D into a Gregorian date for the calendar." + (cond ((integerp d) (calendar-gregorian-from-absolute d)) + ((and (listp d) (= (length d) 3)) d) + ((stringp d) + (let ((d (org-parse-time-string d))) + (list (nth 4 d) (nth 3 d) (nth 5 d)))) + ((listp d) (list (nth 4 d) (nth 3 d) (nth 5 d))))) + +(defun org-parse-time-string (s &optional nodefault zone) + "Parse the standard Org time string. + This should be a lot faster than the normal `parse-time-string'. -If time is not given, defaults to 0:00. However, with optional NODEFAULT, -hour and minute fields will be nil if not given." + +If time is not given, defaults to 0:00. However, with optional +NODEFAULT, hour and minute fields will be nil if not given. + +The optional ZONE is omitted or nil for Emacs local time, t for +Universal Time, ‘wall’ for system wall clock time, or a string as +in the TZ environment variable." (cond ((string-match org-ts-regexp0 s) (list 0 - (if (or (match-beginning 8) (not nodefault)) - (string-to-number (or (match-string 8 s) "0"))) - (if (or (match-beginning 7) (not nodefault)) - (string-to-number (or (match-string 7 s) "0"))) + (when (or (match-beginning 8) (not nodefault)) + (string-to-number (or (match-string 8 s) "0"))) + (when (or (match-beginning 7) (not nodefault)) + (string-to-number (or (match-string 7 s) "0"))) (string-to-number (match-string 4 s)) (string-to-number (match-string 3 s)) (string-to-number (match-string 2 s)) - nil nil nil)) + nil nil zone)) ((string-match "^<[^>]+>$" s) + ;; FIXME: `decode-time' needs to be called with ZONE as its + ;; second argument. However, this requires at least Emacs + ;; 25.1. We can do it when we switch to this version as our + ;; minimal requirement. (decode-time (seconds-to-time (org-matcher-time s)))) - (t (error "Not a standard Org-mode time string: %s" s)))) + (t (error "Not a standard Org time string: %s" s)))) (defun org-timestamp-up (&optional arg) "Increase the date item at the cursor by one. @@ -17355,14 +18007,21 @@ With prefix ARG, change that many days." (org-timestamp-change (- (prefix-numeric-value arg)) 'day) 'updown)) (defun org-at-timestamp-p (&optional inactive-ok) - "Determine if the cursor is in or at a timestamp." + "Non-nil if point is inside a timestamp. + +When optional argument INACTIVE-OK is non-nil, also consider +inactive timestamps. + +When this function returns a non-nil value, match data is set +according to `org-ts-regexp3' or `org-ts-regexp2', depending on +INACTIVE-OK." (interactive) (let* ((tsr (if inactive-ok org-ts-regexp3 org-ts-regexp2)) (pos (point)) (ans (or (looking-at tsr) (save-excursion (skip-chars-backward "^[<\n\r\t") - (if (> (point) (point-min)) (backward-char 1)) + (when (> (point) (point-min)) (backward-char 1)) (and (looking-at tsr) (> (- (match-end 0) pos) -1)))))) (and ans @@ -17403,8 +18062,8 @@ With prefix ARG, change that many days." (defun org-at-clock-log-p nil "Is the cursor on the clock log line?" (save-excursion - (move-beginning-of-line 1) - (looking-at "^[ \t]*CLOCK:"))) + (beginning-of-line) + (looking-at org-clock-line-re))) (defvar org-clock-history) ; defined in org-clock.el (defvar org-clock-adjust-closest nil) ; defined in org-clock.el @@ -17420,19 +18079,19 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays like \"--2d\"." org-ts-what extra rem ts time time0 fixnext clrgx) - (if (not (org-at-timestamp-p t)) - (user-error "Not at a timestamp")) + (unless (org-at-timestamp-p t) + (user-error "Not at a timestamp")) (if (and (not what) (eq org-ts-what 'bracket)) (org-toggle-timestamp-type) ;; Point isn't on brackets. Remember the part of the time-stamp ;; the point was in. Indeed, size of time-stamps may change, ;; but point must be kept in the same category nonetheless. (setq origin-cat org-ts-what) - (if (and (not what) (not (eq org-ts-what 'day)) - org-display-custom-times - (get-text-property (point) 'display) - (not (get-text-property (1- (point)) 'display))) - (setq org-ts-what 'day)) + (when (and (not what) (not (eq org-ts-what 'day)) + org-display-custom-times + (get-text-property (point) 'display) + (not (get-text-property (1- (point)) 'display))) + (setq org-ts-what 'day)) (setq org-ts-what (or what org-ts-what) inactive (= (char-after (match-beginning 0)) ?\[) ts (match-string 0)) @@ -17441,26 +18100,28 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays like \"--2d\"." "\\(\\(-[012][0-9]:[0-5][0-9]\\)?\\( +[.+]?-?[-+][0-9]+[hdwmy]\\(/[0-9]+[hdwmy]\\)?\\)*\\)[]>]" ts) (setq extra (match-string 1 ts)) - (if suppress-tmp-delay - (setq extra (replace-regexp-in-string " --[0-9]+[hdwmy]" "" extra)))) - (if (string-match "^.\\{10\\}.*?[0-9]+:[0-9][0-9]" ts) - (setq with-hm t)) + (when suppress-tmp-delay + (setq extra (replace-regexp-in-string " --[0-9]+[hdwmy]" "" extra)))) + (when (string-match "^.\\{10\\}.*?[0-9]+:[0-9][0-9]" ts) + (setq with-hm t)) (setq time0 (org-parse-time-string ts)) (when (and updown (eq org-ts-what 'minute) (not current-prefix-arg)) ;; This looks like s-up and s-down. Change by one rounding step. (setq n (* dm (cond ((> n 0) 1) ((< n 0) -1) (t 0)))) - (when (not (= 0 (setq rem (% (nth 1 time0) dm)))) + (unless (= 0 (setq rem (% (nth 1 time0) dm))) (setcar (cdr time0) (+ (nth 1 time0) (if (> n 0) (- rem) (- dm rem)))))) (setq time - (encode-time (or (car time0) 0) - (+ (if (eq org-ts-what 'minute) n 0) (nth 1 time0)) - (+ (if (eq org-ts-what 'hour) n 0) (nth 2 time0)) - (+ (if (eq org-ts-what 'day) n 0) (nth 3 time0)) - (+ (if (eq org-ts-what 'month) n 0) (nth 4 time0)) - (+ (if (eq org-ts-what 'year) n 0) (nth 5 time0)))) + (apply #'encode-time + (or (car time0) 0) + (+ (if (eq org-ts-what 'minute) n 0) (nth 1 time0)) + (+ (if (eq org-ts-what 'hour) n 0) (nth 2 time0)) + (+ (if (eq org-ts-what 'day) n 0) (nth 3 time0)) + (+ (if (eq org-ts-what 'month) n 0) (nth 4 time0)) + (+ (if (eq org-ts-what 'year) n 0) (nth 5 time0)) + (nthcdr 6 time0))) (when (and (member org-ts-what '(hour minute)) extra (string-match "-\\([012][0-9]\\):\\([0-5][0-9]\\)" extra)) @@ -17470,15 +18131,15 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays like \"--2d\"." n dm))) (when (integerp org-ts-what) (setq extra (org-modify-ts-extra extra org-ts-what n dm))) - (if (eq what 'calendar) - (let ((cal-date (org-get-date-from-calendar))) - (setcar (nthcdr 4 time0) (nth 0 cal-date)) ; month - (setcar (nthcdr 3 time0) (nth 1 cal-date)) ; day - (setcar (nthcdr 5 time0) (nth 2 cal-date)) ; year - (setcar time0 (or (car time0) 0)) - (setcar (nthcdr 1 time0) (or (nth 1 time0) 0)) - (setcar (nthcdr 2 time0) (or (nth 2 time0) 0)) - (setq time (apply 'encode-time time0)))) + (when (eq what 'calendar) + (let ((cal-date (org-get-date-from-calendar))) + (setcar (nthcdr 4 time0) (nth 0 cal-date)) ; month + (setcar (nthcdr 3 time0) (nth 1 cal-date)) ; day + (setcar (nthcdr 5 time0) (nth 2 cal-date)) ; year + (setcar time0 (or (car time0) 0)) + (setcar (nthcdr 1 time0) (or (nth 1 time0) 0)) + (setcar (nthcdr 2 time0) (or (nth 2 time0) 0)) + (setq time (apply 'encode-time time0)))) ;; Insert the new time-stamp, and ensure point stays in the same ;; category as before (i.e. not after the last position in that ;; category). @@ -17489,17 +18150,21 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays like \"--2d\"." (goto-char pos)) (save-match-data (looking-at org-ts-regexp3) - (goto-char (cond - ;; `day' category ends before `hour' if any, or at - ;; the end of the day name. - ((eq origin-cat 'day) - (min (or (match-beginning 7) (1- (match-end 5))) origin)) - ((eq origin-cat 'hour) (min (match-end 7) origin)) - ((eq origin-cat 'minute) (min (1- (match-end 8)) origin)) - ((integerp origin-cat) (min (1- (match-end 0)) origin)) - ;; `year' and `month' have both fixed size: point - ;; couldn't have moved into another part. - (t origin)))) + (goto-char + (pcase origin-cat + ;; `day' category ends before `hour' if any, or at the end + ;; of the day name. + (`day (min (or (match-beginning 7) (1- (match-end 5))) origin)) + (`hour (min (match-end 7) origin)) + (`minute (min (1- (match-end 8)) origin)) + ((pred integerp) (min (1- (match-end 0)) origin)) + ;; Point was right after the time-stamp. However, the + ;; time-stamp length might have changed, so refer to + ;; (match-end 0) instead. + (`after (match-end 0)) + ;; `year' and `month' have both fixed size: point couldn't + ;; have moved into another part. + (_ origin)))) ;; Update clock if on a CLOCK line. (org-clock-update-time-maybe) ;; Maybe adjust the closest clock in `org-clock-history' @@ -17508,11 +18173,12 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays like \"--2d\"." (< 1 (length (delq nil (mapcar 'marker-position org-clock-history)))))) (message "No clock to adjust") - (cond ((save-excursion ; fix previous clock? + (cond ((save-excursion ; fix previous clock? (re-search-backward org-ts-regexp0 nil t) - (org-looking-back (concat org-clock-string " \\["))) + (looking-back (concat org-clock-string " \\[") + (line-beginning-position))) (setq fixnext 1 clrgx (concat org-ts-regexp0 "\\] =>.*$"))) - ((save-excursion ; fix next clock? + ((save-excursion ; fix next clock? (re-search-backward org-ts-regexp0 nil t) (looking-at (concat org-ts-regexp0 "\\] =>"))) (setq fixnext -1 clrgx (concat org-clock-string " \\[" org-ts-regexp0)))) @@ -17521,8 +18187,8 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays like \"--2d\"." (let* ((p (save-excursion (org-back-to-heading t))) (cl (mapcar (lambda(c) (abs (- (marker-position c) p))) org-clock-history)) (clfixnth - (+ fixnext (- (length cl) (or (length (member (apply #'min cl) cl)) 100)))) - (clfixpos (if (> 0 clfixnth) nil (nth clfixnth org-clock-history)))) + (+ fixnext (- (length cl) (or (length (member (apply 'min cl) cl)) 100)))) + (clfixpos (unless (> 0 clfixnth) (nth clfixnth org-clock-history)))) (if (not clfixpos) (message "No clock to adjust") (save-excursion @@ -17536,10 +18202,10 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays like \"--2d\"." (file-name-nondirectory (buffer-file-name)) (org-get-heading t t))))))))) ;; Try to recenter the calendar window, if any. - (if (and org-calendar-follow-timestamp-change - (get-buffer-window "*Calendar*" t) - (memq org-ts-what '(day month year))) - (org-recenter-calendar (time-to-days time)))))) + (when (and org-calendar-follow-timestamp-change + (get-buffer-window "*Calendar*" t) + (memq org-ts-what '(day month year))) + (org-recenter-calendar (time-to-days time)))))) (defun org-modify-ts-extra (s pos n dm) "Change the different parts of the lead-time and repeat fields in timestamp." @@ -17553,13 +18219,13 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays like \"--2d\"." h (string-to-number (match-string 2 s))) (if (org-pos-in-match-range pos 2) (setq h (+ h n)) - (setq n (* dm (org-no-warnings (signum n)))) - (when (not (= 0 (setq rem (% m dm)))) + (setq n (* dm (with-no-warnings (signum n)))) + (unless (= 0 (setq rem (% m dm))) (setq m (+ m (if (> n 0) (- rem) (- dm rem))))) (setq m (+ m n))) - (if (< m 0) (setq m (+ m 60) h (1- h))) - (if (> m 59) (setq m (- m 60) h (1+ h))) - (setq h (min 24 (max 0 h))) + (when (< m 0) (setq m (+ m 60) h (1- h))) + (when (> m 59) (setq m (- m 60) h (1+ h))) + (setq h (mod h 24)) (setq ng 1 new (format "-%02d:%02d" h m))) ((org-pos-in-match-range pos 6) (setq ng 6 new (car (rassoc (+ n (cdr (assoc (match-string 6 s) idx))) idx)))) @@ -17578,14 +18244,14 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays like \"--2d\"." (substring s (match-end ng)))))) s)) -(defun org-recenter-calendar (date) - "If the calendar is visible, recenter it to DATE." +(defun org-recenter-calendar (d) + "If the calendar is visible, recenter it to date D." (let ((cwin (get-buffer-window "*Calendar*" t))) (when cwin (let ((calendar-move-hook nil)) (with-selected-window cwin - (calendar-goto-date (if (listp date) date - (calendar-gregorian-from-absolute date)))))))) + (calendar-goto-date + (if (listp d) d (calendar-gregorian-from-absolute d)))))))) (defun org-goto-calendar (&optional arg) "Go to the Emacs calendar at the current date. @@ -17596,17 +18262,17 @@ A prefix ARG can be used to force the current date." (calendar-move-hook nil) (calendar-view-holidays-initially-flag nil) (calendar-view-diary-initially-flag nil)) - (if (or (org-at-timestamp-p) - (save-excursion - (beginning-of-line 1) - (looking-at (concat ".*" tsr)))) - (let ((d1 (time-to-days (current-time))) - (d2 (time-to-days - (org-time-string-to-time (match-string 1))))) - (setq diff (- d2 d1)))) + (when (or (org-at-timestamp-p) + (save-excursion + (beginning-of-line 1) + (looking-at (concat ".*" tsr)))) + (let ((d1 (time-to-days (current-time))) + (d2 (time-to-days + (org-time-string-to-time (match-string 1))))) + (setq diff (- d2 d1)))) (calendar) (calendar-goto-today) - (if (and diff (not arg)) (calendar-forward-day diff)))) + (when (and diff (not arg)) (calendar-forward-day diff)))) (defun org-get-date-from-calendar () "Return a list (month day year) of date at point in calendar." @@ -17625,7 +18291,8 @@ If there is already a time stamp at the cursor position, update it." (encode-time 0 0 0 (nth 1 cal-date) (car cal-date) (nth 2 cal-date)))))) (defcustom org-effort-durations - `(("h" . 60) + `(("min" . 1) + ("h" . 60) ("d" . ,(* 60 8)) ("w" . ,(* 60 8 5)) ("m" . ,(* 60 8 5 4)) @@ -17641,7 +18308,8 @@ minutes. For example, if the value of this variable is ((\"hours\" . 60)), then an effort string \"2hours\" is equivalent to 120 minutes." :group 'org-agenda - :version "24.1" + :version "26.1" + :package-version '(Org . "8.3") :type '(alist :key-type (string :tag "Modifier") :value-type (number :tag "Minutes"))) @@ -17734,10 +18402,6 @@ The format is determined by `org-time-clocksum-format', ;; return formatted time duration clocksum)))) -(defalias 'org-minutes-to-hh:mm-string 'org-minutes-to-clocksum-string) -(make-obsolete 'org-minutes-to-hh:mm-string 'org-minutes-to-clocksum-string - "Org mode version 8.0") - (defun org-hours-to-clocksum-string (n) (org-minutes-to-clocksum-string (* n 60))) @@ -17793,19 +18457,21 @@ tables are not re-aligned, etc." :version "24.3" :group 'org-agenda) -(defcustom org-agenda-ignore-drawer-properties nil +(defcustom org-agenda-ignore-properties nil "Avoid updating text properties when building the agenda. -Properties are used to prepare buffers for effort estimates, appointments, -and subtree-local categories. -If you don't use these in the agenda, you can add them to this list and -agenda building will be a bit faster. +Properties are used to prepare buffers for effort estimates, +appointments, statistics and subtree-local categories. +If you don't use these in the agenda, you can add them to this +list and agenda building will be a bit faster. The value is a list, with zero or more of the symbols `effort', `appt', -or `category'." +`stats' or `category'." :type '(set :greedy t (const effort) (const appt) + (const stats) (const category)) - :version "24.3" + :version "26.1" + :package-version '(Org . "8.3") :group 'org-agenda) (defun org-duration-string-to-minutes (s &optional output-to-string) @@ -17821,25 +18487,25 @@ Entries containing a colon are interpreted as H:MM by (regexp-opt (mapcar 'car org-effort-durations)) "\\)"))) (while (string-match re s) - (incf result (* (cdr (assoc (match-string 2 s) org-effort-durations)) - (string-to-number (match-string 1 s)))) + (cl-incf result (* (cdr (assoc (match-string 2 s) org-effort-durations)) + (string-to-number (match-string 1 s)))) (setq s (replace-match "" nil t s))) (setq result (floor result)) - (incf result (org-hh:mm-string-to-minutes s)) + (cl-incf result (org-hh:mm-string-to-minutes s)) (if output-to-string (number-to-string result) result))) ;;;; Files (defun org-save-all-org-buffers () - "Save all Org-mode buffers without user confirmation." + "Save all Org buffers without user confirmation." (interactive) - (message "Saving all Org-mode buffers...") + (message "Saving all Org buffers...") (save-some-buffers t (lambda () (derived-mode-p 'org-mode))) (when (featurep 'org-id) (org-id-locations-save)) - (message "Saving all Org-mode buffers... done")) + (message "Saving all Org buffers... done")) (defun org-revert-all-org-buffers () - "Revert all Org-mode buffers. + "Revert all Org buffers. Prompt for confirmation when there are unsaved changes. Be sure you know what you are doing before letting this function overwrite your changes. @@ -17856,13 +18522,11 @@ changes from another. I believe the procedure must be like this: (user-error "Abort")) (save-excursion (save-window-excursion - (mapc - (lambda (b) - (when (and (with-current-buffer b (derived-mode-p 'org-mode)) - (with-current-buffer b buffer-file-name)) - (org-pop-to-buffer-same-window b) - (revert-buffer t 'no-confirm))) - (buffer-list)) + (dolist (b (buffer-list)) + (when (and (with-current-buffer b (derived-mode-p 'org-mode)) + (with-current-buffer b buffer-file-name)) + (pop-to-buffer-same-window b) + (revert-buffer t 'no-confirm))) (when (and (featurep 'org-id) org-id-track-globally) (org-id-locations-load))))) @@ -17871,29 +18535,19 @@ changes from another. I believe the procedure must be like this: ;;;###autoload (defun org-switchb (&optional arg) "Switch between Org buffers. -With one prefix argument, restrict available buffers to files. -With two prefix arguments, restrict available buffers to agenda files. -Defaults to `iswitchb' for buffer name completion. -Set `org-completion-use-ido' to make it use ido instead." +With `\\[universal-argument]' prefix, restrict available buffers to files. + +With `\\[universal-argument] \\[universal-argument]' \ +prefix, restrict available buffers to agenda files." (interactive "P") - (let ((blist (cond ((equal arg '(4)) (org-buffer-list 'files)) - ((equal arg '(16)) (org-buffer-list 'agenda)) - (t (org-buffer-list)))) - (org-completion-use-iswitchb org-completion-use-iswitchb) - (org-completion-use-ido org-completion-use-ido)) - (unless (or org-completion-use-ido org-completion-use-iswitchb) - (setq org-completion-use-iswitchb t)) - (org-pop-to-buffer-same-window - (org-icompleting-read "Org buffer: " - (mapcar 'list (mapcar 'buffer-name blist)) - nil t)))) - -;;; Define some older names previously used for this functionality -;;;###autoload -(defalias 'org-ido-switchb 'org-switchb) -;;;###autoload -(defalias 'org-iswitchb 'org-switchb) + (let ((blist (org-buffer-list + (cond ((equal arg '(4)) 'files) + ((equal arg '(16)) 'agenda))))) + (pop-to-buffer-same-window + (completing-read "Org buffer: " + (mapcar #'list (mapcar #'buffer-name blist)) + nil t)))) (defun org-buffer-list (&optional predicate exclude-tmp) "Return a list of Org buffers. @@ -17968,8 +18622,10 @@ used by the agenda files. If ARCHIVE is `ifmode', do this only if "Return non-nil, if FILE is an agenda file. If FILE is omitted, use the file associated with the current buffer." - (member (or file (buffer-file-name)) - (org-agenda-files t))) + (let ((fname (or file (buffer-file-name)))) + (and fname + (member (file-truename fname) + (mapcar #'file-truename (org-agenda-files t)))))) (defun org-edit-agenda-file-list () "Edit the list of agenda files. @@ -17981,15 +18637,15 @@ the buffer and restores the previous window configuration." (if (stringp org-agenda-files) (let ((cw (current-window-configuration))) (find-file org-agenda-files) - (org-set-local 'org-window-configuration cw) - (org-add-hook 'after-save-hook - (lambda () - (set-window-configuration - (prog1 org-window-configuration - (kill-buffer (current-buffer)))) - (org-install-agenda-files-menu) - (message "New agenda file list installed")) - nil 'local) + (setq-local org-window-configuration cw) + (add-hook 'after-save-hook + (lambda () + (set-window-configuration + (prog1 org-window-configuration + (kill-buffer (current-buffer)))) + (org-install-agenda-files-menu) + (message "New agenda file list installed")) + nil 'local) (message "%s" (substitute-command-keys "Edit list and finish with \\[save-buffer]"))) (customize-variable 'org-agenda-files))) @@ -18039,19 +18695,16 @@ un-expanded file names." If the current buffer visits an agenda file, find the next one in the list. If the current buffer does not, find the first agenda file." (interactive) - (let* ((fs (org-agenda-files t)) - (files (append fs (list (car fs)))) - (tcf (if buffer-file-name (file-truename buffer-file-name))) + (let* ((fs (or (org-agenda-files t) + (user-error "No agenda files"))) + (files (copy-sequence fs)) + (tcf (and buffer-file-name (file-truename buffer-file-name))) file) - (unless files (user-error "No agenda files")) - (catch 'exit - (dolist (file files) - (if (equal (file-truename file) tcf) - (when (car files) - (find-file (car files)) - (throw 'exit t)))) - (find-file (car fs))) - (if (buffer-base-buffer) (org-pop-to-buffer-same-window (buffer-base-buffer))))) + (when tcf + (while (and (setq file (pop files)) + (not (equal (file-truename file) tcf))))) + (find-file (car (or files fs))) + (when (buffer-base-buffer) (pop-to-buffer-same-window (buffer-base-buffer))))) (defun org-agenda-file-to-front (&optional to-end) "Move/add the current file to the top of the agenda file list. @@ -18069,7 +18722,7 @@ end of the list." x had) (setq x (assoc ctf file-alist) had x) - (if (not x) (setq x (cons ctf (abbreviate-file-name buffer-file-name)))) + (unless x (setq x (cons ctf (abbreviate-file-name buffer-file-name)))) (if to-end (setq file-alist (append (delq x file-alist) (list x))) (setq file-alist (cons x (delq x file-alist)))) @@ -18090,15 +18743,15 @@ Optional argument FILE means use this file instead of the current." (afile (abbreviate-file-name file)) (files (delq nil (mapcar (lambda (x) - (if (equal true-file - (file-truename x)) - nil x)) + (unless (equal true-file + (file-truename x)) + x)) (org-agenda-files t))))) (if (not (= (length files) (length (org-agenda-files t)))) (progn (org-store-new-agenda-file-list files) (org-install-agenda-files-menu) - (message "Removed file: %s" afile)) + (message "Removed from Org Agenda list: %s" afile)) (message "File was not in list: %s (not removed)" afile)))) (defun org-file-menu-entry (file) @@ -18106,7 +18759,7 @@ Optional argument FILE means use this file instead of the current." (defun org-check-agenda-file (file) "Make sure FILE exists. If not, ask user what to do." - (when (not (file-exists-p file)) + (unless (file-exists-p file) (message "Non-existent agenda file %s. [R]emove from list or [A]bort?" (abbreviate-file-name file)) (let ((r (downcase (read-char-exclusive)))) @@ -18114,17 +18767,18 @@ Optional argument FILE means use this file instead of the current." ((equal r ?r) (org-remove-file file) (throw 'nextfile t)) - (t (error "Abort")))))) + (t (user-error "Abort")))))) (defun org-get-agenda-file-buffer (file) - "Get a buffer visiting FILE. If the buffer needs to be created, add -it to the list of buffers which might be released later." + "Get an agenda buffer visiting FILE. +If the buffer needs to be created, add it to the list of buffers +which might be released later." (let ((buf (org-find-base-buffer-visiting file))) (if buf buf ; just return it ;; Make a new buffer and remember it (setq buf (find-file-noselect file)) - (if buf (push buf org-agenda-new-buffers)) + (when buf (push buf org-agenda-new-buffers)) buf))) (defun org-release-buffers (blist) @@ -18149,7 +18803,7 @@ When a buffer is unmodified, it is just killed. When modified, it is saved (inhibit-read-only t) (org-inhibit-startup org-agenda-inhibit-startup) (rea (concat ":" org-archive-tag ":")) - file re pos) + re pos) (setq org-tag-alist-for-agenda nil org-tag-groups-alist-for-agenda nil) (save-excursion @@ -18161,20 +18815,15 @@ When a buffer is unmodified, it is just killed. When modified, it is saved (org-check-agenda-file file) (set-buffer (org-get-agenda-file-buffer file))) (widen) - (org-set-regexps-and-options-for-tags) + (org-set-regexps-and-options 'tags-only) (setq pos (point)) - (goto-char (point-min)) - (let ((case-fold-search t)) - (when (search-forward "#+setupfile" nil t) - ;; Don't set all regexps and options systematically as - ;; this is only run for setting agenda tags from setup - ;; file - (org-set-regexps-and-options))) - (or (memq 'category org-agenda-ignore-drawer-properties) + (or (memq 'category org-agenda-ignore-properties) (org-refresh-category-properties)) - (or (memq 'effort org-agenda-ignore-drawer-properties) - (org-refresh-properties org-effort-property 'org-effort)) - (or (memq 'appt org-agenda-ignore-drawer-properties) + (or (memq 'stats org-agenda-ignore-properties) + (org-refresh-stats-properties)) + (or (memq 'effort org-agenda-ignore-properties) + (org-refresh-effort-properties)) + (or (memq 'appt org-agenda-ignore-properties) (org-refresh-properties "APPT_WARNTIME" 'org-appt-warntime)) (setq org-todo-keywords-for-agenda (append org-todo-keywords-for-agenda org-todo-keywords-1)) @@ -18182,31 +18831,32 @@ When a buffer is unmodified, it is just killed. When modified, it is saved (append org-done-keywords-for-agenda org-done-keywords)) (setq org-todo-keyword-alist-for-agenda (append org-todo-keyword-alist-for-agenda org-todo-key-alist)) - (setq org-drawers-for-agenda - (append org-drawers-for-agenda org-drawers)) (setq org-tag-alist-for-agenda (org-uniquify (append org-tag-alist-for-agenda - org-tag-alist - org-tag-persistent-alist))) - (if org-group-tags - (setq org-tag-groups-alist-for-agenda - (org-uniquify-alist - (append org-tag-groups-alist-for-agenda org-tag-groups-alist)))) + org-current-tag-alist))) + ;; Merge current file's tag groups into global + ;; `org-tag-groups-alist-for-agenda'. + (when org-group-tags + (dolist (alist org-tag-groups-alist) + (let ((old (assoc (car alist) org-tag-groups-alist-for-agenda))) + (if old + (setcdr old (org-uniquify (append (cdr old) (cdr alist)))) + (push alist org-tag-groups-alist-for-agenda))))) (org-with-silent-modifications (save-excursion (remove-text-properties (point-min) (point-max) pall) (when org-agenda-skip-archived-trees (goto-char (point-min)) (while (re-search-forward rea nil t) - (if (org-at-heading-p t) - (add-text-properties (point-at-bol) (org-end-of-subtree t) pa)))) + (when (org-at-heading-p t) + (add-text-properties (point-at-bol) (org-end-of-subtree t) pa)))) (goto-char (point-min)) - (setq re (format org-heading-keyword-regexp-format - org-comment-string)) + (setq re (format "^\\*+ .*\\<%s\\>" org-comment-string)) (while (re-search-forward re nil t) - (add-text-properties - (match-beginning 0) (org-end-of-subtree t) pc)))) + (when (save-match-data (org-in-commented-heading-p t)) + (add-text-properties + (match-beginning 0) (org-end-of-subtree t) pc))))) (goto-char pos))))) (setq org-todo-keywords-for-agenda (org-uniquify org-todo-keywords-for-agenda)) @@ -18223,7 +18873,7 @@ When a buffer is unmodified, it is just killed. When modified, it is saved (org-defkey org-cdlatex-mode-map "^" 'org-cdlatex-underscore-caret) (org-defkey org-cdlatex-mode-map "`" 'cdlatex-math-symbol) (org-defkey org-cdlatex-mode-map "'" 'org-cdlatex-math-modify) -(org-defkey org-cdlatex-mode-map "\C-c{" 'cdlatex-environment) +(org-defkey org-cdlatex-mode-map "\C-c{" 'org-cdlatex-environment-indent) (defvar org-cdlatex-texmathp-advice-is-done nil "Flag remembering if we have applied the advice to texmathp already.") @@ -18231,7 +18881,7 @@ When a buffer is unmodified, it is just killed. When modified, it is saved (define-minor-mode org-cdlatex-mode "Toggle the minor `org-cdlatex-mode'. This mode supports entering LaTeX environment and math in LaTeX fragments -in Org-mode. +in Org mode. \\{org-cdlatex-mode-map}" nil " OCDL" nil (when org-cdlatex-mode @@ -18241,11 +18891,11 @@ in Org-mode. (unless org-cdlatex-texmathp-advice-is-done (setq org-cdlatex-texmathp-advice-is-done t) (defadvice texmathp (around org-math-always-on activate) - "Always return t in org-mode buffers. + "Always return t in Org buffers. This is because we want to insert math symbols without dollars even outside -the LaTeX math segments. If Orgmode thinks that point is actually inside -an embedded LaTeX fragment, let texmathp do its job. -\\[org-cdlatex-mode-map]" +the LaTeX math segments. If Org mode thinks that point is actually inside +an embedded LaTeX fragment, let `texmathp' do its job. +`\\[org-cdlatex-mode-map]'" (interactive) (let (p) (cond @@ -18257,8 +18907,8 @@ an embedded LaTeX fragment, let texmathp do its job. (let ((p (org-inside-LaTeX-fragment-p))) (if (and p (member (car p) (plist-get org-format-latex-options :matchers))) (setq ad-return-value t - texmathp-why '("Org-mode embedded math" . 0)) - (if p ad-do-it))))))))) + texmathp-why '("Org mode embedded math" . 0)) + (when p ad-do-it))))))))) (defun turn-on-org-cdlatex () "Unconditionally turn on `org-cdlatex-mode'." @@ -18283,7 +18933,7 @@ It makes sense to do so if `org-cdlatex-mode' is active and if the cursor is (cdlatex-tab) t) ((org-inside-LaTeX-fragment-p) (cdlatex-tab) t)))) -(defun org-cdlatex-underscore-caret (&optional arg) +(defun org-cdlatex-underscore-caret (&optional _arg) "Execute `cdlatex-sub-superscript' in LaTeX fragments. Revert to the normal definition outside of these fragments." (interactive "P") @@ -18292,7 +18942,7 @@ Revert to the normal definition outside of these fragments." (let (org-cdlatex-mode) (call-interactively (key-binding (vector last-input-event)))))) -(defun org-cdlatex-math-modify (&optional arg) +(defun org-cdlatex-math-modify (&optional _arg) "Execute `cdlatex-math-modify' in LaTeX fragments. Revert to the normal definition outside of these fragments." (interactive "P") @@ -18301,21 +18951,66 @@ Revert to the normal definition outside of these fragments." (let (org-cdlatex-mode) (call-interactively (key-binding (vector last-input-event)))))) +(defun org-cdlatex-environment-indent (&optional environment item) + "Execute `cdlatex-environment' and indent the inserted environment. + +ENVIRONMENT and ITEM are passed to `cdlatex-environment'. + +The inserted environment is indented to current indentation +unless point is at the beginning of the line, in which the +environment remains unintended." + (interactive) + ;; cdlatex-environment always return nil. Therefore, capture output + ;; first and determine if an environment was selected. + (let* ((beg (point-marker)) + (end (copy-marker (point) t)) + (inserted (progn + (ignore-errors (cdlatex-environment environment item)) + (< beg end))) + ;; Figure out how many lines to move forward after the + ;; environment has been inserted. + (lines (when inserted + (save-excursion + (- (cl-loop while (< beg (point)) + with x = 0 + do (forward-line -1) + (cl-incf x) + finally return x) + (if (progn (goto-char beg) + (and (progn (skip-chars-forward " \t") (eolp)) + (progn (skip-chars-backward " \t") (bolp)))) + 1 0))))) + (env (org-trim (delete-and-extract-region beg end)))) + (when inserted + ;; Get indentation of next line unless at column 0. + (let ((ind (if (bolp) 0 + (save-excursion + (org-return-indent) + (prog1 (org-get-indentation) + (when (progn (skip-chars-forward " \t") (eolp)) + (delete-region beg (point))))))) + (bol (progn (skip-chars-backward " \t") (bolp)))) + ;; Insert a newline before environment unless at column zero + ;; to "escape" the current line. Insert a newline if + ;; something is one the same line as \end{ENVIRONMENT}. + (insert + (concat (unless bol "\n") env + (when (and (skip-chars-forward " \t") (not (eolp))) "\n"))) + (unless (zerop ind) + (save-excursion + (goto-char beg) + (while (< (point) end) + (unless (eolp) (indent-line-to ind)) + (forward-line)))) + (goto-char beg) + (forward-line lines) + (indent-line-to ind))) + (set-marker beg nil) + (set-marker end nil))) ;;;; LaTeX fragments -(defvar org-latex-regexps - '(("begin" "^[ \t]*\\(\\\\begin{\\([a-zA-Z0-9\\*]+\\)[^\000]+?\\\\end{\\2}\\)" 1 t) - ;; ("$" "\\([ (]\\|^\\)\\(\\(\\([$]\\)\\([^ \r\n,.$].*?\\(\n.*?\\)\\{0,5\\}[^ \r\n,.$]\\)\\4\\)\\)\\([ .,?;:'\")]\\|$\\)" 2 nil) - ;; \000 in the following regex is needed for org-inside-LaTeX-fragment-p - ("$1" "\\([^$]\\|^\\)\\(\\$[^ \r\n,;.$]\\$\\)\\([- .,?;:'\")\000]\\|$\\)" 2 nil) - ("$" "\\([^$]\\|^\\)\\(\\(\\$\\([^ \r\n,;.$][^$\n\r]*?\\(\n[^$\n\r]*?\\)\\{0,2\\}[^ \r\n,.$]\\)\\$\\)\\)\\([- .,?;:'\")\000]\\|$\\)" 2 nil) - ("\\(" "\\\\([^\000]*?\\\\)" 0 nil) - ("\\[" "\\\\\\[[^\000]*?\\\\\\]" 0 nil) - ("$$" "\\$\\$[^\000]*?\\$\\$" 0 nil)) - "Regular expressions for matching embedded LaTeX.") - (defun org-inside-LaTeX-fragment-p () "Test if point is inside a LaTeX fragment. I.e. after a \\begin, \\(, \\[, $, or $$, without the corresponding closing @@ -18358,7 +19053,7 @@ looks only before point, not after." (while (re-search-backward "\\$\\$" lim t) (setq dd-on (not dd-on))) (goto-char pos) - (if dd-on (cons "$$" m)))))) + (when dd-on (cons "$$" m)))))) (defun org-inside-latex-macro-p () "Is point inside a LaTeX macro or its arguments?" @@ -18366,179 +19061,226 @@ looks only before point, not after." (org-in-regexp "\\\\[a-zA-Z]+\\*?\\(\\(\\[[^][\n{}]*\\]\\)\\|\\({[^{}\n]*}\\)\\)*"))) -(defvar org-latex-fragment-image-overlays nil - "List of overlays carrying the images of latex fragments.") -(make-variable-buffer-local 'org-latex-fragment-image-overlays) +(defun org--format-latex-make-overlay (beg end image &optional imagetype) + "Build an overlay between BEG and END using IMAGE file. +Argument IMAGETYPE is the extension of the displayed image, +as a string. It defaults to \"png\"." + (let ((ov (make-overlay beg end)) + (imagetype (or (intern imagetype) 'png))) + (overlay-put ov 'org-overlay-type 'org-latex-overlay) + (overlay-put ov 'evaporate t) + (overlay-put ov + 'modification-hooks + (list (lambda (o _flag _beg _end &optional _l) + (delete-overlay o)))) + (overlay-put ov + 'display + (list 'image :type imagetype :file image :ascent 'center)))) + +(defun org--list-latex-overlays (&optional beg end) + "List all Org LaTeX overlays in current buffer. +Limit to overlays between BEG and END when those are provided." + (cl-remove-if-not + (lambda (o) (eq (overlay-get o 'org-overlay-type) 'org-latex-overlay)) + (overlays-in (or beg (point-min)) (or end (point-max))))) + +(defun org-remove-latex-fragment-image-overlays (&optional beg end) + "Remove all overlays with LaTeX fragment images in current buffer. +When optional arguments BEG and END are non-nil, remove all +overlays between them instead. Return a non-nil value when some +overlays were removed, nil otherwise." + (let ((overlays (org--list-latex-overlays beg end))) + (mapc #'delete-overlay overlays) + overlays)) + +(defun org-toggle-latex-fragment (&optional arg) + "Preview the LaTeX fragment at point, or all locally or globally. -(defun org-remove-latex-fragment-image-overlays () - "Remove all overlays with LaTeX fragment images in current buffer." - (mapc 'delete-overlay org-latex-fragment-image-overlays) - (setq org-latex-fragment-image-overlays nil)) +If the cursor is on a LaTeX fragment, create the image and overlay +it over the source code, if there is none. Remove it otherwise. +If there is no fragment at point, display all fragments in the +current section. -(defun org-preview-latex-fragment (&optional subtree) - "Preview the LaTeX fragment at point, or all locally or globally. -If the cursor is in a LaTeX fragment, create the image and overlay -it over the source code. If there is no fragment at point, display -all fragments in the current text, from one headline to the next. With -prefix SUBTREE, display all fragments in the current subtree. With a -double prefix arg \\[universal-argument] \\[universal-argument], or when \ -the cursor is before the first headline, -display all fragments in the buffer. -The images can be removed again with \\[org-ctrl-c-ctrl-c]." +With prefix ARG, preview or clear image for all fragments in the +current subtree or in the whole buffer when used before the first +headline. With a prefix ARG `\\[universal-argument] \ +\\[universal-argument]' preview or clear images +for all fragments in the buffer." (interactive "P") - (unless buffer-file-name - (user-error "Can't preview LaTeX fragment in a non-file buffer")) (when (display-graphic-p) - (org-remove-latex-fragment-image-overlays) - (save-excursion - (save-restriction - (let (beg end at msg) + (catch 'exit + (save-excursion + (let (beg end msg) (cond - ((or (equal subtree '(16)) - (not (save-excursion - (re-search-backward org-outline-regexp-bol nil t)))) - (setq beg (point-min) end (point-max) - msg "Creating images for buffer...%s")) - ((equal subtree '(4)) - (org-back-to-heading) - (setq beg (point) end (org-end-of-subtree t) - msg "Creating images for subtree...%s")) + ((or (equal arg '(16)) + (and (equal arg '(4)) + (org-with-limited-levels (org-before-first-heading-p)))) + (if (org-remove-latex-fragment-image-overlays) + (progn (message "LaTeX fragments images removed from buffer") + (throw 'exit nil)) + (setq msg "Creating images for buffer..."))) + ((equal arg '(4)) + (org-with-limited-levels (org-back-to-heading t)) + (setq beg (point)) + (setq end (progn (org-end-of-subtree t) (point))) + (if (org-remove-latex-fragment-image-overlays beg end) + (progn + (message "LaTeX fragment images removed from subtree") + (throw 'exit nil)) + (setq msg "Creating images for subtree..."))) + ((let ((datum (org-element-context))) + (when (memq (org-element-type datum) + '(latex-environment latex-fragment)) + (setq beg (org-element-property :begin datum)) + (setq end (org-element-property :end datum)) + (if (org-remove-latex-fragment-image-overlays beg end) + (progn (message "LaTeX fragment image removed") + (throw 'exit nil)) + (setq msg "Creating image..."))))) (t - (if (setq at (org-inside-LaTeX-fragment-p)) - (goto-char (max (point-min) (- (cdr at) 2))) - (org-back-to-heading)) - (setq beg (point) end (progn (outline-next-heading) (point)) - msg (if at "Creating image...%s" - "Creating images for entry...%s")))) - (message msg "") - (narrow-to-region beg end) - (goto-char beg) - (org-format-latex - (concat org-latex-preview-ltxpng-directory (file-name-sans-extension - (file-name-nondirectory - buffer-file-name))) - default-directory 'overlays msg at 'forbuffer - org-latex-create-formula-image-program) - (message msg "done. Use `C-c C-c' to remove images.")))))) - -(defun org-format-latex (prefix &optional dir overlays msg at - forbuffer processing-type) - "Replace LaTeX fragments with links to an image, and produce images. + (org-with-limited-levels + (setq beg (if (org-at-heading-p) (line-beginning-position) + (outline-previous-heading) + (point))) + (setq end (progn (outline-next-heading) (point))) + (if (org-remove-latex-fragment-image-overlays beg end) + (progn + (message "LaTeX fragment images removed from section") + (throw 'exit nil)) + (setq msg "Creating images for section..."))))) + (let ((file (buffer-file-name (buffer-base-buffer)))) + (org-format-latex + (concat org-preview-latex-image-directory "org-ltximg") + beg end + ;; Emacs cannot overlay images from remote hosts. Create + ;; it in `temporary-file-directory' instead. + (if (or (not file) (file-remote-p file)) + temporary-file-directory + default-directory) + 'overlays msg 'forbuffer org-preview-latex-default-process)) + (message (concat msg "done"))))))) + +(defun org-format-latex + (prefix &optional beg end dir overlays msg forbuffer processing-type) + "Replace LaTeX fragments with links to an image. + +The function takes care of creating the replacement image. + +Only consider fragments between BEG and END when those are +provided. + +When optional argument OVERLAYS is non-nil, display the image on +top of the fragment instead of replacing it. + +PROCESSING-TYPE is the conversion method to use, as a symbol. + Some of the options can be changed using the variable -`org-format-latex-options'." - (if (and overlays (fboundp 'clear-image-cache)) (clear-image-cache)) - (let* ((prefixnodir (file-name-nondirectory prefix)) - (absprefix (expand-file-name prefix dir)) - (todir (file-name-directory absprefix)) - (opt org-format-latex-options) - (optnew org-format-latex-options) - (matchers (plist-get opt :matchers)) - (re-list org-latex-regexps) - (cnt 0) txt hash link beg end re checkdir - string - m n block-type block linkfile movefile ov) - ;; Check the different regular expressions - (dolist (e re-list) - (setq m (car e) re (nth 1 e) n (nth 2 e) block-type (nth 3 e) - block (if block-type "\n\n" "")) - (when (member m matchers) - (goto-char (point-min)) - (while (re-search-forward re nil t) - (when (and (or (not at) (equal (cdr at) (match-beginning n))) - (or (not overlays) - (not (eq (get-char-property (match-beginning n) - 'org-overlay-type) - 'org-latex-overlay)))) - (cond - ((eq processing-type 'verbatim)) - ((eq processing-type 'mathjax) - ;; Prepare for MathJax processing. - (setq string (match-string n)) - (when (member m '("$" "$1")) - (save-excursion - (delete-region (match-beginning n) (match-end n)) - (goto-char (match-beginning n)) - (insert (concat "\\(" (substring string 1 -1) "\\)"))))) - ((or (eq processing-type 'dvipng) - (eq processing-type 'imagemagick)) - ;; Process to an image. - (setq txt (match-string n) - beg (match-beginning n) end (match-end n) - cnt (1+ cnt)) - (let ((face (face-at-point)) - (fg (plist-get opt :foreground)) - (bg (plist-get opt :background)) - ;; Ensure full list is printed. - print-length print-level) - (when forbuffer - ;; Get the colors from the face at point. +`org-format-latex-options', which see." + (when (and overlays (fboundp 'clear-image-cache)) (clear-image-cache)) + (unless (eq processing-type 'verbatim) + (let* ((math-regexp "\\$\\|\\\\[([]\\|^[ \t]*\\\\begin{[A-Za-z0-9*]+}") + (cnt 0) + checkdir-flag) + (goto-char (or beg (point-min))) + ;; Optimize overlay creation: (info "(elisp) Managing Overlays"). + (when (and overlays (memq processing-type '(dvipng imagemagick))) + (overlay-recenter (or end (point-max)))) + (while (re-search-forward math-regexp end t) + (unless (and overlays + (eq (get-char-property (point) 'org-overlay-type) + 'org-latex-overlay)) + (let* ((context (org-element-context)) + (type (org-element-type context))) + (when (memq type '(latex-environment latex-fragment)) + (let ((block-type (eq type 'latex-environment)) + (value (org-element-property :value context)) + (beg (org-element-property :begin context)) + (end (save-excursion + (goto-char (org-element-property :end context)) + (skip-chars-backward " \r\t\n") + (point)))) + (cond + ((eq processing-type 'mathjax) + ;; Prepare for MathJax processing. + (if (not (string-match "\\`\\$\\$?" value)) + (goto-char end) + (delete-region beg end) + (if (string= (match-string 0 value) "$$") + (insert "\\[" (substring value 2 -2) "\\]") + (insert "\\(" (substring value 1 -1) "\\)")))) + ((assq processing-type org-preview-latex-process-alist) + ;; Process to an image. + (cl-incf cnt) (goto-char beg) - (when (eq fg 'auto) - (setq fg (face-attribute face :foreground nil 'default))) - (when (eq bg 'auto) - (setq bg (face-attribute face :background nil 'default))) - (setq optnew (copy-sequence opt)) - (plist-put optnew :foreground fg) - (plist-put optnew :background bg)) - (setq hash (sha1 (prin1-to-string - (list org-format-latex-header - org-latex-default-packages-alist - org-latex-packages-alist - org-format-latex-options - forbuffer txt fg bg))) - linkfile (format "%s_%s.png" prefix hash) - movefile (format "%s_%s.png" absprefix hash))) - (setq link (concat block "[[file:" linkfile "]]" block)) - (if msg (message msg cnt)) - (goto-char beg) - (unless checkdir ; Ensure the directory exists. - (setq checkdir t) - (or (file-directory-p todir) (make-directory todir t))) - (unless (file-exists-p movefile) - (org-create-formula-image - txt movefile optnew forbuffer processing-type)) - (if overlays - (progn - (mapc (lambda (o) - (if (eq (overlay-get o 'org-overlay-type) - 'org-latex-overlay) - (delete-overlay o))) - (overlays-in beg end)) - (setq ov (make-overlay beg end)) - (overlay-put ov 'org-overlay-type 'org-latex-overlay) - (if (featurep 'xemacs) + (let* ((processing-info + (cdr (assq processing-type org-preview-latex-process-alist))) + (face (face-at-point)) + ;; Get the colors from the face at point. + (fg + (let ((color (plist-get org-format-latex-options + :foreground))) + (if (and forbuffer (eq color 'auto)) + (face-attribute face :foreground nil 'default) + color))) + (bg + (let ((color (plist-get org-format-latex-options + :background))) + (if (and forbuffer (eq color 'auto)) + (face-attribute face :background nil 'default) + color))) + (hash (sha1 (prin1-to-string + (list org-format-latex-header + org-latex-default-packages-alist + org-latex-packages-alist + org-format-latex-options + forbuffer value fg bg)))) + (imagetype (or (plist-get processing-info :image-output-type) "png")) + (absprefix (expand-file-name prefix dir)) + (linkfile (format "%s_%s.%s" prefix hash imagetype)) + (movefile (format "%s_%s.%s" absprefix hash imagetype)) + (sep (and block-type "\n\n")) + (link (concat sep "[[file:" linkfile "]]" sep)) + (options + (org-combine-plists + org-format-latex-options + `(:foreground ,fg :background ,bg)))) + (when msg (message msg cnt)) + (unless checkdir-flag ; Ensure the directory exists. + (setq checkdir-flag t) + (let ((todir (file-name-directory absprefix))) + (unless (file-directory-p todir) + (make-directory todir t)))) + (unless (file-exists-p movefile) + (org-create-formula-image + value movefile options forbuffer processing-type)) + (if overlays (progn - (overlay-put ov 'invisible t) - (overlay-put - ov 'end-glyph - (make-glyph (vector 'png :file movefile)))) - (overlay-put - ov 'display - (list 'image :type 'png :file movefile :ascent 'center))) - (push ov org-latex-fragment-image-overlays) - (goto-char end)) - (delete-region beg end) - (insert (org-add-props link - (list 'org-latex-src - (replace-regexp-in-string - "\"" "" txt) - 'org-latex-src-embed-type - (if block-type 'paragraph 'character)))))) - ((eq processing-type 'mathml) - ;; Process to MathML - (unless (save-match-data (org-format-latex-mathml-available-p)) - (user-error "LaTeX to MathML converter not configured")) - (setq txt (match-string n) - beg (match-beginning n) end (match-end n) - cnt (1+ cnt)) - (if msg (message msg cnt)) - (goto-char beg) - (delete-region beg end) - (insert (org-format-latex-as-mathml - txt block-type prefix dir))) - (t - (error "Unknown conversion type %s for LaTeX fragments" - processing-type))))))))) + (dolist (o (overlays-in beg end)) + (when (eq (overlay-get o 'org-overlay-type) + 'org-latex-overlay) + (delete-overlay o))) + (org--format-latex-make-overlay beg end movefile imagetype) + (goto-char end)) + (delete-region beg end) + (insert + (org-add-props link + (list 'org-latex-src + (replace-regexp-in-string "\"" "" value) + 'org-latex-src-embed-type + (if block-type 'paragraph 'character))))))) + ((eq processing-type 'mathml) + ;; Process to MathML. + (unless (org-format-latex-mathml-available-p) + (user-error "LaTeX to MathML converter not configured")) + (cl-incf cnt) + (when msg (message msg cnt)) + (goto-char beg) + (delete-region beg end) + (insert (org-format-latex-as-mathml + value block-type prefix dir))) + (t + (error "Unknown conversion process %s for LaTeX fragments" + processing-type))))))))))) (defun org-create-math-formula (latex-frag &optional mathml-file) "Convert LATEX-FRAG to MathML and store it in MATHML-FILE. @@ -18553,20 +19295,25 @@ inspection." (buffer-substring-no-properties (region-beginning) (region-end))))) (read-string "LaTeX Fragment: " frag nil frag)))) - (unless latex-frag (error "Invalid LaTeX fragment")) - (let* ((tmp-in-file (file-relative-name - (make-temp-name (expand-file-name "ltxmathml-in")))) - (ignore (write-region latex-frag nil tmp-in-file)) + (unless latex-frag (user-error "Invalid LaTeX fragment")) + (let* ((tmp-in-file + (let ((file (file-relative-name + (make-temp-name (expand-file-name "ltxmathml-in"))))) + (write-region latex-frag nil file) + file)) (tmp-out-file (file-relative-name (make-temp-name (expand-file-name "ltxmathml-out")))) (cmd (format-spec org-latex-to-mathml-convert-command - `((?j . ,(shell-quote-argument - (expand-file-name org-latex-to-mathml-jar-file))) + `((?j . ,(and org-latex-to-mathml-jar-file + (shell-quote-argument + (expand-file-name + org-latex-to-mathml-jar-file)))) (?I . ,(shell-quote-argument tmp-in-file)) + (?i . ,latex-frag) (?o . ,(shell-quote-argument tmp-out-file))))) mathml shell-command-output) - (when (org-called-interactively-p 'any) + (when (called-interactively-p 'any) (unless (org-format-latex-mathml-available-p) (user-error "LaTeX to MathML converter not configured"))) (message "Running %s" cmd) @@ -18576,11 +19323,10 @@ inspection." (with-current-buffer (find-file-noselect tmp-out-file t) (goto-char (point-min)) (when (re-search-forward - (concat - (regexp-quote - "") - "\\(.\\|\n\\)*" - (regexp-quote "")) nil t) + (format "]*?%s[^>]*?>\\(.\\|\n\\)*" + (regexp-quote + "xmlns=\"http://www.w3.org/1998/Math/MathML\"")) + nil t) (prog1 (match-string 0) (kill-buffer)))))) (cond (mathml @@ -18588,7 +19334,7 @@ inspection." (concat "\n" mathml)) (when mathml-file (write-region mathml nil mathml-file)) - (when (org-called-interactively-p 'any) + (when (called-interactively-p 'any) (message mathml))) ((message "LaTeX to MathML conversion failed") (message shell-command-output))) @@ -18627,186 +19373,117 @@ inspection." ;; Failed conversion. Return the LaTeX fragment verbatim latex-frag))) -(defun org-create-formula-image (string tofile options buffer &optional type) - "Create an image from LaTeX source using dvipng or convert. -This function calls either `org-create-formula-image-with-dvipng' -or `org-create-formula-image-with-imagemagick' depending on the -value of `org-latex-create-formula-image-program' or on the value -of the optional TYPE variable. - -Note: ultimately these two function should be combined as they -share a good deal of logic." - (org-check-external-command - "latex" "needed to convert LaTeX fragments to images") - (funcall - (case (or type org-latex-create-formula-image-program) - ('dvipng - (org-check-external-command - "dvipng" "needed to convert LaTeX fragments to images") - #'org-create-formula-image-with-dvipng) - ('imagemagick - (org-check-external-command - "convert" "you need to install imagemagick") - #'org-create-formula-image-with-imagemagick) - (t (error - "Invalid value of `org-latex-create-formula-image-program'"))) - string tofile options buffer)) - -(declare-function org-export-get-backend "ox" (name)) -(declare-function org-export--get-global-options "ox" (&optional backend)) -(declare-function org-export--get-inbuffer-options "ox" (&optional backend)) -(declare-function org-latex-guess-inputenc "ox-latex" (header)) -(declare-function org-latex-guess-babel-language "ox-latex" (header info)) -(defun org-create-formula--latex-header () - "Return LaTeX header appropriate for previewing a LaTeX snippet." - (let ((info (org-combine-plists (org-export--get-global-options - (org-export-get-backend 'latex)) - (org-export--get-inbuffer-options - (org-export-get-backend 'latex))))) - (org-latex-guess-babel-language - (org-latex-guess-inputenc - (org-splice-latex-header - org-format-latex-header - org-latex-default-packages-alist - org-latex-packages-alist t - (plist-get info :latex-header))) - info))) - -;; This function borrows from Ganesh Swami's latex2png.el -(defun org-create-formula-image-with-dvipng (string tofile options buffer) - "This calls dvipng." - (require 'ox-latex) - (let* ((tmpdir (if (featurep 'xemacs) - (temp-directory) - temporary-file-directory)) +(defun org--get-display-dpi () + "Get the DPI of the display. +The function assumes that the display has the same pixel width in +the horizontal and vertical directions." + (if (display-graphic-p) + (round (/ (display-pixel-height) + (/ (display-mm-height) 25.4))) + (error "Attempt to calculate the dpi of a non-graphic display"))) + +(defun org-create-formula-image + (string tofile options buffer &optional processing-type) + "Create an image from LaTeX source using external processes. + +The LaTeX STRING is saved to a temporary LaTeX file, then +converted to an image file by process PROCESSING-TYPE defined in +`org-preview-latex-process-alist'. A nil value defaults to +`org-preview-latex-default-process'. + +The generated image file is eventually moved to TOFILE. + +The OPTIONS argument controls the size, foreground color and +background color of the generated image. + +When BUFFER non-nil, this function is used for LaTeX previewing. +Otherwise, it is used to deal with LaTeX snippets showed in +a HTML file." + (let* ((processing-type (or processing-type + org-preview-latex-default-process)) + (processing-info + (cdr (assq processing-type org-preview-latex-process-alist))) + (programs (plist-get processing-info :programs)) + (error-message (or (plist-get processing-info :message) "")) + (use-xcolor (plist-get processing-info :use-xcolor)) + (image-input-type (plist-get processing-info :image-input-type)) + (image-output-type (plist-get processing-info :image-output-type)) + (post-clean (or (plist-get processing-info :post-clean) + '(".dvi" ".xdv" ".pdf" ".tex" ".aux" ".log" + ".svg" ".png" ".jpg" ".jpeg" ".out"))) + (latex-header + (or (plist-get processing-info :latex-header) + (org-latex-make-preamble + (org-export-get-environment (org-export-get-backend 'latex)) + org-format-latex-header + 'snippet))) + (latex-compiler (plist-get processing-info :latex-compiler)) + (image-converter (plist-get processing-info :image-converter)) + (tmpdir temporary-file-directory) (texfilebase (make-temp-name (expand-file-name "orgtex" tmpdir))) (texfile (concat texfilebase ".tex")) - (dvifile (concat texfilebase ".dvi")) - (pngfile (concat texfilebase ".png")) - (fnh (if (featurep 'xemacs) - (font-height (face-font 'default)) - (face-attribute 'default :height nil))) - (scale (or (plist-get options (if buffer :scale :html-scale)) 1.0)) - (dpi (number-to-string (* scale (floor (* 0.9 (if buffer fnh 140.)))))) + (image-size-adjust (or (plist-get processing-info :image-size-adjust) + '(1.0 . 1.0))) + (scale (* (if buffer (car image-size-adjust) (cdr image-size-adjust)) + (or (plist-get options (if buffer :scale :html-scale)) 1.0))) + (dpi (* scale (if buffer (org--get-display-dpi) 140.0))) (fg (or (plist-get options (if buffer :foreground :html-foreground)) "Black")) (bg (or (plist-get options (if buffer :background :html-background)) - "Transparent"))) - (if (eq fg 'default) (setq fg (org-dvipng-color :foreground)) - (unless (string= fg "Transparent") (setq fg (org-dvipng-color-format fg)))) - (if (eq bg 'default) (setq bg (org-dvipng-color :background)) - (unless (string= bg "Transparent") (setq bg (org-dvipng-color-format bg)))) - (let ((latex-header (org-create-formula--latex-header))) + "Transparent")) + (log-buf (get-buffer-create "*Org Preview LaTeX Output*")) + (resize-mini-windows nil)) ;Fix Emacs flicker when creating image. + (dolist (program programs) + (org-check-external-command program error-message)) + (if use-xcolor + (progn (if (eq fg 'default) + (setq fg (org-latex-color :foreground)) + (setq fg (org-latex-color-format fg))) + (if (eq bg 'default) + (setq bg (org-latex-color :background)) + (setq bg (org-latex-color-format + (if (string= bg "Transparent") "white" bg)))) + (with-temp-file texfile + (insert latex-header) + (insert "\n\\begin{document}\n" + "\\definecolor{fg}{rgb}{" fg "}\n" + "\\definecolor{bg}{rgb}{" bg "}\n" + "\n\\pagecolor{bg}\n" + "\n{\\color{fg}\n" + string + "\n}\n" + "\n\\end{document}\n"))) + (if (eq fg 'default) + (setq fg (org-dvipng-color :foreground)) + (unless (string= fg "Transparent") + (setq fg (org-dvipng-color-format fg)))) + (if (eq bg 'default) + (setq bg (org-dvipng-color :background)) + (unless (string= bg "Transparent") + (setq bg (org-dvipng-color-format bg)))) (with-temp-file texfile (insert latex-header) (insert "\n\\begin{document}\n" string "\n\\end{document}\n"))) - (let ((dir default-directory)) - (condition-case nil - (progn - (cd tmpdir) - (call-process "latex" nil nil nil texfile)) - (error nil)) - (cd dir)) - (if (not (file-exists-p dvifile)) - (progn (message "Failed to create dvi file from %s" texfile) nil) - (condition-case nil - (if (featurep 'xemacs) - (call-process "dvipng" nil nil nil - "-fg" fg "-bg" bg - "-T" "tight" - "-o" pngfile - dvifile) - (call-process "dvipng" nil nil nil - "-fg" fg "-bg" bg - "-D" dpi - ;;"-x" scale "-y" scale - "-T" "tight" - "-o" pngfile - dvifile)) - (error nil)) - (if (not (file-exists-p pngfile)) - (if org-format-latex-signal-error - (error "Failed to create png file from %s" texfile) - (message "Failed to create png file from %s" texfile) - nil) - ;; Use the requested file name and clean up - (copy-file pngfile tofile 'replace) - (loop for e in '(".dvi" ".tex" ".aux" ".log" ".png" ".out") do - (if (file-exists-p (concat texfilebase e)) - (delete-file (concat texfilebase e)))) - pngfile)))) - -(declare-function org-latex-compile "ox-latex" (texfile &optional snippet)) -(defun org-create-formula-image-with-imagemagick (string tofile options buffer) - "This calls convert, which is included into imagemagick." - (require 'ox-latex) - (let* ((tmpdir (if (featurep 'xemacs) - (temp-directory) - temporary-file-directory)) - (texfilebase (make-temp-name - (expand-file-name "orgtex" tmpdir))) - (texfile (concat texfilebase ".tex")) - (pdffile (concat texfilebase ".pdf")) - (pngfile (concat texfilebase ".png")) - (fnh (if (featurep 'xemacs) - (font-height (face-font 'default)) - (face-attribute 'default :height nil))) - (scale (or (plist-get options (if buffer :scale :html-scale)) 1.0)) - (dpi (number-to-string (* scale (floor (if buffer fnh 120.))))) - (fg (or (plist-get options (if buffer :foreground :html-foreground)) - "black")) - (bg (or (plist-get options (if buffer :background :html-background)) - "white"))) - (if (eq fg 'default) (setq fg (org-latex-color :foreground)) - (setq fg (org-latex-color-format fg))) - (if (eq bg 'default) (setq bg (org-latex-color :background)) - (setq bg (org-latex-color-format - (if (string= bg "Transparent") "white" bg)))) - (let ((latex-header (org-create-formula--latex-header))) - (with-temp-file texfile - (insert latex-header) - (insert "\n\\begin{document}\n" - "\\definecolor{fg}{rgb}{" fg "}\n" - "\\definecolor{bg}{rgb}{" bg "}\n" - "\n\\pagecolor{bg}\n" - "\n{\\color{fg}\n" - string - "\n}\n" - "\n\\end{document}\n"))) - (org-latex-compile texfile t) - (if (not (file-exists-p pdffile)) - (progn (message "Failed to create pdf file from %s" texfile) nil) - (condition-case nil - (if (featurep 'xemacs) - (call-process "convert" nil nil nil - "-density" "96" - "-trim" - "-antialias" - pdffile - "-quality" "100" - ;; "-sharpen" "0x1.0" - pngfile) - (call-process "convert" nil nil nil - "-density" dpi - "-trim" - "-antialias" - pdffile - "-quality" "100" - ;; "-sharpen" "0x1.0" - pngfile)) - (error nil)) - (if (not (file-exists-p pngfile)) - (if org-format-latex-signal-error - (error "Failed to create png file from %s" texfile) - (message "Failed to create png file from %s" texfile) - nil) - ;; Use the requested file name and clean up - (copy-file pngfile tofile 'replace) - (loop for e in '(".pdf" ".tex" ".aux" ".log" ".png") do - (if (file-exists-p (concat texfilebase e)) - (delete-file (concat texfilebase e)))) - pngfile)))) + + (let* ((err-msg (format "Please adjust '%s' part of \ +`org-preview-latex-process-alist'." + processing-type)) + (image-input-file + (org-compile-file + texfile latex-compiler image-input-type err-msg log-buf)) + (image-output-file + (org-compile-file + image-input-file image-converter image-output-type err-msg log-buf + `((?F . ,(shell-quote-argument fg)) + (?B . ,(shell-quote-argument bg)) + (?D . ,(shell-quote-argument (format "%s" dpi))) + (?S . ,(shell-quote-argument (format "%s" (/ dpi 140.0)))))))) + (copy-file image-output-file tofile 'replace) + (dolist (e post-clean) + (when (file-exists-p (concat texfilebase e)) + (delete-file (concat texfilebase e)))) + image-output-file))) (defun org-splice-latex-header (tpl def-pkg pkg snippets-p &optional extra) "Fill a LaTeX header template TPL. @@ -18830,22 +19507,22 @@ SNIPPETS-P indicates if this is run to create snippet images for HTML." (setq rpl (if (or (match-end 1) (not def-pkg)) "" (org-latex-packages-to-string def-pkg snippets-p t)) tpl (replace-match rpl t t tpl)) - (if def-pkg (setq end (org-latex-packages-to-string def-pkg snippets-p)))) + (when def-pkg (setq end (org-latex-packages-to-string def-pkg snippets-p)))) (if (string-match "\\[\\(NO-\\)?PACKAGES\\][ \t]*\n?" tpl) (setq rpl (if (or (match-end 1) (not pkg)) "" (org-latex-packages-to-string pkg snippets-p t)) tpl (replace-match rpl t t tpl)) - (if pkg (setq end - (concat end "\n" - (org-latex-packages-to-string pkg snippets-p))))) + (when pkg (setq end + (concat end "\n" + (org-latex-packages-to-string pkg snippets-p))))) (if (string-match "\\[\\(NO-\\)?EXTRA\\][ \t]*\n?" tpl) (setq rpl (if (or (match-end 1) (not extra)) "" (concat extra "\n")) tpl (replace-match rpl t t tpl)) - (if (and extra (string-match "\\S-" extra)) - (setq end (concat end "\n" extra)))) + (when (and extra (string-match "\\S-" extra)) + (setq end (concat end "\n" extra)))) (if (string-match "\\S-" end) (concat tpl "\n" end) @@ -18869,35 +19546,21 @@ SNIPPETS-P indicates if this is run to create snippet images for HTML." (defun org-dvipng-color (attr) "Return a RGB color specification for dvipng." - (apply 'format "rgb %s %s %s" - (mapcar 'org-normalize-color - (if (featurep 'xemacs) - (color-rgb-components - (face-property 'default - (cond ((eq attr :foreground) 'foreground) - ((eq attr :background) 'background)))) - (color-values (face-attribute 'default attr nil)))))) + (org-dvipng-color-format (face-attribute 'default attr nil))) (defun org-dvipng-color-format (color-name) "Convert COLOR-NAME to a RGB color value for dvipng." - (apply 'format "rgb %s %s %s" + (apply #'format "rgb %s %s %s" (mapcar 'org-normalize-color - (color-values color-name)))) + (color-values color-name)))) (defun org-latex-color (attr) "Return a RGB color for the LaTeX color package." - (apply 'format "%s,%s,%s" - (mapcar 'org-normalize-color - (if (featurep 'xemacs) - (color-rgb-components - (face-property 'default - (cond ((eq attr :foreground) 'foreground) - ((eq attr :background) 'background)))) - (color-values (face-attribute 'default attr nil)))))) + (org-latex-color-format (face-attribute 'default attr nil))) (defun org-latex-color-format (color-name) "Convert COLOR-NAME to a RGB color value." - (apply 'format "%s,%s,%s" + (apply #'format "%s,%s,%s" (mapcar 'org-normalize-color (color-values color-name)))) @@ -18909,8 +19572,7 @@ SNIPPETS-P indicates if this is run to create snippet images for HTML." ;; Image display -(defvar org-inline-image-overlays nil) -(make-variable-buffer-local 'org-inline-image-overlays) +(defvar-local org-inline-image-overlays nil) (defun org-toggle-inline-images (&optional include-linked) "Toggle the display of inline images. @@ -18919,13 +19581,14 @@ INCLUDE-LINKED is passed to `org-display-inline-images'." (if org-inline-image-overlays (progn (org-remove-inline-images) - (message "Inline image display turned off")) + (when (called-interactively-p 'interactive) + (message "Inline image display turned off"))) (org-display-inline-images include-linked) - (if (and (org-called-interactively-p) - org-inline-image-overlays) - (message "%d images displayed inline" - (length org-inline-image-overlays)) - (message "No images to display inline")))) + (when (called-interactively-p 'interactive) + (message (if org-inline-image-overlays + (format "%d images displayed inline" + (length org-inline-image-overlays)) + "No images to display inline"))))) (defun org-redisplay-inline-images () "Refresh the display of inline images." @@ -18937,68 +19600,116 @@ INCLUDE-LINKED is passed to `org-display-inline-images'." (defun org-display-inline-images (&optional include-linked refresh beg end) "Display inline images. -Normally only links without a description part are inlined, because this -is how it will work for export. When INCLUDE-LINKED is set, also links -with a description part will be inlined. This can be nice for a quick -look at those images, but it does not reflect what exported files will look -like. -When REFRESH is set, refresh existing images between BEG and END. -This will create new image displays only if necessary. -BEG and END default to the buffer boundaries." + +An inline image is a link which follows either of these +conventions: + + 1. Its path is a file with an extension matching return value + from `image-file-name-regexp' and it has no contents. + + 2. Its description consists in a single link of the previous + type. + +When optional argument INCLUDE-LINKED is non-nil, also links with +a text description part will be inlined. This can be nice for +a quick look at those images, but it does not reflect what +exported files will look like. + +When optional argument REFRESH is non-nil, refresh existing +images between BEG and END. This will create new image displays +only if necessary. BEG and END default to the buffer +boundaries." (interactive "P") (when (display-graphic-p) (unless refresh (org-remove-inline-images) - (if (fboundp 'clear-image-cache) (clear-image-cache))) - (save-excursion - (save-restriction - (widen) - (setq beg (or beg (point-min)) end (or end (point-max))) - (goto-char beg) - (let ((re (concat "\\[\\[\\(\\(file:\\)\\|\\([./~]\\)\\)\\([^]\n]+?" - (substring (org-image-file-name-regexp) 0 -2) - "\\)\\]" (if include-linked "" "\\]"))) - (case-fold-search t) - old file ov img type attrwidth width) - (while (re-search-forward re end t) - (setq old (get-char-property-and-overlay (match-beginning 1) - 'org-image-overlay) - file (expand-file-name - (concat (or (match-string 3) "") (match-string 4)))) - (when (image-type-available-p 'imagemagick) - (setq attrwidth (if (or (listp org-image-actual-width) - (null org-image-actual-width)) - (save-excursion - (save-match-data - (when (re-search-backward - "#\\+attr.*:width[ \t]+\\([^ ]+\\)" - (save-excursion - (re-search-backward "^[ \t]*$\\|\\`" nil t)) t) - (string-to-number (match-string 1)))))) - width (cond ((eq org-image-actual-width t) nil) - ((null org-image-actual-width) attrwidth) - ((numberp org-image-actual-width) - org-image-actual-width) - ((listp org-image-actual-width) - (or attrwidth (car org-image-actual-width)))) - type (if width 'imagemagick))) - (when (file-exists-p file) - (if (and (car-safe old) refresh) - (image-refresh (overlay-get (cdr old) 'display)) - (setq img (save-match-data (create-image file type nil :width width))) - (when img - (setq ov (make-overlay (match-beginning 0) (match-end 0))) - (overlay-put ov 'display img) - (overlay-put ov 'face 'default) - (overlay-put ov 'org-image-overlay t) - (overlay-put ov 'modification-hooks - (list 'org-display-inline-remove-overlay)) - (push ov org-inline-image-overlays)))))))))) - -(define-obsolete-function-alias - 'org-display-inline-modification-hook 'org-display-inline-remove-overlay "24.3") - -(defun org-display-inline-remove-overlay (ov after beg end &optional len) + (when (fboundp 'clear-image-cache) (clear-image-cache))) + (org-with-wide-buffer + (goto-char (or beg (point-min))) + (let ((case-fold-search t) + (file-extension-re (image-file-name-regexp))) + (while (re-search-forward "[][]\\[\\(?:file\\|[./~]\\)" end t) + (let ((link (save-match-data (org-element-context)))) + ;; Check if we're at an inline image. + (when (and (equal (org-element-property :type link) "file") + (or include-linked + (not (org-element-property :contents-begin link))) + (let ((parent (org-element-property :parent link))) + (or (not (eq (org-element-type parent) 'link)) + (not (cdr (org-element-contents parent))))) + (string-match-p file-extension-re + (org-element-property :path link))) + (let ((file (expand-file-name + (org-link-unescape + (org-element-property :path link))))) + (when (file-exists-p file) + (let ((width + ;; Apply `org-image-actual-width' specifications. + (cond + ((not (image-type-available-p 'imagemagick)) nil) + ((eq org-image-actual-width t) nil) + ((listp org-image-actual-width) + (or + ;; First try to find a width among + ;; attributes associated to the paragraph + ;; containing link. + (let ((paragraph + (let ((e link)) + (while (and (setq e (org-element-property + :parent e)) + (not (eq (org-element-type e) + 'paragraph)))) + e))) + (when paragraph + (save-excursion + (goto-char (org-element-property :begin paragraph)) + (when + (re-search-forward + "^[ \t]*#\\+attr_.*?: +.*?:width +\\(\\S-+\\)" + (org-element-property + :post-affiliated paragraph) + t) + (string-to-number (match-string 1)))))) + ;; Otherwise, fall-back to provided number. + (car org-image-actual-width))) + ((numberp org-image-actual-width) + org-image-actual-width))) + (old (get-char-property-and-overlay + (org-element-property :begin link) + 'org-image-overlay))) + (if (and (car-safe old) refresh) + (image-refresh (overlay-get (cdr old) 'display)) + (let ((image (create-image file + (and width 'imagemagick) + nil + :width width))) + (when image + (let* ((link + ;; If inline image is the description + ;; of another link, be sure to + ;; consider the latter as the one to + ;; apply the overlay on. + (let ((parent + (org-element-property :parent link))) + (if (eq (org-element-type parent) 'link) + parent + link))) + (ov (make-overlay + (org-element-property :begin link) + (progn + (goto-char + (org-element-property :end link)) + (skip-chars-backward " \t") + (point))))) + (overlay-put ov 'display image) + (overlay-put ov 'face 'default) + (overlay-put ov 'org-image-overlay t) + (overlay-put + ov 'modification-hooks + (list 'org-display-inline-remove-overlay)) + (push ov org-inline-image-overlays))))))))))))))) + +(defun org-display-inline-remove-overlay (ov after _beg _end &optional _len) "Remove inline-display overlay if a corresponding region is modified." (let ((inhibit-modification-hooks t)) (when (and ov after) @@ -19008,7 +19719,7 @@ BEG and END default to the buffer boundaries." (defun org-remove-inline-images () "Remove inline display of images." (interactive) - (mapc 'delete-overlay org-inline-image-overlays) + (mapc #'delete-overlay org-inline-image-overlays) (setq org-inline-image-overlays nil)) ;;;; Key bindings @@ -19016,44 +19727,46 @@ BEG and END default to the buffer boundaries." ;; Outline functions from `outline-mode-prefix-map' ;; that can be remapped in Org: (define-key org-mode-map [remap outline-mark-subtree] 'org-mark-subtree) -(define-key org-mode-map [remap show-subtree] 'org-show-subtree) +(define-key org-mode-map [remap outline-show-subtree] 'org-show-subtree) (define-key org-mode-map [remap outline-forward-same-level] 'org-forward-heading-same-level) (define-key org-mode-map [remap outline-backward-same-level] 'org-backward-heading-same-level) -(define-key org-mode-map [remap show-branches] +(define-key org-mode-map [remap outline-show-branches] 'org-kill-note-or-show-branches) (define-key org-mode-map [remap outline-promote] 'org-promote-subtree) (define-key org-mode-map [remap outline-demote] 'org-demote-subtree) (define-key org-mode-map [remap outline-insert-heading] 'org-ctrl-c-ret) +(define-key org-mode-map [remap outline-next-visible-heading] + 'org-next-visible-heading) +(define-key org-mode-map [remap outline-previous-visible-heading] + 'org-previous-visible-heading) +(define-key org-mode-map [remap show-children] 'org-show-children) ;; Outline functions from `outline-mode-prefix-map' that can not ;; be remapped in Org: -;; + ;; - the column "key binding" shows whether the Outline function is still ;; available in Org mode on the same key that it has been bound to in ;; Outline mode: ;; - "overridden": key used for a different functionality in Org mode ;; - else: key still bound to the same Outline function in Org mode -;; -;; | Outline function | key binding | Org replacement | -;; |------------------------------------+-------------+-----------------------| -;; | `outline-next-visible-heading' | `C-c C-n' | still same function | -;; | `outline-previous-visible-heading' | `C-c C-p' | still same function | -;; | `outline-up-heading' | `C-c C-u' | still same function | -;; | `outline-move-subtree-up' | overridden | better: org-shiftup | -;; | `outline-move-subtree-down' | overridden | better: org-shiftdown | -;; | `show-entry' | overridden | no replacement | -;; | `show-children' | `C-c C-i' | visibility cycling | -;; | `show-branches' | `C-c C-k' | still same function | -;; | `show-subtree' | overridden | visibility cycling | -;; | `show-all' | overridden | no replacement | -;; | `hide-subtree' | overridden | visibility cycling | -;; | `hide-body' | overridden | no replacement | -;; | `hide-entry' | overridden | visibility cycling | -;; | `hide-leaves' | overridden | no replacement | -;; | `hide-sublevels' | overridden | no replacement | -;; | `hide-other' | overridden | no replacement | + +;; | Outline function | key binding | Org replacement | +;; |------------------------------------+-------------+--------------------------| +;; | `outline-up-heading' | `C-c C-u' | still same function | +;; | `outline-move-subtree-up' | overridden | better: org-shiftup | +;; | `outline-move-subtree-down' | overridden | better: org-shiftdown | +;; | `show-entry' | overridden | no replacement | +;; | `show-branches' | `C-c C-k' | still same function | +;; | `show-subtree' | overridden | visibility cycling | +;; | `show-all' | overridden | no replacement | +;; | `hide-subtree' | overridden | visibility cycling | +;; | `hide-body' | overridden | no replacement | +;; | `hide-entry' | overridden | visibility cycling | +;; | `hide-leaves' | overridden | no replacement | +;; | `hide-sublevels' | overridden | no replacement | +;; | `hide-other' | overridden | no replacement | ;; Make `C-c C-x' a prefix key (org-defkey org-mode-map "\C-c\C-x" (make-sparse-keymap)) @@ -19064,8 +19777,7 @@ BEG and END default to the buffer boundaries." (org-defkey org-mode-map [(control tab)] 'org-force-cycle-archived) (org-defkey org-mode-map "\M-\t" #'pcomplete) ;; The following line is necessary under Suse GNU/Linux -(unless (featurep 'xemacs) - (org-defkey org-mode-map [S-iso-lefttab] 'org-shifttab)) +(org-defkey org-mode-map [S-iso-lefttab] 'org-shifttab) (org-defkey org-mode-map [(shift tab)] 'org-shifttab) (define-key org-mode-map [backtab] 'org-shifttab) @@ -19079,6 +19791,8 @@ BEG and END default to the buffer boundaries." (org-defkey org-mode-map [(meta up)] 'org-metaup) (org-defkey org-mode-map [(meta down)] 'org-metadown) +(org-defkey org-mode-map [(control meta shift right)] 'org-increase-number-at-point) +(org-defkey org-mode-map [(control meta shift left)] 'org-decrease-number-at-point) (org-defkey org-mode-map [(meta shift left)] 'org-shiftmetaleft) (org-defkey org-mode-map [(meta shift right)] 'org-shiftmetaright) (org-defkey org-mode-map [(meta shift up)] 'org-shiftmetaup) @@ -19096,17 +19810,14 @@ BEG and END default to the buffer boundaries." ;; Babel keys (define-key org-mode-map org-babel-key-prefix org-babel-map) -(mapc (lambda (pair) - (define-key org-babel-map (car pair) (cdr pair))) - org-babel-key-bindings) +(dolist (pair org-babel-key-bindings) + (define-key org-babel-map (car pair) (cdr pair))) ;;; Extra keys for tty access. ;; We only set them when really needed because otherwise the ;; menus don't show the simple keys -(when (or org-use-extra-keys - (featurep 'xemacs) ;; because XEmacs supports multi-device stuff - (not window-system)) +(when (or org-use-extra-keys (not window-system)) (org-defkey org-mode-map "\C-c\C-xc" 'org-table-copy-down) (org-defkey org-mode-map "\C-c\C-xM" 'org-insert-todo-heading) (org-defkey org-mode-map "\C-c\C-xm" 'org-meta-return) @@ -19138,7 +19849,7 @@ BEG and END default to the buffer boundaries." ;; All the other keys -(org-defkey org-mode-map "\C-c\C-a" 'show-all) ; in case allout messed up. +(org-defkey org-mode-map "\C-c\C-a" 'outline-show-all) ; in case allout messed up. (org-defkey org-mode-map "\C-c\C-r" 'org-reveal) (if (boundp 'narrow-map) (org-defkey narrow-map "s" 'org-narrow-to-subtree) @@ -19185,6 +19896,7 @@ BEG and END default to the buffer boundaries." (org-defkey org-mode-map "\C-c\C-x\C-n" 'org-next-link) (org-defkey org-mode-map "\C-c\C-x\C-p" 'org-previous-link) (org-defkey org-mode-map "\C-c\C-l" 'org-insert-link) +(org-defkey org-mode-map "\C-c\M-l" 'org-insert-last-stored-link) (org-defkey org-mode-map "\C-c\C-\M-l" 'org-insert-all-links) (org-defkey org-mode-map "\C-c\C-o" 'org-open-at-point) (org-defkey org-mode-map "\C-c%" 'org-mark-ring-push) @@ -19209,8 +19921,10 @@ BEG and END default to the buffer boundaries." (org-defkey org-mode-map "\C-c\C-k" 'org-kill-note-or-show-branches) (org-defkey org-mode-map "\C-c#" 'org-update-statistics-cookies) (org-defkey org-mode-map [remap open-line] 'org-open-line) +(org-defkey org-mode-map [remap comment-dwim] 'org-comment-dwim) (org-defkey org-mode-map [remap forward-paragraph] 'org-forward-paragraph) (org-defkey org-mode-map [remap backward-paragraph] 'org-backward-paragraph) +(org-defkey org-mode-map "\M-^" 'org-delete-indentation) (org-defkey org-mode-map "\C-m" 'org-return) (org-defkey org-mode-map "\C-j" 'org-return-indent) (org-defkey org-mode-map "\C-c?" 'org-table-field-info) @@ -19219,6 +19933,8 @@ BEG and END default to the buffer boundaries." (org-defkey org-mode-map "\C-c=" 'org-table-eval-formula) (org-defkey org-mode-map "\C-c'" 'org-edit-special) (org-defkey org-mode-map "\C-c`" 'org-table-edit-field) +(org-defkey org-mode-map "\C-c\"a" 'orgtbl-ascii-plot) +(org-defkey org-mode-map "\C-c\"g" 'org-plot/gnuplot) (org-defkey org-mode-map "\C-c|" 'org-table-create-or-convert-from-region) (org-defkey org-mode-map [(control ?#)] 'org-table-rotate-recalc-marks) (org-defkey org-mode-map "\C-c~" 'org-table-create-with-table.el) @@ -19226,7 +19942,7 @@ BEG and END default to the buffer boundaries." (org-defkey org-mode-map "\C-c}" 'org-table-toggle-coordinate-overlays) (org-defkey org-mode-map "\C-c{" 'org-table-toggle-formula-debugger) (org-defkey org-mode-map "\C-c\C-e" 'org-export-dispatch) -(org-defkey org-mode-map "\C-c:" 'org-toggle-fixed-width-section) +(org-defkey org-mode-map "\C-c:" 'org-toggle-fixed-width) (org-defkey org-mode-map "\C-c\C-x\C-f" 'org-emphasize) (org-defkey org-mode-map "\C-c\C-xf" 'org-footnote-action) (org-defkey org-mode-map "\C-c\C-x\C-mg" 'org-mobile-pull) @@ -19250,7 +19966,7 @@ BEG and END default to the buffer boundaries." (org-defkey org-mode-map "\C-c\C-x\C-d" 'org-clock-display) (org-defkey org-mode-map "\C-c\C-x\C-r" 'org-clock-report) (org-defkey org-mode-map "\C-c\C-x\C-u" 'org-dblock-update) -(org-defkey org-mode-map "\C-c\C-x\C-l" 'org-preview-latex-fragment) +(org-defkey org-mode-map "\C-c\C-x\C-l" 'org-toggle-latex-fragment) (org-defkey org-mode-map "\C-c\C-x\C-v" 'org-toggle-inline-images) (org-defkey org-mode-map "\C-c\C-x\C-\M-v" 'org-redisplay-inline-images) (org-defkey org-mode-map "\C-c\C-x\\" 'org-toggle-pretty-entities) @@ -19260,9 +19976,8 @@ BEG and END default to the buffer boundaries." (org-defkey org-mode-map "\C-c\C-xe" 'org-set-effort) (org-defkey org-mode-map "\C-c\C-xE" 'org-inc-effort) (org-defkey org-mode-map "\C-c\C-xo" 'org-toggle-ordered-property) -(org-defkey org-mode-map "\C-c\C-xi" 'org-insert-columns-dblock) +(org-defkey org-mode-map "\C-c\C-xi" 'org-columns-insert-dblock) (org-defkey org-mode-map [(control ?c) (control ?x) ?\;] 'org-timer-set-timer) -(org-defkey org-mode-map [(control ?c) (control ?x) ?\:] 'org-timer-cancel-timer) (org-defkey org-mode-map "\C-c\C-x." 'org-timer) (org-defkey org-mode-map "\C-c\C-x-" 'org-timer-item) @@ -19280,15 +19995,11 @@ BEG and END default to the buffer boundaries." (define-key org-mode-map "\C-c\C-x[" 'org-reftex-citation) -(when (featurep 'xemacs) - (org-defkey org-mode-map 'button3 'popup-mode-menu)) - - (defconst org-speed-commands-default '( ("Outline Navigation") - ("n" . (org-speed-move-safe 'outline-next-visible-heading)) - ("p" . (org-speed-move-safe 'outline-previous-visible-heading)) + ("n" . (org-speed-move-safe 'org-next-visible-heading)) + ("p" . (org-speed-move-safe 'org-previous-visible-heading)) ("f" . (org-speed-move-safe 'org-forward-heading-same-level)) ("b" . (org-speed-move-safe 'org-backward-heading-same-level)) ("F" . org-next-block) @@ -19303,8 +20014,8 @@ BEG and END default to the buffer boundaries." ("s" . org-narrow-to-subtree) ("=" . org-columns) ("Outline Structure Editing") - ("U" . org-shiftmetaup) - ("D" . org-shiftmetadown) + ("U" . org-metaup) + ("D" . org-metadown) ("r" . org-metaright) ("l" . org-metaleft) ("R" . org-shiftmetaright) @@ -19364,10 +20075,10 @@ BEG and END default to the buffer boundaries." (user-error "Speed commands are not activated, customize `org-use-speed-commands'") (with-output-to-temp-buffer "*Help*" (princ "User-defined Speed commands\n===========================\n") - (mapc 'org-print-speed-command org-speed-commands-user) + (mapc #'org-print-speed-command org-speed-commands-user) (princ "\n") (princ "Built-in Speed commands\n=======================\n") - (mapc 'org-print-speed-command org-speed-commands-default)) + (mapc #'org-print-speed-command org-speed-commands-default)) (with-current-buffer "*Help*" (setq truncate-lines t)))) @@ -19386,9 +20097,6 @@ If not, return to the original position and throw an error." (defvar org-table-auto-blank-field) ; defined in org-table.el (defvar org-speed-command nil) -(define-obsolete-function-alias - 'org-speed-command-default-hook 'org-speed-command-activate "24.3") - (defun org-speed-command-activate (keys) "Hook for activating single-letter speed commands. `org-speed-commands-default' specifies a minimal command set. @@ -19399,9 +20107,6 @@ Use `org-speed-commands-user' for further customization." (cdr (assoc keys (append org-speed-commands-user org-speed-commands-default))))) -(define-obsolete-function-alias - 'org-babel-speed-command-hook 'org-babel-speed-command-activate "24.3") - (defun org-babel-speed-command-activate (keys) "Hook for activating single-letter code block commands." (when (and (bolp) (looking-at org-babel-src-block-regexp)) @@ -19434,9 +20139,11 @@ overwritten, and the table is not marked as requiring realignment." (org-check-before-invisible-edit 'insert) (cond ((and org-use-speed-commands - (setq org-speed-command - (run-hook-with-args-until-success - 'org-speed-command-hook (this-command-keys)))) + (let ((kv (this-command-keys-vector))) + (setq org-speed-command + (run-hook-with-args-until-success + 'org-speed-command-hook + (make-string 1 (aref kv (1- (length kv)))))))) (cond ((commandp org-speed-command) (setq this-command org-speed-command) @@ -19448,94 +20155,98 @@ overwritten, and the table is not marked as requiring realignment." (t (let (org-use-speed-commands) (call-interactively 'org-self-insert-command))))) ((and - (org-table-p) + (org-at-table-p) (progn - ;; check if we blank the field, and if that triggers align + ;; Check if we blank the field, and if that triggers align. (and (featurep 'org-table) org-table-auto-blank-field - (member last-command - '(org-cycle org-return org-shifttab org-ctrl-c-ctrl-c yas/expand)) - (if (or (equal (char-after) ?\ ) (looking-at "[^|\n]* |")) - ;; got extra space, this field does not determine column width + (memq last-command + '(org-cycle org-return org-shifttab org-ctrl-c-ctrl-c)) + (if (or (eq (char-after) ?\s) (looking-at "[^|\n]* |")) + ;; Got extra space, this field does not determine + ;; column width. (let (org-table-may-need-update) (org-table-blank-field)) - ;; no extra space, this field may determine column width + ;; No extra space, this field may determine column + ;; width. (org-table-blank-field))) t) (eq N 1) - (looking-at "[^|\n]* |")) - (let (org-table-may-need-update) - (goto-char (1- (match-end 0))) - (backward-delete-char 1) - (goto-char (match-beginning 0)) - (self-insert-command N))) + (looking-at "[^|\n]* \\( \\)|")) + ;; There is room for insertion without re-aligning the table. + (delete-region (match-beginning 1) (match-end 1)) + (self-insert-command N)) (t (setq org-table-may-need-update t) (self-insert-command N) (org-fix-tags-on-the-fly) - (if org-self-insert-cluster-for-undo - (if (not (eq last-command 'org-self-insert-command)) + (when org-self-insert-cluster-for-undo + (if (not (eq last-command 'org-self-insert-command)) + (setq org-self-insert-command-undo-counter 1) + (if (>= org-self-insert-command-undo-counter 20) (setq org-self-insert-command-undo-counter 1) - (if (>= org-self-insert-command-undo-counter 20) - (setq org-self-insert-command-undo-counter 1) - (and (> org-self-insert-command-undo-counter 0) - buffer-undo-list (listp buffer-undo-list) - (not (cadr buffer-undo-list)) ; remove nil entry - (setcdr buffer-undo-list (cddr buffer-undo-list))) - (setq org-self-insert-command-undo-counter - (1+ org-self-insert-command-undo-counter)))))))) + (and (> org-self-insert-command-undo-counter 0) + buffer-undo-list (listp buffer-undo-list) + (not (cadr buffer-undo-list)) ; remove nil entry + (setcdr buffer-undo-list (cddr buffer-undo-list))) + (setq org-self-insert-command-undo-counter + (1+ org-self-insert-command-undo-counter)))))))) (defun org-check-before-invisible-edit (kind) "Check is editing if kind KIND would be dangerous with invisible text around. The detailed reaction depends on the user option `org-catch-invisible-edits'." ;; First, try to get out of here as quickly as possible, to reduce overhead - (if (and org-catch-invisible-edits - (or (not (boundp 'visible-mode)) (not visible-mode)) - (or (get-char-property (point) 'invisible) - (get-char-property (max (point-min) (1- (point))) 'invisible))) - ;; OK, we need to take a closer look - (let* ((invisible-at-point (get-char-property (point) 'invisible)) - (invisible-before-point (if (bobp) nil (get-char-property - (1- (point)) 'invisible))) - (border-and-ok-direction - (or - ;; Check if we are acting predictably before invisible text - (and invisible-at-point (not invisible-before-point) - (memq kind '(insert delete-backward))) - ;; Check if we are acting predictably after invisible text - ;; This works not well, and I have turned it off. It seems - ;; better to always show and stop after invisible text. - ;; (and (not invisible-at-point) invisible-before-point - ;; (memq kind '(insert delete))) - ))) - (when (or (memq invisible-at-point '(outline org-hide-block t)) - (memq invisible-before-point '(outline org-hide-block t))) - (if (eq org-catch-invisible-edits 'error) - (user-error "Editing in invisible areas is prohibited, make them visible first")) - (if (and org-custom-properties-overlays - (y-or-n-p "Display invisible properties in this buffer? ")) - (org-toggle-custom-properties-visibility) - ;; Make the area visible - (save-excursion - (if invisible-before-point - (goto-char (previous-single-char-property-change - (point) 'invisible))) - (show-subtree)) - (cond - ((eq org-catch-invisible-edits 'show) - ;; That's it, we do the edit after showing - (message - "Unfolding invisible region around point before editing") - (sit-for 1)) - ((and (eq org-catch-invisible-edits 'smart) - border-and-ok-direction) - (message "Unfolding invisible region around point before editing")) - (t - ;; Don't do the edit, make the user repeat it in full visibility - (user-error "Edit in invisible region aborted, repeat to confirm with text visible")))))))) + (when (and org-catch-invisible-edits + (or (not (boundp 'visible-mode)) (not visible-mode)) + (or (get-char-property (point) 'invisible) + (get-char-property (max (point-min) (1- (point))) 'invisible))) + ;; OK, we need to take a closer look + (let* ((invisible-at-point (get-char-property (point) 'invisible)) + (invisible-before-point (unless (bobp) (get-char-property + (1- (point)) 'invisible))) + (border-and-ok-direction + (or + ;; Check if we are acting predictably before invisible text + (and invisible-at-point (not invisible-before-point) + (memq kind '(insert delete-backward))) + ;; Check if we are acting predictably after invisible text + ;; This works not well, and I have turned it off. It seems + ;; better to always show and stop after invisible text. + ;; (and (not invisible-at-point) invisible-before-point + ;; (memq kind '(insert delete))) + ))) + (when (or (memq invisible-at-point '(outline org-hide-block t)) + (memq invisible-before-point '(outline org-hide-block t))) + (when (eq org-catch-invisible-edits 'error) + (user-error "Editing in invisible areas is prohibited, make them visible first")) + (if (and org-custom-properties-overlays + (y-or-n-p "Display invisible properties in this buffer? ")) + (org-toggle-custom-properties-visibility) + ;; Make the area visible + (save-excursion + (when invisible-before-point + (goto-char (previous-single-char-property-change + (point) 'invisible))) + (outline-show-subtree)) + (cond + ((eq org-catch-invisible-edits 'show) + ;; That's it, we do the edit after showing + (message + "Unfolding invisible region around point before editing") + (sit-for 1)) + ((and (eq org-catch-invisible-edits 'smart) + border-and-ok-direction) + (message "Unfolding invisible region around point before editing")) + (t + ;; Don't do the edit, make the user repeat it in full visibility + (user-error "Edit in invisible region aborted, repeat to confirm with text visible")))))))) (defun org-fix-tags-on-the-fly () - (when (and (equal (char-after (point-at-bol)) ?*) + "Align tags in headline at point. +Unlike to `org-set-tags', it ignores region and sorting." + (when (and (eq (char-after (line-beginning-position)) ?*) ;short-circuit (org-at-heading-p)) - (org-align-tags-here org-tags-column))) + (let ((org-ignore-region t) + (org-tags-sort-function nil)) + (org-set-tags nil t)))) (defun org-delete-backward-char (N) "Like `delete-backward-char', insert whitespace at field end in tables. @@ -19546,7 +20257,7 @@ because, in this case the deletion might narrow the column." (interactive "p") (save-match-data (org-check-before-invisible-edit 'delete-backward) - (if (and (org-table-p) + (if (and (org-at-table-p) (eq N 1) (string-match "|" (buffer-substring (point-at-bol) (point))) (looking-at ".*?|")) @@ -19554,14 +20265,13 @@ because, in this case the deletion might narrow the column." (noalign (looking-at "[^|\n\r]* |")) (c org-table-may-need-update)) (backward-delete-char N) - (if (not overwrite-mode) - (progn - (skip-chars-forward "^|") - (insert " ") - (goto-char (1- pos)))) + (unless overwrite-mode + (skip-chars-forward "^|") + (insert " ") + (goto-char (1- pos))) ;; noalign: if there were two spaces at the end, this field ;; does not determine the width of the column. - (if noalign (setq org-table-may-need-update c))) + (when noalign (setq org-table-may-need-update c))) (backward-delete-char N) (org-fix-tags-on-the-fly)))) @@ -19574,7 +20284,7 @@ because, in this case the deletion might narrow the column." (interactive "p") (save-match-data (org-check-before-invisible-edit 'delete) - (if (and (org-table-p) + (if (and (org-at-table-p) (not (bolp)) (not (= (char-after) ?|)) (eq N 1)) @@ -19587,12 +20297,12 @@ because, in this case the deletion might narrow the column." (goto-char pos) ;; noalign: if there were two spaces at the end, this field ;; does not determine the width of the column. - (if noalign (setq org-table-may-need-update c))) + (when noalign (setq org-table-may-need-update c))) (delete-char N)) (delete-char N) (org-fix-tags-on-the-fly)))) -;; Make `delete-selection-mode' work with org-mode and orgtbl-mode +;; Make `delete-selection-mode' work with Org mode and Orgtbl mode (put 'org-self-insert-command 'delete-selection (lambda () (not (run-hook-with-args-until-success @@ -19611,7 +20321,7 @@ because, in this case the deletion might narrow the column." (put 'org-delete-char 'flyspell-delayed t) (put 'org-delete-backward-char 'flyspell-delayed t) -;; Make pabbrev-mode expand after org-mode commands +;; Make pabbrev-mode expand after Org mode commands (put 'org-self-insert-command 'pabbrev-expand-after-command t) (put 'orgtbl-self-insert-command 'pabbrev-expand-after-command t) @@ -19621,9 +20331,7 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command names." (let (new old) (while commands (setq old (pop commands) new (pop commands)) - (if (fboundp 'command-remapping) - (org-defkey map (vector 'remap old) new) - (substitute-key-definition old new map global-map))))) + (org-defkey map (vector 'remap old) new)))) (defun org-transpose-words () "Transpose words for Org. @@ -19765,7 +20473,7 @@ See `org-ctrl-c-ctrl-c-hook' for more information.") (defun org-shiftselect-error () "Throw an error because Shift-Cursor command was applied in wrong context." (if (and (boundp 'shift-select-mode) shift-select-mode) - (user-error "To use shift-selection with Org-mode, customize `org-support-shift-select'") + (user-error "To use shift-selection with Org mode, customize `org-support-shift-select'") (user-error "This command works only in special context like headlines or timestamps"))) (defun org-call-for-shift-select (cmd) @@ -19820,32 +20528,30 @@ individual commands for more information." (call-interactively 'org-indent-item-tree)) (t (org-modifier-cursor-error)))) -(defun org-shiftmetaup (&optional arg) - "Move subtree up or kill table row. -Calls `org-move-subtree-up' or `org-table-kill-row' or -`org-move-item-up' or `org-timestamp-up', depending on context. -See the individual commands for more information." +(defun org-shiftmetaup (&optional _arg) + "Drag the line at point up. +In a table, kill the current row. +On a clock timestamp, update the value of the timestamp like `S-' +but also adjust the previous clocked item in the clock history. +Everywhere else, drag the line at point up." (interactive "P") (cond ((run-hook-with-args-until-success 'org-shiftmetaup-hook)) ((org-at-table-p) (call-interactively 'org-table-kill-row)) - ((org-at-heading-p) (call-interactively 'org-move-subtree-up)) - ((org-at-item-p) (call-interactively 'org-move-item-up)) ((org-at-clock-log-p) (let ((org-clock-adjust-closest t)) (call-interactively 'org-timestamp-up))) (t (call-interactively 'org-drag-line-backward)))) -(defun org-shiftmetadown (&optional arg) - "Move subtree down or insert table row. -Calls `org-move-subtree-down' or `org-table-insert-row' or -`org-move-item-down' or `org-timestamp-up', depending on context. -See the individual commands for more information." +(defun org-shiftmetadown (&optional _arg) + "Drag the line at point down. +In a table, insert an empty row at the current line. +On a clock timestamp, update the value of the timestamp like `S-' +but also adjust the previous clocked item in the clock history. +Everywhere else, drag the line at point down." (interactive "P") (cond ((run-hook-with-args-until-success 'org-shiftmetadown-hook)) ((org-at-table-p) (call-interactively 'org-table-insert-row)) - ((org-at-heading-p) (call-interactively 'org-move-subtree-down)) - ((org-at-item-p) (call-interactively 'org-move-item-down)) ((org-at-clock-log-p) (let ((org-clock-adjust-closest t)) (call-interactively 'org-timestamp-down))) (t (call-interactively 'org-drag-line-forward)))) @@ -19854,11 +20560,16 @@ See the individual commands for more information." (user-error "Hidden subtree, open with TAB or use subtree command M-S-/")) -(defun org-metaleft (&optional arg) - "Promote heading or move table column to left. -Calls `org-do-promote' or `org-table-move-column', depending on context. -With no specific context, calls the Emacs default `backward-word'. -See the individual commands for more information." +(defun org-metaleft (&optional _arg) + "Promote heading, list item at point or move table column left. + +Calls `org-do-promote', `org-outdent-item' or `org-table-move-column', +depending on context. With no specific context, calls the Emacs +default `backward-word'. See the individual commands for more +information. + +This function runs the hook `org-metaleft-hook' as a first step, +and returns at first non-nil value." (interactive "P") (cond ((run-hook-with-args-until-success 'org-metaleft-hook)) @@ -19883,11 +20594,18 @@ See the individual commands for more information." (call-interactively 'org-outdent-item)) (t (call-interactively 'backward-word)))) -(defun org-metaright (&optional arg) - "Demote a subtree, a list item or move table column to right. +(defun org-metaright (&optional _arg) + "Demote heading, list item at point or move table column right. + In front of a drawer or a block keyword, indent it correctly. + +Calls `org-do-demote', `org-indent-item', `org-table-move-column', +`org-indent-drawer' or `org-indent-block' depending on context. With no specific context, calls the Emacs default `forward-word'. -See the individual commands for more information." +See the individual commands for more information. + +This function runs the hook `org-metaright-hook' as a first step, +and returns at first non-nil value." (interactive "P") (cond ((run-hook-with-args-until-success 'org-metaright-hook)) @@ -19937,11 +20655,11 @@ this function returns t, nil otherwise." (goto-char (point-at-eol)) (setq end (max end (point))) (while (re-search-forward re end t) - (if (get-char-property (match-beginning 0) 'invisible) - (throw 'exit t)))) + (when (get-char-property (match-beginning 0) 'invisible) + (throw 'exit t)))) nil)))) -(defun org-metaup (&optional arg) +(defun org-metaup (&optional _arg) "Move subtree up or move table row up. Calls `org-move-subtree-up' or `org-table-move-row' or `org-move-item-up', depending on context. See the individual commands @@ -19963,7 +20681,7 @@ for more information." ((org-at-item-p) (call-interactively 'org-move-item-up)) (t (org-drag-element-backward)))) -(defun org-metadown (&optional arg) +(defun org-metadown (&optional _arg) "Move subtree down or move table row down. Calls `org-move-subtree-down' or `org-table-move-row' or `org-move-item-down', depending on context. See the individual @@ -20149,6 +20867,32 @@ Optional argument N tells to change by that many units." (org-clock-timestamps-down n)) (user-error "Not at a clock log"))) +(defun org-increase-number-at-point (&optional inc) + "Increment the number at point. +With an optional prefix numeric argument INC, increment using +this numeric value." + (interactive "p") + (if (not (number-at-point)) + (user-error "Not on a number") + (unless inc (setq inc 1)) + (let ((pos (point)) + (beg (skip-chars-backward "-+^/*0-9eE.")) + (end (skip-chars-forward "-+^/*0-9eE^.")) nap) + (setq nap (buffer-substring-no-properties + (+ pos beg) (+ pos beg end))) + (delete-region (+ pos beg) (+ pos beg end)) + (insert (calc-eval (concat (number-to-string inc) "+" nap)))) + (when (org-at-table-p) + (org-table-align) + (org-table-end-of-field 1)))) + +(defun org-decrease-number-at-point (&optional inc) + "Decrement the number at point. +With an optional prefix numeric argument INC, decrement using +this numeric value." + (interactive "p") + (org-increase-number-at-point (- (or inc 1)))) + (defun org-ctrl-c-ret () "Call `org-table-hline-and-move' or `org-insert-heading' dep. on context." (interactive) @@ -20183,19 +20927,19 @@ Optional argument N tells to change by that many units." (defun org-copy-special () "Copy region in table or copy current subtree. -Calls `org-table-copy' or `org-copy-subtree', depending on context. -See the individual commands for more information." +Calls `org-table-copy-region' or `org-copy-subtree', depending on +context. See the individual commands for more information." (interactive) (call-interactively - (if (org-at-table-p) 'org-table-copy-region 'org-copy-subtree))) + (if (org-at-table-p) #'org-table-copy-region #'org-copy-subtree))) (defun org-cut-special () "Cut region in table or cut current subtree. -Calls `org-table-copy' or `org-cut-subtree', depending on context. -See the individual commands for more information." +Calls `org-table-cut-region' or `org-cut-subtree', depending on +context. See the individual commands for more information." (interactive) (call-interactively - (if (org-at-table-p) 'org-table-cut-region 'org-cut-subtree))) + (if (org-at-table-p) #'org-table-cut-region #'org-cut-subtree))) (defun org-paste-special (arg) "Paste rectangular region into table, or past subtree relative to level. @@ -20206,57 +20950,65 @@ See the individual commands for more information." (org-table-paste-rectangle) (org-paste-subtree arg))) -(defsubst org-in-fixed-width-region-p () - "Is point in a fixed-width region?" - (save-match-data - (eq 'fixed-width (org-element-type (org-element-at-point))))) - (defun org-edit-special (&optional arg) "Call a special editor for the element at point. When at a table, call the formula editor with `org-table-edit-formulas'. When in a source code block, call `org-edit-src-code'. When in a fixed-width region, call `org-edit-fixed-width-region'. +When in an export block, call `org-edit-export-block'. When at an #+INCLUDE keyword, visit the included file. +When at a footnote reference, call `org-edit-footnote-reference' On a link, call `ffap' to visit the link at point. Otherwise, return a user error." (interactive "P") (let ((element (org-element-at-point))) - (assert (not buffer-read-only) nil - "Buffer is read-only: %s" (buffer-name)) - (case (org-element-type element) - (src-block + (barf-if-buffer-read-only) + (pcase (org-element-type element) + (`src-block (if (not arg) (org-edit-src-code) - (let* ((info (org-babel-get-src-block-info)) - (lang (nth 0 info)) - (params (nth 2 info)) - (session (cdr (assq :session params)))) - (if (not session) (org-edit-src-code) - ;; At a src-block with a session and function called with - ;; an ARG: switch to the buffer related to the inferior - ;; process. - (switch-to-buffer + (let* ((info (org-babel-get-src-block-info)) + (lang (nth 0 info)) + (params (nth 2 info)) + (session (cdr (assq :session params)))) + (if (not session) (org-edit-src-code) + ;; At a src-block with a session and function called with + ;; an ARG: switch to the buffer related to the inferior + ;; process. + (switch-to-buffer (funcall (intern (concat "org-babel-prep-session:" lang)) session params)))))) - (keyword + (`keyword (if (member (org-element-property :key element) '("INCLUDE" "SETUPFILE")) - (find-file - (org-remove-double-quotes - (car (org-split-string (org-element-property :value element))))) + (org-open-link-from-string + (format "[[%s]]" + (expand-file-name + (let ((value (org-element-property :value element))) + (cond ((not (org-string-nw-p value)) + (user-error "No file to edit")) + ((string-match "\\`\"\\(.*?\\)\"" value) + (match-string 1 value)) + ((string-match "\\`[^ \t\"]\\S-*" value) + (match-string 0 value)) + (t (user-error "No valid file specified"))))))) (user-error "No special environment to edit here"))) - (table + (`table (if (eq (org-element-property :type element) 'table.el) - (org-edit-src-code) + (org-edit-table.el) (call-interactively 'org-table-edit-formulas))) ;; Only Org tables contain `table-row' type elements. - (table-row (call-interactively 'org-table-edit-formulas)) - ((example-block export-block) (org-edit-src-code)) - (fixed-width (org-edit-fixed-width-region)) - (otherwise - ;; No notable element at point. Though, we may be at a link, - ;; which is an object. Thus, scan deeper. - (if (eq (org-element-type (org-element-context element)) 'link) - (call-interactively 'ffap) - (user-error "No special environment to edit here")))))) + (`table-row (call-interactively 'org-table-edit-formulas)) + (`example-block (org-edit-src-code)) + (`export-block (org-edit-export-block)) + (`fixed-width (org-edit-fixed-width-region)) + (_ + ;; No notable element at point. Though, we may be at a link or + ;; a footnote reference, which are objects. Thus, scan deeper. + (let ((context (org-element-context element))) + (pcase (org-element-type context) + (`footnote-reference (org-edit-footnote-reference)) + (`inline-src-block (org-edit-inline-src-code)) + (`link (call-interactively #'ffap)) + (_ (user-error "No special environment to edit here")))))))) (defvar org-table-coordinate-overlays) ; defined in org-table.el (defun org-ctrl-c-ctrl-c (&optional arg) @@ -20305,240 +21057,314 @@ This command does many different things, depending on context: inhibited by setting `org-babel-no-eval-on-ctrl-c-ctrl-c'." (interactive "P") (cond - ((or (and (boundp 'org-clock-overlays) org-clock-overlays) - org-occur-highlights - org-latex-fragment-image-overlays) - (and (boundp 'org-clock-overlays) (org-clock-remove-overlays)) + ((or (bound-and-true-p org-clock-overlays) org-occur-highlights) + (when (boundp 'org-clock-overlays) (org-clock-remove-overlays)) (org-remove-occur-highlights) - (org-remove-latex-fragment-image-overlays) (message "Temporary highlights/overlays removed from current buffer")) - ((and (local-variable-p 'org-finish-function (current-buffer)) + ((and (local-variable-p 'org-finish-function) (fboundp org-finish-function)) (funcall org-finish-function)) + ((org-babel-hash-at-point)) ((run-hook-with-args-until-success 'org-ctrl-c-ctrl-c-hook)) (t - (let* ((context (org-element-context)) (type (org-element-type context))) - ;; Test if point is within a blank line. - (if (save-excursion (beginning-of-line) (looking-at "[ \t]*$")) - (or (run-hook-with-args-until-success 'org-ctrl-c-ctrl-c-final-hook) - (user-error "C-c C-c can do nothing useful at this location")) - (case type - ;; When at a link, act according to the parent instead. - (link (setq context (org-element-property :parent context)) - (setq type (org-element-type context))) - ;; Unsupported object types: refer to the first supported - ;; element or object containing it. - ((bold code entity export-snippet inline-babel-call inline-src-block - italic latex-fragment line-break macro strike-through subscript - superscript underline verbatim) - (while (and (setq context (org-element-property :parent context)) - (not (memq (setq type (org-element-type context)) - '(radio-target paragraph verse-block - table-cell))))))) - ;; For convenience: at the first line of a paragraph on the - ;; same line as an item, apply function on that item instead. - (when (eq type 'paragraph) - (let ((parent (org-element-property :parent context))) - (when (and (eq (org-element-type parent) 'item) - (= (point-at-bol) (org-element-property :begin parent))) - (setq context parent type 'item)))) - ;; Act according to type of element or object at point. - (case type - (clock (org-clock-update-time-maybe)) - (dynamic-block - (save-excursion - (goto-char (org-element-property :post-affiliated context)) - (org-update-dblock))) - (footnote-definition + (let* ((context + (org-element-lineage + (org-element-context) + ;; Limit to supported contexts. + '(babel-call clock dynamic-block footnote-definition + footnote-reference inline-babel-call inline-src-block + inlinetask item keyword node-property paragraph + plain-list property-drawer radio-target src-block + statistics-cookie table table-cell table-row + timestamp) + t)) + (type (org-element-type context))) + ;; For convenience: at the first line of a paragraph on the same + ;; line as an item, apply function on that item instead. + (when (eq type 'paragraph) + (let ((parent (org-element-property :parent context))) + (when (and (eq (org-element-type parent) 'item) + (= (line-beginning-position) + (org-element-property :begin parent))) + (setq context parent) + (setq type 'item)))) + ;; Act according to type of element or object at point. + ;; + ;; Do nothing on a blank line, except if it is contained in + ;; a src block. Hence, we first check if point is in such + ;; a block and then if it is at a blank line. + (pcase type + ((or `inline-src-block `src-block) + (unless org-babel-no-eval-on-ctrl-c-ctrl-c + (org-babel-eval-wipe-error-buffer) + (org-babel-execute-src-block + current-prefix-arg (org-babel-get-src-block-info nil context)))) + ((guard (org-match-line "[ \t]*$")) + (or (run-hook-with-args-until-success 'org-ctrl-c-ctrl-c-final-hook) + (user-error + (substitute-command-keys + "`\\[org-ctrl-c-ctrl-c]' can do nothing useful here")))) + ((or `babel-call `inline-babel-call) + (let ((info (org-babel-lob-get-info context))) + (when info (org-babel-execute-src-block nil info)))) + (`clock (org-clock-update-time-maybe)) + (`dynamic-block + (save-excursion (goto-char (org-element-property :post-affiliated context)) - (call-interactively 'org-footnote-action)) - (footnote-reference (call-interactively 'org-footnote-action)) - ((headline inlinetask) - (save-excursion (goto-char (org-element-property :begin context)) - (call-interactively 'org-set-tags))) - (item - ;; At an item: a double C-u set checkbox to "[-]" - ;; unconditionally, whereas a single one will toggle its - ;; presence. Without a universal argument, if the item - ;; has a checkbox, toggle it. Otherwise repair the list. - (let* ((box (org-element-property :checkbox context)) - (struct (org-element-property :structure context)) - (old-struct (copy-tree struct)) - (parents (org-list-parents-alist struct)) - (prevs (org-list-prevs-alist struct)) - (orderedp (org-not-nil (org-entry-get nil "ORDERED")))) - (org-list-set-checkbox - (org-element-property :begin context) struct - (cond ((equal arg '(16)) "[-]") - ((and (not box) (equal arg '(4))) "[ ]") - ((or (not box) (equal arg '(4))) nil) - ((eq box 'on) "[ ]") - (t "[X]"))) - ;; Mimic `org-list-write-struct' but with grabbing - ;; a return value from `org-list-struct-fix-box'. - (org-list-struct-fix-ind struct parents 2) - (org-list-struct-fix-item-end struct) - (org-list-struct-fix-bul struct prevs) - (org-list-struct-fix-ind struct parents) - (let ((block-item - (org-list-struct-fix-box struct parents prevs orderedp))) - (if (and box (equal struct old-struct)) - (if (equal arg '(16)) - (message "Checkboxes already reset") - (user-error "Cannot toggle this checkbox: %s" - (if (eq box 'on) - "all subitems checked" - "unchecked subitems"))) - (org-list-struct-apply-struct struct old-struct) - (org-update-checkbox-count-maybe)) - (when block-item - (message "Checkboxes were removed due to empty box at line %d" - (org-current-line block-item)))))) - (keyword - (let ((org-inhibit-startup-visibility-stuff t) - (org-startup-align-all-tables nil)) - (when (boundp 'org-table-coordinate-overlays) - (mapc 'delete-overlay org-table-coordinate-overlays) - (setq org-table-coordinate-overlays nil)) - (org-save-outline-visibility 'use-markers (org-mode-restart))) - (message "Local setup has been refreshed")) - (plain-list - ;; At a plain list, with a double C-u argument, set - ;; checkboxes of each item to "[-]", whereas a single one - ;; will toggle their presence according to the state of the - ;; first item in the list. Without an argument, repair the - ;; list. - (let* ((begin (org-element-property :contents-begin context)) - (beginm (move-marker (make-marker) begin)) - (struct (org-element-property :structure context)) - (old-struct (copy-tree struct)) - (first-box (save-excursion - (goto-char begin) - (looking-at org-list-full-item-re) - (match-string-no-properties 3))) - (new-box (cond ((equal arg '(16)) "[-]") - ((equal arg '(4)) (unless first-box "[ ]")) - ((equal first-box "[X]") "[ ]") - (t "[X]")))) - (cond - (arg - (mapc (lambda (pos) (org-list-set-checkbox pos struct new-box)) - (org-list-get-all-items - begin struct (org-list-prevs-alist struct)))) - ((and first-box (eq (point) begin)) - ;; For convenience, when point is at bol on the first - ;; item of the list and no argument is provided, simply - ;; toggle checkbox of that item, if any. - (org-list-set-checkbox begin struct new-box))) - (org-list-write-struct - struct (org-list-parents-alist struct) old-struct) - (org-update-checkbox-count-maybe) - (save-excursion (goto-char beginm) (org-list-send-list 'maybe)))) - ((property-drawer node-property) - (call-interactively 'org-property-action)) - ((radio-target target) - (call-interactively 'org-update-radio-target-regexp)) - (statistics-cookie - (call-interactively 'org-update-statistics-cookies)) - ((table table-cell table-row) - ;; At a table, recalculate every field and align it. Also - ;; send the table if necessary. If the table has - ;; a `table.el' type, just give up. At a table row or - ;; cell, maybe recalculate line but always align table. - (if (eq (org-element-property :type context) 'table.el) - (message "%s" "Use C-c ' to edit table.el tables") - (let ((org-enable-table-editor t)) - (if (or (eq type 'table) - ;; Check if point is at a TBLFM line. - (and (eq type 'table-row) - (= (point) (org-element-property :end context)))) - (save-excursion - (if (org-at-TBLFM-p) - (progn (require 'org-table) - (org-table-calc-current-TBLFM)) - (goto-char (org-element-property :contents-begin context)) - (org-call-with-arg 'org-table-recalculate (or arg t)) - (orgtbl-send-table 'maybe))) - (org-table-maybe-eval-formula) - (cond (arg (call-interactively 'org-table-recalculate)) - ((org-table-maybe-recalculate-line)) - (t (org-table-align))))))) - (timestamp (org-timestamp-change 0 'day)) - (otherwise - (or (run-hook-with-args-until-success 'org-ctrl-c-ctrl-c-final-hook) - (user-error - "C-c C-c can do nothing useful at this location"))))))))) + (org-update-dblock))) + (`footnote-definition + (goto-char (org-element-property :post-affiliated context)) + (call-interactively 'org-footnote-action)) + (`footnote-reference (call-interactively #'org-footnote-action)) + ((or `headline `inlinetask) + (save-excursion (goto-char (org-element-property :begin context)) + (call-interactively #'org-set-tags))) + (`item + ;; At an item: `C-u C-u' sets checkbox to "[-]" + ;; unconditionally, whereas `C-u' will toggle its presence. + ;; Without a universal argument, if the item has a checkbox, + ;; toggle it. Otherwise repair the list. + (let* ((box (org-element-property :checkbox context)) + (struct (org-element-property :structure context)) + (old-struct (copy-tree struct)) + (parents (org-list-parents-alist struct)) + (prevs (org-list-prevs-alist struct)) + (orderedp (org-not-nil (org-entry-get nil "ORDERED")))) + (org-list-set-checkbox + (org-element-property :begin context) struct + (cond ((equal arg '(16)) "[-]") + ((and (not box) (equal arg '(4))) "[ ]") + ((or (not box) (equal arg '(4))) nil) + ((eq box 'on) "[ ]") + (t "[X]"))) + ;; Mimic `org-list-write-struct' but with grabbing a return + ;; value from `org-list-struct-fix-box'. + (org-list-struct-fix-ind struct parents 2) + (org-list-struct-fix-item-end struct) + (org-list-struct-fix-bul struct prevs) + (org-list-struct-fix-ind struct parents) + (let ((block-item + (org-list-struct-fix-box struct parents prevs orderedp))) + (if (and box (equal struct old-struct)) + (if (equal arg '(16)) + (message "Checkboxes already reset") + (user-error "Cannot toggle this checkbox: %s" + (if (eq box 'on) + "all subitems checked" + "unchecked subitems"))) + (org-list-struct-apply-struct struct old-struct) + (org-update-checkbox-count-maybe)) + (when block-item + (message "Checkboxes were removed due to empty box at line %d" + (org-current-line block-item)))))) + (`keyword + (let ((org-inhibit-startup-visibility-stuff t) + (org-startup-align-all-tables nil)) + (when (boundp 'org-table-coordinate-overlays) + (mapc #'delete-overlay org-table-coordinate-overlays) + (setq org-table-coordinate-overlays nil)) + (org-save-outline-visibility 'use-markers (org-mode-restart))) + (message "Local setup has been refreshed")) + (`plain-list + ;; At a plain list, with a double C-u argument, set + ;; checkboxes of each item to "[-]", whereas a single one + ;; will toggle their presence according to the state of the + ;; first item in the list. Without an argument, repair the + ;; list. + (let* ((begin (org-element-property :contents-begin context)) + (beginm (move-marker (make-marker) begin)) + (struct (org-element-property :structure context)) + (old-struct (copy-tree struct)) + (first-box (save-excursion + (goto-char begin) + (looking-at org-list-full-item-re) + (match-string-no-properties 3))) + (new-box (cond ((equal arg '(16)) "[-]") + ((equal arg '(4)) (unless first-box "[ ]")) + ((equal first-box "[X]") "[ ]") + (t "[X]")))) + (cond + (arg + (dolist (pos + (org-list-get-all-items + begin struct (org-list-prevs-alist struct))) + (org-list-set-checkbox pos struct new-box))) + ((and first-box (eq (point) begin)) + ;; For convenience, when point is at bol on the first + ;; item of the list and no argument is provided, simply + ;; toggle checkbox of that item, if any. + (org-list-set-checkbox begin struct new-box))) + (org-list-write-struct + struct (org-list-parents-alist struct) old-struct) + (org-update-checkbox-count-maybe) + (save-excursion (goto-char beginm) (org-list-send-list 'maybe)))) + ((or `property-drawer `node-property) + (call-interactively #'org-property-action)) + (`radio-target + (call-interactively #'org-update-radio-target-regexp)) + (`statistics-cookie + (call-interactively #'org-update-statistics-cookies)) + ((or `table `table-cell `table-row) + ;; At a table, recalculate every field and align it. Also + ;; send the table if necessary. If the table has + ;; a `table.el' type, just give up. At a table row or cell, + ;; maybe recalculate line but always align table. + (if (eq (org-element-property :type context) 'table.el) + (message "%s" (substitute-command-keys "\\\ +Use `\\[org-edit-special]' to edit table.el tables")) + (let ((org-enable-table-editor t)) + (if (or (eq type 'table) + ;; Check if point is at a TBLFM line. + (and (eq type 'table-row) + (= (point) (org-element-property :end context)))) + (save-excursion + (if (org-at-TBLFM-p) + (progn (require 'org-table) + (org-table-calc-current-TBLFM)) + (goto-char (org-element-property :contents-begin context)) + (org-call-with-arg 'org-table-recalculate (or arg t)) + (orgtbl-send-table 'maybe))) + (org-table-maybe-eval-formula) + (cond (arg (call-interactively #'org-table-recalculate)) + ((org-table-maybe-recalculate-line)) + (t (org-table-align))))))) + (`timestamp (org-timestamp-change 0 'day)) + ((and `nil (guard (org-at-heading-p))) + ;; When point is on an unsupported object type, we can miss + ;; the fact that it also is at a heading. Handle it here. + (call-interactively #'org-set-tags)) + ((guard + (run-hook-with-args-until-success 'org-ctrl-c-ctrl-c-final-hook))) + (_ + (user-error + (substitute-command-keys + "`\\[org-ctrl-c-ctrl-c]' can do nothing useful here")))))))) (defun org-mode-restart () (interactive) - (let ((indent-status (org-bound-and-true-p org-indent-mode))) + (let ((indent-status (bound-and-true-p org-indent-mode))) (funcall major-mode) (hack-local-variables) - (when (and indent-status (not (org-bound-and-true-p org-indent-mode))) + (when (and indent-status (not (bound-and-true-p org-indent-mode))) (org-indent-mode -1))) (message "%s restarted" major-mode)) (defun org-kill-note-or-show-branches () - "If this is a Note buffer, abort storing the note. Else call `show-branches'." + "Abort storing current note, or call `outline-show-branches'." (interactive) (if (not org-finish-function) (progn - (hide-subtree) - (call-interactively 'show-branches)) + (outline-hide-subtree) + (call-interactively 'outline-show-branches)) (let ((org-note-abort t)) (funcall org-finish-function)))) +(defun org-delete-indentation (&optional arg) + "Join current line to previous and fix whitespace at join. + +If previous line is a headline add to headline title. Otherwise +the function calls `delete-indentation'. + +With a non-nil optional argument, join it to the following one." + (interactive "*P") + (if (save-excursion + (beginning-of-line (if arg 1 0)) + (let ((case-fold-search nil)) + (looking-at org-complex-heading-regexp))) + ;; At headline. + (let ((tags-column (when (match-beginning 5) + (save-excursion (goto-char (match-beginning 5)) + (current-column)))) + (string (concat " " (progn (when arg (forward-line 1)) + (org-trim (delete-and-extract-region + (line-beginning-position) + (line-end-position))))))) + (unless (bobp) (delete-region (point) (1- (point)))) + (goto-char (or (match-end 4) + (match-beginning 5) + (match-end 0))) + (skip-chars-backward " \t") + (save-excursion (insert string)) + ;; Adjust alignment of tags. + (cond + ((not tags-column)) ;no tags + (org-auto-align-tags (org-set-tags nil t)) + (t (org--align-tags-here tags-column)))) ;preserve tags column + (delete-indentation arg))) + (defun org-open-line (n) "Insert a new row in tables, call `open-line' elsewhere. -If `org-special-ctrl-o' is nil, just call `open-line' everywhere." +If `org-special-ctrl-o' is nil, just call `open-line' everywhere. +As a special case, when a document starts with a table, allow to +call `open-line' on the very first character." (interactive "*p") - (cond - ((not org-special-ctrl-o) - (open-line n)) - ((org-at-table-p) - (org-table-insert-row)) - (t - (open-line n)))) + (if (and org-special-ctrl-o (/= (point) 1) (org-at-table-p)) + (org-table-insert-row) + (open-line n))) (defun org-return (&optional indent) "Goto next table row or insert a newline. + Calls `org-table-next-row' or `newline', depending on context. -See the individual commands for more information." + +When optional INDENT argument is non-nil, call +`newline-and-indent' instead of `newline'. + +When `org-return-follows-link' is non-nil and point is on +a timestamp or a link, call `org-open-at-point'. However, it +will not happen if point is in a table or on a \"dead\" +object (e.g., within a comment). In these case, you need to use +`org-open-at-point' directly." (interactive) - (let (org-ts-what) + (let ((context (if org-return-follows-link (org-element-context) + (org-element-at-point)))) (cond - ((or (bobp) (org-in-src-block-p)) - (if indent (newline-and-indent) (newline))) - ((org-at-table-p) + ;; In a table, call `org-table-next-row'. + ((or (and (eq (org-element-type context) 'table) + (>= (point) (org-element-property :contents-begin context)) + (< (point) (org-element-property :contents-end context))) + (org-element-lineage context '(table-row table-cell) t)) (org-table-justify-field-maybe) - (call-interactively 'org-table-next-row)) - ;; when `newline-and-indent' is called within a list, make sure - ;; text moved stays inside the item. - ((and (org-in-item-p) indent) - (if (and (org-at-item-p) (>= (point) (match-end 0))) - (progn - (save-match-data (newline)) - (org-indent-line-to (length (match-string 0)))) - (let ((ind (org-get-indentation))) - (newline) - (if (org-looking-back org-list-end-re) - (org-indent-line) - (org-indent-line-to ind))))) - ((and org-return-follows-link - (org-at-timestamp-p t) - (not (eq org-ts-what 'after))) - (org-follow-timestamp-link)) + (call-interactively #'org-table-next-row)) + ;; On a link or a timestamp, call `org-open-at-point' if + ;; `org-return-follows-link' allows it. Tolerate fuzzy + ;; locations, e.g., in a comment, as `org-open-at-point'. ((and org-return-follows-link - (let ((tprop (get-text-property (point) 'face))) - (or (eq tprop 'org-link) - (and (listp tprop) (memq 'org-link tprop))))) - (call-interactively 'org-open-at-point)) - ((and (org-at-heading-p) - (looking-at - (org-re "\\([ \t]+\\(:[[:alnum:]_@#%:]+:\\)\\)[ \t]*$"))) - (org-show-entry) - (end-of-line 1) - (newline)) + (or (org-in-regexp org-ts-regexp-both nil t) + (org-in-regexp org-tsr-regexp-both nil t) + (org-in-regexp org-any-link-re nil t))) + (call-interactively #'org-open-at-point)) + ;; Insert newline in heading, but preserve tags. + ((and (not (bolp)) + (save-excursion (beginning-of-line) + (let ((case-fold-search nil)) + (looking-at org-complex-heading-regexp)))) + ;; At headline. Split line. However, if point is on keyword, + ;; priority cookie or tags, do not break any of them: add + ;; a newline after the headline instead. + (let ((tags-column (and (match-beginning 5) + (save-excursion (goto-char (match-beginning 5)) + (current-column)))) + (string + (when (and (match-end 4) (org-point-in-group (point) 4)) + (delete-and-extract-region (point) (match-end 4))))) + ;; Adjust tag alignment. + (cond + ((not (and tags-column string))) + (org-auto-align-tags (org-set-tags nil t)) + (t (org--align-tags-here tags-column))) ;preserve tags column + (end-of-line) + (org-show-entry) + (if indent (newline-and-indent) (newline)) + (when string (save-excursion (insert (org-trim string)))))) + ;; In a list, make sure indenting keeps trailing text within. + ((and indent + (not (eolp)) + (org-element-lineage context '(item))) + (let ((trailing-data + (delete-and-extract-region (point) (line-end-position)))) + (newline-and-indent) + (save-excursion (insert trailing-data)))) (t (if indent (newline-and-indent) (newline)))))) (defun org-return-indent () @@ -20571,146 +21397,16 @@ Calls `org-table-insert-hline', `org-toggle-item', or (call-interactively 'org-table-insert-hline)) ((org-region-active-p) (call-interactively 'org-toggle-item)) - ((org-in-item-p) - (call-interactively 'org-cycle-list-bullet)) - (t - (call-interactively 'org-toggle-item)))) - -(defun org-toggle-item (arg) - "Convert headings or normal lines to items, items to normal lines. -If there is no active region, only the current line is considered. - -If the first non blank line in the region is a headline, convert -all headlines to items, shifting text accordingly. - -If it is an item, convert all items to normal lines. - -If it is normal text, change region into a list of items. -With a prefix argument ARG, change the region in a single item." - (interactive "P") - (let ((shift-text - (function - ;; Shift text in current section to IND, from point to END. - ;; The function leaves point to END line. - (lambda (ind end) - (let ((min-i 1000) (end (copy-marker end))) - ;; First determine the minimum indentation (MIN-I) of - ;; the text. - (save-excursion - (catch 'exit - (while (< (point) end) - (let ((i (org-get-indentation))) - (cond - ;; Skip blank lines and inline tasks. - ((looking-at "^[ \t]*$")) - ((looking-at org-outline-regexp-bol)) - ;; We can't find less than 0 indentation. - ((zerop i) (throw 'exit (setq min-i 0))) - ((< i min-i) (setq min-i i)))) - (forward-line)))) - ;; Then indent each line so that a line indented to - ;; MIN-I becomes indented to IND. Ignore blank lines - ;; and inline tasks in the process. - (let ((delta (- ind min-i))) - (while (< (point) end) - (unless (or (looking-at "^[ \t]*$") - (looking-at org-outline-regexp-bol)) - (org-indent-line-to (+ (org-get-indentation) delta))) - (forward-line))))))) - (skip-blanks - (function - ;; Return beginning of first non-blank line, starting from - ;; line at POS. - (lambda (pos) - (save-excursion - (goto-char pos) - (skip-chars-forward " \r\t\n") - (point-at-bol))))) - beg end) - ;; Determine boundaries of changes. - (if (org-region-active-p) - (setq beg (funcall skip-blanks (region-beginning)) - end (copy-marker (region-end))) - (setq beg (funcall skip-blanks (point-at-bol)) - end (copy-marker (point-at-eol)))) - ;; Depending on the starting line, choose an action on the text - ;; between BEG and END. - (org-with-limited-levels - (save-excursion - (goto-char beg) - (cond - ;; Case 1. Start at an item: de-itemize. Note that it only - ;; happens when a region is active: `org-ctrl-c-minus' - ;; would call `org-cycle-list-bullet' otherwise. - ((org-at-item-p) - (while (< (point) end) - (when (org-at-item-p) - (skip-chars-forward " \t") - (delete-region (point) (match-end 0))) - (forward-line))) - ;; Case 2. Start at an heading: convert to items. - ((org-at-heading-p) - (let* ((bul (org-list-bullet-string "-")) - (bul-len (length bul)) - ;; Indentation of the first heading. It should be - ;; relative to the indentation of its parent, if any. - (start-ind (save-excursion - (cond - ((not org-adapt-indentation) 0) - ((not (outline-previous-heading)) 0) - (t (length (match-string 0)))))) - ;; Level of first heading. Further headings will be - ;; compared to it to determine hierarchy in the list. - (ref-level (org-reduced-level (org-outline-level)))) - (while (< (point) end) - (let* ((level (org-reduced-level (org-outline-level))) - (delta (max 0 (- level ref-level)))) - ;; If current headline is less indented than the first - ;; one, set it as reference, in order to preserve - ;; subtrees. - (when (< level ref-level) (setq ref-level level)) - (replace-match bul t t) - (org-indent-line-to (+ start-ind (* delta bul-len))) - ;; Ensure all text down to END (or SECTION-END) belongs - ;; to the newly created item. - (let ((section-end (save-excursion - (or (outline-next-heading) (point))))) - (forward-line) - (funcall shift-text - (+ start-ind (* (1+ delta) bul-len)) - (min end section-end))))))) - ;; Case 3. Normal line with ARG: make the first line of region - ;; an item, and shift indentation of others lines to - ;; set them as item's body. - (arg (let* ((bul (org-list-bullet-string "-")) - (bul-len (length bul)) - (ref-ind (org-get-indentation))) - (skip-chars-forward " \t") - (insert bul) - (forward-line) - (while (< (point) end) - ;; Ensure that lines less indented than first one - ;; still get included in item body. - (funcall shift-text - (+ ref-ind bul-len) - (min end (save-excursion (or (outline-next-heading) - (point))))) - (forward-line)))) - ;; Case 4. Normal line without ARG: turn each non-item line - ;; into an item. - (t - (while (< (point) end) - (unless (or (org-at-heading-p) (org-at-item-p)) - (if (looking-at "\\([ \t]*\\)\\(\\S-\\)") - (replace-match - (concat "\\1" (org-list-bullet-string "-") "\\2")))) - (forward-line)))))))) + ((org-in-item-p) + (call-interactively 'org-cycle-list-bullet)) + (t + (call-interactively 'org-toggle-item)))) (defun org-toggle-heading (&optional nstars) "Convert headings to normal text, or items or text to headings. If there is no active region, only convert the current line. -With a \\[universal-argument] prefix, convert the whole list at +With a `\\[universal-argument]' prefix, convert the whole list at point into heading. In a region: @@ -20746,7 +21442,7 @@ number of stars to add." ;; do not consider the last line to be in the region. (when (and current-prefix-arg (org-at-item-p)) - (if (listp current-prefix-arg) (setq current-prefix-arg 1)) + (when (listp current-prefix-arg) (setq current-prefix-arg 1)) (org-mark-element)) (if (org-region-active-p) @@ -20771,31 +21467,17 @@ number of stars to add." ;; Case 2. Started at an item: change items into headlines. ;; One star will be added by `org-list-to-subtree'. ((org-at-item-p) - (let* ((stars (make-string - ;; subtract the star that will be added again by - ;; `org-list-to-subtree' - (if (numberp nstars) (1- nstars) - (or (org-current-level) 0)) - ?*)) - (add-stars - (cond (nstars "") ; stars from prefix only - ((equal stars "") "") ; before first heading - (org-odd-levels-only "*") ; inside heading, odd - (t "")))) ; inside heading, oddeven - (while (< (point) end) - (when (org-at-item-p) - ;; Pay attention to cases when region ends before list. - (let* ((struct (org-list-struct)) - (list-end (min (org-list-get-bottom-point struct) (1+ end)))) - (save-restriction - (narrow-to-region (point) list-end) - (insert - (org-list-to-subtree - (org-list-parse-list t) - `(:istart (concat ',stars ',add-stars (funcall get-stars depth)) - :icount (concat ',stars ',add-stars (funcall get-stars depth))))))) - (setq toggled t)) - (forward-line)))) + (while (< (point) end) + (when (org-at-item-p) + ;; Pay attention to cases when region ends before list. + (let* ((struct (org-list-struct)) + (list-end + (min (org-list-get-bottom-point struct) (1+ end)))) + (save-restriction + (narrow-to-region (point) list-end) + (insert (org-list-to-subtree (org-list-to-lisp t)) "\n"))) + (setq toggled t)) + (forward-line))) ;; Case 3. Started at normal text: make every line an heading, ;; skipping headlines and items. (t (let* ((stars @@ -20807,7 +21489,7 @@ number of stars to add." (org-odd-levels-only "**") ; inside heading, odd (t "*"))) ; inside heading, oddeven (rpl (concat stars add-stars " ")) - (lend (if (listp nstars) (save-excursion (end-of-line) (point))))) + (lend (when (listp nstars) (save-excursion (end-of-line) (point))))) (while (< (point) (if (equal nstars '(4)) lend end)) (when (and (not (or (org-at-heading-p) (org-at-item-p) (org-at-comment-p))) (looking-at "\\([ \t]*\\)\\(\\S-\\)")) @@ -20822,17 +21504,8 @@ on context. See the individual commands for more information." (interactive) (org-check-before-invisible-edit 'insert) (or (run-hook-with-args-until-success 'org-metareturn-hook) - (let* ((element (org-element-at-point)) - (type (org-element-type element))) - (when (eq type 'table-row) - (setq element (org-element-property :parent element)) - (setq type 'table)) - (if (and (eq type 'table) - (eq (org-element-property :type element) 'org) - (>= (point) (org-element-property :contents-begin element)) - (< (point) (org-element-property :contents-end element))) - (call-interactively 'org-table-wrap-region) - (call-interactively 'org-insert-heading))))) + (call-interactively (if (org-at-table-p) #'org-table-wrap-region + #'org-insert-heading)))) ;;; Menu entries @@ -20841,7 +21514,7 @@ on context. See the individual commands for more information." (and (not (org-before-first-heading-p)) (not (org-at-table-p)))) -;; Define the Org-mode menus +;; Define the Org mode menus (easy-menu-define org-tbl-menu org-mode-map "Tbl menu" '("Tbl" ["Align" org-ctrl-c-ctrl-c :active (org-at-table-p)] @@ -20888,11 +21561,11 @@ on context. See the individual commands for more information." ["Which Column?" org-table-current-column (org-at-table-p)]) ["Debug Formulas" org-table-toggle-formula-debugger - :style toggle :selected (org-bound-and-true-p org-table-formula-debug)] + :style toggle :selected (bound-and-true-p org-table-formula-debug)] ["Show Col/Row Numbers" org-table-toggle-coordinate-overlays :style toggle - :selected (org-bound-and-true-p org-table-overlay-coordinates)] + :selected (bound-and-true-p org-table-overlay-coordinates)] "--" ["Create" org-table-create (and (not (org-at-table-p)) org-enable-table-editor)] @@ -20900,7 +21573,11 @@ on context. See the individual commands for more information." ["Import from File" org-table-import (not (org-at-table-p))] ["Export to File" org-table-export (org-at-table-p)] "--" - ["Create/Convert from/to table.el" org-table-create-with-table.el t])) + ["Create/Convert from/to table.el" org-table-create-with-table.el t] + "--" + ("Plot" + ["Ascii plot" orgtbl-ascii-plot :active (org-at-table-p) :keys "C-c \" a"] + ["Gnuplot" org-plot/gnuplot :active (org-at-table-p) :keys "C-c \" g"]))) (easy-menu-define org-org-menu org-mode-map "Org menu" '("Org" @@ -20909,7 +21586,7 @@ on context. See the individual commands for more information." ["Cycle Global Visibility" org-shifttab :active (not (org-at-table-p))] ["Sparse Tree..." org-sparse-tree t] ["Reveal Context" org-reveal t] - ["Show All" show-all t] + ["Show All" outline-show-all t] "--" ["Subtree to indirect buffer" org-tree-to-indirect-buffer t]) "--" @@ -20925,8 +21602,8 @@ on context. See the individual commands for more information." ("Edit Structure" ["Refile Subtree" org-refile (org-in-subtree-not-table-p)] "--" - ["Move Subtree Up" org-shiftmetaup (org-in-subtree-not-table-p)] - ["Move Subtree Down" org-shiftmetadown (org-in-subtree-not-table-p)] + ["Move Subtree Up" org-metaup (org-at-heading-p)] + ["Move Subtree Down" org-metadown (org-at-heading-p)] "--" ["Copy Subtree" org-copy-special (org-in-subtree-not-table-p)] ["Cut Subtree" org-cut-special (org-in-subtree-not-table-p)] @@ -21012,7 +21689,7 @@ on context. See the individual commands for more information." "--" ["Set property" org-set-property (not (org-before-first-heading-p))] ["Column view of properties" org-columns t] - ["Insert Column View DBlock" org-insert-columns-dblock t]) + ["Insert Column View DBlock" org-columns-insert-dblock t]) ("Dates and Scheduling" ["Timestamp" org-time-stamp (not (org-before-first-heading-p))] ["Timestamp (inactive)" org-time-stamp-inactive (not (org-before-first-heading-p))] @@ -21073,9 +21750,7 @@ on context. See the individual commands for more information." ["Insert math symbol" cdlatex-math-symbol (fboundp 'cdlatex-math-symbol)] ["Modify math symbol" org-cdlatex-math-modify (org-inside-LaTeX-fragment-p)] - ["Insert citation" org-reftex-citation t] - "--" - ["Template for BEAMER" (org-beamer-insert-options-template) t]) + ["Insert citation" org-reftex-citation t]) "--" ("MobileOrg" ["Push Files and Views" org-mobile-push t] @@ -21101,20 +21776,20 @@ on context. See the individual commands for more information." )) (defun org-info (&optional node) - "Read documentation for Org-mode in the info system. + "Read documentation for Org in the info system. With optional NODE, go directly to that node." (interactive) (info (format "(org)%s" (or node "")))) ;;;###autoload (defun org-submit-bug-report () - "Submit a bug report on Org-mode via mail. + "Submit a bug report on Org via mail. Don't hesitate to report any problems or inaccurate documentation. If you don't have setup sending mail from (X)Emacs, please copy the output buffer into your mail program, as it gives us important -information about your Org-mode version and configuration." +information about your Org version and configuration." (interactive) (require 'reporter) (defvar reporter-prompt-for-summary-p) @@ -21126,12 +21801,12 @@ information about your Org-mode version and configuration." (org-version nil 'full) (let (list) (save-window-excursion - (org-pop-to-buffer-same-window (get-buffer-create "*Warn about privacy*")) + (pop-to-buffer-same-window (get-buffer-create "*Warn about privacy*")) (delete-other-windows) (erase-buffer) - (insert "You are about to submit a bug report to the Org-mode mailing list. + (insert "You are about to submit a bug report to the Org mailing list. -We would like to add your full Org-mode and Outline configuration to the +We would like to add your full Org and Outline configuration to the bug report. This greatly simplifies the work of the maintainer and other experts on the mailing list. @@ -21141,7 +21816,7 @@ appear in the form of file names, tags, todo states, or search strings. If you answer yes to the prompt, you might want to check and remove such private information before sending the email.") (add-text-properties (point-min) (point-max) '(face org-warning)) - (when (yes-or-no-p "Include your Org-mode configuration ") + (when (yes-or-no-p "Include your Org configuration ") (mapatoms (lambda (v) (and (boundp v) @@ -21160,11 +21835,11 @@ what in fact did happen. You don't know how to make a good report? See http://orgmode.org/manual/Feedback.html#Feedback -Your bug report will be posted to the Org-mode mailing list. +Your bug report will be posted to the Org mailing list. ------------------------------------------------------------------------") (save-excursion - (if (re-search-backward "^\\(Subject: \\)Org-mode version \\(.*?\\);[ \t]*\\(.*\\)" nil t) - (replace-match "\\1Bug: \\3 [\\2]"))))) + (when (re-search-backward "^\\(Subject: \\)Org mode version \\(.*?\\);[ \t]*\\(.*\\)" nil t) + (replace-match "\\1Bug: \\3 [\\2]"))))) (defun org-install-agenda-files-menu () @@ -21172,7 +21847,7 @@ Your bug report will be posted to the Org-mode mailing list. (save-excursion (while bl (set-buffer (pop bl)) - (if (derived-mode-p 'org-mode) (setq bl nil))) + (when (derived-mode-p 'org-mode) (setq bl nil))) (when (derived-mode-p 'org-mode) (easy-menu-change '("Org") "File List for Agenda" @@ -21190,7 +21865,7 @@ Your bug report will be posted to the Org-mode mailing list. (defun org-require-autoloaded-modules () (interactive) - (mapc 'require + (mapc #'require '(org-agenda org-archive org-attach org-clock org-colview org-id org-table org-timer))) @@ -21203,13 +21878,8 @@ With prefix arg UNCOMPILED, load the uncompiled versions." (let* ((org-dir (org-find-library-dir "org")) (contrib-dir (or (org-find-library-dir "org-contribdir") org-dir)) (feature-re "^\\(org\\|ob\\|ox\\)\\(-.*\\)?") - (remove-re (mapconcat 'identity - (mapcar (lambda (f) (concat "^" f "$")) - (list (if (featurep 'xemacs) - "org-colview" - "org-colview-xemacs") - "org" "org-loaddefs" "org-version")) - "\\|")) + (remove-re (format "\\`%s\\'" + (regexp-opt '("org" "org-loaddefs" "org-version")))) (feats (delete-dups (mapcar 'file-name-sans-extension (mapcar 'file-name-nondirectory @@ -21241,9 +21911,9 @@ With prefix arg UNCOMPILED, load the uncompiled versions." 't) f)) lfeat))) - (if load-uncore - (message "The following feature%s found in load-path, please check if that's correct:\n%s" - (if (> (length load-uncore) 1) "s were" " was") load-uncore)) + (when load-uncore + (message "The following feature%s found in load-path, please check if that's correct:\n%s" + (if (> (length load-uncore) 1) "s were" " was") load-uncore)) (if load-misses (message "Some error occurred while reloading Org feature%s\n%s\nPlease check *Messages*!\n%s" (if (> (length load-misses) 1) "s" "") load-misses (org-version nil 'full)) @@ -21258,7 +21928,7 @@ With prefix arg UNCOMPILED, load the uncompiled versions." (customize-browse 'org)) (defun org-create-customize-menu () - "Create a full customization menu for Org-mode, insert it into the menu." + "Create a full customization menu for Org mode, insert it into the menu." (interactive) (org-load-modules-maybe) (org-require-autoloaded-modules) @@ -21281,9 +21951,9 @@ With prefix arg UNCOMPILED, load the uncompiled versions." ;;; Generally useful functions -(defun org-get-at-bol (property) - "Get text property PROPERTY at beginning of line." - (get-text-property (point-at-bol) property)) +(defun org-get-at-eol (property n) + "Get text property PROPERTY at the end of line less N characters." + (get-text-property (- (point-at-eol) n) property)) (defun org-find-text-property-in-string (prop s) "Return the first non-nil value of property PROP in string S." @@ -21291,19 +21961,9 @@ With prefix arg UNCOMPILED, load the uncompiled versions." (get-text-property (or (next-single-property-change 0 prop s) 0) prop s))) -(defun org-display-warning (message) ;; Copied from Emacs-Muse +(defun org-display-warning (message) "Display the given MESSAGE as a warning." - (if (fboundp 'display-warning) - (display-warning 'org message - (if (featurep 'xemacs) 'warning :warning)) - (let ((buf (get-buffer-create "*Org warnings*"))) - (with-current-buffer buf - (goto-char (point-max)) - (insert "Warning (Org): " message) - (unless (bolp) - (newline))) - (display-buffer buf) - (sit-for 0)))) + (display-warning 'org message :warning)) (defun org-eval (form) "Eval FORM and return result." @@ -21322,17 +21982,6 @@ With prefix arg UNCOMPILED, load the uncompiled versions." (>= (match-end 0) pos) start)))) -(defun org-in-commented-line () - "Is point in a line starting with `#'?" - (equal (char-after (point-at-bol)) ?#)) - -(defun org-in-indented-comment-line () - "Is point in a line starting with `#' after some white space?" - (save-excursion - (save-match-data - (goto-char (point-at-bol)) - (looking-at "[ \t]*#")))) - (defun org-in-verbatim-emphasis () (save-match-data (and (org-in-regexp org-emph-re 2) @@ -21340,14 +21989,35 @@ With prefix arg UNCOMPILED, load the uncompiled versions." (<= (point) (match-end 4)) (member (match-string 3) '("=" "~"))))) +(defun org-overlay-display (ovl text &optional face evap) + "Make overlay OVL display TEXT with face FACE." + (overlay-put ovl 'display text) + (if face (overlay-put ovl 'face face)) + (if evap (overlay-put ovl 'evaporate t))) + +(defun org-overlay-before-string (ovl text &optional face evap) + "Make overlay OVL display TEXT with face FACE." + (if face (org-add-props text nil 'face face)) + (overlay-put ovl 'before-string text) + (if evap (overlay-put ovl 'evaporate t))) + +(defun org-find-overlays (prop &optional pos delete) + "Find all overlays specifying PROP at POS or point. +If DELETE is non-nil, delete all those overlays." + (let (found) + (dolist (ov (overlays-at (or pos (point))) found) + (cond ((not (overlay-get ov prop))) + (delete (delete-overlay ov)) + (t (push ov found)))))) + (defun org-goto-marker-or-bmk (marker &optional bookmark) "Go to MARKER, widen if necessary. When marker is not live, try BOOKMARK." (if (and marker (marker-buffer marker) (buffer-live-p (marker-buffer marker))) (progn - (org-pop-to-buffer-same-window (marker-buffer marker)) - (if (or (> marker (point-max)) (< marker (point-min))) - (widen)) + (pop-to-buffer-same-window (marker-buffer marker)) + (when (or (> marker (point-max)) (< marker (point-min))) + (widen)) (goto-char marker) (org-show-context 'org-goto)) (if bookmark @@ -21390,7 +22060,7 @@ upon the next fontification round." l)) (defun org-shorten-string (s maxlength) - "Shorten string S so tht it is no longer than MAXLENGTH characters. + "Shorten string S so that it is no longer than MAXLENGTH characters. If the string is shorter or has length MAXLENGTH, just return the original string. If it is longer, the functions finds a space in the string, breaks this string off at that locations and adds three dots @@ -21410,8 +22080,8 @@ if necessary." "Get the indentation of the current line, interpreting tabs. When LINE is given, assume it represents a line and compute its indentation." (if line - (if (string-match "^ *" (org-remove-tabs line)) - (match-end 0)) + (when (string-match "^ *" (org-remove-tabs line)) + (match-end 0)) (save-excursion (beginning-of-line 1) (skip-chars-forward " \t") @@ -21448,35 +22118,45 @@ leave it alone. If it is larger than ind, set it to the target." (let* ((l (org-remove-tabs line)) (i (org-get-indentation l)) (i1 (car ind)) (i2 (cdr ind))) - (if (>= i i2) (setq l (substring line i2))) + (when (>= i i2) (setq l (substring line i2))) (if (> i1 0) (concat (make-string i1 ?\ ) l) l))) (defun org-remove-indentation (code &optional n) - "Remove the maximum common indentation from the lines in CODE. -N may optionally be the number of spaces to remove." + "Remove maximum common indentation in string CODE and return it. +N may optionally be the number of columns to remove. Return CODE +as-is if removal failed." (with-temp-buffer (insert code) - (org-do-remove-indentation n) - (buffer-string))) + (if (org-do-remove-indentation n) (buffer-string) code))) (defun org-do-remove-indentation (&optional n) - "Remove the maximum common indentation from the buffer." - (untabify (point-min) (point-max)) - (let ((min 10000) re) - (if n - (setq min n) - (goto-char (point-min)) - (while (re-search-forward "^ *[^ \n]" nil t) - (setq min (min min (1- (- (match-end 0) (match-beginning 0))))))) - (unless (or (= min 0) (= min 10000)) - (setq re (format "^ \\{%d\\}" min)) - (goto-char (point-min)) - (while (re-search-forward re nil t) - (replace-match "") - (end-of-line 1)) - min))) + "Remove the maximum common indentation from the buffer. +When optional argument N is a positive integer, remove exactly +that much characters from indentation, if possible. Return nil +if it fails." + (catch :exit + (goto-char (point-min)) + ;; Find maximum common indentation, if not specified. + (let ((n (or n + (let ((min-ind (point-max))) + (save-excursion + (while (re-search-forward "^[ \t]*\\S-" nil t) + (let ((ind (1- (current-column)))) + (if (zerop ind) (throw :exit nil) + (setq min-ind (min min-ind ind)))))) + min-ind)))) + (if (zerop n) (throw :exit nil) + ;; Remove exactly N indentation, but give up if not possible. + (while (not (eobp)) + (let ((ind (progn (skip-chars-forward " \t") (current-column)))) + (cond ((eolp) (delete-region (line-beginning-position) (point))) + ((< ind n) (throw :exit nil)) + (t (indent-line-to (- ind n)))) + (forward-line))) + ;; Signal success. + t)))) (defun org-fill-template (template alist) "Find each %key of ALIST in TEMPLATE and replace it." @@ -21496,12 +22176,6 @@ N may optionally be the number of spaces to remove." (or (buffer-base-buffer buffer) buffer))) -(defun org-trim (s) - "Remove whitespace at beginning and end of string." - (if (string-match "\\`[ \t\n\r]+" s) (setq s (replace-match "" t t s))) - (if (string-match "[ \t\n\r]+\\'" s) (setq s (replace-match "" t t s))) - s) - (defun org-wrap (string &optional width lines) "Wrap string to either a number of lines, or a width in characters. If WIDTH is non-nil, the string is wrapped to that width, however many lines @@ -21539,13 +22213,12 @@ The return value is a list of lines, without newlines at the end." (defun org-split-string (string &optional separators) "Splits STRING into substrings at SEPARATORS. +SEPARATORS is a regular expression. No empty strings are returned if there are matches at the beginning and end of string." - (let ((rexp (or separators "[ \f\t\n\r\v]+")) - (start 0) - notfirst - (list nil)) - (while (and (string-match rexp string + ;; FIXME: why not use (split-string STRING SEPARATORS t)? + (let ((start 0) notfirst list) + (while (and (string-match (or separators "[ \f\t\n\r\v]+") string (if (and notfirst (= start (match-beginning 0)) (< start (length string))) @@ -21555,14 +22228,10 @@ and end of string." (or (eq (match-beginning 0) 0) (and (eq (match-beginning 0) (match-end 0)) (eq (match-beginning 0) start)) - (setq list - (cons (substring string start (match-beginning 0)) - list))) + (push (substring string start (match-beginning 0)) list)) (setq start (match-end 0))) (or (eq start (length string)) - (setq list - (cons (substring string start) - list))) + (push (substring string start) list)) (nreverse list))) (defun org-quote-vert (s) @@ -21579,10 +22248,8 @@ and end of string." "Whether point is in a code source block. When INSIDE is non-nil, don't consider we are within a src block when point is at #+BEGIN_SRC or #+END_SRC." - (let ((case-fold-search t) ov) - (or (and (setq ov (overlays-at (point))) - (memq 'org-block-background - (overlay-properties (car ov)))) + (let ((case-fold-search t)) + (or (and (eq (get-char-property (point) 'src-block) t)) (and (not inside) (save-match-data (save-excursion @@ -21604,13 +22271,13 @@ contexts are: :item on the first line of a plain list item :item-bullet on the bullet/number of a plain list item :checkbox on the checkbox in a plain list item -:table in an org-mode table +:table in an Org table :table-special on a special filed in a table :table-table in a table.el table :clocktable in a clocktable :src-block in a source block :link on a hyperlink -:keyword on a keyword: SCHEDULED, DEADLINE, CLOSE, COMMENT, QUOTE. +:keyword on a keyword: SCHEDULED, DEADLINE, CLOSE, COMMENT. :target on a <> :radio-target on a <<>> :latex-fragment on a LaTeX fragment @@ -21635,8 +22302,8 @@ and :keyword." (push (org-point-in-group p 4 :tags) clist)) (goto-char p) (skip-chars-backward "^[\n\r \t") (or (bobp) (backward-char 1)) - (if (looking-at "\\[#[A-Z0-9]\\]") - (push (org-point-in-group p 0 :priority) clist))) + (when (looking-at "\\[#[A-Z0-9]\\]") + (push (org-point-in-group p 0 :priority) clist))) ((org-at-item-p) (push (org-point-in-group p 2 :item-bullet) clist) @@ -21648,10 +22315,10 @@ and :keyword." ((org-at-table-p) (push (list :table (org-table-begin) (org-table-end)) clist) - (if (memq 'org-formula faces) - (push (list :table-special - (previous-single-property-change p 'face) - (next-single-property-change p 'face)) clist))) + (when (memq 'org-formula faces) + (push (list :table-special + (previous-single-property-change p 'face) + (next-single-property-change p 'face)) clist))) ((org-at-table-p 'any) (push (list :table-table) clist))) (goto-char p) @@ -21660,16 +22327,16 @@ and :keyword." ;; New the "medium" contexts: clocktables, source blocks (cond ((org-in-clocktable-p) (push (list :clocktable - (and (or (looking-at "#\\+BEGIN: clocktable") - (search-backward "#+BEGIN: clocktable" nil t)) - (match-beginning 0)) - (and (re-search-forward "#\\+END:?" nil t) + (and (or (looking-at "[ \t]*\\(#\\+BEGIN: clocktable\\)") + (re-search-backward "[ \t]*\\(#+BEGIN: clocktable\\)" nil t)) + (match-beginning 1)) + (and (re-search-forward "[ \t]*#\\+END:?" nil t) (match-end 0))) clist)) ((org-in-src-block-p) (push (list :src-block - (and (or (looking-at "#\\+BEGIN_SRC") - (search-backward "#+BEGIN_SRC" nil t)) - (match-beginning 0)) + (and (or (looking-at "[ \t]*\\(#\\+BEGIN_SRC\\)") + (re-search-backward "[ \t]*\\(#+BEGIN_SRC\\)" nil t)) + (match-beginning 1)) (and (search-forward "#+END_SRC" nil t) (match-beginning 0))) clist)))) (goto-char p) @@ -21689,14 +22356,14 @@ and :keyword." ((org-at-target-p) (push (org-point-in-group p 0 :target) clist) (goto-char (1- (match-beginning 0))) - (if (looking-at org-radio-target-regexp) - (push (org-point-in-group p 0 :radio-target) clist)) + (when (looking-at org-radio-target-regexp) + (push (org-point-in-group p 0 :radio-target) clist)) (goto-char p)) - ((setq o (car (delq nil - (mapcar - (lambda (x) - (if (memq x org-latex-fragment-image-overlays) x)) - (overlays-at (point)))))) + ((setq o (cl-some + (lambda (o) + (and (eq (overlay-get o 'org-overlay-type) 'org-latex-overlay) + o)) + (overlays-at (point)))) (push (list :latex-fragment (overlay-start o) (overlay-end o)) clist) (push (list :latex-preview @@ -21708,35 +22375,27 @@ and :keyword." (setq clist (nreverse (delq nil clist))) clist)) -;; FIXME: Compare with at-regexp-p Do we need both? -(defun org-in-regexp (re &optional nlines visually) - "Check if point is inside a match of regexp. -Normally only the current line is checked, but you can include NLINES extra -lines both before and after point into the search. -If VISUALLY is set, require that the cursor is not after the match but -really on, so that the block visually is on the match." - (catch 'exit +(defun org-in-regexp (regexp &optional nlines visually) + "Check if point is inside a match of REGEXP. + +Normally only the current line is checked, but you can include +NLINES extra lines around point into the search. If VISUALLY is +set, require that the cursor is not after the match but really +on, so that the block visually is on the match. + +Return nil or a cons cell (BEG . END) where BEG and END are, +respectively, the positions at the beginning and the end of the +match." + (catch :exit (let ((pos (point)) - (eol (point-at-eol (+ 1 (or nlines 0)))) - (inc (if visually 1 0))) + (eol (line-end-position (if nlines (1+ nlines) 1)))) (save-excursion (beginning-of-line (- 1 (or nlines 0))) - (while (re-search-forward re eol t) - (if (and (<= (match-beginning 0) pos) - (>= (+ inc (match-end 0)) pos)) - (throw 'exit (cons (match-beginning 0) (match-end 0))))))))) - -(defun org-at-regexp-p (regexp) - "Is point inside a match of REGEXP in the current line?" - (catch 'exit - (save-excursion - (let ((pos (point)) (end (point-at-eol))) - (beginning-of-line 1) - (while (re-search-forward regexp end t) - (if (and (<= (match-beginning 0) pos) - (>= (match-end 0) pos)) - (throw 'exit t))) - nil)))) + (while (and (re-search-forward regexp eol t) + (<= (match-beginning 0) pos)) + (let ((end (match-end 0))) + (when (or (> end pos) (and (= end pos) (not visually))) + (throw :exit (cons (match-beginning 0) (match-end 0)))))))))) (defun org-between-regexps-p (start-re end-re &optional lim-up lim-down) "Non-nil when point is between matches of START-RE and END-RE. @@ -21757,7 +22416,7 @@ position before START-RE (resp. after END-RE)." (save-excursion ;; Point is on a block when on START-RE or if START-RE can be ;; found before it... - (and (or (org-at-regexp-p start-re) + (and (or (org-in-regexp start-re) (re-search-backward start-re limit-up t)) (setq beg (match-beginning 0)) ;; ... and END-RE after it... @@ -21783,27 +22442,15 @@ block from point." (let ((case-fold-search t) (lim-up (save-excursion (outline-previous-heading))) (lim-down (save-excursion (outline-next-heading)))) - (mapc (lambda (name) - (let ((n (regexp-quote name))) - (when (org-between-regexps-p - (concat "^[ \t]*#\\+begin_" n) - (concat "^[ \t]*#\\+end_" n) - lim-up lim-down) - (throw 'exit n)))) - names)) + (dolist (name names) + (let ((n (regexp-quote name))) + (when (org-between-regexps-p + (concat "^[ \t]*#\\+begin_" n) + (concat "^[ \t]*#\\+end_" n) + lim-up lim-down) + (throw 'exit n))))) nil))) -(defun org-in-drawer-p () - "Is point within a drawer?" - (save-match-data - (let ((case-fold-search t) - (lim-up (save-excursion (outline-previous-heading))) - (lim-down (save-excursion (outline-next-heading)))) - (org-between-regexps-p - (concat "^[ \t]*:" (regexp-opt org-drawers) ":") - "^[ \t]*:end:.*$" - lim-up lim-down)))) - (defun org-occur-in-agenda-files (regexp &optional _nlines) "Call `multi-occur' with buffers for all agenda files." (interactive "sOrg-files matching: ") @@ -21815,40 +22462,21 @@ block from point." (setq files (org-add-archive-files files))) (dolist (f extra) (unless (member (file-truename f) tnames) - (unless (member f files) (setq files (append files (list f)))) - (setq tnames (append tnames (list (file-truename f)))))) + (unless (member f files) (setq files (append files (list f)))) + (setq tnames (append tnames (list (file-truename f)))))) (multi-occur (mapcar (lambda (x) (with-current-buffer - ;; FIXME: Why not just (find-file-noselect x)? - ;; Is it to avoid the "revert buffer" prompt? + ;; FIXME: Why not just (find-file-noselect x)? + ;; Is it to avoid the "revert buffer" prompt? (or (get-file-buffer x) (find-file-noselect x)) (widen) (current-buffer))) files) regexp))) -(if (boundp 'occur-mode-find-occurrence-hook) - ;; Emacs 23 - (add-hook 'occur-mode-find-occurrence-hook - (lambda () - (when (derived-mode-p 'org-mode) - (org-reveal)))) - ;; Emacs 22 - (defadvice occur-mode-goto-occurrence - (after org-occur-reveal activate) - (and (derived-mode-p 'org-mode) (org-reveal))) - (defadvice occur-mode-goto-occurrence-other-window - (after org-occur-reveal activate) - (and (derived-mode-p 'org-mode) (org-reveal))) - (defadvice occur-mode-display-occurrence - (after org-occur-reveal activate) - (when (derived-mode-p 'org-mode) - (let ((pos (occur-mode-find-occurrence))) - (with-current-buffer (marker-buffer pos) - (save-excursion - (goto-char pos) - (org-reveal))))))) +(add-hook 'occur-mode-find-occurrence-hook + (lambda () (when (derived-mode-p 'org-mode) (org-reveal)))) (defun org-occur-link-in-agenda-files () "Create a link and search for it in the agendas. @@ -21878,81 +22506,27 @@ merge (a 1) and (a 3) into (a 1 3). The function returns the new ALIST." (let (rtn) - (mapc - (lambda (e) - (let (n) - (if (not (assoc (car e) rtn)) - (push e rtn) - (setq n (cons (car e) (append (cdr (assoc (car e) rtn)) (cdr e)))) - (setq rtn (assq-delete-all (car e) rtn)) - (push n rtn)))) - alist) - rtn)) + (dolist (e alist rtn) + (let (n) + (if (not (assoc (car e) rtn)) + (push e rtn) + (setq n (cons (car e) (append (cdr (assoc (car e) rtn)) (cdr e)))) + (setq rtn (assq-delete-all (car e) rtn)) + (push n rtn)))))) (defun org-delete-all (elts list) - "Remove all elements in ELTS from LIST." + "Remove all elements in ELTS from LIST. +Comparison is done with `equal'. It is a destructive operation +that may remove elements by altering the list structure." (while elts (setq list (delete (pop elts) list))) list) -(defun org-count (cl-item cl-seq) - "Count the number of occurrences of ITEM in SEQ. -Taken from `count' in cl-seq.el with all keyword arguments removed." - (let ((cl-end (length cl-seq)) (cl-start 0) (cl-count 0) cl-x) - (when (consp cl-seq) (setq cl-seq (nthcdr cl-start cl-seq))) - (while (< cl-start cl-end) - (setq cl-x (if (consp cl-seq) (pop cl-seq) (aref cl-seq cl-start))) - (if (equal cl-item cl-x) (setq cl-count (1+ cl-count))) - (setq cl-start (1+ cl-start))) - cl-count)) - -(defun org-remove-if (predicate seq) - "Remove everything from SEQ that fulfills PREDICATE." - (let (res e) - (while seq - (setq e (pop seq)) - (if (not (funcall predicate e)) (push e res))) - (nreverse res))) - -(defun org-remove-if-not (predicate seq) - "Remove everything from SEQ that does not fulfill PREDICATE." - (let (res e) - (while seq - (setq e (pop seq)) - (if (funcall predicate e) (push e res))) - (nreverse res))) - -(defun org-reduce (cl-func cl-seq &rest cl-keys) - "Reduce two-argument FUNCTION across SEQ. -Taken from `reduce' in cl-seq.el with all keyword arguments but -\":initial-value\" removed." - (let ((cl-accum (cond ((memq :initial-value cl-keys) - (cadr (memq :initial-value cl-keys))) - (cl-seq (pop cl-seq)) - (t (funcall cl-func))))) - (while cl-seq - (setq cl-accum (funcall cl-func cl-accum (pop cl-seq)))) - cl-accum)) - -(defun org-every (pred seq) - "Return true if PREDICATE is true of every element of SEQ. -Adapted from `every' in cl.el." - (catch 'org-every - (mapc (lambda (e) (unless (funcall pred e) (throw 'org-every nil))) seq) - t)) - -(defun org-some (pred seq) - "Return true if PREDICATE is true of any element of SEQ. -Adapted from `some' in cl.el." - (catch 'org-some - (mapc (lambda (e) (when (funcall pred e) (throw 'org-some t))) seq) - nil)) - (defun org-back-over-empty-lines () "Move backwards over whitespace, to the beginning of the first empty line. Returns the number of empty lines passed." (let ((pos (point))) - (if (cdr (assoc 'heading org-blank-before-new-entry)) + (if (cdr (assq 'heading org-blank-before-new-entry)) (skip-chars-backward " \t\n\r") (unless (eobp) (forward-line -1))) @@ -22005,7 +22579,7 @@ so values can contain further %-escapes if they are define later in TABLE." (let ((tbl (copy-alist table)) (case-fold-search nil) (pchg 0) - e re rpl) + re rpl) (dolist (e tbl) (setq re (concat "%-?[0-9.]*" (substring (car e) 1))) (when (and (cdr e) (string-match re (cdr e))) @@ -22023,16 +22597,6 @@ so values can contain further %-escapes if they are define later in TABLE." (setq string (replace-match sref t t string))))) string)) -(defun org-sublist (list start end) - "Return a section of LIST, from START to END. -Counting starts at 1." - (let (rtn (c start)) - (setq list (nthcdr (1- start) list)) - (while (and list (<= c end)) - (push (pop list) rtn) - (setq c (1+ c))) - (nreverse rtn))) - (defun org-find-base-buffer-visiting (file) "Like `find-buffer-visiting' but always return the base buffer and not an indirect buffer." @@ -22042,26 +22606,12 @@ not an indirect buffer." (or (buffer-base-buffer buf) buf) nil))) -(defun org-image-file-name-regexp (&optional extensions) - "Return regexp matching the file names of images. -If EXTENSIONS is given, only match these." - (if (and (not extensions) (fboundp 'image-file-name-regexp)) - (image-file-name-regexp) - (let ((image-file-name-extensions - (or extensions - '("png" "jpeg" "jpg" "gif" "tiff" "tif" - "xbm" "xpm" "pbm" "pgm" "ppm")))) - (concat "\\." - (regexp-opt (nconc (mapcar 'upcase - image-file-name-extensions) - image-file-name-extensions) - t) - "\\'")))) - -(defun org-file-image-p (file &optional extensions) +;;; TODO: Only called once, from ox-odt which should probably use +;;; org-export-inline-image-p or something. +(defun org-file-image-p (file) "Return non-nil if FILE is an image." (save-match-data - (string-match (org-image-file-name-regexp extensions) file))) + (string-match (image-file-name-regexp) file))) (defun org-get-cursor-date (&optional with-time) "Return the date at cursor in as a time. @@ -22085,10 +22635,10 @@ the agenda) or the current time of the day." (nth 1 date) (nth 0 date) (nth 2 date)))) ((eq major-mode 'org-agenda-mode) (setq day (get-text-property (point) 'day)) - (if day - (setq date (calendar-gregorian-from-absolute day) - defd (encode-time 0 (or mod 0) (or hod 0) - (nth 1 date) (nth 0 date) (nth 2 date)))))) + (when day + (setq date (calendar-gregorian-from-absolute day) + defd (encode-time 0 (or mod 0) (or hod 0) + (nth 1 date) (nth 0 date) (nth 2 date)))))) (or defd (current-time)))) (defun org-mark-subtree (&optional up) @@ -22101,177 +22651,440 @@ hierarchy of headlines by UP levels before marking the subtree." (cond ((org-at-heading-p) (beginning-of-line)) ((org-before-first-heading-p) (user-error "Not in a subtree")) (t (outline-previous-visible-heading 1)))) - (when up (while (and (> up 0) (org-up-heading-safe)) (decf up))) - (if (org-called-interactively-p 'any) + (when up (while (and (> up 0) (org-up-heading-safe)) (cl-decf up))) + (if (called-interactively-p 'any) (call-interactively 'org-mark-element) (org-mark-element))) +(defun org-file-newer-than-p (file time) + "Non-nil if FILE is newer than TIME. +FILE is a filename, as a string, TIME is a list of integers, as +returned by, e.g., `current-time'." + (and (file-exists-p file) + ;; Only compare times up to whole seconds as some file-systems + ;; (e.g. HFS+) do not retain any finer granularity. As + ;; a consequence, make sure we return non-nil when the two + ;; times are equal. + (not (time-less-p (cl-subseq (nth 5 (file-attributes file)) 0 2) + (cl-subseq time 0 2))))) + +(defun org-compile-file (source process ext &optional err-msg log-buf spec) + "Compile a SOURCE file using PROCESS. + +PROCESS is either a function or a list of shell commands, as +strings. EXT is a file extension, without the leading dot, as +a string. It is used to check if the process actually succeeded. + +PROCESS must create a file with the same base name and directory +as SOURCE, but ending with EXT. The function then returns its +filename. Otherwise, it raises an error. The error message can +then be refined by providing string ERR-MSG, which is appended to +the standard message. + +If PROCESS is a function, it is called with a single argument: +the SOURCE file. + +If it is a list of commands, each of them is called using +`shell-command'. By default, in each command, %b, %f, %F, %o and +%O are replaced with, respectively, SOURCE base name, name, full +name, directory and absolute output file name. It is possible, +however, to use more place-holders by specifying them in optional +argument SPEC, as an alist following the pattern + + (CHARACTER . REPLACEMENT-STRING). + +When PROCESS is a list of commands, optional argument LOG-BUF can +be set to a buffer or a buffer name. `shell-command' then uses +it for output." + (let* ((base-name (file-name-base source)) + (full-name (file-truename source)) + (out-dir (or (file-name-directory source) "./")) + (output (expand-file-name (concat base-name "." ext) out-dir)) + (time (current-time)) + (err-msg (if (stringp err-msg) (concat ". " err-msg) ""))) + (save-window-excursion + (pcase process + ((pred functionp) (funcall process (shell-quote-argument source))) + ((pred consp) + (let ((log-buf (and log-buf (get-buffer-create log-buf))) + (spec (append spec + `((?b . ,(shell-quote-argument base-name)) + (?f . ,(shell-quote-argument source)) + (?F . ,(shell-quote-argument full-name)) + (?o . ,(shell-quote-argument out-dir)) + (?O . ,(shell-quote-argument output)))))) + (dolist (command process) + (shell-command (format-spec command spec) log-buf)))) + (_ (error "No valid command to process %S%s" source err-msg)))) + ;; Check for process failure. Output file is expected to be + ;; located in the same directory as SOURCE. + (unless (org-file-newer-than-p output time) + (error (format "File %S wasn't produced%s" output err-msg))) + output)) ;;; Indentation +(defvar org-element-greater-elements) +(defun org--get-expected-indentation (element contentsp) + "Expected indentation column for current line, according to ELEMENT. +ELEMENT is an element containing point. CONTENTSP is non-nil +when indentation is to be computed according to contents of +ELEMENT." + (let ((type (org-element-type element)) + (start (org-element-property :begin element)) + (post-affiliated (org-element-property :post-affiliated element))) + (org-with-wide-buffer + (cond + (contentsp + (cl-case type + ((diary-sexp footnote-definition) 0) + ((headline inlinetask nil) + (if (not org-adapt-indentation) 0 + (let ((level (org-current-level))) + (if level (1+ level) 0)))) + ((item plain-list) (org-list-item-body-column post-affiliated)) + (t + (goto-char start) + (org-get-indentation)))) + ((memq type '(headline inlinetask nil)) + (if (org-match-line "[ \t]*$") + (org--get-expected-indentation element t) + 0)) + ((memq type '(diary-sexp footnote-definition)) 0) + ;; First paragraph of a footnote definition or an item. + ;; Indent like parent. + ((< (line-beginning-position) start) + (org--get-expected-indentation + (org-element-property :parent element) t)) + ;; At first line: indent according to previous sibling, if any, + ;; ignoring footnote definitions and inline tasks, or parent's + ;; contents. + ((= (line-beginning-position) start) + (catch 'exit + (while t + (if (= (point-min) start) (throw 'exit 0) + (goto-char (1- start)) + (let* ((previous (org-element-at-point)) + (parent previous)) + (while (and parent (<= (org-element-property :end parent) start)) + (setq previous parent + parent (org-element-property :parent parent))) + (cond + ((not previous) (throw 'exit 0)) + ((> (org-element-property :end previous) start) + (throw 'exit (org--get-expected-indentation previous t))) + ((memq (org-element-type previous) + '(footnote-definition inlinetask)) + (setq start (org-element-property :begin previous))) + (t (goto-char (org-element-property :begin previous)) + (throw 'exit + (if (bolp) (org-get-indentation) + ;; At first paragraph in an item or + ;; a footnote definition. + (org--get-expected-indentation + (org-element-property :parent previous) t)))))))))) + ;; Otherwise, move to the first non-blank line above. + (t + (beginning-of-line) + (let ((pos (point))) + (skip-chars-backward " \r\t\n") + (cond + ;; Two blank lines end a footnote definition or a plain + ;; list. When we indent an empty line after them, the + ;; containing list or footnote definition is over, so it + ;; qualifies as a previous sibling. Therefore, we indent + ;; like its first line. + ((and (memq type '(footnote-definition plain-list)) + (> (count-lines (point) pos) 2)) + (goto-char start) + (org-get-indentation)) + ;; Line above is the first one of a paragraph at the + ;; beginning of an item or a footnote definition. Indent + ;; like parent. + ((< (line-beginning-position) start) + (org--get-expected-indentation + (org-element-property :parent element) t)) + ;; Line above is the beginning of an element, i.e., point + ;; was originally on the blank lines between element's start + ;; and contents. + ((= (line-beginning-position) post-affiliated) + (org--get-expected-indentation element t)) + ;; POS is after contents in a greater element. Indent like + ;; the beginning of the element. + ((and (memq type org-element-greater-elements) + (let ((cend (org-element-property :contents-end element))) + (and cend (<= cend pos)))) + ;; As a special case, if point is at the end of a footnote + ;; definition or an item, indent like the very last element + ;; within. If that last element is an item, indent like + ;; its contents. + (if (memq type '(footnote-definition item plain-list)) + (let ((last (org-element-at-point))) + (goto-char pos) + (org--get-expected-indentation + last (eq (org-element-type last) 'item))) + (goto-char start) + (org-get-indentation))) + ;; In any other case, indent like the current line. + (t (org-get-indentation))))))))) + +(defun org--align-node-property () + "Align node property at point. +Alignment is done according to `org-property-format', which see." + (when (save-excursion + (beginning-of-line) + (looking-at org-property-re)) + (replace-match + (concat (match-string 4) + (org-trim + (format org-property-format (match-string 1) (match-string 3)))) + t t))) + (defun org-indent-line () - "Indent line depending on context." + "Indent line depending on context. + +Indentation is done according to the following rules: + + - Footnote definitions, diary sexps, headlines and inline tasks + have to start at column 0. + + - On the very first line of an element, consider, in order, the + next rules until one matches: + + 1. If there's a sibling element before, ignoring footnote + definitions and inline tasks, indent like its first line. + + 2. If element has a parent, indent like its contents. More + precisely, if parent is an item, indent after the + description part, if any, or the bullet (see + `org-list-description-max-indent'). Else, indent like + parent's first line. + + 3. Otherwise, indent relatively to current level, if + `org-adapt-indentation' is non-nil, or to left margin. + + - On a blank line at the end of an element, indent according to + the type of the element. More precisely + + 1. If element is a plain list, an item, or a footnote + definition, indent like the very last element within. + + 2. If element is a paragraph, indent like its last non blank + line. + + 3. Otherwise, indent like its very first line. + + - In the code part of a source block, use language major mode + to indent current line if `org-src-tab-acts-natively' is + non-nil. If it is nil, do nothing. + + - Otherwise, indent like the first non-blank line above. + +The function doesn't indent an item as it could break the whole +list structure. Instead, use \\`\\[org-shiftmetaleft]' or \ +`\\[org-shiftmetaright]'. + +Also align node properties according to `org-property-format'." (interactive) - (let* ((pos (point)) - (itemp (org-at-item-p)) - (case-fold-search t) - (org-drawer-regexp (or org-drawer-regexp "\000")) - (inline-task-p (and (featurep 'org-inlinetask) - (org-inlinetask-in-task-p))) - (inline-re (and inline-task-p - (org-inlinetask-outline-regexp))) - column) - (if (and orgstruct-is-++ (eq pos (point))) - (let ((indent-line-function (cadadr (assoc 'indent-line-function org-fb-vars)))) - (indent-according-to-mode)) - (beginning-of-line 1) - (cond - ;; Headings - ((looking-at org-outline-regexp) (setq column 0)) - ;; Footnote definition - ((looking-at org-footnote-definition-re) (setq column 0)) - ;; Literal examples - ((looking-at "[ \t]*:\\( \\|$\\)") - (setq column (org-get-indentation))) ; do nothing - ;; Lists - ((ignore-errors (goto-char (org-in-item-p))) - (setq column (if itemp - (org-get-indentation) - (org-list-item-body-column (point)))) - (goto-char pos)) - ;; Drawers - ((and (looking-at "[ \t]*:END:") - (save-excursion (re-search-backward org-drawer-regexp nil t))) - (save-excursion - (goto-char (1- (match-beginning 1))) - (setq column (current-column)))) - ;; Special blocks - ((and (looking-at "[ \t]*#\\+end_\\([a-z]+\\)") - (save-excursion - (re-search-backward - (concat "^[ \t]*#\\+begin_" (downcase (match-string 1))) nil t))) - (setq column (org-get-indentation (match-string 0)))) - ((and (not (looking-at "[ \t]*#\\+begin_")) - (org-between-regexps-p "^[ \t]*#\\+begin_" "[ \t]*#\\+end_")) - (save-excursion - (re-search-backward "^[ \t]*#\\+begin_\\([a-z]+\\)" nil t)) - (setq column - (cond ((equal (downcase (match-string 1)) "src") - ;; src blocks: let `org-edit-src-exit' handle them - (org-get-indentation)) - ((equal (downcase (match-string 1)) "example") - (max (org-get-indentation) - (org-get-indentation (match-string 0)))) - (t - (org-get-indentation (match-string 0)))))) - ;; This line has nothing special, look at the previous relevant - ;; line to compute indentation - (t - (beginning-of-line 0) - (while (and (not (bobp)) - (not (looking-at org-table-line-regexp)) - (not (looking-at org-drawer-regexp)) - ;; When point started in an inline task, do not move - ;; above task starting line. - (not (and inline-task-p (looking-at inline-re))) - ;; Skip drawers, blocks, empty lines, verbatim, - ;; comments, tables, footnotes definitions, lists, - ;; inline tasks. - (or (and (looking-at "[ \t]*:END:") - (re-search-backward org-drawer-regexp nil t)) - (and (looking-at "[ \t]*#\\+end_") - (re-search-backward "[ \t]*#\\+begin_"nil t)) - (looking-at "[ \t]*[\n:#|]") - (looking-at org-footnote-definition-re) - (and (not inline-task-p) - (featurep 'org-inlinetask) - (org-inlinetask-in-task-p) - (or (org-inlinetask-goto-beginning) t)))) - (beginning-of-line 0)) - (cond - ;; There was a list item above. - ((ignore-errors (goto-char (org-in-item-p))) - (goto-char (org-list-get-top-point (org-list-struct))) - (setq column (org-get-indentation))) - ;; There was an heading above. - ((looking-at "\\*+[ \t]+") - (if (not org-adapt-indentation) - (setq column 0) - (goto-char (match-end 0)) - (setq column (current-column)))) - ;; A drawer had started and is unfinished - ((looking-at org-drawer-regexp) - (goto-char (1- (match-beginning 1))) - (setq column (current-column))) - ;; Else, nothing noticeable found: get indentation and go on. - (t (setq column (org-get-indentation)))))) - ;; Now apply indentation and move cursor accordingly - (goto-char pos) - (if (<= (current-column) (current-indentation)) - (org-indent-line-to column) - (save-excursion (org-indent-line-to column))) - ;; Special polishing for properties, see `org-property-format' - (setq column (current-column)) - (beginning-of-line 1) - (if (looking-at org-property-re) - (replace-match (concat (match-string 4) - (format org-property-format - (match-string 1) (match-string 3))) - t t)) - (org-move-to-column column)))) + (cond + (orgstruct-is-++ + (let ((indent-line-function + (cl-cadadr (assq 'indent-line-function org-fb-vars)))) + (indent-according-to-mode))) + ((org-at-heading-p) 'noindent) + (t + (let* ((element (save-excursion (beginning-of-line) (org-element-at-point))) + (type (org-element-type element))) + (cond ((and (memq type '(plain-list item)) + (= (line-beginning-position) + (org-element-property :post-affiliated element))) + 'noindent) + ((and (eq type 'latex-environment) + (>= (point) (org-element-property :post-affiliated element)) + (< (point) (org-with-wide-buffer + (goto-char (org-element-property :end element)) + (skip-chars-backward " \r\t\n") + (line-beginning-position 2)))) + 'noindent) + ((and (eq type 'src-block) + org-src-tab-acts-natively + (> (line-beginning-position) + (org-element-property :post-affiliated element)) + (< (line-beginning-position) + (org-with-wide-buffer + (goto-char (org-element-property :end element)) + (skip-chars-backward " \r\t\n") + (line-beginning-position)))) + (org-babel-do-key-sequence-in-edit-buffer (kbd "TAB"))) + (t + (let ((column (org--get-expected-indentation element nil))) + ;; Preserve current column. + (if (<= (current-column) (current-indentation)) + (indent-line-to column) + (save-excursion (indent-line-to column)))) + ;; Align node property. Also preserve current column. + (when (eq type 'node-property) + (let ((column (current-column))) + (org--align-node-property) + (org-move-to-column column))))))))) + +(defun org-indent-region (start end) + "Indent each non-blank line in the region. +Called from a program, START and END specify the region to +indent. The function will not indent contents of example blocks, +verse blocks and export blocks as leading white spaces are +assumed to be significant there." + (interactive "r") + (save-excursion + (goto-char start) + (skip-chars-forward " \r\t\n") + (unless (eobp) (beginning-of-line)) + (let ((indent-to + (lambda (ind pos) + ;; Set IND as indentation for all lines between point and + ;; POS. Blank lines are ignored. Leave point after POS + ;; once done. + (let ((limit (copy-marker pos))) + (while (< (point) limit) + (unless (looking-at-p "[ \t]*$") (indent-line-to ind)) + (forward-line)) + (set-marker limit nil)))) + (end (copy-marker end))) + (while (< (point) end) + (if (or (looking-at-p " \r\t\n") (org-at-heading-p)) (forward-line) + (let* ((element (org-element-at-point)) + (type (org-element-type element)) + (element-end (copy-marker (org-element-property :end element))) + (ind (org--get-expected-indentation element nil))) + (cond + ;; Element indented as a single block. Example blocks + ;; preserving indentation are a special case since the + ;; "contents" must not be indented whereas the block + ;; boundaries can. + ((or (memq type '(export-block latex-environment)) + (and (eq type 'example-block) + (not + (or org-src-preserve-indentation + (org-element-property :preserve-indent element))))) + (let ((offset (- ind (org-get-indentation)))) + (unless (zerop offset) + (indent-rigidly (org-element-property :begin element) + (org-element-property :end element) + offset))) + (goto-char element-end)) + ;; Elements indented line wise. Be sure to exclude + ;; example blocks (preserving indentation) and source + ;; blocks from this category as they are treated + ;; specially later. + ((or (memq type '(paragraph table table-row)) + (not (or (org-element-property :contents-begin element) + (memq type '(example-block src-block))))) + (when (eq type 'node-property) + (org--align-node-property) + (beginning-of-line)) + (funcall indent-to ind (min element-end end))) + ;; Elements consisting of three parts: before the + ;; contents, the contents, and after the contents. The + ;; contents are treated specially, according to the + ;; element type, or not indented at all. Other parts are + ;; indented as a single block. + (t + (let* ((post (copy-marker + (org-element-property :post-affiliated element))) + (cbeg + (copy-marker + (cond + ((not (org-element-property :contents-begin element)) + ;; Fake contents for source blocks. + (org-with-wide-buffer + (goto-char post) + (line-beginning-position 2))) + ((memq type '(footnote-definition item plain-list)) + ;; Contents in these elements could start on + ;; the same line as the beginning of the + ;; element. Make sure we start indenting + ;; from the second line. + (org-with-wide-buffer + (goto-char post) + (end-of-line) + (skip-chars-forward " \r\t\n") + (if (eobp) (point) (line-beginning-position)))) + (t (org-element-property :contents-begin element))))) + (cend (copy-marker + (or (org-element-property :contents-end element) + ;; Fake contents for source blocks. + (org-with-wide-buffer + (goto-char element-end) + (skip-chars-backward " \r\t\n") + (line-beginning-position))) + t))) + ;; Do not change items indentation individually as it + ;; might break the list as a whole. On the other + ;; hand, when at a plain list, indent it as a whole. + (cond ((eq type 'plain-list) + (let ((offset (- ind (org-get-indentation)))) + (unless (zerop offset) + (indent-rigidly (org-element-property :begin element) + (org-element-property :end element) + offset)) + (goto-char cbeg))) + ((eq type 'item) (goto-char cbeg)) + (t (funcall indent-to ind (min cbeg end)))) + (when (< (point) end) + (cl-case type + ((example-block verse-block)) + (src-block + ;; In a source block, indent source code + ;; according to language major mode, but only if + ;; `org-src-tab-acts-natively' is non-nil. + (when (and (< (point) end) org-src-tab-acts-natively) + (ignore-errors + (org-babel-do-in-edit-buffer + (indent-region (point-min) (point-max)))))) + (t (org-indent-region (point) (min cend end)))) + (goto-char (min cend end)) + (when (< (point) end) + (funcall indent-to ind (min element-end end)))) + (set-marker post nil) + (set-marker cbeg nil) + (set-marker cend nil)))) + (set-marker element-end nil)))) + (set-marker end nil)))) (defun org-indent-drawer () "Indent the drawer at point." (interactive) - (let ((p (point)) - (e (and (save-excursion (re-search-forward ":END:" nil t)) - (match-end 0))) - (folded - (save-excursion - (end-of-line) - (when (overlays-at (point)) - (member 'invisible (overlay-properties - (car (overlays-at (point))))))))) - (when folded (org-cycle)) - (indent-for-tab-command) - (while (and (move-beginning-of-line 2) (< (point) e)) - (indent-for-tab-command)) - (goto-char p) - (when folded (org-cycle))) + (unless (save-excursion + (beginning-of-line) + (looking-at-p org-drawer-regexp)) + (user-error "Not at a drawer")) + (let ((element (org-element-at-point))) + (unless (memq (org-element-type element) '(drawer property-drawer)) + (user-error "Not at a drawer")) + (org-with-wide-buffer + (org-indent-region (org-element-property :begin element) + (org-element-property :end element)))) (message "Drawer at point indented")) (defun org-indent-block () "Indent the block at point." (interactive) - (let ((p (point)) - (case-fold-search t) - (e (and (save-excursion (re-search-forward "#\\+end_?\\(?:[a-z]+\\)?" nil t)) - (match-end 0))) - (folded - (save-excursion - (end-of-line) - (when (overlays-at (point)) - (member 'invisible (overlay-properties - (car (overlays-at (point))))))))) - (when folded (org-cycle)) - (indent-for-tab-command) - (while (and (move-beginning-of-line 2) (< (point) e)) - (indent-for-tab-command)) - (goto-char p) - (when folded (org-cycle))) + (unless (save-excursion + (beginning-of-line) + (let ((case-fold-search t)) + (looking-at-p "[ \t]*#\\+\\(begin\\|end\\)_"))) + (user-error "Not at a block")) + (let ((element (org-element-at-point))) + (unless (memq (org-element-type element) + '(comment-block center-block dynamic-block example-block + export-block quote-block special-block + src-block verse-block)) + (user-error "Not at a block")) + (org-with-wide-buffer + (org-indent-region (org-element-property :begin element) + (org-element-property :end element)))) (message "Block at point indented")) -(defun org-indent-region (start end) - "Indent region." - (interactive "r") - (save-excursion - (let ((line-end (org-current-line end))) - (goto-char start) - (while (< (org-current-line) line-end) - (cond ((org-in-src-block-p t) (org-src-native-tab-command-maybe)) - (t (call-interactively 'org-indent-line))) - (move-beginning-of-line 2))))) - ;;; Filling @@ -22294,20 +23107,20 @@ hierarchy of headlines by UP levels before marking the subtree." (require 'org-element) ;; Prevent auto-fill from inserting unwanted new items. (when (boundp 'fill-nobreak-predicate) - (org-set-local - 'fill-nobreak-predicate + (setq-local + fill-nobreak-predicate (org-uniquify (append fill-nobreak-predicate '(org-fill-line-break-nobreak-p org-fill-paragraph-with-timestamp-nobreak-p))))) (let ((paragraph-ending (substring org-element-paragraph-separate 1))) - (org-set-local 'paragraph-start paragraph-ending) - (org-set-local 'paragraph-separate paragraph-ending)) - (org-set-local 'fill-paragraph-function 'org-fill-paragraph) - (org-set-local 'auto-fill-inhibit-regexp nil) - (org-set-local 'adaptive-fill-function 'org-adaptive-fill-function) - (org-set-local 'normal-auto-fill-function 'org-auto-fill-function) - (org-set-local 'comment-line-break-function 'org-comment-line-break-function)) + (setq-local paragraph-start paragraph-ending) + (setq-local paragraph-separate paragraph-ending)) + (setq-local fill-paragraph-function 'org-fill-paragraph) + (setq-local auto-fill-inhibit-regexp nil) + (setq-local adaptive-fill-function 'org-adaptive-fill-function) + (setq-local normal-auto-fill-function 'org-auto-fill-function) + (setq-local comment-line-break-function 'org-comment-line-break-function)) (defun org-fill-line-break-nobreak-p () "Non-nil when a new line at point would create an Org line break." @@ -22332,69 +23145,64 @@ matches in paragraphs or comments, use it." (when (derived-mode-p 'message-mode) (save-excursion (beginning-of-line) - (cond ((or (not (message-in-body-p)) - (looking-at orgtbl-line-start-regexp)) - (throw 'exit nil)) + (cond ((not (message-in-body-p)) (throw 'exit nil)) + ((looking-at-p org-table-line-regexp) (throw 'exit nil)) ((looking-at message-cite-prefix-regexp) (throw 'exit (match-string-no-properties 0))) ((looking-at org-outline-regexp) - (throw 'exit (make-string (length (match-string 0)) ? )))))) + (throw 'exit (make-string (length (match-string 0)) ?\s)))))) (org-with-wide-buffer - (let* ((p (line-beginning-position)) - (element (save-excursion - (beginning-of-line) - (or (ignore-errors (org-element-at-point)) - (user-error "An element cannot be parsed line %d" - (line-number-at-pos (point)))))) - (type (org-element-type element)) - (post-affiliated (org-element-property :post-affiliated element))) - (unless (and post-affiliated (< p post-affiliated)) - (case type - (comment - (save-excursion - (beginning-of-line) - (looking-at "[ \t]*") - (concat (match-string 0) "# "))) - (footnote-definition "") - ((item plain-list) - (make-string (org-list-item-body-column - (or post-affiliated - (org-element-property :begin element))) - ? )) - (paragraph - ;; Fill prefix is usually the same as the current line, - ;; unless the paragraph is at the beginning of an item. - (let ((parent (org-element-property :parent element))) + (unless (org-at-heading-p) + (let* ((p (line-beginning-position)) + (element (save-excursion + (beginning-of-line) + (org-element-at-point))) + (type (org-element-type element)) + (post-affiliated (org-element-property :post-affiliated element))) + (unless (< p post-affiliated) + (cl-case type + (comment (save-excursion (beginning-of-line) - (cond ((eq (org-element-type parent) 'item) - (make-string (org-list-item-body-column - (org-element-property :begin parent)) - ? )) - ((and adaptive-fill-regexp - ;; Locally disable - ;; `adaptive-fill-function' to let - ;; `fill-context-prefix' handle - ;; `adaptive-fill-regexp' variable. - (let (adaptive-fill-function) - (fill-context-prefix - post-affiliated - (org-element-property :end element))))) - ((looking-at "[ \t]+") (match-string 0)) - (t ""))))) - (comment-block - ;; Only fill contents if P is within block boundaries. - (let* ((cbeg (save-excursion (goto-char post-affiliated) - (forward-line) - (point))) - (cend (save-excursion - (goto-char (org-element-property :end element)) - (skip-chars-backward " \r\t\n") - (line-beginning-position)))) - (when (and (>= p cbeg) (< p cend)) - (if (save-excursion (beginning-of-line) (looking-at "[ \t]+")) - (match-string 0) - "")))))))))) + (looking-at "[ \t]*") + (concat (match-string 0) "# "))) + (footnote-definition "") + ((item plain-list) + (make-string (org-list-item-body-column post-affiliated) ?\s)) + (paragraph + ;; Fill prefix is usually the same as the current line, + ;; unless the paragraph is at the beginning of an item. + (let ((parent (org-element-property :parent element))) + (save-excursion + (beginning-of-line) + (cond ((eq (org-element-type parent) 'item) + (make-string (org-list-item-body-column + (org-element-property :begin parent)) + ?\s)) + ((and adaptive-fill-regexp + ;; Locally disable + ;; `adaptive-fill-function' to let + ;; `fill-context-prefix' handle + ;; `adaptive-fill-regexp' variable. + (let (adaptive-fill-function) + (fill-context-prefix + post-affiliated + (org-element-property :end element))))) + ((looking-at "[ \t]+") (match-string 0)) + (t ""))))) + (comment-block + ;; Only fill contents if P is within block boundaries. + (let* ((cbeg (save-excursion (goto-char post-affiliated) + (forward-line) + (point))) + (cend (save-excursion + (goto-char (org-element-property :end element)) + (skip-chars-backward " \r\t\n") + (line-beginning-position)))) + (when (and (>= p cbeg) (< p cend)) + (if (save-excursion (beginning-of-line) (looking-at "[ \t]+")) + (match-string 0) + ""))))))))))) (declare-function message-goto-body "message" ()) (defvar message-cite-prefix-regexp) ; From message.el @@ -22420,11 +23228,11 @@ a footnote definition, try to fill the first paragraph within." (looking-at message-cite-prefix-regexp)))) ;; First ensure filling is correct in message-mode. (let ((fill-paragraph-function - (cadadr (assoc 'fill-paragraph-function org-fb-vars))) - (fill-prefix (cadadr (assoc 'fill-prefix org-fb-vars))) - (paragraph-start (cadadr (assoc 'paragraph-start org-fb-vars))) + (cl-cadadr (assq 'fill-paragraph-function org-fb-vars))) + (fill-prefix (cl-cadadr (assq 'fill-prefix org-fb-vars))) + (paragraph-start (cl-cadadr (assq 'paragraph-start org-fb-vars))) (paragraph-separate - (cadadr (assoc 'paragraph-separate org-fb-vars)))) + (cl-cadadr (assq 'paragraph-separate org-fb-vars)))) (fill-paragraph nil)) (with-syntax-table org-mode-transpose-word-syntax-table ;; Move to end of line in order to get the first paragraph @@ -22436,7 +23244,7 @@ a footnote definition, try to fill the first paragraph within." (line-number-at-pos (point))))))) ;; First check if point is in a blank line at the beginning of ;; the buffer. In that case, ignore filling. - (case (org-element-type element) + (cl-case (org-element-type element) ;; Use major mode filling function is src blocks. (src-block (org-babel-do-key-sequence-in-edit-buffer (kbd "M-q"))) ;; Align Org tables, leave table.el tables as-is. @@ -22465,25 +23273,18 @@ a footnote definition, try to fill the first paragraph within." (concat "^" message-cite-prefix-regexp) end t)) (setq end (match-beginning 0)))) ;; Fill paragraph, taking line breaks into account. - ;; For that, slice the paragraph using line breaks as - ;; separators, and fill the parts in reverse order to - ;; avoid messing with markers. (save-excursion - (goto-char end) - (mapc - (lambda (pos) - (fill-region-as-paragraph pos (point) justify) - (goto-char pos)) - ;; Find the list of ending positions for line breaks - ;; in the current paragraph. Add paragraph - ;; beginning to include first slice. - (nreverse - (cons beg - (org-element-map - (org-element--parse-objects - beg end nil (org-element-restriction 'paragraph)) - 'line-break - (lambda (lb) (org-element-property :end lb))))))) + (goto-char beg) + (let ((cuts (list beg))) + (while (re-search-forward "\\\\\\\\[ \t]*\n" end t) + (when (eq 'line-break + (org-element-type + (save-excursion (backward-char) + (org-element-context)))) + (push (point) cuts))) + (dolist (c (delq end cuts)) + (fill-region-as-paragraph c end justify) + (setq end c)))) t))) ;; Contents of `comment-block' type elements should be ;; filled as plain text, but only if point is within block @@ -22564,6 +23365,130 @@ non-nil." (insert-before-markers-and-inherit fill-prefix)) +;;; Fixed Width Areas + +(defun org-toggle-fixed-width () + "Toggle fixed-width markup. + +Add or remove fixed-width markup on current line, whenever it +makes sense. Return an error otherwise. + +If a region is active and if it contains only fixed-width areas +or blank lines, remove all fixed-width markup in it. If the +region contains anything else, convert all non-fixed-width lines +to fixed-width ones. + +Blank lines at the end of the region are ignored unless the +region only contains such lines." + (interactive) + (if (not (org-region-active-p)) + ;; No region: + ;; + ;; Remove fixed width marker only in a fixed-with element. + ;; + ;; Add fixed width maker in paragraphs, in blank lines after + ;; elements or at the beginning of a headline or an inlinetask, + ;; and before any one-line elements (e.g., a clock). + (progn + (beginning-of-line) + (let* ((element (org-element-at-point)) + (type (org-element-type element))) + (cond + ((and (eq type 'fixed-width) + (looking-at "[ \t]*\\(:\\(?: \\|$\\)\\)")) + (replace-match + "" nil nil nil (if (= (line-end-position) (match-end 0)) 0 1))) + ((and (memq type '(babel-call clock comment diary-sexp headline + horizontal-rule keyword paragraph + planning)) + (<= (org-element-property :post-affiliated element) (point))) + (skip-chars-forward " \t") + (insert ": ")) + ((and (looking-at-p "[ \t]*$") + (or (eq type 'inlinetask) + (save-excursion + (skip-chars-forward " \r\t\n") + (<= (org-element-property :end element) (point))))) + (delete-region (point) (line-end-position)) + (org-indent-line) + (insert ": ")) + (t (user-error "Cannot insert a fixed-width line here"))))) + ;; Region active. + (let* ((begin (save-excursion + (goto-char (region-beginning)) + (line-beginning-position))) + (end (copy-marker + (save-excursion + (goto-char (region-end)) + (unless (eolp) (beginning-of-line)) + (if (save-excursion (re-search-backward "\\S-" begin t)) + (progn (skip-chars-backward " \r\t\n") (point)) + (point))))) + (all-fixed-width-p + (catch 'not-all-p + (save-excursion + (goto-char begin) + (skip-chars-forward " \r\t\n") + (when (eobp) (throw 'not-all-p nil)) + (while (< (point) end) + (let ((element (org-element-at-point))) + (if (eq (org-element-type element) 'fixed-width) + (goto-char (org-element-property :end element)) + (throw 'not-all-p nil)))) + t)))) + (if all-fixed-width-p + (save-excursion + (goto-char begin) + (while (< (point) end) + (when (looking-at "[ \t]*\\(:\\(?: \\|$\\)\\)") + (replace-match + "" nil nil nil + (if (= (line-end-position) (match-end 0)) 0 1))) + (forward-line))) + (let ((min-ind (point-max))) + ;; Find minimum indentation across all lines. + (save-excursion + (goto-char begin) + (if (not (save-excursion (re-search-forward "\\S-" end t))) + (setq min-ind 0) + (catch 'zerop + (while (< (point) end) + (unless (looking-at-p "[ \t]*$") + (let ((ind (org-get-indentation))) + (setq min-ind (min min-ind ind)) + (when (zerop ind) (throw 'zerop t)))) + (forward-line))))) + ;; Loop over all lines and add fixed-width markup everywhere + ;; but in fixed-width lines. + (save-excursion + (goto-char begin) + (while (< (point) end) + (cond + ((org-at-heading-p) + (insert ": ") + (forward-line) + (while (and (< (point) end) (looking-at-p "[ \t]*$")) + (insert ":") + (forward-line))) + ((looking-at-p "[ \t]*:\\( \\|$\\)") + (let* ((element (org-element-at-point)) + (element-end (org-element-property :end element))) + (if (eq (org-element-type element) 'fixed-width) + (progn (goto-char element-end) + (skip-chars-backward " \r\t\n") + (forward-line)) + (let ((limit (min end element-end))) + (while (< (point) limit) + (org-move-to-column min-ind t) + (insert ": ") + (forward-line)))))) + (t + (org-move-to-column min-ind t) + (insert ": ") + (forward-line))))))) + (set-marker end nil)))) + + ;;; Comments ;; Org comments syntax is quite complex. It requires the entire line @@ -22584,87 +23509,139 @@ non-nil." (defun org-setup-comments-handling () (interactive) - (org-set-local 'comment-use-syntax nil) - (org-set-local 'comment-start "# ") - (org-set-local 'comment-start-skip "^\\s-*#\\(?: \\|$\\)") - (org-set-local 'comment-insert-comment-function 'org-insert-comment) - (org-set-local 'comment-region-function 'org-comment-or-uncomment-region) - (org-set-local 'uncomment-region-function 'org-comment-or-uncomment-region)) + (setq-local comment-use-syntax nil) + (setq-local comment-start "# ") + (setq-local comment-start-skip "^\\s-*#\\(?: \\|$\\)") + (setq-local comment-insert-comment-function 'org-insert-comment) + (setq-local comment-region-function 'org-comment-or-uncomment-region) + (setq-local uncomment-region-function 'org-comment-or-uncomment-region)) (defun org-insert-comment () "Insert an empty comment above current line. -If the line is empty, insert comment at its beginning." - (beginning-of-line) - (if (looking-at "\\s-*$") (replace-match "") (open-line 1)) - (org-indent-line) - (insert "# ")) +If the line is empty, insert comment at its beginning. When +point is within a source block, comment according to the related +major mode." + (if (let ((element (org-element-at-point))) + (and (eq (org-element-type element) 'src-block) + (< (save-excursion + (goto-char (org-element-property :post-affiliated element)) + (line-end-position)) + (point)) + (> (save-excursion + (goto-char (org-element-property :end element)) + (skip-chars-backward " \r\t\n") + (line-beginning-position)) + (point)))) + (org-babel-do-in-edit-buffer (call-interactively 'comment-dwim)) + (beginning-of-line) + (if (looking-at "\\s-*$") (delete-region (point) (point-at-eol)) + (open-line 1)) + (org-indent-line) + (insert "# "))) (defvar comment-empty-lines) ; From newcomment.el. (defun org-comment-or-uncomment-region (beg end &rest _) "Comment or uncomment each non-blank line in the region. Uncomment each non-blank line between BEG and END if it only -contains commented lines. Otherwise, comment them." - (save-restriction - ;; Restrict region - (narrow-to-region (save-excursion (goto-char beg) - (skip-chars-forward " \r\t\n" end) - (line-beginning-position)) - (save-excursion (goto-char end) - (skip-chars-backward " \r\t\n" beg) - (line-end-position))) - (let ((uncommentp - ;; UNCOMMENTP is non-nil when every non blank line between - ;; BEG and END is a comment. - (save-excursion - (goto-char (point-min)) - (while (and (not (eobp)) - (let ((element (org-element-at-point))) - (and (eq (org-element-type element) 'comment) - (goto-char (min (point-max) - (org-element-property - :end element))))))) - (eobp)))) - (if uncommentp - ;; Only blank lines and comments in region: uncomment it. - (save-excursion - (goto-char (point-min)) - (while (not (eobp)) - (when (looking-at "[ \t]*\\(#\\(?: \\|$\\)\\)") - (replace-match "" nil nil nil 1)) - (forward-line))) - ;; Comment each line in region. - (let ((min-indent (point-max))) - ;; First find the minimum indentation across all lines. - (save-excursion - (goto-char (point-min)) - (while (and (not (eobp)) (not (zerop min-indent))) - (unless (looking-at "[ \t]*$") - (setq min-indent (min min-indent (current-indentation)))) - (forward-line))) - ;; Then loop over all lines. - (save-excursion - (goto-char (point-min)) - (while (not (eobp)) - (unless (and (not comment-empty-lines) (looking-at "[ \t]*$")) - ;; Don't get fooled by invisible text (e.g. link path) - ;; when moving to column MIN-INDENT. - (let ((buffer-invisibility-spec nil)) - (org-move-to-column min-indent t)) - (insert comment-start)) - (forward-line)))))))) +contains commented lines. Otherwise, comment them. If region is +strictly within a source block, use appropriate comment syntax." + (if (let ((element (org-element-at-point))) + (and (eq (org-element-type element) 'src-block) + (< (save-excursion + (goto-char (org-element-property :post-affiliated element)) + (line-end-position)) + beg) + (>= (save-excursion + (goto-char (org-element-property :end element)) + (skip-chars-backward " \r\t\n") + (line-beginning-position)) + end))) + ;; Translate region boundaries for the Org buffer to the source + ;; buffer. + (let ((offset (- end beg))) + (save-excursion + (goto-char beg) + (org-babel-do-in-edit-buffer + (comment-or-uncomment-region (point) (+ offset (point)))))) + (save-restriction + ;; Restrict region + (narrow-to-region (save-excursion (goto-char beg) + (skip-chars-forward " \r\t\n" end) + (line-beginning-position)) + (save-excursion (goto-char end) + (skip-chars-backward " \r\t\n" beg) + (line-end-position))) + (let ((uncommentp + ;; UNCOMMENTP is non-nil when every non blank line between + ;; BEG and END is a comment. + (save-excursion + (goto-char (point-min)) + (while (and (not (eobp)) + (let ((element (org-element-at-point))) + (and (eq (org-element-type element) 'comment) + (goto-char (min (point-max) + (org-element-property + :end element))))))) + (eobp)))) + (if uncommentp + ;; Only blank lines and comments in region: uncomment it. + (save-excursion + (goto-char (point-min)) + (while (not (eobp)) + (when (looking-at "[ \t]*\\(#\\(?: \\|$\\)\\)") + (replace-match "" nil nil nil 1)) + (forward-line))) + ;; Comment each line in region. + (let ((min-indent (point-max))) + ;; First find the minimum indentation across all lines. + (save-excursion + (goto-char (point-min)) + (while (and (not (eobp)) (not (zerop min-indent))) + (unless (looking-at "[ \t]*$") + (setq min-indent (min min-indent (current-indentation)))) + (forward-line))) + ;; Then loop over all lines. + (save-excursion + (goto-char (point-min)) + (while (not (eobp)) + (unless (and (not comment-empty-lines) (looking-at "[ \t]*$")) + ;; Don't get fooled by invisible text (e.g. link path) + ;; when moving to column MIN-INDENT. + (let ((buffer-invisibility-spec nil)) + (org-move-to-column min-indent t)) + (insert comment-start)) + (forward-line))))))))) + +(defun org-comment-dwim (_arg) + "Call `comment-dwim' within a source edit buffer if needed." + (interactive "*P") + (if (org-in-src-block-p) + (org-babel-do-in-edit-buffer (call-interactively 'comment-dwim)) + (call-interactively 'comment-dwim))) -;;; Planning +;;; Timestamps API ;; This section contains tools to operate on timestamp objects, as ;; returned by, e.g. `org-element-context'. +(defun org-timestamp--to-internal-time (timestamp &optional end) + "Encode TIMESTAMP object into Emacs internal time. +Use end of date range or time range when END is non-nil." + (apply #'encode-time + (cons 0 + (mapcar + (lambda (prop) (or (org-element-property prop timestamp) 0)) + (if end '(:minute-end :hour-end :day-end :month-end :year-end) + '(:minute-start :hour-start :day-start :month-start + :year-start)))))) + (defun org-timestamp-has-time-p (timestamp) "Non-nil when TIMESTAMP has a time specified." (org-element-property :hour-start timestamp)) -(defun org-timestamp-format (timestamp format &optional end zone) - "Format a TIMESTAMP element into a string. +(defun org-timestamp-format (timestamp format &optional end utc) + "Format a TIMESTAMP object into a string. FORMAT is a format specifier to be passed to `format-time-string'. @@ -22672,33 +23649,22 @@ FORMAT is a format specifier to be passed to When optional argument END is non-nil, use end of date-range or time-range, if possible. -The optional ZONE is omitted or nil for Emacs local time, t for -Universal Time, `wall' for system wall clock time, or a string as -in the TZ environment variable. It can also be a list (as from -`current-time-zone') or an integer (as from `decode-time') -applied without consideration for daylight saving time." +When optional argument UTC is non-nil, time will be expressed as +Universal Time." (format-time-string - format - (apply 'encode-time - (cons 0 - (mapcar - (lambda (prop) (or (org-element-property prop timestamp) 0)) - (if end '(:minute-end :hour-end :day-end :month-end :year-end) - '(:minute-start :hour-start :day-start :month-start - :year-start))))) - zone)) + format (org-timestamp--to-internal-time timestamp end) + (and utc t))) (defun org-timestamp-split-range (timestamp &optional end) - "Extract a timestamp object from a date or time range. + "Extract a TIMESTAMP object from a date or time range. -TIMESTAMP is a timestamp object. END, when non-nil, means extract -the end of the range. Otherwise, extract its start. +END, when non-nil, means extract the end of the range. +Otherwise, extract its start. -Return a new timestamp object sharing the same parent as -TIMESTAMP." +Return a new timestamp object." (let ((type (org-element-property :type timestamp))) (if (memq type '(active inactive diary)) timestamp - (let ((split-ts (list 'timestamp (copy-sequence (nth 1 timestamp))))) + (let ((split-ts (org-element-copy timestamp))) ;; Set new type. (org-element-put-property split-ts :type (if (eq type 'active-range) 'active 'inactive)) @@ -22712,91 +23678,43 @@ TIMESTAMP." (dolist (p-cell p-alist) (org-element-put-property split-ts - (funcall (if end 'car 'cdr) p-cell) + (funcall (if end #'car #'cdr) p-cell) (org-element-property - (funcall (if end 'cdr 'car) p-cell) split-ts))) + (funcall (if end #'cdr #'car) p-cell) split-ts))) ;; Eventually refresh `:raw-value'. (org-element-put-property split-ts :raw-value nil) (org-element-put-property split-ts :raw-value (org-element-interpret-data split-ts))))))) (defun org-timestamp-translate (timestamp &optional boundary) - "Apply `org-translate-time' on a TIMESTAMP object. + "Translate TIMESTAMP object to custom format. + +Format string is defined in `org-time-stamp-custom-formats', +which see. + When optional argument BOUNDARY is non-nil, it is either the symbol `start' or `end'. In this case, only translate the starting or ending part of TIMESTAMP if it is a date or time -range. Otherwise, translate both parts." - (if (and (not boundary) - (memq (org-element-property :type timestamp) - '(active-range inactive-range))) - (concat - (org-translate-time - (org-element-property :raw-value - (org-timestamp-split-range timestamp))) - "--" - (org-translate-time - (org-element-property :raw-value - (org-timestamp-split-range timestamp t)))) - (org-translate-time - (org-element-property - :raw-value - (if (not boundary) timestamp - (org-timestamp-split-range timestamp (eq boundary 'end))))))) +range. Otherwise, translate both parts. +Return timestamp as-is if `org-display-custom-times' is nil or if +it has a `diary' type." + (let ((type (org-element-property :type timestamp))) + (if (or (not org-display-custom-times) (eq type 'diary)) + (org-element-interpret-data timestamp) + (let ((fmt (funcall (if (org-timestamp-has-time-p timestamp) #'cdr #'car) + org-time-stamp-custom-formats))) + (if (and (not boundary) (memq type '(active-range inactive-range))) + (concat (org-timestamp-format timestamp fmt) + "--" + (org-timestamp-format timestamp fmt t)) + (org-timestamp-format timestamp fmt (eq boundary 'end))))))) -;;; Other stuff. -(defun org-toggle-fixed-width-section (arg) - "Toggle the fixed-width export. -If there is no active region, the QUOTE keyword at the current headline is -inserted or removed. When present, it causes the text between this headline -and the next to be exported as fixed-width text, and unmodified. -If there is an active region, this command adds or removes a colon as the -first character of this line. If the first character of a line is a colon, -this line is also exported in fixed-width font." - (interactive "P") - (let* ((cc 0) - (regionp (org-region-active-p)) - (beg (if regionp (region-beginning) (point))) - (end (if regionp (region-end))) - (nlines (or arg (if (and beg end) (count-lines beg end) 1))) - (case-fold-search nil) - (re "[ \t]*\\(:\\(?: \\|$\\)\\)") - off) - (if regionp - (save-excursion - (goto-char beg) - (setq cc (current-column)) - (beginning-of-line 1) - (setq off (looking-at re)) - (while (> nlines 0) - (setq nlines (1- nlines)) - (beginning-of-line 1) - (cond - (arg - (org-move-to-column cc t) - (insert ": \n") - (forward-line -1)) - ((and off (looking-at re)) - (replace-match "" t t nil 1)) - ((not off) (org-move-to-column cc t) (insert ": "))) - (forward-line 1))) - (save-excursion - (org-back-to-heading) - (cond - ((looking-at (format org-heading-keyword-regexp-format - org-quote-string)) - (goto-char (match-end 1)) - (looking-at (concat " +" org-quote-string)) - (replace-match "" t t) - (when (eolp) (insert " "))) - ((looking-at org-outline-regexp) - (goto-char (match-end 0)) - (insert org-quote-string " "))))))) +;;; Other stuff. (defvar reftex-docstruct-symbol) -(defvar reftex-cite-format) (defvar org--rds) (defun org-reftex-citation () @@ -22814,131 +23732,137 @@ Export of such citations to both LaTeX and HTML is handled by the contributed package ox-bibtex by Taru Karttunen." (interactive) (let ((reftex-docstruct-symbol 'org--rds) - (reftex-cite-format "\\cite{%l}") org--rds bib) - (save-excursion - (save-restriction - (widen) - (let ((case-fold-search t) - (re "^#\\+bibliography:[ \t]+\\([^ \t\n]+\\)")) - (if (not (save-excursion - (or (re-search-forward re nil t) - (re-search-backward re nil t)))) - (error "No bibliography defined in file") - (setq bib (concat (match-string 1) ".bib") - org--rds (list (list 'bib bib))))))) + (org-with-wide-buffer + (let ((case-fold-search t) + (re "^[ \t]*#\\+BIBLIOGRAPHY:[ \t]+\\([^ \t\n]+\\)")) + (if (not (save-excursion + (or (re-search-forward re nil t) + (re-search-backward re nil t)))) + (user-error "No bibliography defined in file") + (setq bib (concat (match-string 1) ".bib") + org--rds (list (list 'bib bib)))))) (call-interactively 'reftex-citation))) ;;;; Functions extending outline functionality -(defun org-beginning-of-line (&optional arg) - "Go to the beginning of the current line. If that is invisible, continue -to a visible line beginning. This makes the function of C-a more intuitive. -If this is a headline, and `org-special-ctrl-a/e' is set, ignore tags on the -first attempt, and only move to after the tags when the cursor is already -beyond the end of the headline." - (interactive "P") - (let ((pos (point)) - (special (if (consp org-special-ctrl-a/e) - (car org-special-ctrl-a/e) - org-special-ctrl-a/e)) - deactivate-mark refpos) - (if (org-bound-and-true-p visual-line-mode) - (beginning-of-visual-line 1) - (beginning-of-line 1)) - (if (and arg (fboundp 'move-beginning-of-line)) - (call-interactively 'move-beginning-of-line) - (if (bobp) - nil - (backward-char 1) - (if (org-truely-invisible-p) - (while (and (not (bobp)) (org-truely-invisible-p)) - (backward-char 1) - (beginning-of-line 1)) - (forward-char 1)))) - (when special - (cond - ((and (looking-at org-complex-heading-regexp) - (= (char-after (match-end 1)) ?\ )) - (setq refpos (min (1+ (or (match-end 3) (match-end 2) (match-end 1))) - (point-at-eol))) - (goto-char - (if (eq special t) - (cond ((> pos refpos) refpos) - ((= pos (point)) refpos) - (t (point))) - (cond ((> pos (point)) (point)) - ((not (eq last-command this-command)) (point)) - (t refpos))))) - ((org-at-item-p) - ;; Being at an item and not looking at an the item means point - ;; was previously moved to beginning of a visual line, which - ;; doesn't contain the item. Therefore, do nothing special, - ;; just stay here. - (when (looking-at org-list-full-item-re) - ;; Set special position at first white space character after - ;; bullet, and check-box, if any. - (let ((after-bullet - (let ((box (match-end 3))) - (if (not box) (match-end 1) - (let ((after (char-after box))) - (if (and after (= after ? )) (1+ box) box)))))) - ;; Special case: Move point to special position when - ;; currently after it or at beginning of line. - (if (eq special t) - (when (or (> pos after-bullet) (= (point) pos)) - (goto-char after-bullet)) - ;; Reversed case: Move point to special position when - ;; point was already at beginning of line and command is - ;; repeated. - (when (and (= (point) pos) (eq last-command this-command)) - (goto-char after-bullet)))))))) - (org-no-warnings - (and (featurep 'xemacs) (setq zmacs-region-stays t)))) - (setq disable-point-adjustment - (or (not (invisible-p (point))) - (not (invisible-p (max (point-min) (1- (point)))))))) - -(defun org-end-of-line (&optional arg) - "Go to the end of the line. +(defun org-beginning-of-line (&optional n) + "Go to the beginning of the current visible line. + If this is a headline, and `org-special-ctrl-a/e' is set, ignore tags on the first attempt, and only move to after the tags when -the cursor is already beyond the end of the headline." - (interactive "P") - (let ((special (if (consp org-special-ctrl-a/e) (cdr org-special-ctrl-a/e) - org-special-ctrl-a/e)) - (move-fun (cond ((org-bound-and-true-p visual-line-mode) - 'end-of-visual-line) - ((fboundp 'move-end-of-line) 'move-end-of-line) - (t 'end-of-line))) +the cursor is already beyond the end of the headline. + +With argument N not nil or 1, move forward N - 1 lines first." + (interactive "^p") + (let ((origin (point)) + (special (pcase org-special-ctrl-a/e + (`(,C-a . ,_) C-a) (_ org-special-ctrl-a/e))) deactivate-mark) - (if (or (not special) arg) (call-interactively move-fun) - (let* ((element (save-excursion (beginning-of-line) - (org-element-at-point))) - (type (org-element-type element))) - (cond - ((memq type '(headline inlinetask)) - (let ((pos (point))) - (beginning-of-line 1) - (if (looking-at (org-re ".*?\\(?:\\([ \t]*\\)\\(:[[:alnum:]_@#%:]+:\\)?[ \t]*\\)?$")) - (if (eq special t) - (if (or (< pos (match-beginning 1)) (= pos (match-end 0))) - (goto-char (match-beginning 1)) - (goto-char (match-end 0))) - (if (or (< pos (match-end 0)) - (not (eq this-command last-command))) - (goto-char (match-end 0)) - (goto-char (match-beginning 1)))) - (call-interactively move-fun)))) - ((org-element-property :hiddenp element) - ;; If element is hidden, `move-end-of-line' would put point - ;; after it. Use `end-of-line' to stay on current line. - (call-interactively 'end-of-line)) - (t (call-interactively move-fun))))) - (org-no-warnings (and (featurep 'xemacs) (setq zmacs-region-stays t)))) - (setq disable-point-adjustment - (or (not (invisible-p (point))) - (not (invisible-p (max (point-min) (1- (point)))))))) + ;; First move to a visible line. + (if (bound-and-true-p visual-line-mode) + (beginning-of-visual-line n) + (move-beginning-of-line n) + ;; `move-beginning-of-line' may leave point after invisible + ;; characters if line starts with such of these (e.g., with + ;; a link at column 0). Really move to the beginning of the + ;; current visible line. + (beginning-of-line)) + (cond + ;; No special behavior. Point is already at the beginning of + ;; a line, logical or visual. + ((not special)) + ;; `beginning-of-visual-line' left point before logical beginning + ;; of line: point is at the beginning of a visual line. Bail + ;; out. + ((and (bound-and-true-p visual-line-mode) (not (bolp)))) + ((let ((case-fold-search nil)) (looking-at org-complex-heading-regexp)) + ;; At a headline, special position is before the title, but + ;; after any TODO keyword or priority cookie. + (let ((refpos (min (1+ (or (match-end 3) (match-end 2) (match-end 1))) + (line-end-position))) + (bol (point))) + (if (eq special 'reversed) + (when (and (= origin bol) (eq last-command this-command)) + (goto-char refpos)) + (when (or (> origin refpos) (= origin bol)) + (goto-char refpos))))) + ((and (looking-at org-list-full-item-re) + (memq (org-element-type (save-match-data (org-element-at-point))) + '(item plain-list))) + ;; Set special position at first white space character after + ;; bullet, and check-box, if any. + (let ((after-bullet + (let ((box (match-end 3))) + (cond ((not box) (match-end 1)) + ((eq (char-after box) ?\s) (1+ box)) + (t box))))) + (if (eq special 'reversed) + (when (and (= (point) origin) (eq last-command this-command)) + (goto-char after-bullet)) + (when (or (> origin after-bullet) (= (point) origin)) + (goto-char after-bullet))))) + ;; No special context. Point is already at beginning of line. + (t nil)))) + +(defun org-end-of-line (&optional n) + "Go to the end of the line, but before ellipsis, if any. + +If this is a headline, and `org-special-ctrl-a/e' is set, ignore +tags on the first attempt, and only move to after the tags when +the cursor is already beyond the end of the headline. + +With argument N not nil or 1, move forward N - 1 lines first." + (interactive "^p") + (let ((origin (point)) + (special (pcase org-special-ctrl-a/e + (`(,_ . ,C-e) C-e) (_ org-special-ctrl-a/e))) + deactivate-mark) + ;; First move to a visible line. + (if (bound-and-true-p visual-line-mode) + (beginning-of-visual-line n) + (move-beginning-of-line n)) + (cond + ;; At a headline, with tags. + ((and special + (save-excursion + (beginning-of-line) + (let ((case-fold-search nil)) + (looking-at org-complex-heading-regexp))) + (match-end 5)) + (let ((tags (save-excursion + (goto-char (match-beginning 5)) + (skip-chars-backward " \t") + (point))) + (visual-end (and (bound-and-true-p visual-line-mode) + (save-excursion + (end-of-visual-line) + (point))))) + ;; If `end-of-visual-line' brings us before end of line or + ;; even tags, i.e., the headline spans over multiple visual + ;; lines, move there. + (cond ((and visual-end + (< visual-end tags) + (<= origin visual-end)) + (goto-char visual-end)) + ((eq special 'reversed) + (if (and (= origin (line-end-position)) + (eq this-command last-command)) + (goto-char tags) + (end-of-line))) + (t + (if (or (< origin tags) (= origin (line-end-position))) + (goto-char tags) + (end-of-line)))))) + ((bound-and-true-p visual-line-mode) + (let ((bol (line-beginning-position))) + (end-of-visual-line) + ;; If `end-of-visual-line' gets us past the ellipsis at the + ;; end of a line, backtrack and use `end-of-line' instead. + (when (/= bol (line-beginning-position)) + (goto-char bol) + (end-of-line)))) + (t (end-of-line))))) (define-key org-mode-map "\C-a" 'org-beginning-of-line) (define-key org-mode-map "\C-e" 'org-end-of-line) @@ -22948,18 +23872,43 @@ the cursor is already beyond the end of the headline." This will call `backward-sentence' or `org-table-beginning-of-field', depending on context." (interactive) - (cond - ((org-at-table-p) (call-interactively 'org-table-beginning-of-field)) - (t (call-interactively 'backward-sentence)))) + (let* ((element (org-element-at-point)) + (contents-begin (org-element-property :contents-begin element)) + (table (org-element-lineage element '(table) t))) + (if (and table + (> (point) contents-begin) + (<= (point) (org-element-property :contents-end table))) + (call-interactively #'org-table-beginning-of-field) + (save-restriction + (when (and contents-begin + (< (point-min) contents-begin) + (> (point) contents-begin)) + (narrow-to-region contents-begin + (org-element-property :contents-end element))) + (call-interactively #'backward-sentence))))) (defun org-forward-sentence (&optional _arg) "Go to end of sentence, or end of table field. This will call `forward-sentence' or `org-table-end-of-field', depending on context." (interactive) - (cond - ((org-at-table-p) (call-interactively 'org-table-end-of-field)) - (t (call-interactively 'forward-sentence)))) + (let* ((element (org-element-at-point)) + (contents-end (org-element-property :contents-end element)) + (table (org-element-lineage element '(table) t))) + (if (and table + (>= (point) (org-element-property :contents-begin table)) + (< (point) contents-end)) + (call-interactively #'org-table-end-of-field) + (save-restriction + (when (and contents-end + (> (point-max) contents-end) + ;; Skip blank lines between elements. + (< (org-element-property :end element) + (save-excursion (goto-char contents-end) + (skip-chars-forward " \r\t\n")))) + (narrow-to-region (org-element-property :contents-begin element) + contents-end)) + (call-interactively #'forward-sentence))))) (define-key org-mode-map "\M-a" 'org-backward-sentence) (define-key org-mode-map "\M-e" 'org-forward-sentence) @@ -22971,14 +23920,14 @@ depending on context." ((or (not org-special-ctrl-k) (bolp) (not (org-at-heading-p))) - (if (and (get-char-property (min (point-max) (point-at-eol)) 'invisible) - org-ctrl-k-protect-subtree) - (if (or (eq org-ctrl-k-protect-subtree 'error) - (not (y-or-n-p "Kill hidden subtree along with headline? "))) - (user-error "C-k aborted as it would kill a hidden subtree"))) + (when (and (get-char-property (min (point-max) (point-at-eol)) 'invisible) + org-ctrl-k-protect-subtree + (or (eq org-ctrl-k-protect-subtree 'error) + (not (y-or-n-p "Kill hidden subtree along with headline? ")))) + (user-error "C-k aborted as it would kill a hidden subtree")) (call-interactively - (if (org-bound-and-true-p visual-line-mode) 'kill-visual-line 'kill-line))) - ((looking-at (org-re ".*?\\S-\\([ \t]+\\(:[[:alnum:]_@#%:]+:\\)\\)[ \t]*$")) + (if (bound-and-true-p visual-line-mode) 'kill-visual-line 'kill-line))) + ((looking-at ".*?\\S-\\([ \t]+\\(:[[:alnum:]_@#%:]+:\\)\\)[ \t]*$") (kill-region (point) (match-beginning 1)) (org-set-tags nil t)) (t (kill-region (point) (point-at-eol))))) @@ -22991,24 +23940,25 @@ This command will look at the current kill and check if is a single subtree, or a series of subtrees[1]. If it passes the test, and if the cursor is at the beginning of a line or after the stars of a currently empty headline, then the yank is handled specially. How exactly depends -on the value of the following variables, both set by default. +on the value of the following variables. -org-yank-folded-subtrees - When set, the subtree(s) will be folded after insertion, but only - if doing so would now swallow text after the yanked text. +`org-yank-folded-subtrees' + By default, this variable is non-nil, which results in + subtree(s) being folded after insertion, except if doing so + would swallow text after the yanked text. -org-yank-adjusted-subtrees - When set, the subtree will be promoted or demoted in order to - fit into the local outline tree structure, which means that the level - will be adjusted so that it becomes the smaller one of the two - *visible* surrounding headings. +`org-yank-adjusted-subtrees' + When non-nil (the default value is nil), the subtree will be + promoted or demoted in order to fit into the local outline tree + structure, which means that the level will be adjusted so that it + becomes the smaller one of the two *visible* surrounding headings. Any prefix to this command will cause `yank' to be called directly with -no special treatment. In particular, a simple \\[universal-argument] prefix \ +no special treatment. In particular, a simple `\\[universal-argument]' prefix \ will just plainly yank the text as it is. -[1] The test checks if the first non-white line is a heading +\[1] The test checks if the first non-white line is a heading and if there are no other headings with fewer stars." (interactive "P") (org-yank-generic 'yank arg)) @@ -23051,7 +24001,7 @@ interactive command with similar behavior." (or (looking-at org-outline-regexp) (re-search-forward org-outline-regexp-bol end t)) (while (and (< (point) end) (looking-at org-outline-regexp)) - (hide-subtree) + (outline-hide-subtree) (org-cycle-show-empty-lines 'folded) (condition-case nil (outline-forward-same-level 1) @@ -23082,11 +24032,9 @@ interactive command with similar behavior." (setq level (org-outline-level))) (goto-char end) (skip-chars-forward " \t\r\n\v\f") - (if (or (eobp) - (and (bolp) (looking-at org-outline-regexp) - (<= (org-outline-level) level))) - nil ; Nothing would be swallowed - t))))) ; something would swallow + (not (or (eobp) + (and (bolp) (looking-at-p org-outline-regexp) + (<= (org-outline-level) level)))))))) (define-key org-mode-map "\C-y" 'org-yank) @@ -23094,17 +24042,18 @@ interactive command with similar behavior." "Check if point is at a character currently not visible. This version does not only check the character property, but also `visible-mode'." - ;; Early versions of noutline don't have `outline-invisible-p'. - (if (org-bound-and-true-p visible-mode) - nil - (outline-invisible-p))) + (unless (bound-and-true-p visible-mode) + (org-invisible-p))) (defun org-invisible-p2 () - "Check if point is at a character currently not visible." + "Check if point is at a character currently not visible. + +If the point is at EOL (and not at the beginning of a buffer too), +move it back by one char before doing this check." (save-excursion - (if (and (eolp) (not (bobp))) (backward-char 1)) - ;; Early versions of noutline don't have `outline-invisible-p'. - (outline-invisible-p))) + (when (and (eolp) (not (bobp))) + (backward-char 1)) + (org-invisible-p))) (defun org-back-to-heading (&optional invisible-ok) "Call `outline-back-to-heading', but provide a better error message." @@ -23121,14 +24070,28 @@ This version does not only check the character property, but also (defun org-at-heading-p (&optional ignored) (outline-on-heading-p t)) -;; Compatibility alias with Org versions < 7.8.03 -(defalias 'org-on-heading-p 'org-at-heading-p) + +(defun org-in-commented-heading-p (&optional no-inheritance) + "Non-nil if point is under a commented heading. +This function also checks ancestors of the current headline, +unless optional argument NO-INHERITANCE is non-nil." + (cond + ((org-before-first-heading-p) nil) + ((let ((headline (nth 4 (org-heading-components)))) + (and headline + (let ((case-fold-search nil)) + (string-match-p (concat "^" org-comment-string "\\(?: \\|$\\)") + headline))))) + (no-inheritance nil) + (t + (save-excursion (and (org-up-heading-safe) (org-in-commented-heading-p)))))) (defun org-at-comment-p nil - "Is cursor in a line starting with a # character?" + "Is cursor in a commented line?" (save-excursion - (beginning-of-line) - (looking-at "^#"))) + (save-match-data + (beginning-of-line) + (looking-at "^[ \t]*# ")))) (defun org-at-drawer-p nil "Is cursor at a drawer keyword?" @@ -23146,13 +24109,13 @@ This version does not only check the character property, but also "If point is at the end of an empty headline, return t, else nil. If the heading only contains a TODO keyword, it is still still considered empty." - (and (looking-at "[ \t]*$") - (when org-todo-line-regexp + (let ((case-fold-search nil)) + (and (looking-at "[ \t]*$") + org-todo-line-regexp (save-excursion - (beginning-of-line 1) - (let ((case-fold-search nil)) - (looking-at org-todo-line-regexp) - (string= (match-string 3) "")))))) + (beginning-of-line) + (looking-at org-todo-line-regexp) + (string= (match-string 3) ""))))) (defun org-at-heading-or-item-p () (or (org-at-heading-p) (org-at-item-p))) @@ -23167,9 +24130,7 @@ empty." "Move to the heading line of which the present line is a subheading. This function considers both visible and invisible heading lines. With argument, move up ARG levels." - (if (fboundp 'outline-up-heading-all) - (outline-up-heading-all arg) ; emacs 21 version of outline.el - (outline-up-heading arg t))) ; emacs 22 version of outline.el + (outline-up-heading arg t)) (defun org-up-heading-safe () "Move to the heading line of which the present line is a subheading. @@ -23179,14 +24140,11 @@ headline found, or nil if no higher level is found. Also, this function will be a lot faster than `outline-up-heading', because it relies on stars being the outline starters. This can really make a significant difference in outlines with very many siblings." - (let (start-level re) - (org-back-to-heading t) - (setq start-level (funcall outline-level)) - (if (equal start-level 1) - nil - (setq re (concat "^\\*\\{1," (number-to-string (1- start-level)) "\\} ")) - (if (re-search-backward re nil t) - (funcall outline-level))))) + (when (ignore-errors (org-back-to-heading t)) + (let ((level-up (1- (funcall outline-level)))) + (and (> level-up 0) + (re-search-backward (format "^\\*\\{1,%d\\} " level-up) nil t) + (funcall outline-level))))) (defun org-first-sibling-p () "Is this heading the first child of its parents?" @@ -23211,7 +24169,7 @@ move point." (pos (point)) (re org-outline-regexp-bol) level l) - (when (condition-case nil (org-back-to-heading t) (error nil)) + (when (ignore-errors (org-back-to-heading t)) (setq level (funcall outline-level)) (catch 'exit (or previous (forward-char 1)) @@ -23235,7 +24193,7 @@ move point." Return t when a child was found. Otherwise don't move point and return nil." (let (level (pos (point)) (re org-outline-regexp-bol)) - (when (condition-case nil (org-back-to-heading t) (error nil)) + (when (ignore-errors (org-back-to-heading t)) (setq level (outline-level)) (forward-char 1) (if (and (re-search-forward re nil t) (> (outline-level) level)) @@ -23271,8 +24229,7 @@ This is like outline-next-sibling, but invisible headings are ok." (outline-next-heading) (while (and (not (eobp)) (> (funcall outline-level) level)) (outline-next-heading)) - (if (or (eobp) (< (funcall outline-level) level)) - nil + (unless (or (eobp) (< (funcall outline-level) level)) (point)))) (defun org-get-last-sibling () @@ -23285,8 +24242,7 @@ If there is no such heading, return nil." (while (and (> (funcall outline-level) level) (not (bobp))) (outline-previous-heading)) - (if (< (funcall outline-level) level) - nil + (unless (< (funcall outline-level) level) (point))))) (defun org-end-of-subtree (&optional invisible-ok to-heading) @@ -23302,7 +24258,7 @@ If there is no such heading, return nil." (let ((first t) (level (funcall outline-level))) (if (and (derived-mode-p 'org-mode) (< level 1000)) - ;; A true heading (not a plain list item), in Org-mode + ;; A true heading (not a plain list item), in Org ;; This means we can easily find the end by looking ;; only for the right number of stars. Using a regexp to do ;; this is so much faster than using a Lisp loop. @@ -23315,33 +24271,36 @@ If there is no such heading, return nil." (setq first nil) (outline-next-heading))) (unless to-heading - (if (memq (preceding-char) '(?\n ?\^M)) - (progn - ;; Go to end of line before heading - (forward-char -1) - (if (memq (preceding-char) '(?\n ?\^M)) - ;; leave blank line before heading - (forward-char -1)))))) + (when (memq (preceding-char) '(?\n ?\^M)) + ;; Go to end of line before heading + (forward-char -1) + (when (memq (preceding-char) '(?\n ?\^M)) + ;; leave blank line before heading + (forward-char -1))))) (point)) -(defun org-end-of-meta-data-and-drawers () - "Jump to the first text after meta data and drawers in the current entry. -This will move over empty lines, lines with planning time stamps, -clocking lines, and drawers." +(defun org-end-of-meta-data (&optional full) + "Skip planning line and properties drawer in current entry. +When optional argument FULL is non-nil, also skip empty lines, +clocking lines and regular drawers at the beginning of the +entry." (org-back-to-heading t) - (let ((end (save-excursion (outline-next-heading) (point))) - (re (concat "\\(" org-drawer-regexp "\\)" - "\\|" "[ \t]*" org-keyword-time-regexp))) - (forward-line 1) - (while (re-search-forward re end t) - (if (not (match-end 1)) - ;; empty or planning line - (forward-line 1) - ;; a drawer, find the end - (re-search-forward "^[ \t]*:END:" end 'move) - (forward-line 1))) - (and (re-search-forward "[^\n]" nil t) (backward-char 1)) - (point))) + (forward-line) + (when (looking-at-p org-planning-line-re) (forward-line)) + (when (looking-at org-property-drawer-re) + (goto-char (match-end 0)) + (forward-line)) + (when (and full (not (org-at-heading-p))) + (catch 'exit + (let ((end (save-excursion (outline-next-heading) (point))) + (re (concat "[ \t]*$" "\\|" org-clock-line-re))) + (while (not (eobp)) + (cond ((looking-at-p org-drawer-regexp) + (if (re-search-forward "^[ \t]*:END:[ \t]*$" end t) + (forward-line) + (throw 'exit t))) + ((looking-at-p re) (forward-line)) + (t (throw 'exit t)))))))) (defun org-forward-heading-same-level (arg &optional invisible-ok) "Move forward to the ARG'th subheading at same level as this one. @@ -23349,32 +24308,27 @@ Stop at the first and last subheadings of a superior heading. Normally this only looks at visible headings, but when INVISIBLE-OK is non-nil it will also look at invisible ones." (interactive "p") - (if (not (ignore-errors (org-back-to-heading invisible-ok))) - (if (and arg (< arg 0)) - (goto-char (point-min)) - (outline-next-heading)) - (org-at-heading-p) - (let ((level (- (match-end 0) (match-beginning 0) 1)) - (f (if (and arg (< arg 0)) - 're-search-backward - 're-search-forward)) - (count (if arg (abs arg) 1)) - (result (point))) - (while (and (prog1 (> count 0) - (forward-char (if (and arg (< arg 0)) -1 1))) - (funcall f org-outline-regexp-bol nil 'move)) - (let ((l (- (match-end 0) (match-beginning 0) 1))) - (cond ((< l level) (setq count 0)) - ((and (= l level) - (or invisible-ok - (progn - (goto-char (line-beginning-position)) - (not (outline-invisible-p))))) - (setq count (1- count)) - (when (eq l level) - (setq result (point))))))) - (goto-char result)) - (beginning-of-line 1))) + (let ((backward? (and arg (< arg 0)))) + (if (org-before-first-heading-p) + (if backward? (goto-char (point-min)) (outline-next-heading)) + (org-back-to-heading invisible-ok) + (unless backward? (end-of-line)) ;do not match current headline + (let ((level (- (match-end 0) (match-beginning 0) 1)) + (f (if backward? #'re-search-backward #'re-search-forward)) + (count (if arg (abs arg) 1)) + (result (point))) + (while (and (> count 0) + (funcall f org-outline-regexp-bol nil 'move)) + (let ((l (- (match-end 0) (match-beginning 0) 1))) + (cond ((< l level) (setq count 0)) + ((and (= l level) + (or invisible-ok + (not (org-invisible-p + (line-beginning-position))))) + (cl-decf count) + (when (= l level) (setq result (point))))))) + (goto-char result)) + (beginning-of-line)))) (defun org-backward-heading-same-level (arg &optional invisible-ok) "Move backward to the ARG'th subheading at same level as this one. @@ -23382,20 +24336,64 @@ Stop at the first and last subheadings of a superior heading." (interactive "p") (org-forward-heading-same-level (if arg (- arg) -1) invisible-ok)) +(defun org-next-visible-heading (arg) + "Move to the next visible heading. + +This function wraps `outline-next-visible-heading' with +`org-with-limited-levels' in order to skip over inline tasks and +respect customization of `org-odd-levels-only'." + (interactive "p") + (org-with-limited-levels + (outline-next-visible-heading arg))) + +(defun org-previous-visible-heading (arg) + "Move to the previous visible heading. + +This function wraps `outline-previous-visible-heading' with +`org-with-limited-levels' in order to skip over inline tasks and +respect customization of `org-odd-levels-only'." + (interactive "p") + (org-with-limited-levels + (outline-previous-visible-heading arg))) + (defun org-next-block (arg &optional backward block-regexp) "Jump to the next block. -With a prefix argument ARG, jump forward ARG many source blocks. + +With a prefix argument ARG, jump forward ARG many blocks. + When BACKWARD is non-nil, jump to the previous block. -When BLOCK-REGEXP is non-nil, use this regexp to find blocks." + +When BLOCK-REGEXP is non-nil, use this regexp to find blocks. +Match data is set according to this regexp when the function +returns. + +Return point at beginning of the opening line of found block. +Throw an error if no block is found." (interactive "p") - (let ((re (or block-regexp org-block-regexp)) - (re-search-fn (or (and backward 're-search-backward) - 're-search-forward))) - (if (looking-at re) (forward-char 1)) - (condition-case nil - (funcall re-search-fn re nil nil arg) - (error (error "No %s code blocks" (if backward "previous" "further" )))) - (goto-char (match-beginning 0)) (org-show-context))) + (let ((re (or block-regexp "^[ \t]*#\\+BEGIN")) + (case-fold-search t) + (search-fn (if backward #'re-search-backward #'re-search-forward)) + (count (or arg 1)) + (origin (point)) + last-element) + (if backward (beginning-of-line) (end-of-line)) + (while (and (> count 0) (funcall search-fn re nil t)) + (let ((element (save-excursion + (goto-char (match-beginning 0)) + (save-match-data (org-element-at-point))))) + (when (and (memq (org-element-type element) + '(center-block comment-block dynamic-block + example-block export-block quote-block + special-block src-block verse-block)) + (<= (match-beginning 0) + (org-element-property :post-affiliated element))) + (setq last-element element) + (cl-decf count)))) + (if (= count 0) + (prog1 (goto-char (org-element-property :post-affiliated last-element)) + (save-match-data (org-show-context))) + (goto-char origin) + (user-error "No %s code blocks" (if backward "previous" "further"))))) (defun org-previous-block (arg &optional block-regexp) "Jump to the previous block. @@ -23434,7 +24432,7 @@ item, etc. It also provides some special moves for convenience: (skip-chars-forward " \r\t\n") (or (eobp) (beginning-of-line))) ;; On affiliated keywords, move to element's beginning. - ((and post-affiliated (< (point) post-affiliated)) + ((< (point) post-affiliated) (goto-char post-affiliated)) ;; At a table row, move to the end of the table. Similarly, ;; at a node property, move to the end of the property @@ -23461,8 +24459,8 @@ item, etc. It also provides some special moves for convenience: ;; With no contents, just skip element. ((not contents-begin) (goto-char end)) ;; If contents are invisible, skip the element altogether. - ((outline-invisible-p (line-end-position)) - (case type + ((org-invisible-p (line-end-position)) + (cl-case type (headline (org-with-limited-levels (outline-next-visible-heading 1))) ;; At a plain list, make sure we move to the next item @@ -23473,7 +24471,7 @@ item, etc. It also provides some special moves for convenience: ((>= (point) contents-end) (goto-char end)) ((>= (point) contents-begin) ;; This can only happen on paragraphs and plain lists. - (case type + (cl-case type (paragraph (goto-char end)) ;; At a plain list, try to move to second element in ;; first item, if possible. @@ -23513,7 +24511,7 @@ convenience: ((= (point) begin) (backward-char) (org-backward-paragraph)) - ((and post-affiliated (<= (point) post-affiliated)) (goto-char begin)) + ((<= (point) post-affiliated) (goto-char begin)) ((memq type '(node-property table-row)) (goto-char (org-element-property :post-affiliated (org-element-property :parent element)))) @@ -23548,7 +24546,7 @@ convenience: (org-backward-paragraph)) (t (goto-char (or post-affiliated begin)))) ;; Ensure we never leave point invisible. - (when (outline-invisible-p (point)) (beginning-of-visual-line)))) + (when (org-invisible-p (point)) (beginning-of-visual-line)))) (defun org-forward-element () "Move forward by one element. @@ -23587,18 +24585,21 @@ Move to the previous element at the same level, when possible." (progn (goto-char origin) (user-error "Cannot move further up")))))) (t - (let* ((trail (org-element-at-point 'keep-trail)) - (elem (car trail)) - (prev-elem (nth 1 trail)) + (let* ((elem (org-element-at-point)) (beg (org-element-property :begin elem))) (cond ;; Move to beginning of current element if point isn't ;; there already. ((null beg) (message "No element at point")) ((/= (point) beg) (goto-char beg)) - (prev-elem (goto-char (org-element-property :begin prev-elem))) - ((org-before-first-heading-p) (goto-char (point-min))) - (t (org-back-to-heading))))))) + (t (goto-char beg) + (skip-chars-backward " \r\t\n") + (unless (bobp) + (let ((prev (org-element-at-point))) + (goto-char (org-element-property :begin prev)) + (while (and (setq prev (org-element-property :parent prev)) + (<= (org-element-property :end prev) beg)) + (goto-char (org-element-property :begin prev))))))))))) (defun org-up-element () "Move to upper element." @@ -23612,7 +24613,6 @@ Move to the previous element at the same level, when possible." (user-error "No surrounding element") (org-with-limited-levels (org-back-to-heading))))))) -(defvar org-element-greater-elements) (defun org-down-element () "Move to inner element." (interactive) @@ -23623,7 +24623,7 @@ Move to the previous element at the same level, when possible." (forward-char)) ((memq (org-element-type element) org-element-greater-elements) ;; If contents are hidden, first disclose them. - (when (org-element-property :hiddenp element) (org-cycle)) + (when (org-invisible-p (line-end-position)) (org-cycle)) (goto-char (or (org-element-property :contents-begin element) (user-error "No content for this element")))) (t (user-error "No inner element"))))) @@ -23631,24 +24631,41 @@ Move to the previous element at the same level, when possible." (defun org-drag-element-backward () "Move backward element at point." (interactive) - (if (org-with-limited-levels (org-at-heading-p)) (org-move-subtree-up) - (let* ((trail (org-element-at-point 'keep-trail)) - (elem (car trail)) - (prev-elem (nth 1 trail))) - ;; Error out if no previous element or previous element is - ;; a parent of the current one. - (if (or (not prev-elem) (org-element-nested-p elem prev-elem)) - (user-error "Cannot drag element backward") - (let ((pos (point))) - (org-element-swap-A-B prev-elem elem) - (goto-char (+ (org-element-property :begin prev-elem) - (- pos (org-element-property :begin elem))))))))) + (let ((elem (or (org-element-at-point) + (user-error "No element at point")))) + (if (eq (org-element-type elem) 'headline) + ;; Preserve point when moving a whole tree, even if point was + ;; on blank lines below the headline. + (let ((offset (skip-chars-backward " \t\n"))) + (unwind-protect (org-move-subtree-up) + (forward-char (- offset)))) + (let ((prev-elem + (save-excursion + (goto-char (org-element-property :begin elem)) + (skip-chars-backward " \r\t\n") + (unless (bobp) + (let* ((beg (org-element-property :begin elem)) + (prev (org-element-at-point)) + (up prev)) + (while (and (setq up (org-element-property :parent up)) + (<= (org-element-property :end up) beg)) + (setq prev up)) + prev))))) + ;; Error out if no previous element or previous element is + ;; a parent of the current one. + (if (or (not prev-elem) (org-element-nested-p elem prev-elem)) + (user-error "Cannot drag element backward") + (let ((pos (point))) + (org-element-swap-A-B prev-elem elem) + (goto-char (+ (org-element-property :begin prev-elem) + (- pos (org-element-property :begin elem)))))))))) (defun org-drag-element-forward () "Move forward element at point." (interactive) (let* ((pos (point)) - (elem (org-element-at-point))) + (elem (or (org-element-at-point) + (user-error "No element at point")))) (when (= (point-max) (org-element-property :end elem)) (user-error "Cannot drag element forward")) (goto-char (org-element-property :end elem)) @@ -23681,7 +24698,7 @@ Move to the previous element at the same level, when possible." (defun org-drag-line-forward (arg) "Drag the line at point ARG lines forward." (interactive "p") - (dotimes (n (abs arg)) + (dotimes (_ (abs arg)) (let ((c (current-column))) (if (< 0 arg) (progn @@ -23705,7 +24722,7 @@ mode) if the mark is active, it marks the next element after the ones already marked." (interactive) (let (deactivate-mark) - (if (and (org-called-interactively-p 'any) + (if (and (called-interactively-p 'any) (or (and (eq last-command this-command) (mark t)) (and transient-mark-mode mark-active))) (set-mark @@ -23751,13 +24768,10 @@ modified." (interactive) (unless (eq major-mode 'org-mode) (user-error "Cannot un-indent a buffer not in Org mode")) - (let* ((parse-tree (org-element-parse-buffer 'greater-element)) - unindent-tree ; For byte-compiler. - (unindent-tree - (function - (lambda (contents) - (mapc - (lambda (element) + (letrec ((parse-tree (org-element-parse-buffer 'greater-element)) + (unindent-tree + (lambda (contents) + (dolist (element (reverse contents)) (if (memq (org-element-type element) '(headline section)) (funcall unindent-tree (org-element-contents element)) (save-excursion @@ -23765,10 +24779,49 @@ modified." (narrow-to-region (org-element-property :begin element) (org-element-property :end element)) - (org-do-remove-indentation))))) - (reverse contents)))))) + (org-do-remove-indentation)))))))) (funcall unindent-tree (org-element-contents parse-tree)))) +(defun org-show-children (&optional level) + "Show all direct subheadings of this heading. +Prefix arg LEVEL is how many levels below the current level +should be shown. Default is enough to cause the following +heading to appear." + (interactive "p") + ;; If `orgstruct-mode' is active, use the slower version. + (if orgstruct-mode (call-interactively #'outline-show-children) + (save-excursion + (org-back-to-heading t) + (let* ((current-level (funcall outline-level)) + (max-level (org-get-valid-level + current-level + (if level (prefix-numeric-value level) 1))) + (end (save-excursion (org-end-of-subtree t t))) + (regexp-fmt "^\\*\\{%d,%s\\}\\(?: \\|$\\)") + (past-first-child nil) + ;; Make sure to skip inlinetasks. + (re (format regexp-fmt + current-level + (cond + ((not (featurep 'org-inlinetask)) "") + (org-odd-levels-only (- (* 2 org-inlinetask-min-level) + 3)) + (t (1- org-inlinetask-min-level)))))) + ;; Display parent heading. + (outline-flag-region (line-end-position 0) (line-end-position) nil) + (forward-line) + ;; Display children. First child may be deeper than expected + ;; MAX-LEVEL. Since we want to display it anyway, adjust + ;; MAX-LEVEL accordingly. + (while (re-search-forward re end t) + (unless past-first-child + (setq re (format regexp-fmt + current-level + (max (funcall outline-level) max-level))) + (setq past-first-child t)) + (outline-flag-region + (line-end-position 0) (line-end-position) nil)))))) + (defun org-show-subtree () "Show everything after this heading at deeper levels." (interactive) @@ -23783,58 +24836,33 @@ modified." Show the heading too, if it is currently invisible." (interactive) (save-excursion - (condition-case nil - (progn - (org-back-to-heading t) - (outline-flag-region - (max (point-min) (1- (point))) - (save-excursion - (if (re-search-forward - (concat "[\r\n]\\(" org-outline-regexp "\\)") nil t) - (match-beginning 1) - (point-max))) - nil) - (org-cycle-hide-drawers 'children)) - (error nil)))) + (ignore-errors + (org-back-to-heading t) + (outline-flag-region + (max (point-min) (1- (point))) + (save-excursion + (if (re-search-forward + (concat "[\r\n]\\(" org-outline-regexp "\\)") nil t) + (match-beginning 1) + (point-max))) + nil) + (org-cycle-hide-drawers 'children)))) (defun org-make-options-regexp (kwds &optional extra) - "Make a regular expression for keyword lines." - (concat - "^#\\+\\(" - (mapconcat 'regexp-quote kwds "\\|") - (if extra (concat "\\|" extra)) - "\\):[ \t]*\\(.*\\)")) - -;; Make isearch reveal the necessary context -(defun org-isearch-end () - "Reveal context after isearch exits." - (when isearch-success ; only if search was successful - (if (featurep 'xemacs) - ;; Under XEmacs, the hook is run in the correct place, - ;; we directly show the context. - (org-show-context 'isearch) - ;; In Emacs the hook runs *before* restoring the overlays. - ;; So we have to use a one-time post-command-hook to do this. - ;; (Emacs 22 has a special variable, see function `org-mode') - (unless (and (boundp 'isearch-mode-end-hook-quit) - isearch-mode-end-hook-quit) - ;; Only when the isearch was not quitted. - (org-add-hook 'post-command-hook 'org-isearch-post-command - 'append 'local))))) - -(defun org-isearch-post-command () - "Remove self from hook, and show context." - (remove-hook 'post-command-hook 'org-isearch-post-command 'local) - (org-show-context 'isearch)) - + "Make a regular expression for keyword lines. +KWDS is a list of keywords, as strings. Optional argument EXTRA, +when non-nil, is a regexp matching keywords names." + (concat "^[ \t]*#\\+\\(" + (regexp-opt kwds) + (and extra (concat (and kwds "\\|") extra)) + "\\):[ \t]*\\(.*\\)")) ;;;; Integration with and fixes for other packages ;;; Imenu support -(defvar org-imenu-markers nil +(defvar-local org-imenu-markers nil "All markers currently used by Imenu.") -(make-variable-buffer-local 'org-imenu-markers) (defun org-imenu-new-marker (&optional pos) "Return a new marker for use by Imenu, and remember the marker." @@ -23845,50 +24873,48 @@ Show the heading too, if it is currently invisible." (defun org-imenu-get-tree () "Produce the index for Imenu." - (mapc (lambda (x) (move-marker x nil)) org-imenu-markers) + (dolist (x org-imenu-markers) (move-marker x nil)) (setq org-imenu-markers nil) - (let* ((n org-imenu-depth) + (let* ((case-fold-search nil) + (n org-imenu-depth) (re (concat "^" (org-get-limited-outline-regexp))) (subs (make-vector (1+ n) nil)) (last-level 0) m level head0 head) - (save-excursion - (save-restriction - (widen) - (goto-char (point-max)) - (while (re-search-backward re nil t) - (setq level (org-reduced-level (funcall outline-level))) - (when (and (<= level n) - (looking-at org-complex-heading-regexp) - (setq head0 (org-match-string-no-properties 4))) - (setq head (org-link-display-format head0) - m (org-imenu-new-marker)) - (org-add-props head nil 'org-imenu-marker m 'org-imenu t) - (if (>= level last-level) - (push (cons head m) (aref subs level)) - (push (cons head (aref subs (1+ level))) (aref subs level)) - (loop for i from (1+ level) to n do (aset subs i nil))) - (setq last-level level))))) + (org-with-wide-buffer + (goto-char (point-max)) + (while (re-search-backward re nil t) + (setq level (org-reduced-level (funcall outline-level))) + (when (and (<= level n) + (looking-at org-complex-heading-regexp) + (setq head0 (match-string-no-properties 4))) + (setq head (org-link-display-format head0) + m (org-imenu-new-marker)) + (org-add-props head nil 'org-imenu-marker m 'org-imenu t) + (if (>= level last-level) + (push (cons head m) (aref subs level)) + (push (cons head (aref subs (1+ level))) (aref subs level)) + (cl-loop for i from (1+ level) to n do (aset subs i nil))) + (setq last-level level)))) (aref subs 1))) (eval-after-load "imenu" '(progn (add-hook 'imenu-after-jump-hook (lambda () - (if (derived-mode-p 'org-mode) - (org-show-context 'org-goto)))))) + (when (derived-mode-p 'org-mode) + (org-show-context 'org-goto)))))) -(defun org-link-display-format (link) - "Replace a link with its the description. +(defun org-link-display-format (s) + "Replace links in string S with their description. If there is no description, use the link target." (save-match-data - (if (string-match org-bracket-link-analytic-regexp link) - (replace-match (if (match-end 5) - (match-string 5 link) - (concat (match-string 1 link) - (match-string 3 link))) - nil t link) - link))) + (replace-regexp-in-string + org-bracket-link-analytic-regexp + (lambda (m) + (if (match-end 5) (match-string 5 m) + (concat (match-string 1 m) (match-string 3 m)))) + s nil t))) (defun org-toggle-link-display () "Toggle the literal or descriptive display of links." @@ -23909,11 +24935,11 @@ If there is no description, use the link target." 'face 'org-agenda-restriction-lock) (overlay-put org-speedbar-restriction-lock-overlay 'help-echo "Agendas are currently limited to this item.") -(org-detach-overlay org-speedbar-restriction-lock-overlay) +(delete-overlay org-speedbar-restriction-lock-overlay) (defun org-speedbar-set-agenda-restriction () "Restrict future agenda commands to the location at point in speedbar. -To get rid of the restriction, use \\[org-agenda-remove-restriction-lock]." +To get rid of the restriction, use `\\[org-agenda-remove-restriction-lock]'." (interactive) (require 'org-agenda) (let (p m tp np dir txt) @@ -23937,9 +24963,9 @@ To get rid of the restriction, use \\[org-agenda-remove-restriction-lock]." (let ((default-directory dir)) (expand-file-name txt))) (unless (derived-mode-p 'org-mode) - (user-error "Cannot restrict to non-Org-mode file")) + (user-error "Cannot restrict to non-Org mode file")) (org-agenda-set-restriction-lock 'file))) - (t (user-error "Don't know how to restrict Org-mode's agenda"))) + (t (user-error "Don't know how to restrict Org mode agenda"))) (move-overlay org-speedbar-restriction-lock-overlay (point-at-bol) (point-at-eol)) (setq current-prefix-arg nil) @@ -23959,34 +24985,98 @@ To get rid of the restriction, use \\[org-agenda-remove-restriction-lock]." ;;; Fixes and Hacks for problems with other packages -;; Make flyspell not check words in links, to not mess up our keymap -(defvar org-element-affiliated-keywords) ; From org-element.el -(defvar org-element-block-name-alist) ; From org-element.el +(defun org--flyspell-object-check-p (element) + "Non-nil when Flyspell can check object at point. +ELEMENT is the element at point." + (let ((object (save-excursion + (when (looking-at-p "\\>") (backward-char)) + (org-element-context element)))) + (cl-case (org-element-type object) + ;; Prevent checks in links due to keybinding conflict with + ;; Flyspell. + ((code entity export-snippet inline-babel-call + inline-src-block line-break latex-fragment link macro + statistics-cookie target timestamp verbatim) + nil) + (footnote-reference + ;; Only in inline footnotes, within the definition. + (and (eq (org-element-property :type object) 'inline) + (< (save-excursion + (goto-char (org-element-property :begin object)) + (search-forward ":" nil t 2)) + (point)))) + (otherwise t)))) + (defun org-mode-flyspell-verify () - "Don't let flyspell put overlays at active buttons, or on - {todo,all-time,additional-option-like}-keywords." - (require 'org-element) ; For `org-element-affiliated-keywords' - (let ((pos (max (1- (point)) (point-min))) - (word (thing-at-point 'word))) - (and (not (get-text-property pos 'keymap)) - (not (get-text-property pos 'org-no-flyspell)) - (not (member word org-todo-keywords-1)) - (not (member word org-all-time-keywords)) - (not (member word org-options-keywords)) - (not (member word (mapcar 'car org-startup-options))) - (not (member-ignore-case word org-element-affiliated-keywords)) - (not (member-ignore-case word (org-get-export-keywords))) - (not (member-ignore-case - word (mapcar 'car org-element-block-name-alist))) - (not (member-ignore-case word '("BEGIN" "END" "ATTR"))) - (not (org-in-src-block-p))))) + "Function used for `flyspell-generic-check-word-predicate'." + (if (org-at-heading-p) + ;; At a headline or an inlinetask, check title only. This is + ;; faster than relying on `org-element-at-point'. + (and (save-excursion (beginning-of-line) + (and (let ((case-fold-search t)) + (not (looking-at-p "\\*+ END[ \t]*$"))) + (let ((case-fold-search nil)) + (looking-at org-complex-heading-regexp)))) + (match-beginning 4) + (>= (point) (match-beginning 4)) + (or (not (match-beginning 5)) + (< (point) (match-beginning 5)))) + (let* ((element (org-element-at-point)) + (post-affiliated (org-element-property :post-affiliated element))) + (cond + ;; Ignore checks in all affiliated keywords but captions. + ((< (point) post-affiliated) + (and (save-excursion + (beginning-of-line) + (let ((case-fold-search t)) (looking-at "[ \t]*#\\+CAPTION:"))) + (> (point) (match-end 0)) + (org--flyspell-object-check-p element))) + ;; Ignore checks in LOGBOOK (or equivalent) drawer. + ((let ((log (org-log-into-drawer))) + (and log + (let ((drawer (org-element-lineage element '(drawer)))) + (and drawer + (eq (compare-strings + log nil nil + (org-element-property :drawer-name drawer) nil nil t) + t))))) + nil) + (t + (cl-case (org-element-type element) + ((comment quote-section) t) + (comment-block + ;; Allow checks between block markers, not on them. + (and (> (line-beginning-position) post-affiliated) + (save-excursion + (end-of-line) + (skip-chars-forward " \r\t\n") + (< (point) (org-element-property :end element))))) + ;; Arbitrary list of keywords where checks are meaningful. + ;; Make sure point is on the value part of the element. + (keyword + (and (member (org-element-property :key element) + '("DESCRIPTION" "TITLE")) + (save-excursion + (search-backward ":" (line-beginning-position) t)))) + ;; Check is globally allowed in paragraphs verse blocks and + ;; table rows (after affiliated keywords) but some objects + ;; must not be affected. + ((paragraph table-row verse-block) + (let ((cbeg (org-element-property :contents-begin element)) + (cend (org-element-property :contents-end element))) + (and cbeg (>= (point) cbeg) (< (point) cend) + (org--flyspell-object-check-p element)))))))))) +(put 'org-mode 'flyspell-mode-predicate 'org-mode-flyspell-verify) (defun org-remove-flyspell-overlays-in (beg end) "Remove flyspell overlays in region." - (and (org-bound-and-true-p flyspell-mode) + (and (bound-and-true-p flyspell-mode) (fboundp 'flyspell-delete-region-overlays) - (flyspell-delete-region-overlays beg end)) - (add-text-properties beg end '(org-no-flyspell t))) + (flyspell-delete-region-overlays beg end))) + +(defvar flyspell-delayed-commands) +(eval-after-load "flyspell" + '(add-to-list 'flyspell-delayed-commands 'org-self-insert-command)) ;; Make `bookmark-jump' shows the jump location if it was hidden. (eval-after-load "bookmark" @@ -24008,17 +25098,38 @@ To get rid of the restriction, use \\[org-agenda-remove-restriction-lock]." (eval-after-load "ecb" '(defadvice ecb-method-clicked (after esf/org-show-context activate) "Make hierarchy visible when jumping into location from ECB tree buffer." - (if (derived-mode-p 'org-mode) - (org-show-context)))) + (when (derived-mode-p 'org-mode) + (org-show-context)))) (defun org-bookmark-jump-unhide () "Unhide the current position, to show the bookmark location." (and (derived-mode-p 'org-mode) - (or (outline-invisible-p) + (or (org-invisible-p) (save-excursion (goto-char (max (point-min) (1- (point)))) - (outline-invisible-p))) + (org-invisible-p))) (org-show-context 'bookmark-jump))) +(defun org-mark-jump-unhide () + "Make the point visible with `org-show-context' after jumping to the mark." + (when (and (derived-mode-p 'org-mode) + (org-invisible-p)) + (org-show-context 'mark-goto))) + +(eval-after-load "simple" + '(defadvice pop-to-mark-command (after org-make-visible activate) + "Make the point visible with `org-show-context'." + (org-mark-jump-unhide))) + +(eval-after-load "simple" + '(defadvice exchange-point-and-mark (after org-make-visible activate) + "Make the point visible with `org-show-context'." + (org-mark-jump-unhide))) + +(eval-after-load "simple" + '(defadvice pop-global-mark (after org-make-visible activate) + "Make the point visible with `org-show-context'." + (org-mark-jump-unhide))) + ;; Make session.el ignore our circular variable (defvar session-globals-exclude) (eval-after-load "session" diff --git a/lisp/org/ox-ascii.el b/lisp/org/ox-ascii.el index 6ba70d700b2..8dc31be99d7 100644 --- a/lisp/org/ox-ascii.el +++ b/lisp/org/ox-ascii.el @@ -1,4 +1,4 @@ -;;; ox-ascii.el --- ASCII Back-End for Org Export Engine +;;; ox-ascii.el --- ASCII Back-End for Org Export Engine -*- lexical-binding: t; -*- ;; Copyright (C) 2012-2017 Free Software Foundation, Inc. @@ -27,9 +27,9 @@ ;;; Code: -(eval-when-compile (require 'cl)) (require 'ox) (require 'ox-publish) +(require 'cl-lib) (declare-function aa2u "ext:ascii-art-to-unicode" ()) @@ -49,8 +49,6 @@ (center-block . org-ascii-center-block) (clock . org-ascii-clock) (code . org-ascii-code) - (comment . (lambda (&rest args) "")) - (comment-block . (lambda (&rest args) "")) (drawer . org-ascii-drawer) (dynamic-block . org-ascii-dynamic-block) (entity . org-ascii-entity) @@ -71,12 +69,13 @@ (latex-fragment . org-ascii-latex-fragment) (line-break . org-ascii-line-break) (link . org-ascii-link) + (node-property . org-ascii-node-property) (paragraph . org-ascii-paragraph) (plain-list . org-ascii-plain-list) (plain-text . org-ascii-plain-text) (planning . org-ascii-planning) + (property-drawer . org-ascii-property-drawer) (quote-block . org-ascii-quote-block) - (quote-section . org-ascii-quote-section) (radio-target . org-ascii-radio-target) (section . org-ascii-section) (special-block . org-ascii-special-block) @@ -94,7 +93,6 @@ (underline . org-ascii-underline) (verbatim . org-ascii-verbatim) (verse-block . org-ascii-verse-block)) - :export-block "ASCII" :menu-entry '(?t "Export to Plain Text" ((?A "As ASCII buffer" @@ -119,7 +117,30 @@ (:filter-parse-tree org-ascii-filter-paragraph-spacing org-ascii-filter-comment-spacing) (:filter-section . org-ascii-filter-headline-blank-lines)) - :options-alist '((:ascii-charset nil nil org-ascii-charset))) + :options-alist + '((:subtitle "SUBTITLE" nil nil parse) + (:ascii-bullets nil nil org-ascii-bullets) + (:ascii-caption-above nil nil org-ascii-caption-above) + (:ascii-charset nil nil org-ascii-charset) + (:ascii-global-margin nil nil org-ascii-global-margin) + (:ascii-format-drawer-function nil nil org-ascii-format-drawer-function) + (:ascii-format-inlinetask-function + nil nil org-ascii-format-inlinetask-function) + (:ascii-headline-spacing nil nil org-ascii-headline-spacing) + (:ascii-indented-line-width nil nil org-ascii-indented-line-width) + (:ascii-inlinetask-width nil nil org-ascii-inlinetask-width) + (:ascii-inner-margin nil nil org-ascii-inner-margin) + (:ascii-links-to-notes nil nil org-ascii-links-to-notes) + (:ascii-list-margin nil nil org-ascii-list-margin) + (:ascii-paragraph-spacing nil nil org-ascii-paragraph-spacing) + (:ascii-quote-margin nil nil org-ascii-quote-margin) + (:ascii-table-keep-all-vertical-lines + nil nil org-ascii-table-keep-all-vertical-lines) + (:ascii-table-use-ascii-art nil nil org-ascii-table-use-ascii-art) + (:ascii-table-widen-columns nil nil org-ascii-table-widen-columns) + (:ascii-text-width nil nil org-ascii-text-width) + (:ascii-underline nil nil org-ascii-underline) + (:ascii-verbatim-format nil nil org-ascii-verbatim-format))) @@ -162,6 +183,15 @@ This margin is applied on both sides of the text." :package-version '(Org . "8.0") :type 'integer) +(defcustom org-ascii-list-margin 0 + "Width of margin used for plain lists, in characters. +This margin applies to top level list only, not to its +sub-lists." + :group 'org-export-ascii + :version "26.1" + :package-version '(Org . "8.3") + :type 'integer) + (defcustom org-ascii-inlinetask-width 30 "Width of inline tasks, in number of characters. This number ignores any margin." @@ -339,7 +369,7 @@ Otherwise, place it right after it." :type 'string) (defcustom org-ascii-format-drawer-function - (lambda (name contents width) contents) + (lambda (_name contents _width) contents) "Function called to format a drawer in ASCII. The function must accept three parameters: @@ -384,14 +414,18 @@ nil to ignore the inline task." ;; Internal functions fall into three categories. -;; The first one is about text formatting. The core function is -;; `org-ascii--current-text-width', which determines the current -;; text width allowed to a given element. In other words, it helps -;; keeping each line width within maximum text width defined in -;; `org-ascii-text-width'. Once this information is known, -;; `org-ascii--fill-string', `org-ascii--justify-string', -;; `org-ascii--box-string' and `org-ascii--indent-string' can -;; operate on a given output string. +;; The first one is about text formatting. The core functions are +;; `org-ascii--current-text-width' and +;; `org-ascii--current-justification', which determine, respectively, +;; the current text width allowed to a given element and its expected +;; justification. Once this information is known, +;; `org-ascii--fill-string', `org-ascii--justify-lines', +;; `org-ascii--justify-element' `org-ascii--box-string' and +;; `org-ascii--indent-string' can operate on a given output string. +;; In particular, justification happens at the regular (i.e., +;; non-greater) element level, which means that when the exporting +;; process reaches a container (e.g., a center block) content are +;; already justified. ;; The second category contains functions handling elements listings, ;; triggered by "#+TOC:" keyword. As such, `org-ascii--build-toc' @@ -420,7 +454,8 @@ a communication channel. Optional argument JUSTIFY can specify any type of justification among `left', `center', `right' or `full'. A nil value is equivalent to `left'. For a justification that doesn't also fill -string, see `org-ascii--justify-string'. +string, see `org-ascii--justify-lines' and +`org-ascii--justify-block'. Return nil if S isn't a string." (when (stringp s) @@ -435,8 +470,8 @@ Return nil if S isn't a string." (fill-region (point-min) (point-max) justify)) (buffer-string))))) -(defun org-ascii--justify-string (s text-width how) - "Justify string S. +(defun org-ascii--justify-lines (s text-width how) + "Justify all lines in string S. TEXT-WIDTH is an integer specifying maximum length of a line. HOW determines the type of justification: it can be `left', `right', `full' or `center'." @@ -452,6 +487,48 @@ HOW determines the type of justification: it can be `left', (forward-line))) (buffer-string))) +(defun org-ascii--justify-element (contents element info) + "Justify CONTENTS of ELEMENT. +INFO is a plist used as a communication channel. Justification +is done according to the type of element. More accurately, +paragraphs are filled and other elements are justified as blocks, +that is according to the widest non blank line in CONTENTS." + (if (not (org-string-nw-p contents)) contents + (let ((text-width (org-ascii--current-text-width element info)) + (how (org-ascii--current-justification element))) + (cond + ((eq (org-element-type element) 'paragraph) + ;; Paragraphs are treated specially as they need to be filled. + (org-ascii--fill-string contents text-width info how)) + ((eq how 'left) contents) + (t (with-temp-buffer + (insert contents) + (goto-char (point-min)) + (catch 'exit + (let ((max-width 0)) + ;; Compute maximum width. Bail out if it is greater + ;; than page width, since no justification is + ;; possible. + (save-excursion + (while (not (eobp)) + (unless (looking-at-p "[ \t]*$") + (end-of-line) + (let ((column (current-column))) + (cond + ((>= column text-width) (throw 'exit contents)) + ((> column max-width) (setq max-width column))))) + (forward-line))) + ;; Justify every line according to TEXT-WIDTH and + ;; MAX-WIDTH. + (let ((offset (/ (- text-width max-width) + (if (eq how 'right) 1 2)))) + (if (zerop offset) (throw 'exit contents) + (while (not (eobp)) + (unless (looking-at-p "[ \t]*$") + (indent-to-column offset)) + (forward-line))))) + (buffer-string)))))))) + (defun org-ascii--indent-string (s width) "Indent string S by WIDTH white spaces. Empty lines are not indented." @@ -472,26 +549,28 @@ INFO is a plist used as a communication channel." (defun org-ascii--current-text-width (element info) "Return maximum text width for ELEMENT's contents. INFO is a plist used as a communication channel." - (case (org-element-type element) + (pcase (org-element-type element) ;; Elements with an absolute width: `headline' and `inlinetask'. - (inlinetask org-ascii-inlinetask-width) - (headline - (- org-ascii-text-width + (`inlinetask (plist-get info :ascii-inlinetask-width)) + (`headline + (- (plist-get info :ascii-text-width) (let ((low-level-rank (org-export-low-level-p element info))) - (if low-level-rank (* low-level-rank 2) org-ascii-global-margin)))) + (if low-level-rank (* low-level-rank 2) + (plist-get info :ascii-global-margin))))) ;; Elements with a relative width: store maximum text width in ;; TOTAL-WIDTH. - (otherwise - (let* ((genealogy (cons element (org-export-get-genealogy element))) + (_ + (let* ((genealogy (org-element-lineage element nil t)) ;; Total width is determined by the presence, or not, of an ;; inline task among ELEMENT parents. (total-width - (if (loop for parent in genealogy - thereis (eq (org-element-type parent) 'inlinetask)) - org-ascii-inlinetask-width + (if (cl-some (lambda (parent) + (eq (org-element-type parent) 'inlinetask)) + genealogy) + (plist-get info :ascii-inlinetask-width) ;; No inlinetask: Remove global margin from text width. - (- org-ascii-text-width - org-ascii-global-margin + (- (plist-get info :ascii-text-width) + (plist-get info :ascii-global-margin) (let ((parent (org-export-get-parent-headline element))) ;; Inner margin doesn't apply to text before first ;; headline. @@ -502,41 +581,67 @@ INFO is a plist used as a communication channel." ;; low level headlines, since they've got their ;; own indentation mechanism. (if low-level-rank (* low-level-rank 2) - org-ascii-inner-margin)))))))) + (plist-get info :ascii-inner-margin))))))))) (- total-width - ;; Each `quote-block', `quote-section' and `verse-block' above - ;; narrows text width by twice the standard margin size. - (+ (* (loop for parent in genealogy - when (memq (org-element-type parent) - '(quote-block quote-section verse-block)) - count parent) - 2 org-ascii-quote-margin) + ;; Each `quote-block' and `verse-block' above narrows text + ;; width by twice the standard margin size. + (+ (* (cl-count-if (lambda (parent) + (memq (org-element-type parent) + '(quote-block verse-block))) + genealogy) + 2 + (plist-get info :ascii-quote-margin)) + ;; Apply list margin once per "top-level" plain-list + ;; containing current line + (* (cl-count-if + (lambda (e) + (and (eq (org-element-type e) 'plain-list) + (not (eq (org-element-type (org-export-get-parent e)) + 'item)))) + genealogy) + (plist-get info :ascii-list-margin)) ;; Text width within a plain-list is restricted by ;; indentation of current item. If that's the case, ;; compute it with the help of `:structure' property from ;; parent item, if any. - (let ((parent-item + (let ((item (if (eq (org-element-type element) 'item) element - (loop for parent in genealogy - when (eq (org-element-type parent) 'item) - return parent)))) - (if (not parent-item) 0 + (cl-find-if (lambda (parent) + (eq (org-element-type parent) 'item)) + genealogy)))) + (if (not item) 0 ;; Compute indentation offset of the current item, ;; that is the sum of the difference between its ;; indentation and the indentation of the top item in ;; the list and current item bullet's length. Also ;; remove checkbox length, and tag length (for ;; description lists) or bullet length. - (let ((struct (org-element-property :structure parent-item)) - (beg-item (org-element-property :begin parent-item))) + (let ((struct (org-element-property :structure item)) + (beg-item (org-element-property :begin item))) (+ (- (org-list-get-ind beg-item struct) (org-list-get-ind (org-list-get-top-point struct) struct)) - (string-width (or (org-ascii--checkbox parent-item info) + (string-width (or (org-ascii--checkbox item info) "")) (string-width - (or (org-list-get-tag beg-item struct) - (org-list-get-bullet beg-item struct))))))))))))) + (let ((tag (org-element-property :tag item))) + (if tag (org-export-data tag info) + (org-element-property :bullet item)))))))))))))) + +(defun org-ascii--current-justification (element) + "Return expected justification for ELEMENT's contents. +Return value is a symbol among `left', `center', `right' and +`full'." + (let (justification) + (while (and (not justification) + (setq element (org-element-property :parent element))) + (pcase (org-element-type element) + (`center-block (setq justification 'center)) + (`special-block + (let ((name (org-element-property :type element))) + (cond ((string= name "JUSTIFYRIGHT") (setq justification 'right)) + ((string= name "JUSTIFYLEFT") (setq justification 'left))))))) + (or justification 'left))) (defun org-ascii--build-title (element info text-width &optional underline notags toc) @@ -601,14 +706,14 @@ possible. It doesn't apply to `inlinetask' elements." (let ((under-char (nth (1- (org-export-get-relative-level element info)) (cdr (assq (plist-get info :ascii-charset) - org-ascii-underline))))) + (plist-get info :ascii-underline)))))) (and under-char (concat "\n" (make-string (/ (string-width first-part) (char-width under-char)) under-char)))))))) -(defun org-ascii--has-caption-p (element info) +(defun org-ascii--has-caption-p (element _info) "Non-nil when ELEMENT has a caption affiliated keyword. INFO is a plist used as a communication channel. This function is meant to be used as a predicate for `org-export-get-ordinal'." @@ -630,9 +735,9 @@ caption keyword." (org-export-get-ordinal element info nil 'org-ascii--has-caption-p)) (title-fmt (org-ascii--translate - (case (org-element-type element) - (table "Table %d:") - (src-block "Listing %d:")) + (pcase (org-element-type element) + (`table "Table %d:") + (`src-block "Listing %d:")) info))) (org-ascii--fill-string (concat (format title-fmt reference) @@ -640,7 +745,7 @@ caption keyword." (org-export-data caption info)) (org-ascii--current-text-width element info) info))))) -(defun org-ascii--build-toc (info &optional n keyword) +(defun org-ascii--build-toc (info &optional n keyword local) "Return a table of contents. INFO is a plist used as a communication channel. @@ -649,28 +754,34 @@ Optional argument N, when non-nil, is an integer specifying the depth of the table. Optional argument KEYWORD specifies the TOC keyword, if any, from -which the table of contents generation has been initiated." - (let ((title (org-ascii--translate "Table of Contents" info))) - (concat - title "\n" - (make-string (string-width title) - (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_)) - "\n\n" - (let ((text-width - (if keyword (org-ascii--current-text-width keyword info) - (- org-ascii-text-width org-ascii-global-margin)))) - (mapconcat - (lambda (headline) - (let* ((level (org-export-get-relative-level headline info)) - (indent (* (1- level) 3))) - (concat - (unless (zerop indent) (concat (make-string (1- indent) ?.) " ")) - (org-ascii--build-title - headline info (- text-width indent) nil - (or (not (plist-get info :with-tags)) - (eq (plist-get info :with-tags) 'not-in-toc)) - 'toc)))) - (org-export-collect-headlines info n) "\n"))))) +which the table of contents generation has been initiated. + +When optional argument LOCAL is non-nil, build a table of +contents according to the current headline." + (concat + (unless local + (let ((title (org-ascii--translate "Table of Contents" info))) + (concat title "\n" + (make-string + (string-width title) + (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_)) + "\n\n"))) + (let ((text-width + (if keyword (org-ascii--current-text-width keyword info) + (- (plist-get info :ascii-text-width) + (plist-get info :ascii-global-margin))))) + (mapconcat + (lambda (headline) + (let* ((level (org-export-get-relative-level headline info)) + (indent (* (1- level) 3))) + (concat + (unless (zerop indent) (concat (make-string (1- indent) ?.) " ")) + (org-ascii--build-title + headline info (- text-width indent) nil + (or (not (plist-get info :with-tags)) + (eq (plist-get info :with-tags) 'not-in-toc)) + 'toc)))) + (org-export-collect-headlines info n (and local keyword)) "\n")))) (defun org-ascii--list-listings (keyword info) "Return a list of listings. @@ -685,7 +796,8 @@ generation. INFO is a plist used as a communication channel." "\n\n" (let ((text-width (if keyword (org-ascii--current-text-width keyword info) - (- org-ascii-text-width org-ascii-global-margin))) + (- (plist-get info :ascii-text-width) + (plist-get info :ascii-global-margin)))) ;; Use a counter instead of retrieving ordinal of each ;; src-block. (count 0)) @@ -696,7 +808,7 @@ generation. INFO is a plist used as a communication channel." ;; filling (like contents of a description list item). (let* ((initial-text (format (org-ascii--translate "Listing %d:" info) - (incf count))) + (cl-incf count))) (initial-width (string-width initial-text))) (concat initial-text " " @@ -724,7 +836,8 @@ generation. INFO is a plist used as a communication channel." "\n\n" (let ((text-width (if keyword (org-ascii--current-text-width keyword info) - (- org-ascii-text-width org-ascii-global-margin))) + (- (plist-get info :ascii-text-width) + (plist-get info :ascii-global-margin)))) ;; Use a counter instead of retrieving ordinal of each ;; src-block. (count 0)) @@ -735,7 +848,7 @@ generation. INFO is a plist used as a communication channel." ;; filling (like contents of a description list item). (let* ((initial-text (format (org-ascii--translate "Table %d:" info) - (incf count))) + (cl-incf count))) (initial-width (string-width initial-text))) (concat initial-text " " @@ -756,69 +869,106 @@ ELEMENT is either a headline element or a section element. INFO is a plist used as a communication channel." (let* (seen (unique-link-p - (function - ;; Return LINK if it wasn't referenced so far, or nil. - ;; Update SEEN links along the way. - (lambda (link) - (let ((footprint - ;; Normalize description in footprints. - (cons (org-element-property :raw-link link) - (let ((contents (org-element-contents link))) - (and contents - (replace-regexp-in-string - "[ \r\t\n]+" " " - (org-trim - (org-element-interpret-data contents)))))))) - ;; Ignore LINK if it hasn't been translated already. - ;; It can happen if it is located in an affiliated - ;; keyword that was ignored. - (when (and (org-string-nw-p - (gethash link (plist-get info :exported-data))) - (not (member footprint seen))) - (push footprint seen) link))))) - ;; If at a section, find parent headline, if any, in order to - ;; count links that might be in the title. - (headline - (if (eq (org-element-type element) 'headline) element - (or (org-export-get-parent-headline element) element)))) - ;; Get all links in HEADLINE. - (org-element-map headline 'link - (lambda (l) (funcall unique-link-p l)) info nil nil t))) + ;; Return LINK if it wasn't referenced so far, or nil. + ;; Update SEEN links along the way. + (lambda (link) + (let ((footprint + ;; Normalize description in footprints. + (cons (org-element-property :raw-link link) + (let ((contents (org-element-contents link))) + (and contents + (replace-regexp-in-string + "[ \r\t\n]+" " " + (org-trim + (org-element-interpret-data contents)))))))) + ;; Ignore LINK if it hasn't been translated already. It + ;; can happen if it is located in an affiliated keyword + ;; that was ignored. + (when (and (org-string-nw-p + (gethash link (plist-get info :exported-data))) + (not (member footprint seen))) + (push footprint seen) link))))) + (org-element-map (if (eq (org-element-type element) 'section) + element + ;; In a headline, only retrieve links in title + ;; and relative section, not in children. + (list (org-element-property :title element) + (car (org-element-contents element)))) + 'link unique-link-p info nil 'headline t))) + +(defun org-ascii--describe-datum (datum info) + "Describe DATUM object or element. +If DATUM is a string, consider it to be a file name, per +`org-export-resolve-id-link'. INFO is the communication channel, +as a plist." + (pcase (org-element-type datum) + (`plain-text (format "See file %s" datum)) ;External file + (`headline + (format (org-ascii--translate "See section %s" info) + (if (org-export-numbered-headline-p datum info) + (mapconcat #'number-to-string + (org-export-get-headline-number datum info) + ".") + (org-export-data (org-element-property :title datum) info)))) + (_ + (let ((number (org-export-get-ordinal + datum info nil #'org-ascii--has-caption-p)) + ;; If destination is a target, make sure we can name the + ;; container it refers to. + (enumerable + (org-element-lineage datum + '(headline paragraph src-block table) t))) + (pcase (org-element-type enumerable) + (`headline + (format (org-ascii--translate "See section %s" info) + (if (org-export-numbered-headline-p enumerable info) + (mapconcat #'number-to-string number ".") + (org-export-data + (org-element-property :title enumerable) info)))) + ((guard (not number)) + (org-ascii--translate "Unknown reference" info)) + (`paragraph + (format (org-ascii--translate "See figure %s" info) number)) + (`src-block + (format (org-ascii--translate "See listing %s" info) number)) + (`table + (format (org-ascii--translate "See table %s" info) number)) + (_ (org-ascii--translate "Unknown reference" info))))))) (defun org-ascii--describe-links (links width info) "Return a string describing a list of links. - LINKS is a list of link type objects, as returned by `org-ascii--unique-links'. WIDTH is the text width allowed for the output string. INFO is a plist used as a communication channel." (mapconcat (lambda (link) - (let ((type (org-element-property :type link)) - (anchor (let ((desc (org-element-contents link))) - (if desc (org-export-data desc info) - (org-element-property :raw-link link))))) + (let* ((type (org-element-property :type link)) + (description (org-element-contents link)) + (anchor (org-export-data + (or description (org-element-property :raw-link link)) + info))) (cond - ;; Coderefs, radio links and fuzzy links are ignored. - ((member type '("coderef" "radio" "fuzzy")) nil) - ;; Id and custom-id links: Headlines refer to their numbering. - ((member type '("custom-id" "id")) - (let ((dest (org-export-resolve-id-link link info))) - (concat - (org-ascii--fill-string - (format - "[%s] %s" - anchor - (if (not dest) (org-ascii--translate "Unknown reference" info) - (format - (org-ascii--translate "See section %s" info) - (mapconcat 'number-to-string - (org-export-get-headline-number dest info) ".")))) - width info) "\n\n"))) + ((member type '("coderef" "radio")) nil) + ((member type '("custom-id" "fuzzy" "id")) + ;; Only links with a description need an entry. Other are + ;; already handled in `org-ascii-link'. + (when description + (let ((dest (if (equal type "fuzzy") + (org-export-resolve-fuzzy-link link info) + (org-export-resolve-id-link link info)))) + (concat + (org-ascii--fill-string + (format "[%s] %s" anchor (org-ascii--describe-datum dest info)) + width info) + "\n\n")))) ;; Do not add a link that cannot be resolved and doesn't have ;; any description: destination is already visible in the ;; paragraph. ((not (org-element-contents link)) nil) + ;; Do not add a link already handled by custom export + ;; functions. + ((org-export-custom-protocol-maybe link anchor 'ascii) nil) (t (concat (org-ascii--fill-string @@ -831,10 +981,10 @@ channel." "Return checkbox string for ITEM or nil. INFO is a plist used as a communication channel." (let ((utf8p (eq (plist-get info :ascii-charset) 'utf-8))) - (case (org-element-property :checkbox item) - (on (if utf8p "☑ " "[X] ")) - (off (if utf8p "☐ " "[ ] ")) - (trans (if utf8p "☒ " "[-] "))))) + (pcase (org-element-property :checkbox item) + (`on (if utf8p "☑ " "[X] ")) + (`off (if utf8p "☐ " "[ ] ")) + (`trans (if utf8p "☒ " "[-] "))))) @@ -843,11 +993,15 @@ INFO is a plist used as a communication channel." (defun org-ascii-template--document-title (info) "Return document title, as a string. INFO is a plist used as a communication channel." - (let* ((text-width org-ascii-text-width) + (let* ((text-width (plist-get info :ascii-text-width)) ;; Links in the title will not be resolved later, so we make ;; sure their path is located right after them. - (org-ascii-links-to-notes nil) - (title (org-export-data (plist-get info :title) info)) + (info (org-combine-plists info '(:ascii-links-to-notes nil))) + (with-title (plist-get info :with-title)) + (title (org-export-data + (when with-title (plist-get info :title)) info)) + (subtitle (org-export-data + (when with-title (plist-get info :subtitle)) info)) (author (and (plist-get info :with-author) (let ((auth (plist-get info :author))) (and auth (org-export-data auth info))))) @@ -878,7 +1032,7 @@ INFO is a plist used as a communication channel." date "\n\n\n")) ((org-string-nw-p date) (concat - (org-ascii--justify-string date text-width 'right) + (org-ascii--justify-lines date text-width 'right) "\n\n\n")) ((and (org-string-nw-p author) (org-string-nw-p email)) (concat author "\n" email "\n\n\n")) @@ -890,8 +1044,14 @@ INFO is a plist used as a communication channel." (let* ((utf8p (eq (plist-get info :ascii-charset) 'utf-8)) ;; Format TITLE. It may be filled if it is too wide, ;; that is wider than the two thirds of the total width. - (title-len (min (length title) (/ (* 2 text-width) 3))) + (title-len (min (apply #'max + (mapcar #'length + (org-split-string + (concat title "\n" subtitle) "\n"))) + (/ (* 2 text-width) 3))) (formatted-title (org-ascii--fill-string title title-len info)) + (formatted-subtitle (when (org-string-nw-p subtitle) + (org-ascii--fill-string subtitle title-len info))) (line (make-string (min (+ (max title-len @@ -899,17 +1059,16 @@ INFO is a plist used as a communication channel." (string-width (or email ""))) 2) text-width) (if utf8p ?━ ?_)))) - (org-ascii--justify-string + (org-ascii--justify-lines (concat line "\n" (unless utf8p "\n") (upcase formatted-title) + (and formatted-subtitle (concat "\n" formatted-subtitle)) (cond ((and (org-string-nw-p author) (org-string-nw-p email)) - (concat (if utf8p "\n\n\n" "\n\n") author "\n" email)) - ((org-string-nw-p author) - (concat (if utf8p "\n\n\n" "\n\n") author)) - ((org-string-nw-p email) - (concat (if utf8p "\n\n\n" "\n\n") email))) + (concat "\n\n" author "\n" email)) + ((org-string-nw-p author) (concat "\n\n" author)) + ((org-string-nw-p email) (concat "\n\n" email))) "\n" line (when (org-string-nw-p date) (concat "\n\n\n" date)) "\n\n\n") text-width 'center))))) @@ -919,81 +1078,83 @@ INFO is a plist used as a communication channel." CONTENTS is the transcoded contents string. INFO is a plist holding export options." (org-element-normalize-string - (org-ascii--indent-string - (concat - ;; 1. Document's body. - contents - ;; 2. Footnote definitions. - (let ((definitions (org-export-collect-footnote-definitions - (plist-get info :parse-tree) info)) - ;; Insert full links right inside the footnote definition - ;; as they have no chance to be inserted later. - (org-ascii-links-to-notes nil)) - (when definitions - (concat - "\n\n\n" - (let ((title (org-ascii--translate "Footnotes" info))) - (concat - title "\n" - (make-string - (string-width title) - (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_)))) - "\n\n" - (let ((text-width (- org-ascii-text-width org-ascii-global-margin))) - (mapconcat - (lambda (ref) - (let ((id (format "[%s] " (car ref)))) - ;; Distinguish between inline definitions and - ;; full-fledged definitions. - (org-trim - (let ((def (nth 2 ref))) - (if (eq (org-element-type def) 'org-data) - ;; Full-fledged definition: footnote ID is - ;; inserted inside the first parsed paragraph - ;; (FIRST), if any, to be sure filling will - ;; take it into consideration. - (let ((first (car (org-element-contents def)))) - (if (not (eq (org-element-type first) 'paragraph)) - (concat id "\n" (org-export-data def info)) - (push id (nthcdr 2 first)) - (org-export-data def info))) - ;; Fill paragraph once footnote ID is inserted - ;; in order to have a correct length for first - ;; line. - (org-ascii--fill-string - (concat id (org-export-data def info)) - text-width info)))))) - definitions "\n\n")))))) - org-ascii-global-margin))) + (let ((global-margin (plist-get info :ascii-global-margin))) + (org-ascii--indent-string + (concat + ;; 1. Document's body. + contents + ;; 2. Footnote definitions. + (let ((definitions (org-export-collect-footnote-definitions info)) + ;; Insert full links right inside the footnote definition + ;; as they have no chance to be inserted later. + (info (org-combine-plists info '(:ascii-links-to-notes nil)))) + (when definitions + (concat + "\n\n\n" + (let ((title (org-ascii--translate "Footnotes" info))) + (concat + title "\n" + (make-string + (string-width title) + (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_)))) + "\n\n" + (let ((text-width (- (plist-get info :ascii-text-width) + global-margin))) + (mapconcat + (lambda (ref) + (let ((id (format "[%s] " (car ref)))) + ;; Distinguish between inline definitions and + ;; full-fledged definitions. + (org-trim + (let ((def (nth 2 ref))) + (if (org-element-map def org-element-all-elements + #'identity info 'first-match) + ;; Full-fledged definition: footnote ID is + ;; inserted inside the first parsed + ;; paragraph (FIRST), if any, to be sure + ;; filling will take it into consideration. + (let ((first (car (org-element-contents def)))) + (if (not (eq (org-element-type first) 'paragraph)) + (concat id "\n" (org-export-data def info)) + (push id (nthcdr 2 first)) + (org-export-data def info))) + ;; Fill paragraph once footnote ID is inserted + ;; in order to have a correct length for first + ;; line. + (org-ascii--fill-string + (concat id (org-export-data def info)) + text-width info)))))) + definitions "\n\n")))))) + global-margin)))) (defun org-ascii-template (contents info) "Return complete document string after ASCII conversion. CONTENTS is the transcoded contents string. INFO is a plist holding export options." - (concat - ;; 1. Build title block. - (org-ascii--indent-string - (concat (org-ascii-template--document-title info) - ;; 2. Table of contents. - (let ((depth (plist-get info :with-toc))) - (when depth - (concat - (org-ascii--build-toc info (and (wholenump depth) depth)) - "\n\n\n")))) - org-ascii-global-margin) - ;; 3. Document's body. - contents - ;; 4. Creator. Ignore `comment' value as there are no comments in - ;; ASCII. Justify it to the bottom right. - (org-ascii--indent-string - (let ((creator-info (plist-get info :with-creator)) - (text-width (- org-ascii-text-width org-ascii-global-margin))) - (unless (or (not creator-info) (eq creator-info 'comment)) - (concat - "\n\n\n" - (org-ascii--fill-string - (plist-get info :creator) text-width info 'right)))) - org-ascii-global-margin))) + (let ((global-margin (plist-get info :ascii-global-margin))) + (concat + ;; Build title block. + (org-ascii--indent-string + (concat (org-ascii-template--document-title info) + ;; 2. Table of contents. + (let ((depth (plist-get info :with-toc))) + (when depth + (concat + (org-ascii--build-toc info (and (wholenump depth) depth)) + "\n\n\n")))) + global-margin) + ;; Document's body. + contents + ;; Creator. Justify it to the bottom right. + (and (plist-get info :with-creator) + (org-ascii--indent-string + (let ((text-width + (- (plist-get info :ascii-text-width) global-margin))) + (concat + "\n\n\n" + (org-ascii--fill-string + (plist-get info :creator) text-width info 'right))) + global-margin))))) (defun org-ascii--translate (s info) "Translate string S according to specified language and charset. @@ -1007,7 +1168,7 @@ INFO is a plist used as a communication channel." ;;;; Bold -(defun org-ascii-bold (bold contents info) +(defun org-ascii-bold (_bold contents _info) "Transcode BOLD from Org to ASCII. CONTENTS is the text with bold markup. INFO is a plist holding contextual information." @@ -1016,39 +1177,41 @@ contextual information." ;;;; Center Block -(defun org-ascii-center-block (center-block contents info) +(defun org-ascii-center-block (_center-block contents _info) "Transcode a CENTER-BLOCK element from Org to ASCII. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." - (org-ascii--justify-string - contents (org-ascii--current-text-width center-block info) 'center)) + ;; Center has already been taken care of at a lower level, so + ;; there's nothing left to do. + contents) ;;;; Clock -(defun org-ascii-clock (clock contents info) +(defun org-ascii-clock (clock _contents info) "Transcode a CLOCK object from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." - (concat org-clock-string " " - (org-translate-time - (org-element-property :raw-value - (org-element-property :value clock))) - (let ((time (org-element-property :duration clock))) - (and time - (concat " => " - (apply 'format - "%2s:%02s" - (org-split-string time ":"))))))) + (org-ascii--justify-element + (concat org-clock-string " " + (org-timestamp-translate (org-element-property :value clock)) + (let ((time (org-element-property :duration clock))) + (and time + (concat " => " + (apply 'format + "%2s:%02s" + (org-split-string time ":")))))) + clock info)) ;;;; Code -(defun org-ascii-code (code contents info) +(defun org-ascii-code (code _contents info) "Return a CODE object from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." - (format org-ascii-verbatim-format (org-element-property :value code))) + (format (plist-get info :ascii-verbatim-format) + (org-element-property :value code))) ;;;; Drawer @@ -1059,12 +1222,13 @@ CONTENTS holds the contents of the block. INFO is a plist holding contextual information." (let ((name (org-element-property :drawer-name drawer)) (width (org-ascii--current-text-width drawer info))) - (funcall org-ascii-format-drawer-function name contents width))) + (funcall (plist-get info :ascii-format-drawer-function) + name contents width))) ;;;; Dynamic Block -(defun org-ascii-dynamic-block (dynamic-block contents info) +(defun org-ascii-dynamic-block (_dynamic-block contents _info) "Transcode a DYNAMIC-BLOCK element from Org to ASCII. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." @@ -1073,7 +1237,7 @@ holding contextual information." ;;;; Entity -(defun org-ascii-entity (entity contents info) +(defun org-ascii-entity (entity _contents info) "Transcode an ENTITY object from Org to ASCII. CONTENTS are the definition itself. INFO is a plist holding contextual information." @@ -1084,16 +1248,18 @@ contextual information." ;;;; Example Block -(defun org-ascii-example-block (example-block contents info) +(defun org-ascii-example-block (example-block _contents info) "Transcode a EXAMPLE-BLOCK element from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." - (org-ascii--box-string - (org-export-format-code-default example-block info) info)) + (org-ascii--justify-element + (org-ascii--box-string + (org-export-format-code-default example-block info) info) + example-block info)) ;;;; Export Snippet -(defun org-ascii-export-snippet (export-snippet contents info) +(defun org-ascii-export-snippet (export-snippet _contents _info) "Transcode a EXPORT-SNIPPET object from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." (when (eq (org-export-snippet-backend export-snippet) 'ascii) @@ -1102,21 +1268,24 @@ CONTENTS is nil. INFO is a plist holding contextual information." ;;;; Export Block -(defun org-ascii-export-block (export-block contents info) +(defun org-ascii-export-block (export-block _contents info) "Transcode a EXPORT-BLOCK element from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." (when (string= (org-element-property :type export-block) "ASCII") - (org-remove-indentation (org-element-property :value export-block)))) + (org-ascii--justify-element + (org-element-property :value export-block) export-block info))) ;;;; Fixed Width -(defun org-ascii-fixed-width (fixed-width contents info) +(defun org-ascii-fixed-width (fixed-width _contents info) "Transcode a FIXED-WIDTH element from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." - (org-ascii--box-string - (org-remove-indentation - (org-element-property :value fixed-width)) info)) + (org-ascii--justify-element + (org-ascii--box-string + (org-remove-indentation + (org-element-property :value fixed-width)) info) + fixed-width info)) ;;;; Footnote Definition @@ -1127,7 +1296,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." ;;;; Footnote Reference -(defun org-ascii-footnote-reference (footnote-reference contents info) +(defun org-ascii-footnote-reference (footnote-reference _contents info) "Transcode a FOOTNOTE-REFERENCE element from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." (format "[%s]" (org-export-get-footnote-number footnote-reference info))) @@ -1142,57 +1311,62 @@ holding contextual information." ;; Don't export footnote section, which will be handled at the end ;; of the template. (unless (org-element-property :footnote-section-p headline) - (let* ((low-level-rank (org-export-low-level-p headline info)) + (let* ((low-level (org-export-low-level-p headline info)) (width (org-ascii--current-text-width headline info)) + ;; Export title early so that any link in it can be + ;; exported and seen in `org-ascii--unique-links'. + (title (org-ascii--build-title headline info width (not low-level))) ;; Blank lines between headline and its contents. ;; `org-ascii-headline-spacing', when set, overwrites ;; original buffer's spacing. (pre-blanks - (make-string - (if org-ascii-headline-spacing (car org-ascii-headline-spacing) - (org-element-property :pre-blank headline)) ?\n)) - ;; Even if HEADLINE has no section, there might be some - ;; links in its title that we shouldn't forget to describe. - (links - (unless (or (eq (caar (org-element-contents headline)) 'section)) - (let ((title (org-element-property :title headline))) - (when (consp title) - (org-ascii--describe-links - (org-ascii--unique-links title info) width info)))))) + (make-string (or (car (plist-get info :ascii-headline-spacing)) + (org-element-property :pre-blank headline) + 0) + ?\n)) + (links (and (plist-get info :ascii-links-to-notes) + (org-ascii--describe-links + (org-ascii--unique-links headline info) width info))) + ;; Re-build contents, inserting section links at the right + ;; place. The cost is low since build results are cached. + (body + (if (not (org-string-nw-p links)) contents + (let* ((contents (org-element-contents headline)) + (section (let ((first (car contents))) + (and (eq (org-element-type first) 'section) + first)))) + (concat (and section + (concat (org-element-normalize-string + (org-export-data section info)) + "\n\n")) + links + (mapconcat (lambda (e) (org-export-data e info)) + (if section (cdr contents) contents) + "")))))) ;; Deep subtree: export it as a list item. - (if low-level-rank - (concat - ;; Bullet. - (let ((bullets (cdr (assq (plist-get info :ascii-charset) - org-ascii-bullets)))) - (char-to-string - (nth (mod (1- low-level-rank) (length bullets)) bullets))) - " " - ;; Title. - (org-ascii--build-title headline info width) "\n" - ;; Contents, indented by length of bullet. - pre-blanks - (org-ascii--indent-string - (concat contents - (when (org-string-nw-p links) (concat "\n\n" links))) - 2)) + (if low-level + (let* ((bullets (cdr (assq (plist-get info :ascii-charset) + (plist-get info :ascii-bullets)))) + (bullet + (format "%c " + (nth (mod (1- low-level) (length bullets)) bullets)))) + (concat bullet title "\n" pre-blanks + ;; Contents, indented by length of bullet. + (org-ascii--indent-string body (length bullet)))) ;; Else: Standard headline. - (concat - (org-ascii--build-title headline info width 'underline) - "\n" pre-blanks - (concat (when (org-string-nw-p links) links) contents)))))) + (concat title "\n" pre-blanks body))))) ;;;; Horizontal Rule -(defun org-ascii-horizontal-rule (horizontal-rule contents info) +(defun org-ascii-horizontal-rule (horizontal-rule _contents info) "Transcode an HORIZONTAL-RULE object from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." (let ((text-width (org-ascii--current-text-width horizontal-rule info)) (spec-width (org-export-read-attribute :attr_ascii horizontal-rule :width))) - (org-ascii--justify-string + (org-ascii--justify-lines (make-string (if (and spec-width (string-match "^[0-9]+$" spec-width)) (string-to-number spec-width) text-width) @@ -1202,23 +1376,23 @@ information." ;;;; Inline Src Block -(defun org-ascii-inline-src-block (inline-src-block contents info) +(defun org-ascii-inline-src-block (inline-src-block _contents info) "Transcode an INLINE-SRC-BLOCK element from Org to ASCII. CONTENTS holds the contents of the item. INFO is a plist holding contextual information." - (format org-ascii-verbatim-format + (format (plist-get info :ascii-verbatim-format) (org-element-property :value inline-src-block))) ;;;; Inlinetask (defun org-ascii-format-inlinetask-default - (todo type priority name tags contents width inlinetask info) + (_todo _type _priority _name _tags contents width inlinetask info) "Format an inline task element for ASCII export. See `org-ascii-format-inlinetask-function' for a description of the parameters." (let* ((utf8p (eq (plist-get info :ascii-charset) 'utf-8)) - (width (or width org-ascii-inlinetask-width))) + (width (or width (plist-get info :ascii-inlinetask-width)))) (org-ascii--indent-string (concat ;; Top line, with an additional blank line if not in UTF-8. @@ -1236,9 +1410,9 @@ of the parameters." ;; Bottom line. (make-string width (if utf8p ?━ ?_))) ;; Flush the inlinetask to the right. - (- org-ascii-text-width org-ascii-global-margin + (- (plist-get info :ascii-text-width) (plist-get info :ascii-global-margin) (if (not (org-export-get-parent-headline inlinetask)) 0 - org-ascii-inner-margin) + (plist-get info :ascii-inner-margin)) (org-ascii--current-text-width inlinetask info))))) (defun org-ascii-inlinetask (inlinetask contents info) @@ -1246,7 +1420,7 @@ of the parameters." CONTENTS holds the contents of the block. INFO is a plist holding contextual information." (let ((width (org-ascii--current-text-width inlinetask info))) - (funcall org-ascii-format-inlinetask-function + (funcall (plist-get info :ascii-format-inlinetask-function) ;; todo. (and (plist-get info :with-todo-keywords) (let ((todo (org-element-property @@ -1268,7 +1442,7 @@ holding contextual information." ;;;; Italic -(defun org-ascii-italic (italic contents info) +(defun org-ascii-italic (_italic contents _info) "Transcode italic from Org to ASCII. CONTENTS is the text with italic markup. INFO is a plist holding contextual information." @@ -1288,12 +1462,12 @@ contextual information." ;; First parent of ITEM is always the plain-list. Get ;; `:type' property from it. (org-list-bullet-string - (case list-type - (descriptive + (pcase list-type + (`descriptive (concat checkbox (org-export-data (org-element-property :tag item) info) ": ")) - (ordered + (`ordered ;; Return correct number for ITEM, paying attention to ;; counters. (let* ((struct (org-element-property :structure item)) @@ -1305,7 +1479,7 @@ contextual information." (org-list-prevs-alist struct) (org-list-parents-alist struct))))))) (replace-regexp-in-string "[0-9]+" num bul))) - (t (let ((bul (org-element-property :bullet item))) + (_ (let ((bul (org-element-property :bullet item))) ;; Change bullets into more visible form if UTF-8 is active. (if (not utf8p) bul (replace-regexp-in-string @@ -1327,42 +1501,45 @@ contextual information." ;;;; Keyword -(defun org-ascii-keyword (keyword contents info) +(defun org-ascii-keyword (keyword _contents info) "Transcode a KEYWORD element from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." (let ((key (org-element-property :key keyword)) (value (org-element-property :value keyword))) (cond - ((string= key "ASCII") value) + ((string= key "ASCII") (org-ascii--justify-element value keyword info)) ((string= key "TOC") - (let ((value (downcase value))) - (cond - ((string-match "\\" value) - (let ((depth (or (and (string-match "[0-9]+" value) - (string-to-number (match-string 0 value))) - (plist-get info :with-toc)))) - (org-ascii--build-toc - info (and (wholenump depth) depth) keyword))) - ((string= "tables" value) - (org-ascii--list-tables keyword info)) - ((string= "listings" value) - (org-ascii--list-listings keyword info)))))))) + (org-ascii--justify-element + (let ((case-fold-search t)) + (cond + ((string-match-p "\\" value) + (let ((depth (and (string-match "\\<[0-9]+\\>" value) + (string-to-number (match-string 0 value)))) + (localp (string-match-p "\\" value))) + (org-ascii--build-toc info depth keyword localp))) + ((string-match-p "\\" value) + (org-ascii--list-tables keyword info)) + ((string-match-p "\\" value) + (org-ascii--list-listings keyword info)))) + keyword info))))) ;;;; Latex Environment -(defun org-ascii-latex-environment (latex-environment contents info) +(defun org-ascii-latex-environment (latex-environment _contents info) "Transcode a LATEX-ENVIRONMENT element from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." (when (plist-get info :with-latex) - (org-remove-indentation (org-element-property :value latex-environment)))) + (org-ascii--justify-element + (org-remove-indentation (org-element-property :value latex-environment)) + latex-environment info))) ;;;; Latex Fragment -(defun org-ascii-latex-fragment (latex-fragment contents info) +(defun org-ascii-latex-fragment (latex-fragment _contents info) "Transcode a LATEX-FRAGMENT object from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." @@ -1372,7 +1549,7 @@ information." ;;;; Line Break -(defun org-ascii-line-break (line-break contents info) +(defun org-ascii-line-break (_line-break _contents _info) "Transcode a LINE-BREAK object from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." hard-newline) @@ -1385,9 +1562,9 @@ CONTENTS is nil. INFO is a plist holding contextual DESC is the description part of the link, or the empty string. INFO is a plist holding contextual information." - (let ((raw-link (org-element-property :raw-link link)) - (type (org-element-property :type link))) + (let ((type (org-element-property :type link))) (cond + ((org-export-custom-protocol-maybe link desc 'ascii)) ((string= type "coderef") (let ((ref (org-element-property :path link))) (format (org-export-get-coderef-format ref desc) @@ -1395,23 +1572,51 @@ INFO is a plist holding contextual information." ;; Do not apply a special syntax on radio links. Though, use ;; transcoded target's contents as output. ((string= type "radio") desc) - ;; Do not apply a special syntax on fuzzy links pointing to - ;; targets. - ((string= type "fuzzy") - (let ((destination (org-export-resolve-fuzzy-link link info))) - (if (org-string-nw-p desc) desc - (when destination - (let ((number - (org-export-get-ordinal - destination info nil 'org-ascii--has-caption-p))) - (when number - (if (atom number) (number-to-string number) - (mapconcat 'number-to-string number ".")))))))) + ((member type '("custom-id" "fuzzy" "id")) + (let ((destination (if (string= type "fuzzy") + (org-export-resolve-fuzzy-link link info) + (org-export-resolve-id-link link info)))) + (pcase (org-element-type destination) + ((guard desc) + (if (plist-get info :ascii-links-to-notes) + (format "[%s]" desc) + (concat desc + (format " (%s)" + (org-ascii--describe-datum destination info))))) + ;; External file. + (`plain-text destination) + (`headline + (if (org-export-numbered-headline-p destination info) + (mapconcat #'number-to-string + (org-export-get-headline-number destination info) + ".") + (org-export-data (org-element-property :title destination) info))) + ;; Handle enumerable elements and targets within them. + ((and (let number (org-export-get-ordinal + destination info nil #'org-ascii--has-caption-p)) + (guard number)) + (if (atom number) (number-to-string number) + (mapconcat #'number-to-string number "."))) + ;; Don't know what to do. Signal it. + (_ "???")))) (t - (if (not (org-string-nw-p desc)) (format "[%s]" raw-link) - (concat - (format "[%s]" desc) - (unless org-ascii-links-to-notes (format " (%s)" raw-link)))))))) + (let ((raw-link (org-element-property :raw-link link))) + (if (not (org-string-nw-p desc)) (format "[%s]" raw-link) + (concat (format "[%s]" desc) + (and (not (plist-get info :ascii-links-to-notes)) + (format " (%s)" raw-link))))))))) + + +;;;; Node Properties + +(defun org-ascii-node-property (node-property _contents _info) + "Transcode a NODE-PROPERTY element from Org to ASCII. +CONTENTS is nil. INFO is a plist holding contextual +information." + (format "%s:%s" + (org-element-property :key node-property) + (let ((value (org-element-property :value node-property))) + (if value (concat " " value) "")))) ;;;; Paragraph @@ -1420,16 +1625,17 @@ INFO is a plist holding contextual information." "Transcode a PARAGRAPH element from Org to ASCII. CONTENTS is the contents of the paragraph, as a string. INFO is the plist used as a communication channel." - (org-ascii--fill-string - (if (not (wholenump org-ascii-indented-line-width)) contents - (concat - ;; Do not indent first paragraph in a section. - (unless (and (not (org-export-get-previous-element paragraph info)) - (eq (org-element-type (org-export-get-parent paragraph)) - 'section)) - (make-string org-ascii-indented-line-width ?\s)) - (replace-regexp-in-string "\\`[ \t]+" "" contents))) - (org-ascii--current-text-width paragraph info) info)) + (org-ascii--justify-element + (let ((indented-line-width (plist-get info :ascii-indented-line-width))) + (if (not (wholenump indented-line-width)) contents + (concat + ;; Do not indent first paragraph in a section. + (unless (and (not (org-export-get-previous-element paragraph info)) + (eq (org-element-type (org-export-get-parent paragraph)) + 'section)) + (make-string indented-line-width ?\s)) + (replace-regexp-in-string "\\`[ \t]+" "" contents)))) + paragraph info)) ;;;; Plain List @@ -1438,7 +1644,11 @@ the plist used as a communication channel." "Transcode a PLAIN-LIST element from Org to ASCII. CONTENTS is the contents of the list. INFO is a plist holding contextual information." - contents) + (let ((margin (plist-get info :ascii-list-margin))) + (if (or (< margin 1) + (eq (org-element-type (org-export-get-parent plain-list)) 'item)) + contents + (org-ascii--indent-string contents margin)))) ;;;; Plain Text @@ -1462,62 +1672,52 @@ INFO is a plist used as a communication channel." ;;;; Planning -(defun org-ascii-planning (planning contents info) +(defun org-ascii-planning (planning _contents info) "Transcode a PLANNING element from Org to ASCII. CONTENTS is nil. INFO is a plist used as a communication channel." - (mapconcat - 'identity - (delq nil - (list (let ((closed (org-element-property :closed planning))) - (when closed - (concat org-closed-string " " - (org-translate-time - (org-element-property :raw-value closed))))) - (let ((deadline (org-element-property :deadline planning))) - (when deadline - (concat org-deadline-string " " - (org-translate-time - (org-element-property :raw-value deadline))))) - (let ((scheduled (org-element-property :scheduled planning))) - (when scheduled - (concat org-scheduled-string " " - (org-translate-time - (org-element-property :raw-value scheduled))))))) - " ")) + (org-ascii--justify-element + (mapconcat + #'identity + (delq nil + (list (let ((closed (org-element-property :closed planning))) + (when closed + (concat org-closed-string " " + (org-timestamp-translate closed)))) + (let ((deadline (org-element-property :deadline planning))) + (when deadline + (concat org-deadline-string " " + (org-timestamp-translate deadline)))) + (let ((scheduled (org-element-property :scheduled planning))) + (when scheduled + (concat org-scheduled-string " " + (org-timestamp-translate scheduled)))))) + " ") + planning info)) + + +;;;; Property Drawer + +(defun org-ascii-property-drawer (property-drawer contents info) + "Transcode a PROPERTY-DRAWER element from Org to ASCII. +CONTENTS holds the contents of the drawer. INFO is a plist +holding contextual information." + (and (org-string-nw-p contents) + (org-ascii--justify-element contents property-drawer info))) ;;;; Quote Block -(defun org-ascii-quote-block (quote-block contents info) +(defun org-ascii-quote-block (_quote-block contents info) "Transcode a QUOTE-BLOCK element from Org to ASCII. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." - (org-ascii--indent-string contents org-ascii-quote-margin)) - - -;;;; Quote Section - -(defun org-ascii-quote-section (quote-section contents info) - "Transcode a QUOTE-SECTION element from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual information." - (let ((width (org-ascii--current-text-width quote-section info)) - (value - (org-export-data - (org-remove-indentation (org-element-property :value quote-section)) - info))) - (org-ascii--indent-string - value - (+ org-ascii-quote-margin - ;; Don't apply inner margin if parent headline is low level. - (let ((headline (org-export-get-parent-headline quote-section))) - (if (org-export-low-level-p headline info) 0 - org-ascii-inner-margin)))))) + (org-ascii--indent-string contents (plist-get info :ascii-quote-margin))) ;;;; Radio Target -(defun org-ascii-radio-target (radio-target contents info) +(defun org-ascii-radio-target (_radio-target contents _info) "Transcode a RADIO-TARGET object from Org to ASCII. CONTENTS is the contents of the target. INFO is a plist holding contextual information." @@ -1530,50 +1730,56 @@ contextual information." "Transcode a SECTION element from Org to ASCII. CONTENTS is the contents of the section. INFO is a plist holding contextual information." - (org-ascii--indent-string - (concat - contents - (when org-ascii-links-to-notes - ;; Add list of links at the end of SECTION. - (let ((links (org-ascii--describe-links - (org-ascii--unique-links section info) - (org-ascii--current-text-width section info) info))) - ;; Separate list of links and section contents. - (when (org-string-nw-p links) (concat "\n\n" links))))) - ;; Do not apply inner margin if parent headline is low level. - (let ((headline (org-export-get-parent-headline section))) - (if (or (not headline) (org-export-low-level-p headline info)) 0 - org-ascii-inner-margin)))) + (let ((links + (and (plist-get info :ascii-links-to-notes) + ;; Take care of links in first section of the document. + (not (org-element-lineage section '(headline))) + (org-ascii--describe-links + (org-ascii--unique-links section info) + (org-ascii--current-text-width section info) + info)))) + (org-ascii--indent-string + (if (not (org-string-nw-p links)) contents + (concat (org-element-normalize-string contents) "\n\n" links)) + ;; Do not apply inner margin if parent headline is low level. + (let ((headline (org-export-get-parent-headline section))) + (if (or (not headline) (org-export-low-level-p headline info)) 0 + (plist-get info :ascii-inner-margin)))))) ;;;; Special Block -(defun org-ascii-special-block (special-block contents info) +(defun org-ascii-special-block (_special-block contents _info) "Transcode a SPECIAL-BLOCK element from Org to ASCII. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." + ;; "JUSTIFYLEFT" and "JUSTIFYRIGHT" have already been taken care of + ;; at a lower level. There is no other special block type to + ;; handle. contents) ;;;; Src Block -(defun org-ascii-src-block (src-block contents info) +(defun org-ascii-src-block (src-block _contents info) "Transcode a SRC-BLOCK element from Org to ASCII. CONTENTS holds the contents of the item. INFO is a plist holding contextual information." (let ((caption (org-ascii--build-caption src-block info)) + (caption-above-p (plist-get info :ascii-caption-above)) (code (org-export-format-code-default src-block info))) (if (equal code "") "" - (concat - (when (and caption org-ascii-caption-above) (concat caption "\n")) - (org-ascii--box-string code info) - (when (and caption (not org-ascii-caption-above)) - (concat "\n" caption)))))) + (org-ascii--justify-element + (concat + (and caption caption-above-p (concat caption "\n")) + (org-ascii--box-string code info) + (and caption (not caption-above-p) (concat "\n" caption))) + src-block info)))) ;;;; Statistics Cookie -(defun org-ascii-statistics-cookie (statistics-cookie contents info) +(defun org-ascii-statistics-cookie (statistics-cookie _contents _info) "Transcode a STATISTICS-COOKIE object from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." (org-element-property :value statistics-cookie)) @@ -1581,7 +1787,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." ;;;; Subscript -(defun org-ascii-subscript (subscript contents info) +(defun org-ascii-subscript (subscript contents _info) "Transcode a SUBSCRIPT object from Org to ASCII. CONTENTS is the contents of the object. INFO is a plist holding contextual information." @@ -1592,7 +1798,7 @@ contextual information." ;;;; Superscript -(defun org-ascii-superscript (superscript contents info) +(defun org-ascii-superscript (superscript contents _info) "Transcode a SUPERSCRIPT object from Org to ASCII. CONTENTS is the contents of the object. INFO is a plist holding contextual information." @@ -1603,7 +1809,7 @@ contextual information." ;;;; Strike-through -(defun org-ascii-strike-through (strike-through contents info) +(defun org-ascii-strike-through (_strike-through contents _info) "Transcode STRIKE-THROUGH from Org to ASCII. CONTENTS is text with strike-through markup. INFO is a plist holding contextual information." @@ -1616,26 +1822,29 @@ holding contextual information." "Transcode a TABLE element from Org to ASCII. CONTENTS is the contents of the table. INFO is a plist holding contextual information." - (let ((caption (org-ascii--build-caption table info))) - (concat - ;; Possibly add a caption string above. - (when (and caption org-ascii-caption-above) (concat caption "\n")) - ;; Insert table. Note: "table.el" tables are left unmodified. - (cond ((eq (org-element-property :type table) 'org) contents) - ((and org-ascii-table-use-ascii-art - (eq (plist-get info :ascii-charset) 'utf-8) - (require 'ascii-art-to-unicode nil t)) - (with-temp-buffer - (insert (org-remove-indentation - (org-element-property :value table))) - (goto-char (point-min)) - (aa2u) - (goto-char (point-max)) - (skip-chars-backward " \r\t\n") - (buffer-substring (point-min) (point)))) - (t (org-remove-indentation (org-element-property :value table)))) - ;; Possible add a caption string below. - (and (not org-ascii-caption-above) caption)))) + (let ((caption (org-ascii--build-caption table info)) + (caption-above-p (plist-get info :ascii-caption-above))) + (org-ascii--justify-element + (concat + ;; Possibly add a caption string above. + (and caption caption-above-p (concat caption "\n")) + ;; Insert table. Note: "table.el" tables are left unmodified. + (cond ((eq (org-element-property :type table) 'org) contents) + ((and (plist-get info :ascii-table-use-ascii-art) + (eq (plist-get info :ascii-charset) 'utf-8) + (require 'ascii-art-to-unicode nil t)) + (with-temp-buffer + (insert (org-remove-indentation + (org-element-property :value table))) + (goto-char (point-min)) + (aa2u) + (goto-char (point-max)) + (skip-chars-backward " \r\t\n") + (buffer-substring (point-min) (point)))) + (t (org-remove-indentation (org-element-property :value table)))) + ;; Possible add a caption string below. + (and (not caption-above-p) caption)) + table info))) ;;;; Table Cell @@ -1661,12 +1870,13 @@ are ignored." (plist-put info :ascii-table-cell-width-cache (make-hash-table :test 'equal))) :ascii-table-cell-width-cache))) - (key (cons table col))) + (key (cons table col)) + (widenp (plist-get info :ascii-table-widen-columns))) (or (gethash key cache) (puthash key (let ((cookie-width (org-export-table-cell-width table-cell info))) - (or (and (not org-ascii-table-widen-columns) cookie-width) + (or (and (not widenp) cookie-width) (let ((contents-width (let ((max-width 0)) (org-element-map table 'table-row @@ -1681,8 +1891,7 @@ are ignored." info) max-width))) (cond ((not cookie-width) contents-width) - (org-ascii-table-widen-columns - (max cookie-width contents-width)) + (widenp (max cookie-width contents-width)) (t cookie-width))))) cache)))) @@ -1696,14 +1905,14 @@ a communication channel." ;; each cell in the column. (let ((width (org-ascii--table-cell-width table-cell info))) ;; When contents are too large, truncate them. - (unless (or org-ascii-table-widen-columns + (unless (or (plist-get info :ascii-table-widen-columns) (<= (string-width (or contents "")) width)) (setq contents (concat (substring contents 0 (- width 2)) "=>"))) ;; Align contents correctly within the cell. (let* ((indent-tabs-mode nil) (data (when contents - (org-ascii--justify-string + (org-ascii--justify-lines contents width (org-export-table-cell-alignment table-cell info))))) (setq contents @@ -1770,7 +1979,7 @@ a communication channel." ;;;; Timestamp -(defun org-ascii-timestamp (timestamp contents info) +(defun org-ascii-timestamp (timestamp _contents info) "Transcode a TIMESTAMP object from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." (org-ascii-plain-text (org-timestamp-translate timestamp) info)) @@ -1778,7 +1987,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." ;;;; Underline -(defun org-ascii-underline (underline contents info) +(defun org-ascii-underline (_underline contents _info) "Transcode UNDERLINE from Org to ASCII. CONTENTS is the text with underline markup. INFO is a plist holding contextual information." @@ -1787,10 +1996,10 @@ holding contextual information." ;;;; Verbatim -(defun org-ascii-verbatim (verbatim contents info) +(defun org-ascii-verbatim (verbatim _contents info) "Return a VERBATIM object from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." - (format org-ascii-verbatim-format + (format (plist-get info :ascii-verbatim-format) (org-element-property :value verbatim))) @@ -1800,48 +2009,48 @@ CONTENTS is nil. INFO is a plist holding contextual information." "Transcode a VERSE-BLOCK element from Org to ASCII. CONTENTS is verse block contents. INFO is a plist holding contextual information." - (let ((verse-width (org-ascii--current-text-width verse-block info))) - (org-ascii--indent-string - (org-ascii--justify-string contents verse-width 'left) - org-ascii-quote-margin))) + (org-ascii--indent-string + (org-ascii--justify-element contents verse-block info) + (plist-get info :ascii-quote-margin))) ;;; Filters -(defun org-ascii-filter-headline-blank-lines (headline back-end info) +(defun org-ascii-filter-headline-blank-lines (headline _backend info) "Filter controlling number of blank lines after a headline. -HEADLINE is a string representing a transcoded headline. -BACK-END is symbol specifying back-end used for export. INFO is -plist containing the communication channel. +HEADLINE is a string representing a transcoded headline. BACKEND +is symbol specifying back-end used for export. INFO is plist +containing the communication channel. This function only applies to `ascii' back-end. See `org-ascii-headline-spacing' for information." - (if (not org-ascii-headline-spacing) headline - (let ((blanks (make-string (1+ (cdr org-ascii-headline-spacing)) ?\n))) - (replace-regexp-in-string "\n\\(?:\n[ \t]*\\)*\\'" blanks headline)))) + (let ((headline-spacing (plist-get info :ascii-headline-spacing))) + (if (not headline-spacing) headline + (let ((blanks (make-string (1+ (cdr headline-spacing)) ?\n))) + (replace-regexp-in-string "\n\\(?:\n[ \t]*\\)*\\'" blanks headline))))) -(defun org-ascii-filter-paragraph-spacing (tree back-end info) +(defun org-ascii-filter-paragraph-spacing (tree _backend info) "Filter controlling number of blank lines between paragraphs. -TREE is the parse tree. BACK-END is the symbol specifying +TREE is the parse tree. BACKEND is the symbol specifying back-end used for export. INFO is a plist used as a communication channel. See `org-ascii-paragraph-spacing' for information." - (when (wholenump org-ascii-paragraph-spacing) - (org-element-map tree 'paragraph - (lambda (p) - (when (eq (org-element-type (org-export-get-next-element p info)) - 'paragraph) - (org-element-put-property - p :post-blank org-ascii-paragraph-spacing))))) + (let ((paragraph-spacing (plist-get info :ascii-paragraph-spacing))) + (when (wholenump paragraph-spacing) + (org-element-map tree 'paragraph + (lambda (p) + (when (eq (org-element-type (org-export-get-next-element p info)) + 'paragraph) + (org-element-put-property p :post-blank paragraph-spacing)))))) tree) -(defun org-ascii-filter-comment-spacing (tree backend info) +(defun org-ascii-filter-comment-spacing (tree _backend info) "Filter removing blank lines between comments. -TREE is the parse tree. BACK-END is the symbol specifying +TREE is the parse tree. BACKEND is the symbol specifying back-end used for export. INFO is a plist used as a communication channel." (org-element-map tree '(comment comment-block) diff --git a/lisp/org/ox-beamer.el b/lisp/org/ox-beamer.el index a8d48b67189..82651d3848e 100644 --- a/lisp/org/ox-beamer.el +++ b/lisp/org/ox-beamer.el @@ -1,4 +1,4 @@ -;;; ox-beamer.el --- Beamer Back-End for Org Export Engine +;;; ox-beamer.el --- Beamer Back-End for Org Export Engine -*- lexical-binding: t; -*- ;; Copyright (C) 2007-2017 Free Software Foundation, Inc. @@ -29,7 +29,7 @@ ;;; Code: -(eval-when-compile (require 'cl)) +(require 'cl-lib) (require 'ox-latex) ;; Install a default set-up for Beamer export. @@ -105,7 +105,9 @@ key Selection key for `org-beamer-select-environment' open The opening template for the environment, with the following escapes %a the action/overlay specification %A the default action/overlay specification - %o the options argument of the template + %R the raw BEAMER_act value + %o the options argument, with square brackets + %O the raw BEAMER_opt value %h the headline text %r the raw headline text (i.e. without any processing) %H if there is headline text, that raw text in {} braces @@ -133,6 +135,15 @@ You might want to put e.g. \"allowframebreaks=0.9\" here." :type '(string :tag "Outline frame options")) +(defcustom org-beamer-subtitle-format "\\subtitle{%s}" + "Format string used for transcoded subtitle. +The format string should have at most one \"%s\"-expression, +which is replaced with the subtitle." + :group 'org-export-beamer + :version "26.1" + :package-version '(Org . "8.3") + :type '(string :tag "Format string")) + ;;; Internal Variables @@ -191,19 +202,14 @@ TYPE is a symbol among the following: `defaction' Return ARGUMENT within both square and angular brackets. `option' Return ARGUMENT within square brackets." (if (not (string-match "\\S-" argument)) "" - (case type - (action (if (string-match "\\`<.*>\\'" argument) argument - (format "<%s>" argument))) - (defaction (cond - ((string-match "\\`\\[<.*>\\]\\'" argument) argument) - ((string-match "\\`<.*>\\'" argument) - (format "[%s]" argument)) - ((string-match "\\`\\[\\(.*\\)\\]\\'" argument) - (format "[<%s>]" (match-string 1 argument))) - (t (format "[<%s>]" argument)))) - (option (if (string-match "\\`\\[.*\\]\\'" argument) argument - (format "[%s]" argument))) - (otherwise argument)))) + (cl-case type + (action (format "<%s>" (org-unbracket-string "<" ">" argument))) + (defaction + (format "[<%s>]" + (org-unbracket-string "<" ">" (org-unbracket-string "[" "]" argument)))) + (option (format "[%s]" (org-unbracket-string "[" "]" argument))) + (otherwise (error "Invalid `type' argument to `org-beamer--normalize-argument': %s" + type))))) (defun org-beamer--element-has-overlay-p (element) "Non-nil when ELEMENT has an overlay specified. @@ -213,14 +219,14 @@ Return overlay specification, as a string, or nil." (let ((first-object (car (org-element-contents element)))) (when (eq (org-element-type first-object) 'export-snippet) (let ((value (org-element-property :value first-object))) - (and (string-match "\\`<.*>\\'" value) value))))) + (and (string-prefix-p "<" value) (string-suffix-p ">" value) + value))))) ;;; Define Back-End (org-export-define-derived-backend 'beamer 'latex - :export-block "BEAMER" :menu-entry '(?l 1 ((?B "As LaTeX buffer (Beamer)" org-beamer-export-as-latex) @@ -231,15 +237,20 @@ Return overlay specification, as a string, or nil." (if a (org-beamer-export-to-pdf t s v b) (org-open-file (org-beamer-export-to-pdf nil s v b))))))) :options-alist - '((:beamer-theme "BEAMER_THEME" nil org-beamer-theme) + '((:headline-levels nil "H" org-beamer-frame-level) + (:latex-class "LATEX_CLASS" nil "beamer" t) + (:beamer-subtitle-format nil nil org-beamer-subtitle-format) + (:beamer-column-view-format "COLUMNS" nil org-beamer-column-view-format) + (:beamer-theme "BEAMER_THEME" nil org-beamer-theme) (:beamer-color-theme "BEAMER_COLOR_THEME" nil nil t) (:beamer-font-theme "BEAMER_FONT_THEME" nil nil t) (:beamer-inner-theme "BEAMER_INNER_THEME" nil nil t) (:beamer-outer-theme "BEAMER_OUTER_THEME" nil nil t) - (:beamer-header-extra "BEAMER_HEADER" nil nil newline) - ;; Modify existing properties. - (:headline-levels nil "H" org-beamer-frame-level) - (:latex-class "LATEX_CLASS" nil "beamer" t)) + (:beamer-header "BEAMER_HEADER" nil nil newline) + (:beamer-environments-extra nil nil org-beamer-environments-extra) + (:beamer-frame-default-options nil nil org-beamer-frame-default-options) + (:beamer-outline-frame-options nil nil org-beamer-outline-frame-options) + (:beamer-outline-frame-title nil nil org-beamer-outline-frame-title)) :translate-alist '((bold . org-beamer-bold) (export-block . org-beamer-export-block) (export-snippet . org-beamer-export-snippet) @@ -249,7 +260,6 @@ Return overlay specification, as a string, or nil." (link . org-beamer-link) (plain-list . org-beamer-plain-list) (radio-target . org-beamer-radio-target) - (target . org-beamer-target) (template . org-beamer-template))) @@ -258,7 +268,7 @@ Return overlay specification, as a string, or nil." ;;;; Bold -(defun org-beamer-bold (bold contents info) +(defun org-beamer-bold (bold contents _info) "Transcode BLOCK object into Beamer code. CONTENTS is the text being bold. INFO is a plist used as a communication channel." @@ -269,7 +279,7 @@ a communication channel." ;;;; Export Block -(defun org-beamer-export-block (export-block contents info) +(defun org-beamer-export-block (export-block _contents _info) "Transcode an EXPORT-BLOCK element into Beamer code. CONTENTS is nil. INFO is a plist used as a communication channel." @@ -279,7 +289,7 @@ channel." ;;;; Export Snippet -(defun org-beamer-export-snippet (export-snippet contents info) +(defun org-beamer-export-snippet (export-snippet _contents info) "Transcode an EXPORT-SNIPPET object into Beamer code. CONTENTS is nil. INFO is a plist used as a communication channel." @@ -315,16 +325,21 @@ channel." INFO is a plist used as a communication channel. The value is either the label specified in \"BEAMER_opt\" -property, or a fallback value built from headline's number. This -function assumes HEADLINE will be treated as a frame." - (let ((opt (org-element-property :BEAMER_OPT headline))) - (if (and (org-string-nw-p opt) - (string-match "\\(?:^\\|,\\)label=\\(.*?\\)\\(?:$\\|,\\)" opt)) - (match-string 1 opt) - (format "sec-%s" - (mapconcat 'number-to-string - (org-export-get-headline-number headline info) - "-"))))) +property, the custom ID, if there is one and +`:latex-prefer-user-labels' property has a non nil value, or +a unique internal label. This function assumes HEADLINE will be +treated as a frame." + (cond + ((let ((opt (org-element-property :BEAMER_OPT headline))) + (and (stringp opt) + (string-match "\\(?:^\\|,\\)label=\\(.*?\\)\\(?:$\\|,\\)" opt) + (let ((label (match-string 1 opt))) + (if (string-match-p "\\`{.*}\\'" label) + (substring label 1 -1) + label))))) + ((and (plist-get info :latex-prefer-user-labels) + (org-element-property :CUSTOM_ID headline))) + (t (format "sec:%s" (org-export-get-reference headline info))))) (defun org-beamer--frame-level (headline info) "Return frame level in subtree containing HEADLINE. @@ -333,12 +348,10 @@ INFO is a plist used as a communication channel." ;; 1. Look for "frame" environment in parents, starting from the ;; farthest. (catch 'exit - (mapc (lambda (parent) - (let ((env (org-element-property :BEAMER_ENV parent))) - (when (and env (member-ignore-case env '("frame" "fullframe"))) - (throw 'exit (org-export-get-relative-level parent info))))) - (nreverse (org-export-get-genealogy headline))) - nil) + (dolist (parent (nreverse (org-element-lineage headline))) + (let ((env (org-element-property :BEAMER_ENV parent))) + (when (and env (member-ignore-case env '("frame" "fullframe"))) + (throw 'exit (org-export-get-relative-level parent info)))))) ;; 2. Look for "frame" environment in HEADLINE. (let ((env (org-element-property :BEAMER_ENV headline))) (and env (member-ignore-case env '("frame" "fullframe")) @@ -413,7 +426,8 @@ used as a communication channel." ;; Collect options from default value and headline's ;; properties. Also add a label for links. (append - (org-split-string org-beamer-frame-default-options ",") + (org-split-string + (plist-get info :beamer-frame-default-options) ",") (and beamer-opt (org-split-string ;; Remove square brackets if user provided @@ -422,12 +436,20 @@ used as a communication channel." (match-string 1 beamer-opt)) ",")) ;; Provide an automatic label for the frame - ;; unless the user specified one. + ;; unless the user specified one. Also refrain + ;; from labeling `allowframebreaks' frames; this + ;; is not allowed by beamer. (unless (and beamer-opt - (string-match "\\(^\\|,\\)label=" beamer-opt)) + (or (string-match "\\(^\\|,\\)label=" beamer-opt) + (string-match "allowframebreaks" beamer-opt))) (list - (format "label=%s" - (org-beamer--get-label headline info))))))) + (let ((label (org-beamer--get-label headline info))) + ;; Labels containing colons need to be + ;; wrapped within braces. + (format (if (string-match-p ":" label) + "label={%s}" + "label=%s") + label))))))) ;; Change options list into a string. (org-beamer--normalize-argument (mapconcat @@ -475,14 +497,15 @@ used as a communication channel." (env-format (cond ((member environment '("column" "columns")) nil) ((assoc environment - (append org-beamer-environments-extra + (append (plist-get info :beamer-environments-extra) org-beamer-environments-default))) (t (user-error "Wrong block type at a headline named \"%s\"" raw-title)))) (title (org-export-data (org-element-property :title headline) info)) - (options (let ((options (org-element-property :BEAMER_OPT headline))) - (if (not options) "" - (org-beamer--normalize-argument options 'option)))) + (raw-options (org-element-property :BEAMER_OPT headline)) + (options (if raw-options + (org-beamer--normalize-argument raw-options 'option) + "")) ;; Start a "columns" environment when explicitly requested or ;; when there is no previous headline or the previous ;; headline do not have a BEAMER_column property. @@ -521,7 +544,7 @@ used as a communication channel." ;; One can specify placement for column only when ;; HEADLINE stands for a column on its own. (if (equal environment "column") options "") - (format "%s\\textwidth" column-width))) + (format "%s\\columnwidth" column-width))) ;; Block's opening string. (when (nth 2 env-format) (concat @@ -534,15 +557,19 @@ used as a communication channel." ;; overlay specification and the default one is nil. (let ((action (org-element-property :BEAMER_ACT headline))) (cond - ((not action) (list (cons "a" "") (cons "A" ""))) - ((string-match "\\`\\[.*\\]\\'" action) + ((not action) (list (cons "a" "") (cons "A" "") (cons "R" ""))) + ((and (string-prefix-p "[" action) + (string-suffix-p "]" action)) (list (cons "A" (org-beamer--normalize-argument action 'defaction)) - (cons "a" ""))) + (cons "a" "") + (cons "R" action))) (t (list (cons "a" (org-beamer--normalize-argument action 'action)) - (cons "A" ""))))) + (cons "A" "") + (cons "R" action))))) (list (cons "o" options) + (cons "O" (or raw-options "")) (cons "h" title) (cons "r" raw-title) (cons "H" (if (equal raw-title "") "" @@ -578,28 +605,27 @@ as a communication channel." (when overlay (org-beamer--normalize-argument overlay - (if (string-match "^\\[.*\\]$" overlay) 'defaction + (if (string-match "\\`\\[.*\\]\\'" overlay) 'defaction 'action)))) ;; Options. (let ((options (org-element-property :BEAMER_OPT headline))) (when options (org-beamer--normalize-argument options 'option))) ;; Resolve reference provided by "BEAMER_ref" - ;; property. This is done by building a minimal fake - ;; link and calling the appropriate resolve function, - ;; depending on the reference syntax. - (let* ((type - (progn - (string-match "^\\(id:\\|#\\|\\*\\)?\\(.*\\)" ref) - (cond - ((or (not (match-string 1 ref)) - (equal (match-string 1 ref) "*")) 'fuzzy) - ((equal (match-string 1 ref) "id:") 'id) - (t 'custom-id)))) - (link (list 'link (list :path (match-string 2 ref)))) - (target (if (eq type 'fuzzy) - (org-export-resolve-fuzzy-link link info) - (org-export-resolve-id-link link info)))) + ;; property. This is done by building a minimal + ;; fake link and calling the appropriate resolve + ;; function, depending on the reference syntax. + (let ((target + (if (string-match "\\`\\(id:\\|#\\)" ref) + (org-export-resolve-id-link + `(link (:path ,(substring ref (match-end 0)))) + info) + (org-export-resolve-fuzzy-link + `(link (:path + ;; Look for headlines only. + ,(if (eq (string-to-char ref) ?*) ref + (concat "*" ref)))) + info)))) ;; Now use user-defined label provided in TARGET ;; headline, or fallback to standard one. (format "{%s}" (org-beamer--get-label target info))))))) @@ -640,15 +666,27 @@ as a communication channel." "Transcode an ITEM element into Beamer code. CONTENTS holds the contents of the item. INFO is a plist holding contextual information." - (let ((action (let ((first-element (car (org-element-contents item)))) - (and (eq (org-element-type first-element) 'paragraph) - (org-beamer--element-has-overlay-p first-element)))) - (output (org-export-with-backend 'latex item contents info))) - (if (or (not action) (not (string-match "\\\\item" output))) output - ;; If the item starts with a paragraph and that paragraph starts - ;; with an export snippet specifying an overlay, insert it after - ;; \item command. - (replace-match (concat "\\\\item" action) nil nil output)))) + (org-export-with-backend + ;; Delegate item export to `latex'. However, we use `beamer' + ;; transcoders for objects in the description tag. + (org-export-create-backend + :parent 'beamer + :transcoders + (list + (cons + 'item + (lambda (item _c _i) + (let ((action + (let ((first (car (org-element-contents item)))) + (and (eq (org-element-type first) 'paragraph) + (org-beamer--element-has-overlay-p first)))) + (output (org-latex-item item contents info))) + (if (not (and action (string-match "\\\\item" output))) output + ;; If the item starts with a paragraph and that paragraph + ;; starts with an export snippet specifying an overlay, + ;; append it to the \item command. + (replace-match (concat "\\\\item" action) nil nil output))))))) + item contents info)) ;;;; Keyword @@ -681,46 +719,16 @@ channel." "Transcode a LINK object into Beamer code. CONTENTS is the description part of the link. INFO is a plist used as a communication channel." - (let ((type (org-element-property :type link)) - (path (org-element-property :path link))) - ;; Use \hyperlink command for all internal links. - (cond - ((equal type "radio") - (let ((destination (org-export-resolve-radio-link link info))) - (if (not destination) contents - (format "\\hyperlink%s{%s}{%s}" - (or (org-beamer--element-has-overlay-p link) "") - (org-export-solidify-link-text - (org-element-property :value destination)) - contents)))) - ((and (member type '("custom-id" "fuzzy" "id")) - (let ((destination (if (string= type "fuzzy") - (org-export-resolve-fuzzy-link link info) - (org-export-resolve-id-link link info)))) - (case (org-element-type destination) - (headline - (let ((label - (format "sec-%s" - (mapconcat - 'number-to-string - (org-export-get-headline-number - destination info) - "-")))) - (if (and (plist-get info :section-numbers) (not contents)) - (format "\\ref{%s}" label) - (format "\\hyperlink%s{%s}{%s}" - (or (org-beamer--element-has-overlay-p link) "") - label - contents)))) - (target - (let ((path (org-export-solidify-link-text path))) - (if (not contents) (format "\\ref{%s}" path) - (format "\\hyperlink%s{%s}{%s}" - (or (org-beamer--element-has-overlay-p link) "") - path - contents)))))))) - ;; Otherwise, use `latex' back-end. - (t (org-export-with-backend 'latex link contents info))))) + (or (org-export-custom-protocol-maybe link contents 'beamer) + ;; Fall-back to LaTeX export. However, prefer "\hyperlink" over + ;; "\hyperref" since the former handles overlay specifications. + (let ((latex-link (org-export-with-backend 'latex link contents info))) + (if (string-match "\\`\\\\hyperref\\[\\(.*?\\)\\]" latex-link) + (replace-match + (format "\\\\hyperlink%s{\\1}" + (or (org-beamer--element-has-overlay-p link) "")) + nil nil latex-link) + latex-link)))) ;;;; Plain List @@ -755,7 +763,8 @@ contextual information." 'option) ;; Eventually insert contents and close environment. contents - latex-type)))) + latex-type) + info))) ;;;; Radio Target @@ -766,21 +775,10 @@ TEXT is the text of the target. INFO is a plist holding contextual information." (format "\\hypertarget%s{%s}{%s}" (or (org-beamer--element-has-overlay-p radio-target) "") - (org-export-solidify-link-text - (org-element-property :value radio-target)) + (org-export-get-reference radio-target info) text)) -;;;; Target - -(defun org-beamer-target (target contents info) - "Transcode a TARGET object into Beamer code. -CONTENTS is nil. INFO is a plist holding contextual -information." - (format "\\hypertarget{%s}{}" - (org-export-solidify-link-text (org-element-property :value target)))) - - ;;;; Template ;; ;; Template used is similar to the one used in `latex' back-end, @@ -790,37 +788,17 @@ information." "Return complete document string after Beamer conversion. CONTENTS is the transcoded contents string. INFO is a plist holding export options." - (let ((title (org-export-data (plist-get info :title) info))) + (let ((title (org-export-data (plist-get info :title) info)) + (subtitle (org-export-data (plist-get info :subtitle) info))) (concat - ;; 1. Time-stamp. + ;; Time-stamp. (and (plist-get info :time-stamp-file) (format-time-string "%% Created %Y-%m-%d %a %H:%M\n")) - ;; 2. Document class and packages. - (let* ((class (plist-get info :latex-class)) - (class-options (plist-get info :latex-class-options)) - (header (nth 1 (assoc class org-latex-classes))) - (document-class-string - (and (stringp header) - (if (not class-options) header - (replace-regexp-in-string - "^[ \t]*\\\\documentclass\\(\\(\\[[^]]*\\]\\)?\\)" - class-options header t nil 1))))) - (if (not document-class-string) - (user-error "Unknown LaTeX class `%s'" class) - (org-latex-guess-babel-language - (org-latex-guess-inputenc - (org-element-normalize-string - (org-splice-latex-header - document-class-string - org-latex-default-packages-alist - org-latex-packages-alist nil - (concat (org-element-normalize-string - (plist-get info :latex-header)) - (org-element-normalize-string - (plist-get info :latex-header-extra)) - (plist-get info :beamer-header-extra))))) - info))) - ;; 3. Insert themes. + ;; LaTeX compiler + (org-latex--insert-compiler info) + ;; Document class and packages. + (org-latex-make-preamble info) + ;; Insert themes. (let ((format-theme (function (lambda (prop command) @@ -840,11 +818,11 @@ holding export options." (:beamer-inner-theme "\\useinnertheme") (:beamer-outer-theme "\\useoutertheme")) "")) - ;; 4. Possibly limit depth for headline numbering. + ;; Possibly limit depth for headline numbering. (let ((sec-num (plist-get info :section-numbers))) (when (integerp sec-num) (format "\\setcounter{secnumdepth}{%d}\n" sec-num))) - ;; 5. Author. + ;; Author. (let ((author (and (plist-get info :with-author) (let ((auth (plist-get info :author))) (and auth (org-export-data auth info))))) @@ -852,52 +830,52 @@ holding export options." (org-export-data (plist-get info :email) info)))) (cond ((and author email (not (string= "" email))) (format "\\author{%s\\thanks{%s}}\n" author email)) - (author (format "\\author{%s}\n" author)) - (t "\\author{}\n"))) - ;; 6. Date. + ((or author email) (format "\\author{%s}\n" (or author email))))) + ;; Date. (let ((date (and (plist-get info :with-date) (org-export-get-date info)))) (format "\\date{%s}\n" (org-export-data date info))) - ;; 7. Title + ;; Title (format "\\title{%s}\n" title) - ;; 8. Hyperref options. - (when (plist-get info :latex-hyperref-p) - (format "\\hypersetup{\n pdfkeywords={%s},\n pdfsubject={%s},\n pdfcreator={%s}}\n" - (or (plist-get info :keywords) "") - (or (plist-get info :description) "") - (if (not (plist-get info :with-creator)) "" - (plist-get info :creator)))) - ;; 9. Document start. + (when (org-string-nw-p subtitle) + (concat (format (plist-get info :beamer-subtitle-format) subtitle) "\n")) + ;; Beamer-header + (let ((beamer-header (plist-get info :beamer-header))) + (when beamer-header + (format "%s\n" (plist-get info :beamer-header)))) + ;; 9. Hyperref options. + (let ((template (plist-get info :latex-hyperref-template))) + (and (stringp template) + (format-spec template (org-latex--format-spec info)))) + ;; Document start. "\\begin{document}\n\n" - ;; 10. Title command. + ;; Title command. (org-element-normalize-string - (cond ((string= "" title) nil) + (cond ((not (plist-get info :with-title)) nil) + ((string= "" title) nil) ((not (stringp org-latex-title-command)) nil) ((string-match "\\(?:[^%]\\|^\\)%s" org-latex-title-command) (format org-latex-title-command title)) (t org-latex-title-command))) - ;; 11. Table of contents. + ;; Table of contents. (let ((depth (plist-get info :with-toc))) (when depth (concat (format "\\begin{frame}%s{%s}\n" (org-beamer--normalize-argument - org-beamer-outline-frame-options 'option) - org-beamer-outline-frame-title) + (plist-get info :beamer-outline-frame-options) 'option) + (plist-get info :beamer-outline-frame-title)) (when (wholenump depth) (format "\\setcounter{tocdepth}{%d}\n" depth)) "\\tableofcontents\n" "\\end{frame}\n\n"))) - ;; 12. Document's body. + ;; Document's body. contents - ;; 13. Creator. - (let ((creator-info (plist-get info :with-creator))) - (cond - ((not creator-info) "") - ((eq creator-info 'comment) - (format "%% %s\n" (plist-get info :creator))) - (t (concat (plist-get info :creator) "\n")))) - ;; 14. Document end. + ;; Creator. + (if (plist-get info :with-creator) + (concat (plist-get info :creator) "\n") + "") + ;; Document end. "\\end{document}"))) @@ -933,7 +911,7 @@ value." (save-excursion (org-back-to-heading t) ;; Filter out Beamer-related tags and install environment tag. - (let ((tags (org-remove-if (lambda (x) (string-match "^B_" x)) + (let ((tags (cl-remove-if (lambda (x) (string-match "^B_" x)) (org-get-tags))) (env-tag (and (org-string-nw-p value) (concat "B_" value)))) (org-set-tags-to (if env-tag (cons env-tag tags) tags)) @@ -1085,7 +1063,7 @@ aid, but the tag does not have any semantic meaning." (let* ((envs (append org-beamer-environments-special org-beamer-environments-extra org-beamer-environments-default)) - (org-tag-alist + (org-current-tag-alist (append '((:startgroup)) (mapcar (lambda (e) (cons (concat "B_" (car e)) (string-to-char (nth 1 e)))) @@ -1120,30 +1098,6 @@ aid, but the tag does not have any semantic meaning." (org-entry-put nil "BEAMER_env" (match-string 1 tags))) (t (org-entry-delete nil "BEAMER_env")))))) -;;;###autoload -(defun org-beamer-insert-options-template (&optional kind) - "Insert a settings template, to make sure users do this right." - (interactive (progn - (message "Current [s]ubtree or [g]lobal?") - (if (eq (read-char-exclusive) ?g) (list 'global) - (list 'subtree)))) - (if (eq kind 'subtree) - (progn - (org-back-to-heading t) - (org-reveal) - (org-entry-put nil "EXPORT_LaTeX_CLASS" "beamer") - (org-entry-put nil "EXPORT_LaTeX_CLASS_OPTIONS" "[presentation]") - (org-entry-put nil "EXPORT_FILE_NAME" "presentation.pdf") - (when org-beamer-column-view-format - (org-entry-put nil "COLUMNS" org-beamer-column-view-format)) - (org-entry-put nil "BEAMER_col_ALL" org-beamer-column-widths)) - (insert "#+LaTeX_CLASS: beamer\n") - (insert "#+LaTeX_CLASS_OPTIONS: [presentation]\n") - (when org-beamer-theme (insert "#+BEAMER_THEME: " org-beamer-theme "\n")) - (when org-beamer-column-view-format - (insert "#+COLUMNS: " org-beamer-column-view-format "\n")) - (insert "#+PROPERTY: BEAMER_col_ALL " org-beamer-column-widths "\n"))) - ;;;###autoload (defun org-beamer-publish-to-latex (plist filename pub-dir) "Publish an Org file to a Beamer presentation (LaTeX). @@ -1168,9 +1122,13 @@ Return output file name." ;; working directory and then moved to publishing directory. (org-publish-attachment plist - (org-latex-compile - (org-publish-org-to - 'beamer filename ".tex" plist (file-name-directory filename))) + ;; Default directory could be anywhere when this function is + ;; called. We ensure it is set to source file directory during + ;; compilation so as to not break links to external documents. + (let ((default-directory (file-name-directory filename))) + (org-latex-compile + (org-publish-org-to + 'beamer filename ".tex" plist (file-name-directory filename)))) pub-dir)) diff --git a/lisp/org/ox-html.el b/lisp/org/ox-html.el index 86ca3a6bb28..49562fa6918 100644 --- a/lisp/org/ox-html.el +++ b/lisp/org/ox-html.el @@ -1,4 +1,4 @@ -;;; ox-html.el --- HTML Back-End for Org Export Engine +;;; ox-html.el --- HTML Back-End for Org Export Engine -*- lexical-binding: t; -*- ;; Copyright (C) 2011-2017 Free Software Foundation, Inc. @@ -30,20 +30,24 @@ ;;; Dependencies +(require 'cl-lib) +(require 'format-spec) (require 'ox) (require 'ox-publish) -(require 'format-spec) -(eval-when-compile (require 'cl) (require 'table nil 'noerror)) +(require 'table) ;;; Function Declarations (declare-function org-id-find-id-file "org-id" (id)) (declare-function htmlize-region "ext:htmlize" (beg end)) -(declare-function org-pop-to-buffer-same-window - "org-compat" (&optional buffer-or-name norecord label)) (declare-function mm-url-decode-entities "mm-url" ()) +(defvar htmlize-css-name-prefix) +(defvar htmlize-output-type) +(defvar htmlize-output-type) +(defvar htmlize-css-name-prefix) + ;;; Define Back-End (org-export-define-backend 'html @@ -72,13 +76,13 @@ (latex-fragment . org-html-latex-fragment) (line-break . org-html-line-break) (link . org-html-link) + (node-property . org-html-node-property) (paragraph . org-html-paragraph) (plain-list . org-html-plain-list) (plain-text . org-html-plain-text) (planning . org-html-planning) (property-drawer . org-html-property-drawer) (quote-block . org-html-quote-block) - (quote-section . org-html-quote-section) (radio-target . org-html-radio-target) (section . org-html-section) (special-block . org-html-special-block) @@ -96,7 +100,6 @@ (underline . org-html-underline) (verbatim . org-html-verbatim) (verse-block . org-html-verse-block)) - :export-block "HTML" :filters-alist '((:filter-options . org-html-infojs-install-script) (:filter-final-output . org-html-final-function)) :menu-entry @@ -108,10 +111,10 @@ (if a (org-html-export-to-html t s v b) (org-open-file (org-html-export-to-html nil s v b))))))) :options-alist - '((:html-extension nil nil org-html-extension) - (:html-link-org-as-html nil nil org-html-link-org-files-as-html) - (:html-doctype "HTML_DOCTYPE" nil org-html-doctype) + '((:html-doctype "HTML_DOCTYPE" nil org-html-doctype) (:html-container "HTML_CONTAINER" nil org-html-container-element) + (:description "DESCRIPTION" nil nil newline) + (:keywords "KEYWORDS" nil nil space) (:html-html5-fancy nil "html5-fancy" org-html-html5-fancy) (:html-link-use-abs-url nil "html-link-use-abs-url" org-html-link-use-abs-url) (:html-link-home "HTML_LINK_HOME" nil org-html-link-home) @@ -121,12 +124,52 @@ (:html-preamble nil "html-preamble" org-html-preamble) (:html-head "HTML_HEAD" nil org-html-head newline) (:html-head-extra "HTML_HEAD_EXTRA" nil org-html-head-extra newline) - (:html-head-include-default-style nil "html-style" org-html-head-include-default-style) + (:subtitle "SUBTITLE" nil nil parse) + (:html-head-include-default-style + nil "html-style" org-html-head-include-default-style) (:html-head-include-scripts nil "html-scripts" org-html-head-include-scripts) + (:html-allow-name-attribute-in-anchors + nil nil org-html-allow-name-attribute-in-anchors) + (:html-divs nil nil org-html-divs) + (:html-checkbox-type nil nil org-html-checkbox-type) + (:html-extension nil nil org-html-extension) + (:html-footnote-format nil nil org-html-footnote-format) + (:html-footnote-separator nil nil org-html-footnote-separator) + (:html-footnotes-section nil nil org-html-footnotes-section) + (:html-format-drawer-function nil nil org-html-format-drawer-function) + (:html-format-headline-function nil nil org-html-format-headline-function) + (:html-format-inlinetask-function + nil nil org-html-format-inlinetask-function) + (:html-home/up-format nil nil org-html-home/up-format) + (:html-indent nil nil org-html-indent) + (:html-infojs-options nil nil org-html-infojs-options) + (:html-infojs-template nil nil org-html-infojs-template) + (:html-inline-image-rules nil nil org-html-inline-image-rules) + (:html-link-org-files-as-html nil nil org-html-link-org-files-as-html) + (:html-mathjax-options nil nil org-html-mathjax-options) + (:html-mathjax-template nil nil org-html-mathjax-template) + (:html-metadata-timestamp-format nil nil org-html-metadata-timestamp-format) + (:html-postamble-format nil nil org-html-postamble-format) + (:html-preamble-format nil nil org-html-preamble-format) + (:html-table-align-individual-fields + nil nil org-html-table-align-individual-fields) + (:html-table-caption-above nil nil org-html-table-caption-above) + (:html-table-data-tags nil nil org-html-table-data-tags) + (:html-table-header-tags nil nil org-html-table-header-tags) + (:html-table-use-header-tags-for-first-column + nil nil org-html-table-use-header-tags-for-first-column) + (:html-tag-class-prefix nil nil org-html-tag-class-prefix) + (:html-text-markup-alist nil nil org-html-text-markup-alist) + (:html-todo-kwd-class-prefix nil nil org-html-todo-kwd-class-prefix) + (:html-toplevel-hlevel nil nil org-html-toplevel-hlevel) + (:html-use-infojs nil nil org-html-use-infojs) + (:html-validation-link nil nil org-html-validation-link) + (:html-viewport nil nil org-html-viewport) + (:html-inline-images nil nil org-html-inline-images) (:html-table-attributes nil nil org-html-table-default-attributes) - (:html-table-row-tags nil nil org-html-table-row-tags) + (:html-table-row-open-tag nil nil org-html-table-row-open-tag) + (:html-table-row-close-tag nil nil org-html-table-row-close-tag) (:html-xml-declaration nil nil org-html-xml-declaration) - (:html-inline-images nil nil org-html-inline-images) (:infojs-opt "INFOJS_OPT" nil nil) ;; Redefine regular options. (:creator "CREATOR" nil org-html-creator-string) @@ -186,7 +229,7 @@ property on the headline itself.") @licstart The following is the entire license notice for the JavaScript code in this tag. -Copyright (C) 2012-2013 Free Software Foundation, Inc. +Copyright (C) 2012-2017 Free Software Foundation, Inc. The JavaScript code in this tag is free software: you can redistribute it and/or modify it under the terms of the GNU @@ -232,16 +275,22 @@ for the JavaScript code in this tag. (defconst org-html-style-default "" "The default style specification for exported HTML files. @@ -385,7 +518,7 @@ means to use the maximum value consistent with other options." * @licstart The following is the entire license notice for the * JavaScript code in %SCRIPT_PATH. * - * Copyright (C) 2012-2013 Free Software Foundation, Inc. + * Copyright (C) 2012-2017 Free Software Foundation, Inc. * * * The JavaScript code in this tag is free software: you can @@ -414,7 +547,7 @@ means to use the maximum value consistent with other options." @licstart The following is the entire license notice for the JavaScript code in this tag. -Copyright (C) 2012-2013 Free Software Foundation, Inc. +Copyright (C) 2012-2017 Free Software Foundation, Inc. The JavaScript code in this tag is free software: you can redistribute it and/or modify it under the terms of the GNU @@ -447,23 +580,24 @@ Option settings will replace the %MANAGER-OPTIONS cookie." :package-version '(Org . "8.0") :type 'string) -(defun org-html-infojs-install-script (exp-plist backend) +(defun org-html-infojs-install-script (exp-plist _backend) "Install script in export options when appropriate. EXP-PLIST is a plist containing export options. BACKEND is the export back-end currently used." (unless (or (memq 'body-only (plist-get exp-plist :export-options)) - (not org-html-use-infojs) - (and (eq org-html-use-infojs 'when-configured) - (or (not (plist-get exp-plist :infojs-opt)) - (string= "" (plist-get exp-plist :infojs-opt)) - (string-match "\\" - (plist-get exp-plist :infojs-opt))))) - (let* ((template org-html-infojs-template) + (not (plist-get exp-plist :html-use-infojs)) + (and (eq (plist-get exp-plist :html-use-infojs) 'when-configured) + (let ((opt (plist-get exp-plist :infojs-opt))) + (or (not opt) + (string= "" opt) + (string-match "\\" opt))))) + (let* ((template (plist-get exp-plist :html-infojs-template)) (ptoc (plist-get exp-plist :with-toc)) (hlevels (plist-get exp-plist :headline-levels)) (sdepth hlevels) (tdepth (if (integerp ptoc) (min ptoc hlevels) hlevels)) (options (plist-get exp-plist :infojs-opt)) + (infojs-opt (plist-get exp-plist :html-infojs-options)) (table org-html-infojs-opts-table) style) (dolist (entry table) @@ -472,7 +606,7 @@ export back-end currently used." ;; Compute default values for script option OPT from ;; `org-html-infojs-options' variable. (default - (let ((default (cdr (assq opt org-html-infojs-options)))) + (let ((default (cdr (assq opt infojs-opt)))) (if (and (symbolp default) (not (memq default '(t nil)))) (plist-get exp-plist default) default))) @@ -483,21 +617,21 @@ export back-end currently used." options)) (match-string 1 options) default))) - (case opt - (path (setq template - (replace-regexp-in-string - "%SCRIPT_PATH" val template t t))) - (sdepth (when (integerp (read val)) - (setq sdepth (min (read val) sdepth)))) - (tdepth (when (integerp (read val)) - (setq tdepth (min (read val) tdepth)))) - (otherwise (setq val - (cond - ((or (eq val t) (equal val "t")) "1") - ((or (eq val nil) (equal val "nil")) "0") - ((stringp val) val) - (t (format "%s" val)))) - (push (cons var val) style))))) + (pcase opt + (`path (setq template + (replace-regexp-in-string + "%SCRIPT_PATH" val template t t))) + (`sdepth (when (integerp (read val)) + (setq sdepth (min (read val) sdepth)))) + (`tdepth (when (integerp (read val)) + (setq tdepth (min (read val) tdepth)))) + (_ (setq val + (cond + ((or (eq val t) (equal val "t")) "1") + ((or (eq val nil) (equal val "nil")) "0") + ((stringp val) val) + (t (format "%s" val)))) + (push (cons var val) style))))) ;; Now we set the depth of the *generated* TOC to SDEPTH, ;; because the toc will actually determine the splitting. How ;; much of the toc will actually be displayed is governed by the @@ -509,9 +643,9 @@ export back-end currently used." (push (cons "TOC_DEPTH" tdepth) style) ;; Build style string. (setq style (mapconcat - (lambda (x) (format "org_html_manager.set(\"%s\", \"%s\");" - (car x) - (cdr x))) + (lambda (x) + (format "org_html_manager.set(\"%s\", \"%s\");" + (car x) (cdr x))) style "\n")) (when (and style (> (length style) 0)) (and (string-match "%MANAGER_OPTIONS" template) @@ -561,17 +695,9 @@ Warning: non-nil may break indentation of source code blocks." :package-version '(Org . "8.0") :type 'boolean) -(defcustom org-html-use-unicode-chars nil - "Non-nil means to use unicode characters instead of HTML entities." - :group 'org-export-html - :version "24.4" - :package-version '(Org . "8.0") - :type 'boolean) - ;;;; Drawers -(defcustom org-html-format-drawer-function - (lambda (name contents) contents) +(defcustom org-html-format-drawer-function (lambda (_name contents) contents) "Function called to format a drawer in HTML code. The function must accept two parameters: @@ -628,28 +754,30 @@ document title." :group 'org-export-html :type 'integer) -(defcustom org-html-format-headline-function 'ignore +(defcustom org-html-format-headline-function + 'org-html-format-headline-default-function "Function to format headline text. -This function will be called with 5 arguments: +This function will be called with six arguments: TODO the todo keyword (string or nil). TODO-TYPE the type of todo (symbol: `todo', `done', nil) PRIORITY the priority of the headline (integer or nil) TEXT the main headline text (string). TAGS the tags (string or nil). +INFO the export options (plist). The function result will be used in the section format string." :group 'org-export-html - :version "24.4" - :package-version '(Org . "8.0") + :version "26.1" + :package-version '(Org . "8.3") :type 'function) ;;;; HTML-specific -(defcustom org-html-allow-name-attribute-in-anchors t +(defcustom org-html-allow-name-attribute-in-anchors nil "When nil, do not set \"name\" attribute in anchors. -By default, anchors are formatted with both \"id\" and \"name\" -attributes, when appropriate." +By default, when appropriate, anchors are formatted with \"id\" +but without \"name\" attribute." :group 'org-export-html :version "24.4" :package-version '(Org . "8.0") @@ -657,21 +785,23 @@ attributes, when appropriate." ;;;; Inlinetasks -(defcustom org-html-format-inlinetask-function 'ignore +(defcustom org-html-format-inlinetask-function + 'org-html-format-inlinetask-default-function "Function called to format an inlinetask in HTML code. -The function must accept six parameters: +The function must accept seven parameters: TODO the todo keyword, as a string TODO-TYPE the todo type, a symbol among `todo', `done' and nil. PRIORITY the inlinetask priority, as a string NAME the inlinetask name, as a string. TAGS the inlinetask tags, as a list of strings. CONTENTS the contents of the inlinetask, as a string. + INFO the export options, as a plist The function should return the string to be exported." :group 'org-export-html - :version "24.4" - :package-version '(Org . "8.0") + :version "26.1" + :package-version '(Org . "8.3") :type 'function) ;;;; LaTeX @@ -685,24 +815,20 @@ fragments. This option can also be set with the +OPTIONS line, e.g. \"tex:mathjax\". Allowed values are: -nil Ignore math snippets. -`verbatim' Keep everything in verbatim -`dvipng' Process the LaTeX fragments to images. This will also - include processing of non-math environments. -`imagemagick' Convert the LaTeX fragments to pdf files and use - imagemagick to convert pdf files to png files. -`mathjax' Do MathJax preprocessing and arrange for MathJax.js to - be loaded. -t Synonym for `mathjax'." + nil Ignore math snippets. + `verbatim' Keep everything in verbatim + `mathjax', t Do MathJax preprocessing and arrange for MathJax.js to + be loaded. + SYMBOL Any symbol defined in `org-preview-latex-process-alist', + e.g., `dvipng'." :group 'org-export-html :version "24.4" :package-version '(Org . "8.0") :type '(choice (const :tag "Do not process math in any way" nil) - (const :tag "Use dvipng to make images" dvipng) - (const :tag "Use imagemagick to make images" imagemagick) + (const :tag "Leave math verbatim" verbatim) (const :tag "Use MathJax to display math" mathjax) - (const :tag "Leave math verbatim" verbatim))) + (symbol :tag "Convert to image to display math" :value dvipng))) ;;;; Links :: Generic @@ -710,11 +836,11 @@ t Synonym for `mathjax'." "Non-nil means make file links to `file.org' point to `file.html'. When `org-mode' is exporting an `org-mode' file to HTML, links to non-html files are directly put into a href tag in HTML. -However, links to other Org-mode files (recognized by the -extension `.org') should become links to the corresponding html +However, links to other Org files (recognized by the extension +\".org\") should become links to the corresponding HTML file, assuming that the linked `org-mode' file will also be converted to HTML. -When nil, the links still point to the plain `.org' file." +When nil, the links still point to the plain \".org\" file." :group 'org-export-html :type 'boolean) @@ -745,22 +871,20 @@ link's path." ;;;; Plain Text -(defcustom org-html-protect-char-alist +(defvar org-html-protect-char-alist '(("&" . "&") ("<" . "<") (">" . ">")) - "Alist of characters to be converted by `org-html-protect'." - :group 'org-export-html - :type '(repeat (cons (string :tag "Character") - (string :tag "HTML equivalent")))) + "Alist of characters to be converted by `org-html-encode-plain-text'.") ;;;; Src Block (defcustom org-html-htmlize-output-type 'inline-css "Output type to be used by htmlize when formatting code snippets. -Choices are `css', to export the CSS selectors only, or `inline-css', to -export the CSS attribute values inline in the HTML. We use as default -`inline-css', in order to make the resulting HTML self-containing. +Choices are `css' to export the CSS selectors only,`inline-css' +to export the CSS attribute values inline in the HTML or `nil' to +export plain text. We use as default `inline-css', in order to +make the resulting HTML self-containing. However, this will fail when using Emacs in batch mode for export, because then no rich font definitions are in place. It will also not be good if @@ -771,9 +895,9 @@ a style file to define the look of these classes. To get a start for your css file, start Emacs session and make sure that all the faces you are interested in are defined, for example by loading files in all modes you want. Then, use the command -\\[org-html-htmlize-generate-css] to extract class definitions." +`\\[org-html-htmlize-generate-css]' to extract class definitions." :group 'org-export-html - :type '(choice (const css) (const inline-css))) + :type '(choice (const css) (const inline-css) (const nil))) (defcustom org-html-htmlize-font-prefix "org-" "The prefix for CSS class names for htmlize font specifications." @@ -796,7 +920,7 @@ When exporting to HTML5, these values will be disregarded." :value-type (string :tag "Value"))) (defcustom org-html-table-header-tags '("" . "") - "The opening tag for table header fields. + "The opening and ending tags for table header fields. This is customizable so that alignment options can be specified. The first %s will be filled with the scope of the field, either row or col. The second %s will be replaced by a style entry to align the field. @@ -806,7 +930,7 @@ See also the variable `org-html-table-align-individual-fields'." :type '(cons (string :tag "Opening tag") (string :tag "Closing tag"))) (defcustom org-html-table-data-tags '("" . "") - "The opening tag for table data fields. + "The opening and ending tags for table data fields. This is customizable so that alignment options can be specified. The first %s will be filled with the scope of the field, either row or col. The second %s will be replaced by a style entry to align the field. @@ -814,43 +938,50 @@ See also the variable `org-html-table-align-individual-fields'." :group 'org-export-html :type '(cons (string :tag "Opening tag") (string :tag "Closing tag"))) -(defcustom org-html-table-row-tags '("" . "") - "The opening and ending tags for table rows. +(defcustom org-html-table-row-open-tag "" + "The opening tag for table rows. This is customizable so that alignment options can be specified. -Instead of strings, these can be Lisp forms that will be +Instead of strings, these can be a Lisp function that will be evaluated for each row in order to construct the table row tags. -During evaluation, these variables will be dynamically bound so that -you can reuse them: +The function will be called with these arguments: - `row-number': row number (0 is the first row) - `rowgroup-number': group number of current row - `start-rowgroup-p': non-nil means the row starts a group - `end-rowgroup-p': non-nil means the row ends a group - `top-row-p': non-nil means this is the top row - `bottom-row-p': non-nil means this is the bottom row + `number': row number (0 is the first row) + `group-number': group number of current row + `start-group?': non-nil means the row starts a group + `end-group?': non-nil means the row ends a group + `top?': non-nil means this is the top row + `bottom?': non-nil means this is the bottom row For example: -\(setq org-html-table-row-tags - (cons \\='(cond (top-row-p \"\") - (bottom-row-p \"\") - (t (if (= (mod row-number 2) 1) - \"\" - \"\"))) - \"\")) + (setq org-html-table-row-open-tag + (lambda (number group-number start-group? end-group-p top? bottom?) + (cond (top? \"\") + (bottom? \"\") + (t (if (= (mod number 2) 1) + \"\" + \"\"))))) will use the \"tr-top\" and \"tr-bottom\" classes for the top row and the bottom row, and otherwise alternate between \"tr-odd\" and \"tr-even\" for odd and even rows." :group 'org-export-html - :type '(cons - (choice :tag "Opening tag" - (string :tag "Specify") - (sexp)) - (choice :tag "Closing tag" - (string :tag "Specify") - (sexp)))) + :type '(choice :tag "Opening tag" + (string :tag "Specify") + (function))) + +(defcustom org-html-table-row-close-tag "" + "The closing tag for table rows. +This is customizable so that alignment options can be specified. +Instead of strings, this can be a Lisp function that will be +evaluated for each row in order to construct the table row tags. + +See documentation of `org-html-table-row-open-tag'." + :group 'org-export-html + :type '(choice :tag "Closing tag" + (string :tag "Specify") + (function))) (defcustom org-html-table-align-individual-fields t "Non-nil means attach style attributes for alignment to each table field. @@ -921,7 +1052,10 @@ publishing, with :html-doctype." :group 'org-export-html :version "24.4" :package-version '(Org . "8.0") - :type 'string) + :type (append + '(choice) + (mapcar (lambda (x) `(const ,(car x))) org-html-doctype-alist) + '((string :tag "Custom doctype" )))) (defcustom org-html-html5-fancy nil "Non-nil means using new HTML5 elements. @@ -954,7 +1088,7 @@ org-info.js for your website." (content "div" "content") (postamble "div" "postamble")) "Alist of the three section elements for HTML export. -The car of each entry is one of 'preamble, 'content or 'postamble. +The car of each entry is one of `preamble', `content' or `postamble'. The cdrs of each entry are the ELEMENT_TYPE and ID for each section of the exported document. @@ -973,6 +1107,41 @@ org-info.js for your website." (list :tag "Postamble" (const :format "" postamble) (string :tag " id") (string :tag "element")))) +(defconst org-html-checkbox-types + '((unicode . + ((on . "☑") (off . "☐") (trans . "☐"))) + (ascii . + ((on . "[X]") + (off . "[ ]") + (trans . "[-]"))) + (html . + ((on . "") + (off . "") + (trans . "")))) + "Alist of checkbox types. +The cdr of each entry is an alist list three checkbox types for +HTML export: `on', `off' and `trans'. + +The choices are: + `unicode' Unicode characters (HTML entities) + `ascii' ASCII characters + `html' HTML checkboxes + +Note that only the ascii characters implement tri-state +checkboxes. The other two use the `off' checkbox for `trans'.") + +(defcustom org-html-checkbox-type 'ascii + "The type of checkboxes to use for HTML export. +See `org-html-checkbox-types' for for the values used for each +option." + :group 'org-export-html + :version "24.4" + :package-version '(Org . "8.0") + :type '(choice + (const :tag "ASCII characters" ascii) + (const :tag "Unicode characters" unicode) + (const :tag "HTML checkboxes" html))) + (defcustom org-html-metadata-timestamp-format "%Y-%m-%d %a %H:%M" "Format used for timestamps in preamble, postamble and metadata. See `format-time-string' for more information on its components." @@ -984,82 +1153,107 @@ See `format-time-string' for more information on its components." ;;;; Template :: Mathjax (defcustom org-html-mathjax-options - '((path "http://orgmode.org/mathjax/MathJax.js") + '((path "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_HTML" ) (scale "100") (align "center") - (indent "2em") - (mathml nil)) + (font "TeX") + (linebreaks "false") + (autonumber "AMS") + (indent "0em") + (multlinewidth "85%") + (tagindent ".8em") + (tagside "right")) "Options for MathJax setup. -path The path where to find MathJax -scale Scaling for the HTML-CSS backend, usually between 100 and 133 -align How to align display math: left, center, or right -indent If align is not center, how far from the left/right side? -mathml Should a MathML player be used if available? - This is faster and reduces bandwidth use, but currently - sometimes has lower spacing quality. Therefore, the default is - nil. When browsers get better, this switch can be flipped. +Alist of the following elements. All values are strings. + +path The path to MathJax. +scale Scaling with HTML-CSS, MathML and SVG output engines. +align How to align display math: left, center, or right. +font The font to use with HTML-CSS and SVG output. As of MathJax 2.5 + the following values are understood: \"TeX\", \"STIX-Web\", + \"Asana-Math\", \"Neo-Euler\", \"Gyre-Pagella\", + \"Gyre-Termes\", and \"Latin-Modern\". +linebreaks Let MathJax perform automatic linebreaks. Valid values + are \"true\" and \"false\". +indent If align is not center, how far from the left/right side? + Valid values are \"left\" and \"right\" +multlinewidth The width of the multline environment. +autonumber How to number equations. Valid values are \"None\", + \"all\" and \"AMS Math\". +tagindent The amount tags are indented. +tagside Which side to show tags/labels on. Valid values are + \"left\" and \"right\" You can also customize this for each buffer, using something like -#+MATHJAX: scale:\"133\" align:\"right\" mathml:t path:\"/MathJax/\"" +#+HTML_MATHJAX: align: left indent: 5em tagside: left font: Neo-Euler + +For further information about MathJax options, see the MathJax documentation: + + http://docs.mathjax.org/" :group 'org-export-html + :package-version '(Org . "8.3") :type '(list :greedy t - (list :tag "path (the path from where to load MathJax.js)" - (const :format " " path) (string)) - (list :tag "scale (scaling for the displayed math)" - (const :format " " scale) (string)) - (list :tag "align (alignment of displayed equations)" - (const :format " " align) (string)) - (list :tag "indent (indentation with left or right alignment)" - (const :format " " indent) (string)) - (list :tag "mathml (should MathML display be used is possible)" - (const :format " " mathml) (boolean)))) + (list :tag "path (the path from where to load MathJax.js)" + (const :format " " path) (string)) + (list :tag "scale (scaling for the displayed math)" + (const :format " " scale) (string)) + (list :tag "align (alignment of displayed equations)" + (const :format " " align) (string)) + (list :tag "font (used to display math)" + (const :format " " font) + (choice (const "TeX") + (const "STIX-Web") + (const "Asana-Math") + (const "Neo-Euler") + (const "Gyre-Pagella") + (const "Gyre-Termes") + (const "Latin-Modern"))) + (list :tag "linebreaks (automatic line-breaking)" + (const :format " " linebreaks) + (choice (const "true") + (const "false"))) + (list :tag "autonumber (when should equations be numbered)" + (const :format " " autonumber) + (choice (const "AMS") + (const "None") + (const "All"))) + (list :tag "indent (indentation with left or right alignment)" + (const :format " " indent) (string)) + (list :tag "multlinewidth (width to use for the multline environment)" + (const :format " " multlinewidth) (string)) + (list :tag "tagindent (the indentation of tags from left or right)" + (const :format " " tagindent) (string)) + (list :tag "tagside (location of tags)" + (const :format " " tagside) + (choice (const "left") + (const "right"))))) (defcustom org-html-mathjax-template - " -" - "The MathJax setup for XHTML files." +}); + +" + "The MathJax template. See also `org-html-mathjax-options'." :group 'org-export-html :type 'string) @@ -1068,7 +1262,7 @@ You can also customize this for each buffer, using something like (defcustom org-html-postamble 'auto "Non-nil means insert a postamble in HTML export. -When set to 'auto, check against the +When set to `auto', check against the `org-export-with-author/email/creator/date' variables to set the content of the postamble. When set to a string, use this string as the postamble. When t, insert a string as defined by the @@ -1101,6 +1295,7 @@ The second element of each list is a format string to format the postamble itself. This format string can contain these elements: %t stands for the title. + %s stands for the subtitle. %a stands for the author's name. %e stands for the author's email. %d stands for the date. @@ -1165,6 +1360,7 @@ The second element of each list is a format string to format the preamble itself. This format string can contain these elements: %t stands for the title. + %s stands for the subtitle. %a stands for the author's name. %e stands for the author's email. %d stands for the date. @@ -1216,8 +1412,6 @@ ignored." ;;;; Template :: Scripts -(define-obsolete-variable-alias - 'org-html-style-include-scripts 'org-html-head-include-scripts "24.4") (defcustom org-html-head-include-scripts t "Non-nil means include the JavaScript snippets in exported HTML files. The actual script is defined in `org-html-scripts' and should @@ -1229,8 +1423,6 @@ not be modified." ;;;; Template :: Styles -(define-obsolete-variable-alias - 'org-html-style-include-default 'org-html-head-include-default-style "24.4") (defcustom org-html-head-include-default-style t "Non-nil means include the default style in exported HTML files. The actual style is defined in `org-html-style-default' and @@ -1243,7 +1435,6 @@ style information." ;;;###autoload (put 'org-html-head-include-default-style 'safe-local-variable 'booleanp) -(define-obsolete-variable-alias 'org-html-style 'org-html-head "24.4") (defcustom org-html-head "" "Org-wide head definitions for exported HTML files. @@ -1293,6 +1484,54 @@ or for publication projects using the :html-head-extra property." ;;;###autoload (put 'org-html-head-extra 'safe-local-variable 'stringp) +;;;; Template :: Viewport + +(defcustom org-html-viewport '((width "device-width") + (initial-scale "1") + (minimum-scale "") + (maximum-scale "") + (user-scalable "")) + "Viewport options for mobile-optimized sites. + +The following values are recognized + +width Size of the viewport. +initial-scale Zoom level when the page is first loaded. +minimum-scale Minimum allowed zoom level. +maximum-scale Maximum allowed zoom level. +user-scalable Whether zoom can be changed. + +The viewport meta tag is inserted if this variable is non-nil. + +See the following site for a reference: +https://developer.mozilla.org/en-US/docs/Mozilla/Mobile/Viewport_meta_tag" + :group 'org-export-html + :version "26.1" + :package-version '(Org . "8.3") + :type '(choice (const :tag "Disable" nil) + (list :tag "Enable" + (list :tag "Width of viewport" + (const :format " " width) + (choice (const :tag "unset" "") + (string))) + (list :tag "Initial scale" + (const :format " " initial-scale) + (choice (const :tag "unset" "") + (string))) + (list :tag "Minimum scale/zoom" + (const :format " " minimum-scale) + (choice (const :tag "unset" "") + (string))) + (list :tag "Maximum scale/zoom" + (const :format " " maximum-scale) + (choice (const :tag "unset" "") + (string))) + (list :tag "User scalable/zoomable" + (const :format " " user-scalable) + (choice (const :tag "unset" "") + (const "true") + (const "false")))))) + ;;;; Todos (defcustom org-html-todo-kwd-class-prefix "" @@ -1315,22 +1554,33 @@ CSS classes, then this prefix can be very useful." (let ((dt (downcase (plist-get info :html-doctype)))) (member dt '("html5" "xhtml5" "")))) +(defun org-html--html5-fancy-p (info) + "Non-nil when exporting to HTML5 with fancy elements. +INFO is the current state of the export process, as a plist." + (and (plist-get info :html-html5-fancy) + (org-html-html5-p info))) + (defun org-html-close-tag (tag attr info) - (concat "<" tag " " attr + "Return close-tag for string TAG. +ATTR specifies additional attributes. INFO is a property list +containing current export state." + (concat "<" tag + (org-string-nw-p (concat " " attr)) (if (org-html-xhtml-p info) " />" ">"))) (defun org-html-doctype (info) - "Return correct html doctype tag from `org-html-doctype-alist', -or the literal value of :html-doctype from INFO if :html-doctype -is not found in the alist. -INFO is a plist used as a communication channel." + "Return correct HTML doctype tag. +INFO is a plist used as a communication channel. Doctype tag is +extracted from `org-html-doctype-alist', or the literal value +of :html-doctype from INFO if :html-doctype is not found in the +alist." (let ((dt (plist-get info :html-doctype))) (or (cdr (assoc dt org-html-doctype-alist)) dt))) (defun org-html--make-attribute-string (attributes) "Return a list of attributes, as a string. -ATTRIBUTES is a plist where values are either strings or nil. An -attributes with a nil value will be omitted from the result." +ATTRIBUTES is a plist where values are either strings or nil. An +attribute with a nil value will be omitted from the result." (let (output) (dolist (item attributes (mapconcat 'identity (nreverse output) " ")) (cond ((null item) (pop output)) @@ -1345,15 +1595,13 @@ attributes with a nil value will be omitted from the result." INFO is a plist used as a communication channel. When optional arguments CAPTION and LABEL are given, use them for caption and \"id\" attribute." - (let ((html5-fancy (and (org-html-html5-p info) - (plist-get info :html-html5-fancy)))) - (format (if html5-fancy "\n%s%s\n" - "\n%s%s\n") + (let ((html5-fancy (org-html--html5-fancy-p info))) + (format (if html5-fancy "\n\n%s%s\n" + "\n\n%s%s\n") ;; ID. - (if (not (org-string-nw-p label)) "" - (format " id=\"%s\"" (org-export-solidify-link-text label))) + (if (org-string-nw-p label) (format " id=\"%s\"" label) "") ;; Contents. - (format "\n

%s

" contents) + (if html5-fancy contents (format "

%s

" contents)) ;; Caption. (if (not (org-string-nw-p caption)) "" (format (if html5-fancy "\n
%s
" @@ -1366,17 +1614,42 @@ SOURCE is a string specifying the location of the image. ATTRIBUTES is a plist, as returned by `org-export-read-attribute'. INFO is a plist used as a communication channel." - (org-html-close-tag - "img" - (org-html--make-attribute-string - (org-combine-plists - (list :src source - :alt (if (string-match-p "^ltxpng/" source) - (org-html-encode-plain-text - (org-find-text-property-in-string 'org-latex-src source)) - (file-name-nondirectory source))) - attributes)) - info)) + (if (string= "svg" (file-name-extension source)) + (org-html--svg-image source attributes info) + (org-html-close-tag + "img" + (org-html--make-attribute-string + (org-combine-plists + (list :src source + :alt (if (string-match-p "^ltxpng/" source) + (org-html-encode-plain-text + (org-find-text-property-in-string 'org-latex-src source)) + (file-name-nondirectory source))) + attributes)) + info))) + +(defun org-html--svg-image (source attributes info) + "Return \"object\" embedding svg file SOURCE with given ATTRIBUTES. +INFO is a plist used as a communication channel. + +The special attribute \"fallback\" can be used to specify a +fallback image file to use if the object embedding is not +supported. CSS class \"org-svg\" is assigned as the class of the +object unless a different class is specified with an attribute." + (let ((fallback (plist-get attributes :fallback)) + (attrs (org-html--make-attribute-string + (org-combine-plists + ;; Remove fallback attribute, which is not meant to + ;; appear directly in the attributes string, and + ;; provide a default class if none is set. + '(:class "org-svg") attributes '(:fallback nil))))) + (format "\n%s" + source + attrs + (if fallback + (org-html-close-tag + "img" (format "src=\"%s\" %s" fallback attrs) info) + "Sorry, your browser does not support SVG.")))) (defun org-html--textarea-block (element) "Transcode ELEMENT into a textarea block. @@ -1388,7 +1661,7 @@ ELEMENT is either a src block or an example block." (or (plist-get attr :height) (org-count-lines code)) code))) -(defun org-html--has-caption-p (element &optional info) +(defun org-html--has-caption-p (element &optional _info) "Non-nil when ELEMENT has a caption affiliated keyword. INFO is a plist used as a communication channel. This function is meant to be used as a predicate for `org-export-get-ordinal' or @@ -1435,7 +1708,7 @@ produce code that uses these same face definitions." (when (and (symbolp f) (or (not i) (not (listp i)))) (insert (org-add-props (copy-sequence "1") nil 'face f)))) (htmlize-region (point-min) (point-max)))) - (org-pop-to-buffer-same-window "*html*") + (pop-to-buffer-same-window "*html*") (goto-char (point-min)) (if (re-search-forward "%s %s\n" - (format org-html-footnote-format - (let* ((id (format "fn.%s" n)) - (href (format " href=\"#fnr.%s\"" n)) - (attributes (concat " class=\"footnum\"" href))) - (org-html--anchor id n attributes))) - def))) + (replace-regexp-in-string "[^a-zA-Z0-9_]" "_" kwd nil t)) (defun org-html-footnote-section (info) "Format the footnote section. INFO is a plist used as a communication channel." - (let* ((fn-alist (org-export-collect-footnote-definitions - (plist-get info :parse-tree) info)) + (let* ((fn-alist (org-export-collect-footnote-definitions info)) (fn-alist - (loop for (n type raw) in fn-alist collect - (cons n (if (eq (org-element-type raw) 'org-data) - (org-trim (org-export-data raw info)) - (format "

%s

" - (org-trim (org-export-data raw info)))))))) + (cl-loop for (n _type raw) in fn-alist collect + (cons n (if (eq (org-element-type raw) 'org-data) + (org-trim (org-export-data raw info)) + (format "
%s
" + (org-trim (org-export-data raw info)))))))) (when fn-alist - (org-html-format-footnotes-section + (format + (plist-get info :html-footnotes-section) (org-html--translate "Footnotes" info) (format "\n%s\n" - (mapconcat 'org-html-format-footnote-definition fn-alist "\n")))))) + (mapconcat + (lambda (fn) + (let ((n (car fn)) (def (cdr fn))) + (format + "
%s %s
\n" + (format + (plist-get info :html-footnote-format) + (org-html--anchor + (format "fn.%d" n) + n + (format " class=\"footnum\" href=\"#fnr.%d\"" n) + info)) + def))) + fn-alist + "\n")))))) ;;; Template @@ -1529,37 +1787,52 @@ INFO is a plist used as a communication channel." 'mime-charset)) "iso-8859-1"))) (concat - (format "%s\n" title) (when (plist-get info :time-stamp-file) (format-time-string - (concat "\n"))) + (concat "\n"))) (format (if (org-html-html5-p info) - (org-html-close-tag "meta" " charset=\"%s\"" info) + (org-html-close-tag "meta" "charset=\"%s\"" info) (org-html-close-tag - "meta" " http-equiv=\"Content-Type\" content=\"text/html;charset=%s\"" + "meta" "http-equiv=\"Content-Type\" content=\"text/html;charset=%s\"" info)) charset) "\n" - (org-html-close-tag "meta" " name=\"generator\" content=\"Org-mode\"" info) + (let ((viewport-options + (cl-remove-if-not (lambda (cell) (org-string-nw-p (cadr cell))) + (plist-get info :html-viewport)))) + (and viewport-options + (concat + (org-html-close-tag + "meta" + (format "name=\"viewport\" content=\"%s\"" + (mapconcat + (lambda (elm) (format "%s=%s" (car elm) (cadr elm))) + viewport-options ", ")) + info) + "\n"))) + (format "%s\n" title) + (org-html-close-tag "meta" "name=\"generator\" content=\"Org mode\"" info) "\n" (and (org-string-nw-p author) (concat (org-html-close-tag "meta" - (format " name=\"author\" content=\"%s\"" + (format "name=\"author\" content=\"%s\"" (funcall protect-string author)) info) "\n")) (and (org-string-nw-p description) (concat (org-html-close-tag "meta" - (format " name=\"description\" content=\"%s\"\n" + (format "name=\"description\" content=\"%s\"\n" (funcall protect-string description)) info) "\n")) (and (org-string-nw-p keywords) (concat (org-html-close-tag "meta" - (format " name=\"keywords\" content=\"%s\"" + (format "name=\"keywords\" content=\"%s\"" (funcall protect-string keywords)) info) "\n"))))) @@ -1576,7 +1849,7 @@ INFO is a plist used as a communication channel." (when (and (plist-get info :html-htmlized-css-url) (eq org-html-htmlize-output-type 'css)) (org-html-close-tag "link" - (format " rel=\"stylesheet\" href=\"%s\" type=\"text/css\"" + (format "rel=\"stylesheet\" href=\"%s\" type=\"text/css\"" (plist-get info :html-htmlized-css-url)) info)) (when (plist-get info :html-head-include-scripts) org-html-scripts)))) @@ -1587,55 +1860,43 @@ INFO is a plist used as a communication channel." (when (and (memq (plist-get info :with-latex) '(mathjax t)) (org-element-map (plist-get info :parse-tree) '(latex-fragment latex-environment) 'identity info t)) - (let ((template org-html-mathjax-template) - (options org-html-mathjax-options) - (in-buffer (or (plist-get info :html-mathjax) "")) - name val (yes " ") (no "// ") x) - (mapc - (lambda (e) - (setq name (car e) val (nth 1 e)) - (if (string-match (concat "\\<" (symbol-name name) ":") in-buffer) - (setq val (car (read-from-string - (substring in-buffer (match-end 0)))))) - (if (not (stringp val)) (setq val (format "%s" val))) - (if (string-match (concat "%" (upcase (symbol-name name))) template) - (setq template (replace-match val t t template)))) - options) - (setq val (nth 1 (assq 'mathml options))) - (if (string-match (concat "\\%s" e e)) - (split-string (plist-get info :email) ",+ *") - ", ")) - (?c . ,(plist-get info :creator)) - (?C . ,(let ((file (plist-get info :input-file))) - (format-time-string org-html-metadata-timestamp-format - (if file (nth 5 (file-attributes file)))))) - (?v . ,(or org-html-validation-link "")))) + "Return format specification for preamble and postamble. +INFO is a plist used as a communication channel." + (let ((timestamp-format (plist-get info :html-metadata-timestamp-format))) + `((?t . ,(org-export-data (plist-get info :title) info)) + (?s . ,(org-export-data (plist-get info :subtitle) info)) + (?d . ,(org-export-data (org-export-get-date info timestamp-format) + info)) + (?T . ,(format-time-string timestamp-format)) + (?a . ,(org-export-data (plist-get info :author) info)) + (?e . ,(mapconcat + (lambda (e) (format "%s" e e)) + (split-string (plist-get info :email) ",+ *") + ", ")) + (?c . ,(plist-get info :creator)) + (?C . ,(let ((file (plist-get info :input-file))) + (format-time-string timestamp-format + (and file (nth 5 (file-attributes file)))))) + (?v . ,(or (plist-get info :html-validation-link) ""))))) (defun org-html--build-pre/postamble (type info) "Return document preamble or postamble as a string, or nil. -TYPE is either 'preamble or 'postamble, INFO is a plist used as a +TYPE is either `preamble' or `postamble', INFO is a plist used as a communication channel." (let ((section (plist-get info (intern (format ":html-%s" type)))) (spec (org-html-format-spec info))) @@ -1649,7 +1910,6 @@ communication channel." (author (cdr (assq ?a spec))) (email (cdr (assq ?e spec))) (creator (cdr (assq ?c spec))) - (timestamp (cdr (assq ?T spec))) (validation-link (cdr (assq ?v spec)))) (concat (when (and (plist-get info :with-date) @@ -1671,30 +1931,34 @@ communication channel." (format "

%s: %s

\n" (org-html--translate "Created" info) - (format-time-string org-html-metadata-timestamp-format))) + (format-time-string + (plist-get info :html-metadata-timestamp-format)))) (when (plist-get info :with-creator) (format "

%s

\n" creator)) (format "

%s

\n" validation-link)))) (t (format-spec - (or (cadr (assoc + (or (cadr (assoc-string (plist-get info :language) (eval (intern - (format "org-html-%s-format" type))))) + (format "org-html-%s-format" type))) + t)) (cadr - (assoc + (assoc-string "en" (eval - (intern (format "org-html-%s-format" type)))))) + (intern (format "org-html-%s-format" type))) + t))) spec)))))) - (when (org-string-nw-p section-contents) - (concat - (format "<%s id=\"%s\" class=\"%s\">\n" - (nth 1 (assq type org-html-divs)) - (nth 2 (assq type org-html-divs)) - org-html--pre/postamble-class) - (org-element-normalize-string section-contents) - (format "\n" (nth 1 (assq type org-html-divs))))))))) + (let ((div (assq type (plist-get info :html-divs)))) + (when (org-string-nw-p section-contents) + (concat + (format "<%s id=\"%s\" class=\"%s\">\n" + (nth 1 div) + (nth 2 div) + org-html--pre/postamble-class) + (org-element-normalize-string section-contents) + (format "\n" (nth 1 div))))))))) (defun org-html-inner-template (contents info) "Return body of document string after HTML conversion. @@ -1715,27 +1979,28 @@ CONTENTS is the transcoded contents string. INFO is a plist holding export options." (concat (when (and (not (org-html-html5-p info)) (org-html-xhtml-p info)) - (let ((decl (or (and (stringp org-html-xml-declaration) - org-html-xml-declaration) - (cdr (assoc (plist-get info :html-extension) - org-html-xml-declaration)) - (cdr (assoc "html" org-html-xml-declaration)) - - ""))) - (when (not (or (eq nil decl) (string= "" decl))) + (let* ((xml-declaration (plist-get info :html-xml-declaration)) + (decl (or (and (stringp xml-declaration) xml-declaration) + (cdr (assoc (plist-get info :html-extension) + xml-declaration)) + (cdr (assoc "html" xml-declaration)) + ""))) + (when (not (or (not decl) (string= "" decl))) (format "%s\n" (format decl - (or (and org-html-coding-system - (fboundp 'coding-system-get) - (coding-system-get org-html-coding-system 'mime-charset)) - "iso-8859-1")))))) + (or (and org-html-coding-system + (fboundp 'coding-system-get) + (coding-system-get org-html-coding-system 'mime-charset)) + "iso-8859-1")))))) (org-html-doctype info) "\n" (concat "\n") "\n" (org-html--build-meta-info info) @@ -1746,21 +2011,34 @@ holding export options." (let ((link-up (org-trim (plist-get info :html-link-up))) (link-home (org-trim (plist-get info :html-link-home)))) (unless (and (string= link-up "") (string= link-home "")) - (format org-html-home/up-format + (format (plist-get info :html-home/up-format) (or link-up link-home) (or link-home link-up)))) ;; Preamble. (org-html--build-pre/postamble 'preamble info) ;; Document contents. - (format "<%s id=\"%s\">\n" - (nth 1 (assq 'content org-html-divs)) - (nth 2 (assq 'content org-html-divs))) + (let ((div (assq 'content (plist-get info :html-divs)))) + (format "<%s id=\"%s\">\n" (nth 1 div) (nth 2 div))) ;; Document title. - (let ((title (plist-get info :title))) - (format "

%s

\n" (org-export-data (or title "") info))) + (when (plist-get info :with-title) + (let ((title (plist-get info :title)) + (subtitle (plist-get info :subtitle)) + (html5-fancy (org-html--html5-fancy-p info))) + (when title + (format + (if html5-fancy + "
\n

%s

\n%s
" + "

%s%s

\n") + (org-export-data title info) + (if subtitle + (format + (if html5-fancy + "

%s

\n" + "\n
\n%s\n") + (org-export-data subtitle info)) + ""))))) contents - (format "\n" - (nth 1 (assq 'content org-html-divs))) + (format "\n" (nth 1 (assq 'content (plist-get info :html-divs)))) ;; Postamble. (org-html--build-pre/postamble 'postamble info) ;; Closing document. @@ -1773,9 +2051,9 @@ INFO is a plist used as a communication channel." ;;;; Anchor -(defun org-html--anchor (&optional id desc attributes) +(defun org-html--anchor (id desc attributes info) "Format a HTML anchor." - (let* ((name (and org-html-allow-name-attribute-in-anchors id)) + (let* ((name (and (plist-get info :html-allow-name-attribute-in-anchors) id)) (attributes (concat (and id (format " id=\"%s\"" id)) (and name (format " name=\"%s\"" name)) attributes))) @@ -1783,43 +2061,38 @@ INFO is a plist used as a communication channel." ;;;; Todo -(defun org-html--todo (todo) +(defun org-html--todo (todo info) "Format TODO keywords into HTML." (when todo (format "%s" (if (member todo org-done-keywords) "done" "todo") - org-html-todo-kwd-class-prefix (org-html-fix-class-name todo) + (or (plist-get info :html-todo-kwd-class-prefix) "") + (org-html-fix-class-name todo) todo))) +;;;; Priority + +(defun org-html--priority (priority _info) + "Format a priority into HTML. +PRIORITY is the character code of the priority or nil. INFO is +a plist containing export options." + (and priority (format "[%c]" priority))) + ;;;; Tags -(defun org-html--tags (tags) - "Format TAGS into HTML." +(defun org-html--tags (tags info) + "Format TAGS into HTML. +INFO is a plist containing export options." (when tags (format "%s" (mapconcat (lambda (tag) (format "%s" - (concat org-html-tag-class-prefix + (concat (plist-get info :html-tag-class-prefix) (org-html-fix-class-name tag)) tag)) tags " ")))) -;;;; Headline - -(defun* org-html-format-headline - (todo todo-type priority text tags - &key level section-number headline-label &allow-other-keys) - "Format a headline in HTML." - (let ((section-number - (when section-number - (format "%s " - level section-number))) - (todo (org-html--todo todo)) - (tags (org-html--tags tags))) - (concat section-number todo (and todo " ") text - (and tags "   ") tags))) - ;;;; Src Code (defun org-html-fontify-code (code lang) @@ -1838,6 +2111,10 @@ is the language used for CODE, as a string, or nil." (message "Cannot fontify src block (htmlize.el >= 1.34 required)") ;; Simple transcoding. (org-html-encode-plain-text code)) + ;; Case 3: plain text explicitly set + ((not org-html-htmlize-output-type) + ;; Simple transcoding. + (org-html-encode-plain-text code)) (t ;; Map language (setq lang (or (assoc-default lang org-src-lang-modes) lang)) @@ -1850,25 +2127,30 @@ is the language used for CODE, as a string, or nil." ;; Case 2: Default. Fontify code. (t ;; htmlize - (setq code (with-temp-buffer - ;; Switch to language-specific mode. - (funcall lang-mode) - (insert code) - ;; Fontify buffer. - (org-font-lock-ensure) - ;; Remove formatting on newline characters. - (save-excursion - (let ((beg (point-min)) - (end (point-max))) - (goto-char beg) - (while (progn (end-of-line) (< (point) end)) - (put-text-property (point) (1+ (point)) 'face nil) - (forward-char 1)))) - (org-src-mode) - (set-buffer-modified-p nil) - ;; Htmlize region. - (org-html-htmlize-region-for-paste - (point-min) (point-max)))) + (setq code + (let ((output-type org-html-htmlize-output-type) + (font-prefix org-html-htmlize-font-prefix)) + (with-temp-buffer + ;; Switch to language-specific mode. + (funcall lang-mode) + (insert code) + ;; Fontify buffer. + (org-font-lock-ensure) + ;; Remove formatting on newline characters. + (save-excursion + (let ((beg (point-min)) + (end (point-max))) + (goto-char beg) + (while (progn (end-of-line) (< (point) end)) + (put-text-property (point) (1+ (point)) 'face nil) + (forward-char 1)))) + (org-src-mode) + (set-buffer-modified-p nil) + ;; Htmlize region. + (let ((org-html-htmlize-output-type output-type) + (org-html-htmlize-font-prefix font-prefix)) + (org-html-htmlize-region-for-paste + (point-min) (point-max)))))) ;; Strip any enclosing
 tags.
 	  (let* ((beg (and (string-match "\\`]*>\n*" code) (match-end 0)))
 		 (end (and beg (string-match "\\'" code))))
@@ -1921,38 +2203,39 @@ a plist used as a communication channel."
 	 ;; Does the src block contain labels?
 	 (retain-labels (org-element-property :retain-labels element))
 	 ;; Does it have line numbers?
-	 (num-start (case (org-element-property :number-lines element)
-		      (continued (org-export-get-loc element info))
-		      (new 0))))
+	 (num-start (org-export-get-loc element info)))
     (org-html-do-format-code code lang refs retain-labels num-start)))
 
 
 ;;; Tables of Contents
 
-(defun org-html-toc (depth info)
+(defun org-html-toc (depth info &optional scope)
   "Build a table of contents.
-DEPTH is an integer specifying the depth of the table.  INFO is a
-plist used as a communication channel.  Return the table of
-contents as a string, or nil if it is empty."
+DEPTH is an integer specifying the depth of the table.  INFO is
+a plist used as a communication channel.  Optional argument SCOPE
+is an element defining the scope of the table.  Return the table
+of contents as a string, or nil if it is empty."
   (let ((toc-entries
 	 (mapcar (lambda (headline)
 		   (cons (org-html--format-toc-headline headline info)
 			 (org-export-get-relative-level headline info)))
-		 (org-export-collect-headlines info depth)))
-	(outer-tag (if (and (org-html-html5-p info)
-			    (plist-get info :html-html5-fancy))
-		       "nav"
-		     "div")))
+		 (org-export-collect-headlines info depth scope))))
     (when toc-entries
-      (concat (format "<%s id=\"table-of-contents\">\n" outer-tag)
-	      (format "%s\n"
-		      org-html-toplevel-hlevel
-		      (org-html--translate "Table of Contents" info)
-		      org-html-toplevel-hlevel)
-	      "
" - (org-html--toc-text toc-entries) - "
\n" - (format "\n" outer-tag))))) + (let ((toc (concat "
" + (org-html--toc-text toc-entries) + "
\n"))) + (if scope toc + (let ((outer-tag (if (org-html--html5-fancy-p info) + "nav" + "div"))) + (concat (format "<%s id=\"table-of-contents\">\n" outer-tag) + (let ((top-level (plist-get info :html-toplevel-hlevel))) + (format "%s\n" + top-level + (org-html--translate "Table of Contents" info) + top-level)) + toc + (format "\n" outer-tag)))))))) (defun org-html--toc-text (toc-entries) "Return innards of a table of contents, as a string. @@ -1967,8 +2250,7 @@ and value is its relative level, as an integer." (level (cdr entry))) (concat (let* ((cnt (- level prev-level)) - (times (if (> cnt 0) (1- cnt) (- cnt))) - rtn) + (times (if (> cnt 0) (1- cnt) (- cnt)))) (setq prev-level level) (concat (org-html--make-string @@ -2005,21 +2287,15 @@ INFO is a plist used as a communication channel." (org-export-get-tags headline info)))) (format "%s" ;; Label. - (org-export-solidify-link-text - (or (org-element-property :CUSTOM_ID headline) - (concat "sec-" - (mapconcat #'number-to-string headline-number "-")))) + (or (org-element-property :CUSTOM_ID headline) + (org-export-get-reference headline info)) ;; Body. (concat (and (not (org-export-low-level-p headline info)) (org-export-numbered-headline-p headline info) (concat (mapconcat #'number-to-string headline-number ".") ". ")) - (apply (if (not (eq org-html-format-headline-function 'ignore)) - (lambda (todo todo-type priority text tags &rest ignore) - (funcall org-html-format-headline-function - todo todo-type priority text tags)) - #'org-html-format-headline) + (apply (plist-get info :html-format-headline-function) todo todo-type priority text tags :section-number nil))))) (defun org-html-list-of-listings (info) @@ -2029,17 +2305,19 @@ of listings as a string, or nil if it is empty." (let ((lol-entries (org-export-collect-listings info))) (when lol-entries (concat "
\n" - (format "%s\n" - org-html-toplevel-hlevel - (org-html--translate "List of Listings" info) - org-html-toplevel-hlevel) + (let ((top-level (plist-get info :html-toplevel-hlevel))) + (format "%s\n" + top-level + (org-html--translate "List of Listings" info) + top-level)) "
\n
    \n" (let ((count 0) (initial-fmt (format "%s" (org-html--translate "Listing %d:" info)))) (mapconcat (lambda (entry) - (let ((label (org-element-property :name entry)) + (let ((label (and (org-element-property :name entry) + (org-export-get-reference entry info))) (title (org-trim (org-export-data (or (org-export-get-caption entry t) @@ -2048,10 +2326,12 @@ of listings as a string, or nil if it is empty." (concat "
  • " (if (not label) - (concat (format initial-fmt (incf count)) " " title) + (concat (format initial-fmt (cl-incf count)) + " " + title) (format "%s %s" - (org-export-solidify-link-text label) - (format initial-fmt (incf count)) + label + (format initial-fmt (cl-incf count)) title)) "
  • "))) lol-entries "\n")) @@ -2064,17 +2344,19 @@ of tables as a string, or nil if it is empty." (let ((lol-entries (org-export-collect-tables info))) (when lol-entries (concat "
    \n" - (format "%s\n" - org-html-toplevel-hlevel - (org-html--translate "List of Tables" info) - org-html-toplevel-hlevel) + (let ((top-level (plist-get info :html-toplevel-hlevel))) + (format "%s\n" + top-level + (org-html--translate "List of Tables" info) + top-level)) "
    \n
      \n" (let ((count 0) (initial-fmt (format "%s" (org-html--translate "Table %d:" info)))) (mapconcat (lambda (entry) - (let ((label (org-element-property :name entry)) + (let ((label (and (org-element-property :name entry) + (org-export-get-reference entry info))) (title (org-trim (org-export-data (or (org-export-get-caption entry t) @@ -2083,10 +2365,12 @@ of tables as a string, or nil if it is empty." (concat "
    • " (if (not label) - (concat (format initial-fmt (incf count)) " " title) + (concat (format initial-fmt (cl-incf count)) + " " + title) (format "%s %s" - (org-export-solidify-link-text label) - (format initial-fmt (incf count)) + label + (format initial-fmt (cl-incf count)) title)) "
    • "))) lol-entries "\n")) @@ -2097,24 +2381,24 @@ of tables as a string, or nil if it is empty." ;;;; Bold -(defun org-html-bold (bold contents info) +(defun org-html-bold (_bold contents info) "Transcode BOLD from Org to HTML. CONTENTS is the text with bold markup. INFO is a plist holding contextual information." - (format (or (cdr (assq 'bold org-html-text-markup-alist)) "%s") + (format (or (cdr (assq 'bold (plist-get info :html-text-markup-alist))) "%s") contents)) ;;;; Center Block -(defun org-html-center-block (center-block contents info) +(defun org-html-center-block (_center-block contents _info) "Transcode a CENTER-BLOCK element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." - (format "
      \n%s
      " contents)) + (format "
      \n%s
      " contents)) ;;;; Clock -(defun org-html-clock (clock contents info) +(defun org-html-clock (clock _contents _info) "Transcode a CLOCK element from Org to HTML. CONTENTS is nil. INFO is a plist used as a communication channel." @@ -2124,19 +2408,17 @@ channel."

      " org-clock-string - (org-translate-time - (org-element-property :raw-value - (org-element-property :value clock))) + (org-timestamp-translate (org-element-property :value clock)) (let ((time (org-element-property :duration clock))) (and time (format " (%s)" time))))) ;;;; Code -(defun org-html-code (code contents info) +(defun org-html-code (code _contents info) "Transcode CODE from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." - (format (or (cdr (assq 'code org-html-text-markup-alist)) "%s") + (format (or (cdr (assq 'code (plist-get info :html-text-markup-alist))) "%s") (org-html-encode-plain-text (org-element-property :value code)))) ;;;; Drawer @@ -2145,17 +2427,13 @@ information." "Transcode a DRAWER element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." - (if (functionp org-html-format-drawer-function) - (funcall org-html-format-drawer-function - (org-element-property :drawer-name drawer) - contents) - ;; If there's no user defined function: simply - ;; display contents of the drawer. - contents)) + (funcall (plist-get info :html-format-drawer-function) + (org-element-property :drawer-name drawer) + contents)) ;;;; Dynamic Block -(defun org-html-dynamic-block (dynamic-block contents info) +(defun org-html-dynamic-block (_dynamic-block contents _info) "Transcode a DYNAMIC-BLOCK element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information. See `org-export-data'." @@ -2163,7 +2441,7 @@ holding contextual information. See `org-export-data'." ;;;; Entity -(defun org-html-entity (entity contents info) +(defun org-html-entity (entity _contents _info) "Transcode an ENTITY object from Org to HTML. CONTENTS are the definition itself. INFO is a plist holding contextual information." @@ -2171,18 +2449,25 @@ contextual information." ;;;; Example Block -(defun org-html-example-block (example-block contents info) +(defun org-html-example-block (example-block _contents info) "Transcode a EXAMPLE-BLOCK element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." - (if (org-export-read-attribute :attr_html example-block :textarea) - (org-html--textarea-block example-block) - (format "
      \n%s
      " - (org-html-format-code example-block info)))) + (let ((attributes (org-export-read-attribute :attr_html example-block))) + (if (plist-get attributes :textarea) + (org-html--textarea-block example-block) + (format "
      \n%s
      " + (let* ((name (org-element-property :name example-block)) + (a (org-html--make-attribute-string + (if (or (not name) (plist-member attributes :id)) + attributes + (plist-put attributes :id name))))) + (if (org-string-nw-p a) (concat " " a) "")) + (org-html-format-code example-block info))))) ;;;; Export Snippet -(defun org-html-export-snippet (export-snippet contents info) +(defun org-html-export-snippet (export-snippet _contents _info) "Transcode a EXPORT-SNIPPET object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." @@ -2191,7 +2476,7 @@ information." ;;;; Export Block -(defun org-html-export-block (export-block contents info) +(defun org-html-export-block (export-block _contents _info) "Transcode a EXPORT-BLOCK element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (when (string= (org-element-property :type export-block) "HTML") @@ -2199,7 +2484,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." ;;;; Fixed Width -(defun org-html-fixed-width (fixed-width contents info) +(defun org-html-fixed-width (fixed-width _contents _info) "Transcode a FIXED-WIDTH element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (format "
      \n%s
      " @@ -2209,135 +2494,116 @@ CONTENTS is nil. INFO is a plist holding contextual information." ;;;; Footnote Reference -(defun org-html-footnote-reference (footnote-reference contents info) +(defun org-html-footnote-reference (footnote-reference _contents info) "Transcode a FOOTNOTE-REFERENCE element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (concat ;; Insert separator between two footnotes in a row. (let ((prev (org-export-get-previous-element footnote-reference info))) (when (eq (org-element-type prev) 'footnote-reference) - org-html-footnote-separator)) - (cond - ((not (org-export-footnote-first-reference-p footnote-reference info)) - (org-html-format-footnote-reference - (org-export-get-footnote-number footnote-reference info) - "IGNORED" 100)) - ;; Inline definitions are secondary strings. - ((eq (org-element-property :type footnote-reference) 'inline) - (org-html-format-footnote-reference - (org-export-get-footnote-number footnote-reference info) - "IGNORED" 1)) - ;; Non-inline footnotes definitions are full Org data. - (t (org-html-format-footnote-reference - (org-export-get-footnote-number footnote-reference info) - "IGNORED" 1))))) + (plist-get info :html-footnote-separator))) + (let* ((n (org-export-get-footnote-number footnote-reference info)) + (id (format "fnr.%d%s" + n + (if (org-export-footnote-first-reference-p + footnote-reference info) + "" + ".100")))) + (format + (plist-get info :html-footnote-format) + (org-html--anchor + id n (format " class=\"footref\" href=\"#fn.%d\"" n) info))))) ;;;; Headline -(defun org-html-format-headline--wrap - (headline info &optional format-function &rest extra-keys) - "Transcode a HEADLINE element from Org to HTML. -CONTENTS holds the contents of the headline. INFO is a plist -holding contextual information." - (let* ((level (+ (org-export-get-relative-level headline info) - (1- org-html-toplevel-hlevel))) - (headline-number (org-export-get-headline-number headline info)) - (section-number (and (not (org-export-low-level-p headline info)) - (org-export-numbered-headline-p headline info) - (mapconcat 'number-to-string - headline-number "."))) - (todo (and (plist-get info :with-todo-keywords) - (let ((todo (org-element-property :todo-keyword headline))) - (and todo (org-export-data todo info))))) - (todo-type (and todo (org-element-property :todo-type headline))) - (priority (and (plist-get info :with-priority) - (org-element-property :priority headline))) - (text (org-export-data (org-element-property :title headline) info)) - (tags (and (plist-get info :with-tags) - (org-export-get-tags headline info))) - (headline-label (or (org-element-property :CUSTOM_ID headline) - (concat "sec-" (mapconcat 'number-to-string - headline-number "-")))) - (format-function - (cond ((functionp format-function) format-function) - ((not (eq org-html-format-headline-function 'ignore)) - (lambda (todo todo-type priority text tags &rest ignore) - (funcall org-html-format-headline-function - todo todo-type priority text tags))) - (t 'org-html-format-headline)))) - (apply format-function - todo todo-type priority text tags - :headline-label headline-label :level level - :section-number section-number extra-keys))) - (defun org-html-headline (headline contents info) "Transcode a HEADLINE element from Org to HTML. CONTENTS holds the contents of the headline. INFO is a plist holding contextual information." (unless (org-element-property :footnote-section-p headline) - (let* ((contents (or contents "")) - (numberedp (org-export-numbered-headline-p headline info)) - (level (org-export-get-relative-level headline info)) - (text (org-export-data (org-element-property :title headline) info)) - (todo (and (plist-get info :with-todo-keywords) - (let ((todo (org-element-property :todo-keyword headline))) - (and todo (org-export-data todo info))))) - (todo-type (and todo (org-element-property :todo-type headline))) - (tags (and (plist-get info :with-tags) - (org-export-get-tags headline info))) - (priority (and (plist-get info :with-priority) - (org-element-property :priority headline))) - (section-number (mapconcat #'number-to-string - (org-export-get-headline-number - headline info) "-")) - (ids (delq 'nil - (list (org-element-property :CUSTOM_ID headline) - (concat "sec-" section-number) - (org-element-property :ID headline)))) - (preferred-id (car ids)) - (extra-ids (mapconcat - (lambda (id) - (org-html--anchor - (org-export-solidify-link-text - (if (org-uuidgen-p id) (concat "ID-" id) id)))) - (cdr ids) "")) - ;; Create the headline text. - (full-text (org-html-format-headline--wrap headline info))) + (let* ((numberedp (org-export-numbered-headline-p headline info)) + (numbers (org-export-get-headline-number headline info)) + (level (+ (org-export-get-relative-level headline info) + (1- (plist-get info :html-toplevel-hlevel)))) + (todo (and (plist-get info :with-todo-keywords) + (let ((todo (org-element-property :todo-keyword headline))) + (and todo (org-export-data todo info))))) + (todo-type (and todo (org-element-property :todo-type headline))) + (priority (and (plist-get info :with-priority) + (org-element-property :priority headline))) + (text (org-export-data (org-element-property :title headline) info)) + (tags (and (plist-get info :with-tags) + (org-export-get-tags headline info))) + (full-text (funcall (plist-get info :html-format-headline-function) + todo todo-type priority text tags info)) + (contents (or contents "")) + (ids (delq nil + (list (org-element-property :CUSTOM_ID headline) + (org-export-get-reference headline info) + (org-element-property :ID headline)))) + (preferred-id (car ids)) + (extra-ids + (mapconcat + (lambda (id) + (org-html--anchor + (if (org-uuidgen-p id) (concat "ID-" id) id) + nil nil info)) + (cdr ids) ""))) (if (org-export-low-level-p headline info) - ;; This is a deep sub-tree: export it as a list item. - (let* ((type (if numberedp 'ordered 'unordered)) - (itemized-body - (org-html-format-list-item - contents type nil info nil - (concat (org-html--anchor preferred-id) extra-ids - full-text)))) - (concat - (and (org-export-first-sibling-p headline info) - (org-html-begin-plain-list type)) - itemized-body - (and (org-export-last-sibling-p headline info) - (org-html-end-plain-list type)))) - ;; Standard headline. Export it as a section. - (let ((extra-class (org-element-property :HTML_CONTAINER_CLASS headline)) - (level1 (+ level (1- org-html-toplevel-hlevel))) - (first-content (car (org-element-contents headline)))) - (format "<%s id=\"%s\" class=\"%s\">%s%s\n" - (org-html--container headline info) - (format "outline-container-%s" - (or (org-element-property :CUSTOM_ID headline) - (concat "sec-" section-number))) - (concat (format "outline-%d" level1) (and extra-class " ") - extra-class) - (format "\n%s%s\n" - level1 preferred-id extra-ids full-text level1) - ;; When there is no section, pretend there is an - ;; empty one to get the correct
      %s%s\n" + (org-html--container headline info) + (concat "outline-container-" + (org-export-get-reference headline info)) + (concat (format "outline-%d" level) + (and extra-class " ") + extra-class) + (format "\n%s%s\n" + level + preferred-id + extra-ids + (concat + (and numberedp + (format + "%s " + level + (mapconcat #'number-to-string numbers "."))) + full-text) + level) + ;; When there is no section, pretend there is an + ;; empty one to get the correct
      %s" lang label code))) ;;;; Inlinetask -(defun org-html-format-section (text class &optional id) - "Format a section with TEXT into a HTML div with CLASS and ID." - (let ((extra (concat (when id (format " id=\"%s\"" id))))) - (concat (format "
      \n" class extra) text "
      \n"))) - (defun org-html-inlinetask (inlinetask contents info) "Transcode an INLINETASK element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." - (cond - ;; If `org-html-format-inlinetask-function' is not 'ignore, call it - ;; with appropriate arguments. - ((not (eq org-html-format-inlinetask-function 'ignore)) - (let ((format-function - (function* - (lambda (todo todo-type priority text tags - &key contents &allow-other-keys) - (funcall org-html-format-inlinetask-function - todo todo-type priority text tags contents))))) - (org-html-format-headline--wrap - inlinetask info format-function :contents contents))) - ;; Otherwise, use a default template. - (t (format "
      \n%s%s\n%s
      " - (org-html-format-headline--wrap inlinetask info) - (org-html-close-tag "br" nil info) - contents)))) + (let* ((todo (and (plist-get info :with-todo-keywords) + (let ((todo (org-element-property :todo-keyword inlinetask))) + (and todo (org-export-data todo info))))) + (todo-type (and todo (org-element-property :todo-type inlinetask))) + (priority (and (plist-get info :with-priority) + (org-element-property :priority inlinetask))) + (text (org-export-data (org-element-property :title inlinetask) info)) + (tags (and (plist-get info :with-tags) + (org-export-get-tags inlinetask info)))) + (funcall (plist-get info :html-format-inlinetask-function) + todo todo-type priority text tags contents info))) + +(defun org-html-format-inlinetask-default-function + (todo todo-type priority text tags contents info) + "Default format function for a inlinetasks. +See `org-html-format-inlinetask-function' for details." + (format "
      \n%s%s\n%s
      " + (org-html-format-headline-default-function + todo todo-type priority text tags info) + (org-html-close-tag "br" nil info) + contents)) ;;;; Italic -(defun org-html-italic (italic contents info) +(defun org-html-italic (_italic contents info) "Transcode ITALIC from Org to HTML. CONTENTS is the text with italic markup. INFO is a plist holding contextual information." - (format (or (cdr (assq 'italic org-html-text-markup-alist)) "%s") contents)) + (format + (or (cdr (assq 'italic (plist-get info :html-text-markup-alist))) "%s") + contents)) ;;;; Item -(defun org-html-checkbox (checkbox) - "Format CHECKBOX into HTML." - (case checkbox (on "[X]") - (off "[ ]") - (trans "[-]") - (t ""))) +(defun org-html-checkbox (checkbox info) + "Format CHECKBOX into HTML. +INFO is a plist holding contextual information. See +`org-html-checkbox-type' for customization options." + (cdr (assq checkbox + (cdr (assq (plist-get info :html-checkbox-type) + org-html-checkbox-types))))) (defun org-html-format-list-item (contents type checkbox info - &optional term-counter-id - headline) + &optional term-counter-id + headline) "Format a list item into HTML." - (let ((checkbox (concat (org-html-checkbox checkbox) (and checkbox " "))) + (let ((class (if checkbox + (format " class=\"%s\"" + (symbol-name checkbox)) "")) + (checkbox (concat (org-html-checkbox checkbox info) + (and checkbox " "))) (br (org-html-close-tag "br" nil info))) (concat - (case type - (ordered + (pcase type + (`ordered (let* ((counter term-counter-id) (extra (if counter (format " value=\"%s\"" counter) ""))) (concat - (format "" extra) + (format "" class extra) (when headline (concat headline br))))) - (unordered + (`unordered (let* ((id term-counter-id) (extra (if id (format " id=\"%s\"" id) ""))) (concat - (format "" extra) + (format "" class extra) (when headline (concat headline br))))) - (descriptive + (`descriptive (let* ((term term-counter-id)) (setq term (or term "(no term)")) ;; Check-boxes in descriptive lists are associated to tag. - (concat (format "
      %s
      " - (concat checkbox term)) + (concat (format "%s" + class (concat checkbox term)) "
      ")))) (unless (eq type 'descriptive) checkbox) - contents - (case type - (ordered "") - (unordered "") - (descriptive "
      "))))) + (and contents (org-trim contents)) + (pcase type + (`ordered "") + (`unordered "") + (`descriptive ""))))) (defun org-html-item (item contents info) "Transcode an ITEM element from Org to HTML. @@ -2457,7 +2735,7 @@ contextual information." ;;;; Keyword -(defun org-html-keyword (keyword contents info) +(defun org-html-keyword (keyword _contents info) "Transcode a KEYWORD element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (let ((key (org-element-property :key keyword)) @@ -2465,13 +2743,13 @@ CONTENTS is nil. INFO is a plist holding contextual information." (cond ((string= key "HTML") value) ((string= key "TOC") - (let ((value (downcase value))) + (let ((case-fold-search t)) (cond ((string-match "\\" value) - (let ((depth (or (and (string-match "[0-9]+" value) - (string-to-number (match-string 0 value))) - (plist-get info :with-toc)))) - (org-html-toc depth info))) + (let ((depth (and (string-match "\\<[0-9]+\\>" value) + (string-to-number (match-string 0 value)))) + (localp (string-match-p "\\" value))) + (org-html-toc depth info (and localp keyword)))) ((string= "listings" value) (org-html-list-of-listings info)) ((string= "tables" value) (org-html-list-of-tables info)))))))) @@ -2479,10 +2757,11 @@ CONTENTS is nil. INFO is a plist holding contextual information." (defun org-html-format-latex (latex-frag processing-type info) "Format a LaTeX fragment LATEX-FRAG into HTML. -PROCESSING-TYPE designates the tool used for conversion. It is -a symbol among `mathjax', `dvipng', `imagemagick', `verbatim' nil -and t. See `org-html-with-latex' for more information. INFO is -a plist containing export properties." +PROCESSING-TYPE designates the tool used for conversion. It can +be `mathjax', `verbatim', nil, t or symbols in +`org-preview-latex-process-alist', e.g., `dvipng', `dvisvgm' or +`imagemagick'. See `org-html-with-latex' for more information. +INFO is a plist containing export properties." (let ((cache-relpath "") (cache-dir "")) (unless (eq processing-type 'mathjax) (let ((bfn (or (buffer-file-name) @@ -2497,7 +2776,7 @@ a plist containing export properties." "\n") "\n"))))) (setq cache-relpath - (concat "ltxpng/" + (concat (file-name-as-directory org-preview-latex-image-directory) (file-name-sans-extension (file-name-nondirectory bfn))) cache-dir (file-name-directory bfn)) @@ -2507,51 +2786,51 @@ a plist containing export properties." (setq latex-frag (concat latex-header latex-frag)))) (with-temp-buffer (insert latex-frag) - (org-format-latex cache-relpath cache-dir nil "Creating LaTeX Image..." - nil nil processing-type) + (org-format-latex cache-relpath nil nil cache-dir nil + "Creating LaTeX Image..." nil processing-type) (buffer-string)))) -(defun org-html-latex-environment (latex-environment contents info) +(defun org-html-latex-environment (latex-environment _contents info) "Transcode a LATEX-ENVIRONMENT element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (let ((processing-type (plist-get info :with-latex)) (latex-frag (org-remove-indentation (org-element-property :value latex-environment))) (attributes (org-export-read-attribute :attr_html latex-environment))) - (case processing-type - ((t mathjax) - (org-html-format-latex latex-frag 'mathjax info)) - ((dvipng imagemagick) - (let ((formula-link - (org-html-format-latex latex-frag processing-type info))) - (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link)) - ;; Do not provide a caption or a name to be consistent with - ;; `mathjax' handling. - (org-html--wrap-image - (org-html--format-image - (match-string 1 formula-link) attributes info) info)))) - (t latex-frag)))) + (cond + ((memq processing-type '(t mathjax)) + (org-html-format-latex latex-frag 'mathjax info)) + ((assq processing-type org-preview-latex-process-alist) + (let ((formula-link + (org-html-format-latex latex-frag processing-type info))) + (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link)) + ;; Do not provide a caption or a name to be consistent with + ;; `mathjax' handling. + (org-html--wrap-image + (org-html--format-image + (match-string 1 formula-link) attributes info) info)))) + (t latex-frag)))) ;;;; Latex Fragment -(defun org-html-latex-fragment (latex-fragment contents info) +(defun org-html-latex-fragment (latex-fragment _contents info) "Transcode a LATEX-FRAGMENT object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (let ((latex-frag (org-element-property :value latex-fragment)) (processing-type (plist-get info :with-latex))) - (case processing-type - ((t mathjax) - (org-html-format-latex latex-frag 'mathjax info)) - ((dvipng imagemagick) - (let ((formula-link - (org-html-format-latex latex-frag processing-type info))) - (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link)) - (org-html--format-image (match-string 1 formula-link) nil info)))) - (t latex-frag)))) + (cond + ((memq processing-type '(t mathjax)) + (org-html-format-latex latex-frag 'mathjax info)) + ((assq processing-type org-preview-latex-process-alist) + (let ((formula-link + (org-html-format-latex latex-frag processing-type info))) + (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link)) + (org-html--format-image (match-string 1 formula-link) nil info)))) + (t latex-frag)))) ;;;; Line Break -(defun org-html-line-break (line-break contents info) +(defun org-html-line-break (_line-break _contents info) "Transcode a LINE-BREAK object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (concat (org-html-close-tag "br" nil info) "\n")) @@ -2565,19 +2844,20 @@ inline image when it has no description and targets an image file (see `org-html-inline-image-rules' for more information), or if its description is a single link targeting an image file." (if (not (org-element-contents link)) - (org-export-inline-image-p link org-html-inline-image-rules) + (org-export-inline-image-p + link (plist-get info :html-inline-image-rules)) (not (let ((link-count 0)) (org-element-map (org-element-contents link) (cons 'plain-text org-element-all-objects) (lambda (obj) - (case (org-element-type obj) - (plain-text (org-string-nw-p obj)) - (link (if (= link-count 1) t - (incf link-count) - (not (org-export-inline-image-p - obj org-html-inline-image-rules)))) - (otherwise t))) + (pcase (org-element-type obj) + (`plain-text (org-string-nw-p obj)) + (`link (if (= link-count 1) t + (cl-incf link-count) + (not (org-export-inline-image-p + obj (plist-get info :html-inline-image-rules))))) + (_ t))) info t))))) (defvar org-html-standalone-image-predicate) @@ -2599,9 +2879,9 @@ further. For example, to check for only captioned standalone images, set it to: (lambda (paragraph) (org-element-property :caption paragraph))" - (let ((paragraph (case (org-element-type element) - (paragraph element) - (link (org-export-get-parent element))))) + (let ((paragraph (pcase (org-element-type element) + (`paragraph element) + (`link (org-export-get-parent element))))) (and (eq (org-element-type paragraph) 'paragraph) (or (not (fboundp 'org-html-standalone-image-predicate)) (funcall org-html-standalone-image-predicate paragraph)) @@ -2609,19 +2889,18 @@ images, set it to: (let ((link-count 0)) (org-element-map (org-element-contents paragraph) (cons 'plain-text org-element-all-objects) - #'(lambda (obj) - (when (case (org-element-type obj) - (plain-text (org-string-nw-p obj)) - (link (or (> (incf link-count) 1) - (not (org-html-inline-image-p obj info)))) - (otherwise t)) - (throw 'exit nil))) + (lambda (obj) + (when (pcase (org-element-type obj) + (`plain-text (org-string-nw-p obj)) + (`link (or (> (cl-incf link-count) 1) + (not (org-html-inline-image-p obj info)))) + (_ t)) + (throw 'exit nil))) info nil 'link) (= link-count 1)))))) (defun org-html-link (link desc info) "Transcode a LINK object from Org to HTML. - DESC is the description part of the link, or the empty string. INFO is a plist holding contextual information. See `org-export-data'." @@ -2629,56 +2908,49 @@ INFO is a plist holding contextual information. See (org-trim (plist-get info :html-link-home)))) (use-abs-url (plist-get info :html-link-use-abs-url)) (link-org-files-as-html-maybe - (function - (lambda (raw-path info) - "Treat links to `file.org' as links to `file.html', if needed. - See `org-html-link-org-files-as-html'." - (cond - ((and org-html-link-org-files-as-html - (string= ".org" - (downcase (file-name-extension raw-path ".")))) - (concat (file-name-sans-extension raw-path) "." - (plist-get info :html-extension))) - (t raw-path))))) + (lambda (raw-path info) + ;; Treat links to `file.org' as links to `file.html', if + ;; needed. See `org-html-link-org-files-as-html'. + (cond + ((and (plist-get info :html-link-org-files-as-html) + (string= ".org" + (downcase (file-name-extension raw-path ".")))) + (concat (file-name-sans-extension raw-path) "." + (plist-get info :html-extension))) + (t raw-path)))) (type (org-element-property :type link)) (raw-path (org-element-property :path link)) ;; Ensure DESC really exists, or set it to nil. (desc (org-string-nw-p desc)) (path (cond - ((member type '("http" "https" "ftp" "mailto")) - (org-link-escape - (org-link-unescape - (concat type ":" raw-path)) org-link-escape-chars-browser)) + ((member type '("http" "https" "ftp" "mailto" "news")) + (url-encode-url (org-link-unescape (concat type ":" raw-path)))) ((string= type "file") ;; Treat links to ".org" files as ".html", if needed. (setq raw-path (funcall link-org-files-as-html-maybe raw-path info)) ;; If file path is absolute, prepend it with protocol - ;; component - "file:". + ;; component - "file://". (cond ((file-name-absolute-p raw-path) - (setq raw-path (concat "file:" raw-path))) + (setq raw-path (org-export-file-uri raw-path))) ((and home use-abs-url) (setq raw-path (concat (file-name-as-directory home) raw-path)))) ;; Add search option, if any. A search option can be - ;; relative to a custom-id or a headline title. Any other - ;; option is ignored. + ;; relative to a custom-id, a headline title, a name or + ;; a target. (let ((option (org-element-property :search-option link))) (cond ((not option) raw-path) - ((eq (aref option 0) ?#) (concat raw-path option)) - ;; External fuzzy link: try to resolve it if path - ;; belongs to current project, if any. - ((eq (aref option 0) ?*) - (concat - raw-path - (let ((numbers - (org-publish-resolve-external-fuzzy-link - (org-element-property :path link) option))) - (and numbers (concat "#sec-" - (mapconcat 'number-to-string - numbers "-")))))) - (t raw-path)))) + ;; Since HTML back-end use custom-id value as-is, + ;; resolving is them is trivial. + ((eq (string-to-char option) ?#) (concat raw-path option)) + (t + (concat raw-path + "#" + (org-publish-resolve-external-link + option + (org-element-property :path link))))))) (t raw-path))) ;; Extract attributes from parent's paragraph. HACK: Only do ;; this for the first link in parent (inner image link for @@ -2695,12 +2967,14 @@ INFO is a plist holding contextual information. See (org-export-read-attribute :attr_html parent)))) (attributes (let ((attr (org-html--make-attribute-string attributes-plist))) - (if (org-string-nw-p attr) (concat " " attr) ""))) - protocol) + (if (org-string-nw-p attr) (concat " " attr) "")))) (cond + ;; Link type is handled by a special function. + ((org-export-custom-protocol-maybe link desc 'html)) ;; Image file. - ((and org-html-inline-images - (org-export-inline-image-p link org-html-inline-image-rules)) + ((and (plist-get info :html-inline-images) + (org-export-inline-image-p + link (plist-get info :html-inline-image-rules))) (org-html--format-image path attributes-plist info)) ;; Radio target: Transcode target's contents and use them as ;; link's description. @@ -2708,18 +2982,18 @@ INFO is a plist holding contextual information. See (let ((destination (org-export-resolve-radio-link link info))) (if (not destination) desc (format "%s" - (org-export-solidify-link-text - (org-element-property :value destination)) - attributes desc)))) + (org-export-get-reference destination info) + attributes + desc)))) ;; Links pointing to a headline: Find destination and build ;; appropriate referencing command. ((member type '("custom-id" "fuzzy" "id")) (let ((destination (if (string= type "fuzzy") (org-export-resolve-fuzzy-link link info) (org-export-resolve-id-link link info)))) - (case (org-element-type destination) + (pcase (org-element-type destination) ;; ID link points to an external file. - (plain-text + (`plain-text (let ((fragment (concat "ID-" path)) ;; Treat links to ".org" files as ".html", if needed. (path (funcall link-org-files-as-html-maybe @@ -2727,86 +3001,87 @@ INFO is a plist holding contextual information. See (format "%s" path fragment attributes (or desc destination)))) ;; Fuzzy link points nowhere. - ((nil) + (`nil (format "%s" (or desc (org-export-data (org-element-property :raw-link link) info)))) ;; Link points to a headline. - (headline - (let ((href - ;; What href to use? - (cond - ;; Case 1: Headline is linked via it's CUSTOM_ID - ;; property. Use CUSTOM_ID. - ((string= type "custom-id") - (org-element-property :CUSTOM_ID destination)) - ;; Case 2: Headline is linked via it's ID property - ;; or through other means. Use the default href. - ((member type '("id" "fuzzy")) - (format "sec-%s" - (mapconcat 'number-to-string - (org-export-get-headline-number - destination info) "-"))) - (t (error "Shouldn't reach here")))) + (`headline + (let ((href (or (org-element-property :CUSTOM_ID destination) + (org-export-get-reference destination info))) ;; What description to use? (desc ;; Case 1: Headline is numbered and LINK has no ;; description. Display section number. (if (and (org-export-numbered-headline-p destination info) (not desc)) - (mapconcat 'number-to-string + (mapconcat #'number-to-string (org-export-get-headline-number destination info) ".") ;; Case 2: Either the headline is un-numbered or ;; LINK has a custom description. Display LINK's ;; description or headline's title. - (or desc (org-export-data (org-element-property - :title destination) info))))) - (format "%s" - (org-export-solidify-link-text href) attributes desc))) + (or desc + (org-export-data + (org-element-property :title destination) info))))) + (format "%s" href attributes desc))) ;; Fuzzy link points to a target or an element. - (t - (let* ((path (org-export-solidify-link-text path)) - (org-html-standalone-image-predicate 'org-html--has-caption-p) + (_ + (let* ((ref (org-export-get-reference destination info)) + (org-html-standalone-image-predicate + #'org-html--has-caption-p) (number (cond (desc nil) ((org-html-standalone-image-p destination info) (org-export-get-ordinal (org-element-map destination 'link - 'identity info t) + #'identity info t) info 'link 'org-html-standalone-image-p)) (t (org-export-get-ordinal destination info nil 'org-html--has-caption-p)))) (desc (cond (desc) ((not number) "No description for this link") ((numberp number) (number-to-string number)) - (t (mapconcat 'number-to-string number "."))))) - (format "%s" path attributes desc)))))) + (t (mapconcat #'number-to-string number "."))))) + (format "%s" ref attributes desc)))))) ;; Coderef: replace link with the reference name or the ;; equivalent line number. ((string= type "coderef") - (let ((fragment (concat "coderef-" path))) - (format "%s" + (let ((fragment (concat "coderef-" (org-html-encode-plain-text path)))) + (format "%s" fragment - (org-trim - (format (concat "class=\"coderef\"" - " onmouseover=\"CodeHighlightOn(this, '%s');\"" - " onmouseout=\"CodeHighlightOff(this, '%s');\"") - fragment fragment)) + (format "class=\"coderef\" onmouseover=\"CodeHighlightOn(this, \ +'%s');\" onmouseout=\"CodeHighlightOff(this, '%s');\"" + fragment fragment) attributes (format (org-export-get-coderef-format path desc) (org-export-resolve-coderef path info))))) - ;; Link type is handled by a special function. - ((functionp (setq protocol (nth 2 (assoc type org-link-protocols)))) - (funcall protocol (org-link-unescape path) desc 'html)) ;; External link with a description part. - ((and path desc) (format "%s" path attributes desc)) + ((and path desc) (format "%s" + (org-html-encode-plain-text path) + attributes + desc)) ;; External link without a description part. - (path (format "%s" path attributes path)) + (path (let ((path (org-html-encode-plain-text path))) + (format "%s" + path + attributes + (org-link-unescape path)))) ;; No path, only description. Try to do something useful. (t (format "%s" desc))))) +;;;; Node Property + +(defun org-html-node-property (node-property _contents _info) + "Transcode a NODE-PROPERTY element from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual +information." + (format "%s:%s" + (org-element-property :key node-property) + (let ((value (org-element-property :value node-property))) + (if value (concat " " value) "")))) + ;;;; Paragraph (defun org-html-paragraph (paragraph contents info) @@ -2815,13 +3090,19 @@ CONTENTS is the contents of the paragraph, as a string. INFO is the plist used as a communication channel." (let* ((parent (org-export-get-parent paragraph)) (parent-type (org-element-type parent)) - (style '((footnote-definition " class=\"footpara\""))) - (extra (or (cadr (assoc parent-type style)) ""))) + (style '((footnote-definition " class=\"footpara\"") + (org-data " class=\"footpara\""))) + (attributes (org-html--make-attribute-string + (org-export-read-attribute :attr_html paragraph))) + (extra (or (cadr (assq parent-type style)) ""))) (cond - ((and (eq (org-element-type parent) 'item) - (= (org-element-property :begin paragraph) - (org-element-property :contents-begin parent))) - ;; Leading paragraph in a list item have no tags. + ((and (eq parent-type 'item) + (not (org-export-get-previous-element paragraph info)) + (let ((followers (org-export-get-next-element paragraph info 2))) + (and (not (cdr followers)) + (memq (org-element-type (car followers)) '(nil plain-list))))) + ;; First paragraph in an item has no tag if it is alone or + ;; followed, at most, by a sub-list. contents) ((org-html-standalone-image-p paragraph info) ;; Standalone image. @@ -2829,20 +3110,24 @@ the plist used as a communication channel." (let ((raw (org-export-data (org-export-get-caption paragraph) info)) (org-html-standalone-image-predicate - 'org-html--has-caption-p)) + #'org-html--has-caption-p)) (if (not (org-string-nw-p raw)) raw - (concat - "" - (format (org-html--translate "Figure %d:" info) - (org-export-get-ordinal - (org-element-map paragraph 'link - 'identity info t) - info nil 'org-html-standalone-image-p)) - " " raw)))) - (label (org-element-property :name paragraph))) + (concat "" + (format (org-html--translate "Figure %d:" info) + (org-export-get-ordinal + (org-element-map paragraph 'link + #'identity info t) + info nil #'org-html-standalone-image-p)) + " " + raw)))) + (label (and (org-element-property :name paragraph) + (org-export-get-reference paragraph info)))) (org-html--wrap-image contents info caption label))) ;; Regular paragraph. - (t (format "\n%s

      " extra contents))))) + (t (format "\n%s

      " + (if (org-string-nw-p attributes) + (concat " " attributes) "") + extra contents))))) ;;;; Plain List @@ -2852,26 +3137,25 @@ the plist used as a communication channel." "Insert the beginning of the HTML list depending on TYPE. When ARG1 is a string, use it as the start parameter for ordered lists." - (case type - (ordered + (pcase type + (`ordered (format "
        " (if arg1 (format " start=\"%d\"" arg1) ""))) - (unordered "
          ") - (descriptive "
          "))) + (`unordered "
            ") + (`descriptive "
            "))) (defun org-html-end-plain-list (type) "Insert the end of the HTML list depending on TYPE." - (case type - (ordered "
      ") - (unordered "
    ") - (descriptive ""))) + (pcase type + (`ordered "") + (`unordered "
") + (`descriptive ""))) -(defun org-html-plain-list (plain-list contents info) +(defun org-html-plain-list (plain-list contents _info) "Transcode a PLAIN-LIST element from Org to HTML. CONTENTS is the contents of the list. INFO is a plist holding contextual information." - (let* (arg1 ;; (assoc :counter (org-element-map plain-list 'item - (type (org-element-property :type plain-list))) + (let ((type (org-element-property :type plain-list))) (format "%s\n%s%s" (org-html-begin-plain-list type) contents (org-html-end-plain-list type)))) @@ -2880,22 +3164,16 @@ contextual information." (defun org-html-convert-special-strings (string) "Convert special characters in STRING to HTML." - (let ((all org-html-special-string-regexps) - e a re rpl start) - (while (setq a (pop all)) - (setq re (car a) rpl (cdr a) start 0) - (while (string-match re string start) - (setq string (replace-match rpl t nil string)))) - string)) + (dolist (a org-html-special-string-regexps string) + (let ((re (car a)) + (rpl (cdr a))) + (setq string (replace-regexp-in-string re rpl string t))))) (defun org-html-encode-plain-text (text) "Convert plain text characters from TEXT to HTML equivalent. Possible conversions are set in `org-html-protect-char-alist'." - (mapc - (lambda (pair) - (setq text (replace-regexp-in-string (car pair) (cdr pair) text t t))) - org-html-protect-char-alist) - text) + (dolist (pair org-html-protect-char-alist text) + (setq text (replace-regexp-in-string (car pair) (cdr pair) text t t)))) (defun org-html-plain-text (text info) "Transcode a TEXT string from Org to HTML. @@ -2923,60 +3201,52 @@ contextual information." ;; Planning -(defun org-html-planning (planning contents info) +(defun org-html-planning (planning _contents info) "Transcode a PLANNING element from Org to HTML. CONTENTS is nil. INFO is a plist used as a communication channel." - (let ((span-fmt "%s %s")) - (format - "

%s

" - (mapconcat - 'identity - (delq nil - (list - (let ((closed (org-element-property :closed planning))) - (when closed - (format span-fmt org-closed-string - (org-translate-time - (org-element-property :raw-value closed))))) - (let ((deadline (org-element-property :deadline planning))) - (when deadline - (format span-fmt org-deadline-string - (org-translate-time - (org-element-property :raw-value deadline))))) - (let ((scheduled (org-element-property :scheduled planning))) - (when scheduled - (format span-fmt org-scheduled-string - (org-translate-time - (org-element-property :raw-value scheduled))))))) - " ")))) + (format + "

%s

" + (org-trim + (mapconcat + (lambda (pair) + (let ((timestamp (cdr pair))) + (when timestamp + (let ((string (car pair))) + (format "%s \ +%s " + string + (org-html-plain-text (org-timestamp-translate timestamp) + info)))))) + `((,org-closed-string . ,(org-element-property :closed planning)) + (,org-deadline-string . ,(org-element-property :deadline planning)) + (,org-scheduled-string . ,(org-element-property :scheduled planning))) + "")))) ;;;; Property Drawer -(defun org-html-property-drawer (property-drawer contents info) +(defun org-html-property-drawer (_property-drawer contents _info) "Transcode a PROPERTY-DRAWER element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual -information." - ;; The property drawer isn't exported but we want separating blank - ;; lines nonetheless. - "") +CONTENTS holds the contents of the drawer. INFO is a plist +holding contextual information." + (and (org-string-nw-p contents) + (format "
\n%s
" contents))) ;;;; Quote Block -(defun org-html-quote-block (quote-block contents info) +(defun org-html-quote-block (quote-block contents _info) "Transcode a QUOTE-BLOCK element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." - (format "
\n%s
" contents)) - -;;;; Quote Section - -(defun org-html-quote-section (quote-section contents info) - "Transcode a QUOTE-SECTION element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (let ((value (org-remove-indentation - (org-element-property :value quote-section)))) - (when value (format "
\n%s
" value)))) + (format "\n%s" + (let* ((name (org-element-property :name quote-block)) + (attributes (org-export-read-attribute :attr_html quote-block)) + (a (org-html--make-attribute-string + (if (or (not name) (plist-member attributes :id)) + attributes + (plist-put attributes :id name))))) + (if (org-string-nw-p a) (concat " " a) "")) + contents)) ;;;; Section @@ -2989,16 +3259,19 @@ holding contextual information." (if (not parent) contents ;; Get div's class and id references. (let* ((class-num (+ (org-export-get-relative-level parent info) - (1- org-html-toplevel-hlevel))) + (1- (plist-get info :html-toplevel-hlevel)))) (section-number - (mapconcat - 'number-to-string - (org-export-get-headline-number parent info) "-"))) + (and (org-export-numbered-headline-p parent info) + (mapconcat + #'number-to-string + (org-export-get-headline-number parent info) "-")))) ;; Build return value. (format "
\n%s
" class-num - (or (org-element-property :CUSTOM_ID parent) section-number) - contents))))) + (or (org-element-property :CUSTOM_ID parent) + section-number + (org-export-get-reference parent info)) + (or contents "")))))) ;;;; Radio Target @@ -3006,9 +3279,8 @@ holding contextual information." "Transcode a RADIO-TARGET object from Org to HTML. TEXT is the text of the target. INFO is a plist holding contextual information." - (let ((id (org-export-solidify-link-text - (org-element-property :value radio-target)))) - (org-html--anchor id text))) + (let ((ref (org-export-get-reference radio-target info))) + (org-html--anchor ref text nil info))) ;;;; Special Block @@ -3016,52 +3288,61 @@ contextual information." "Transcode a SPECIAL-BLOCK element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." - (let* ((block-type (downcase - (org-element-property :type special-block))) - (contents (or contents "")) - (html5-fancy (and (org-html-html5-p info) - (plist-get info :html-html5-fancy) - (member block-type org-html-html5-elements))) - (attributes (org-export-read-attribute :attr_html special-block))) + (let* ((block-type (org-element-property :type special-block)) + (html5-fancy (and (org-html--html5-fancy-p info) + (member block-type org-html-html5-elements))) + (attributes (org-export-read-attribute :attr_html special-block))) (unless html5-fancy (let ((class (plist-get attributes :class))) - (setq attributes (plist-put attributes :class - (if class (concat class " " block-type) - block-type))))) - (setq attributes (org-html--make-attribute-string attributes)) - (when (not (equal attributes "")) - (setq attributes (concat " " attributes))) - (if html5-fancy - (format "<%s%s>\n%s" block-type attributes - contents block-type) - (format "\n%s\n
" attributes contents)))) + (setq attributes (plist-put attributes :class + (if class (concat class " " block-type) + block-type))))) + (let* ((contents (or contents "")) + (name (org-element-property :name special-block)) + (a (org-html--make-attribute-string + (if (or (not name) (plist-member attributes :id)) + attributes + (plist-put attributes :id name)))) + (str (if (org-string-nw-p a) (concat " " a) ""))) + (if html5-fancy + (format "<%s%s>\n%s" block-type str contents block-type) + (format "\n%s\n
" str contents))))) ;;;; Src Block -(defun org-html-src-block (src-block contents info) +(defun org-html-src-block (src-block _contents info) "Transcode a SRC-BLOCK element from Org to HTML. CONTENTS holds the contents of the item. INFO is a plist holding contextual information." (if (org-export-read-attribute :attr_html src-block :textarea) (org-html--textarea-block src-block) (let ((lang (org-element-property :language src-block)) - (caption (org-export-get-caption src-block)) (code (org-html-format-code src-block info)) - (label (let ((lbl (org-element-property :name src-block))) - (if (not lbl) "" - (format " id=\"%s\"" - (org-export-solidify-link-text lbl)))))) + (label (let ((lbl (and (org-element-property :name src-block) + (org-export-get-reference src-block info)))) + (if lbl (format " id=\"%s\"" lbl) "")))) (if (not lang) (format "
\n%s
" label code) - (format - "
\n%s%s\n
" - (if (not caption) "" - (format "" - (org-export-data caption info))) - (format "\n
%s
" lang label code)))))) + (format "
\n%s%s\n
" + ;; Build caption. + (let ((caption (org-export-get-caption src-block))) + (if (not caption) "" + (let ((listing-number + (format + "%s " + (format + (org-html--translate "Listing %d:" info) + (org-export-get-ordinal + src-block info nil #'org-html--has-caption-p))))) + (format "" + listing-number + (org-trim (org-export-data caption info)))))) + ;; Contents. + (format "
%s
" + lang label code)))))) ;;;; Statistics Cookie -(defun org-html-statistics-cookie (statistics-cookie contents info) +(defun org-html-statistics-cookie (statistics-cookie _contents _info) "Transcode a STATISTICS-COOKIE object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (let ((cookie-value (org-element-property :value statistics-cookie))) @@ -3069,16 +3350,18 @@ CONTENTS is nil. INFO is a plist holding contextual information." ;;;; Strike-Through -(defun org-html-strike-through (strike-through contents info) +(defun org-html-strike-through (_strike-through contents info) "Transcode STRIKE-THROUGH from Org to HTML. CONTENTS is the text with strike-through markup. INFO is a plist holding contextual information." - (format (or (cdr (assq 'strike-through org-html-text-markup-alist)) "%s") - contents)) + (format + (or (cdr (assq 'strike-through (plist-get info :html-text-markup-alist))) + "%s") + contents)) ;;;; Subscript -(defun org-html-subscript (subscript contents info) +(defun org-html-subscript (_subscript contents _info) "Transcode a SUBSCRIPT object from Org to HTML. CONTENTS is the contents of the object. INFO is a plist holding contextual information." @@ -3086,7 +3369,7 @@ contextual information." ;;;; Superscript -(defun org-html-superscript (superscript contents info) +(defun org-html-superscript (_superscript contents _info) "Transcode a SUPERSCRIPT object from Org to HTML. CONTENTS is the contents of the object. INFO is a plist holding contextual information." @@ -3101,24 +3384,30 @@ channel." (let* ((table-row (org-export-get-parent table-cell)) (table (org-export-get-parent-table table-cell)) (cell-attrs - (if (not org-html-table-align-individual-fields) "" + (if (not (plist-get info :html-table-align-individual-fields)) "" (format (if (and (boundp 'org-html-format-table-no-css) org-html-format-table-no-css) - " align=\"%s\"" " class=\"%s\"") + " align=\"%s\"" " class=\"org-%s\"") (org-export-table-cell-alignment table-cell info))))) (when (or (not contents) (string= "" (org-trim contents))) (setq contents " ")) (cond ((and (org-export-table-has-header-p table info) (= 1 (org-export-table-row-group table-row info))) - (concat "\n" (format (car org-html-table-header-tags) "col" cell-attrs) - contents (cdr org-html-table-header-tags))) - ((and org-html-table-use-header-tags-for-first-column + (let ((header-tags (plist-get info :html-table-header-tags))) + (concat "\n" (format (car header-tags) "col" cell-attrs) + contents + (cdr header-tags)))) + ((and (plist-get info :html-table-use-header-tags-for-first-column) (zerop (cdr (org-export-table-cell-address table-cell info)))) - (concat "\n" (format (car org-html-table-header-tags) "row" cell-attrs) - contents (cdr org-html-table-header-tags))) - (t (concat "\n" (format (car org-html-table-data-tags) cell-attrs) - contents (cdr org-html-table-data-tags)))))) + (let ((header-tags (plist-get info :html-table-header-tags))) + (concat "\n" (format (car header-tags) "row" cell-attrs) + contents + (cdr header-tags)))) + (t (let ((data-tags (plist-get info :html-table-data-tags))) + (concat "\n" (format (car data-tags) cell-attrs) + contents + (cdr data-tags))))))) ;;;; Table Row @@ -3129,40 +3418,45 @@ communication channel." ;; Rules are ignored since table separators are deduced from ;; borders of the current row. (when (eq (org-element-property :type table-row) 'standard) - (let* ((rowgroup-number (org-export-table-row-group table-row info)) - (row-number (org-export-table-row-number table-row info)) - (start-rowgroup-p + (let* ((group (org-export-table-row-group table-row info)) + (number (org-export-table-row-number table-row info)) + (start-group-p (org-export-table-row-starts-rowgroup-p table-row info)) - (end-rowgroup-p + (end-group-p (org-export-table-row-ends-rowgroup-p table-row info)) - ;; `top-row-p' and `end-rowgroup-p' are not used directly - ;; but should be set so that `org-html-table-row-tags' can - ;; use them (see the docstring of this variable.) - (top-row-p (and (equal start-rowgroup-p '(top)) - (equal end-rowgroup-p '(below top)))) - (bottom-row-p (and (equal start-rowgroup-p '(above)) - (equal end-rowgroup-p '(bottom above)))) - (rowgroup-tags + (topp (and (equal start-group-p '(top)) + (equal end-group-p '(below top)))) + (bottomp (and (equal start-group-p '(above)) + (equal end-group-p '(bottom above)))) + (row-open-tag + (pcase (plist-get info :html-table-row-open-tag) + ((and accessor (pred functionp)) + (funcall accessor + number group start-group-p end-group-p topp bottomp)) + (accessor accessor))) + (row-close-tag + (pcase (plist-get info :html-table-row-close-tag) + ((and accessor (pred functionp)) + (funcall accessor + number group start-group-p end-group-p topp bottomp)) + (accessor accessor))) + (group-tags (cond - ;; Case 1: Row belongs to second or subsequent rowgroups. - ((not (= 1 rowgroup-number)) - '("" . "\n")) - ;; Case 2: Row is from first rowgroup. Table has >=1 rowgroups. + ;; Row belongs to second or subsequent groups. + ((not (= 1 group)) '("" . "\n")) + ;; Row is from first group. Table has >=1 groups. ((org-export-table-has-header-p (org-export-get-parent-table table-row) info) '("" . "\n")) - ;; Case 2: Row is from first and only row group. + ;; Row is from first and only group. (t '("" . "\n"))))) - (concat - ;; Begin a rowgroup? - (when start-rowgroup-p (car rowgroup-tags)) - ;; Actual table row - (concat "\n" (eval (car org-html-table-row-tags)) - contents - "\n" - (eval (cdr org-html-table-row-tags))) - ;; End a rowgroup? - (when end-rowgroup-p (cdr rowgroup-tags)))))) + (concat (and start-group-p (car group-tags)) + (concat "\n" + row-open-tag + contents + "\n" + row-close-tag) + (and end-group-p (cdr group-tags)))))) ;;;; Table @@ -3178,7 +3472,7 @@ INFO is a plist used as a communication channel." (if (not special-column-p) (org-element-contents table-row) (cdr (org-element-contents table-row))))) -(defun org-html-table--table.el-table (table info) +(defun org-html-table--table.el-table (table _info) "Format table.el tables into HTML. INFO is a plist used as a communication channel." (when (eq (org-element-property :type table) 'table.el) @@ -3199,134 +3493,123 @@ INFO is a plist used as a communication channel." "Transcode a TABLE element from Org to HTML. CONTENTS is the contents of the table. INFO is a plist holding contextual information." - (case (org-element-property :type table) - ;; Case 1: table.el table. Convert it using appropriate tools. - (table.el (org-html-table--table.el-table table info)) - ;; Case 2: Standard table. - (t - (let* ((label (org-element-property :name table)) - (caption (org-export-get-caption table)) - (number (org-export-get-ordinal - table info nil 'org-html--has-caption-p)) - (attributes - (org-html--make-attribute-string - (org-combine-plists - (and label (list :id (org-export-solidify-link-text label))) - (and (not (org-html-html5-p info)) - (plist-get info :html-table-attributes)) - (org-export-read-attribute :attr_html table)))) - (alignspec - (if (and (boundp 'org-html-format-table-no-css) - org-html-format-table-no-css) - "align=\"%s\"" "class=\"%s\"")) - (table-column-specs - (function - (lambda (table info) - (mapconcat - (lambda (table-cell) - (let ((alignment (org-export-table-cell-alignment - table-cell info))) - (concat - ;; Begin a colgroup? - (when (org-export-table-cell-starts-colgroup-p - table-cell info) - "\n") - ;; Add a column. Also specify it's alignment. - (format "\n%s" - (org-html-close-tag - "col" (concat " " (format alignspec alignment)) info)) - ;; End a colgroup? - (when (org-export-table-cell-ends-colgroup-p - table-cell info) - "\n")))) - (org-html-table-first-row-data-cells table info) "\n"))))) - (format "\n%s\n%s\n%s" - (if (equal attributes "") "" (concat " " attributes)) - (if (not caption) "" - (format (if org-html-table-caption-above - "%s" - "%s") - (concat - "" - (format (org-html--translate "Table %d:" info) number) - " " (org-export-data caption info)))) - (funcall table-column-specs table info) - contents))))) + (if (eq (org-element-property :type table) 'table.el) + ;; "table.el" table. Convert it using appropriate tools. + (org-html-table--table.el-table table info) + ;; Standard table. + (let* ((caption (org-export-get-caption table)) + (number (org-export-get-ordinal + table info nil #'org-html--has-caption-p)) + (attributes + (org-html--make-attribute-string + (org-combine-plists + (and (org-element-property :name table) + (list :id (org-export-get-reference table info))) + (and (not (org-html-html5-p info)) + (plist-get info :html-table-attributes)) + (org-export-read-attribute :attr_html table)))) + (alignspec + (if (bound-and-true-p org-html-format-table-no-css) + "align=\"%s\"" + "class=\"org-%s\"")) + (table-column-specs + (lambda (table info) + (mapconcat + (lambda (table-cell) + (let ((alignment (org-export-table-cell-alignment + table-cell info))) + (concat + ;; Begin a colgroup? + (when (org-export-table-cell-starts-colgroup-p + table-cell info) + "\n") + ;; Add a column. Also specify its alignment. + (format "\n%s" + (org-html-close-tag + "col" (concat " " (format alignspec alignment)) info)) + ;; End a colgroup? + (when (org-export-table-cell-ends-colgroup-p + table-cell info) + "\n")))) + (org-html-table-first-row-data-cells table info) "\n")))) + (format "\n%s\n%s\n%s" + (if (equal attributes "") "" (concat " " attributes)) + (if (not caption) "" + (format (if (plist-get info :html-table-caption-above) + "%s" + "%s") + (concat + "" + (format (org-html--translate "Table %d:" info) number) + " " (org-export-data caption info)))) + (funcall table-column-specs table info) + contents)))) ;;;; Target -(defun org-html-target (target contents info) +(defun org-html-target (target _contents info) "Transcode a TARGET object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." - (let ((id (org-export-solidify-link-text - (org-element-property :value target)))) - (org-html--anchor id))) + (let ((ref (org-export-get-reference target info))) + (org-html--anchor ref nil nil info))) ;;;; Timestamp -(defun org-html-timestamp (timestamp contents info) +(defun org-html-timestamp (timestamp _contents info) "Transcode a TIMESTAMP object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." - (let ((value (org-html-plain-text - (org-timestamp-translate timestamp) info))) + (let ((value (org-html-plain-text (org-timestamp-translate timestamp) info))) (format "%s" (replace-regexp-in-string "--" "–" value)))) ;;;; Underline -(defun org-html-underline (underline contents info) +(defun org-html-underline (_underline contents info) "Transcode UNDERLINE from Org to HTML. CONTENTS is the text with underline markup. INFO is a plist holding contextual information." - (format (or (cdr (assq 'underline org-html-text-markup-alist)) "%s") + (format (or (cdr (assq 'underline (plist-get info :html-text-markup-alist))) + "%s") contents)) ;;;; Verbatim -(defun org-html-verbatim (verbatim contents info) +(defun org-html-verbatim (verbatim _contents info) "Transcode VERBATIM from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." - (format (or (cdr (assq 'verbatim org-html-text-markup-alist)) "%s") + (format (or (cdr (assq 'verbatim (plist-get info :html-text-markup-alist))) "%s") (org-html-encode-plain-text (org-element-property :value verbatim)))) ;;;; Verse Block -(defun org-html-verse-block (verse-block contents info) +(defun org-html-verse-block (_verse-block contents info) "Transcode a VERSE-BLOCK element from Org to HTML. CONTENTS is verse block contents. INFO is a plist holding contextual information." - ;; Replace each newline character with line break. Also replace - ;; each blank line with a line break. - (setq contents (replace-regexp-in-string - "^ *\\\\\\\\$" (format "%s\n" (org-html-close-tag "br" nil info)) - (replace-regexp-in-string - "\\(\\\\\\\\\\)?[ \t]*\n" - (format "%s\n" (org-html-close-tag "br" nil info)) contents))) - ;; Replace each white space at beginning of a line with a - ;; non-breaking space. - (while (string-match "^[ \t]+" contents) - (let* ((num-ws (length (match-string 0 contents))) - (ws (let (out) (dotimes (i num-ws out) - (setq out (concat out " ")))))) - (setq contents (replace-match ws nil t contents)))) - (format "

\n%s

" contents)) + (format "

\n%s

" + ;; Replace leading white spaces with non-breaking spaces. + (replace-regexp-in-string + "^[ \t]+" (lambda (m) (org-html--make-string (length m) " ")) + ;; Replace each newline character with line break. Also + ;; remove any trailing "br" close-tag so as to avoid + ;; duplicates. + (let* ((br (org-html-close-tag "br" nil info)) + (re (format "\\(?:%s\\)?[ \t]*\n" (regexp-quote br)))) + (replace-regexp-in-string re (concat br "\n") contents))))) ;;; Filter Functions -(defun org-html-final-function (contents backend info) +(defun org-html-final-function (contents _backend info) "Filter to indent the HTML and convert HTML entities." (with-temp-buffer (insert contents) (set-auto-mode t) - (if org-html-indent + (if (plist-get info :html-indent) (indent-region (point-min) (point-max))) - (when org-html-use-unicode-chars - (require 'mm-url) - (mm-url-decode-entities)) (buffer-substring-no-properties (point-min) (point-max)))) @@ -3370,10 +3653,10 @@ is non-nil." ;;;###autoload (defun org-html-convert-region-to-html () - "Assume the current region has org-mode syntax, and convert it to HTML. + "Assume the current region has Org syntax, and convert it to HTML. This can be used in any buffer. For example, you can write an -itemized list in org-mode syntax in an HTML buffer and use this -command to convert it." +itemized list in Org syntax in an HTML buffer and use this command +to convert it." (interactive) (org-export-replace-region-by 'html)) @@ -3407,7 +3690,9 @@ file-local settings. Return output file's name." (interactive) - (let* ((extension (concat "." org-html-extension)) + (let* ((extension (concat "." (or (plist-get ext-plist :html-extension) + org-html-extension + "html"))) (file (org-export-output-file-name extension subtreep)) (org-export-coding-system org-html-coding-system)) (org-export-to-file 'html file @@ -3424,7 +3709,8 @@ publishing directory. Return output file name." (org-publish-org-to 'html filename (concat "." (or (plist-get plist :html-extension) - org-html-extension "html")) + org-html-extension + "html")) plist pub-dir)) diff --git a/lisp/org/ox-icalendar.el b/lisp/org/ox-icalendar.el index fe6d08a85b5..9ccbb272448 100644 --- a/lisp/org/ox-icalendar.el +++ b/lisp/org/ox-icalendar.el @@ -1,4 +1,4 @@ -;;; ox-icalendar.el --- iCalendar Back-End for Org Export Engine +;;; ox-icalendar.el --- iCalendar Back-End for Org Export Engine -*- lexical-binding: t; -*- ;; Copyright (C) 2004-2017 Free Software Foundation, Inc. @@ -31,7 +31,7 @@ ;;; Code: -(eval-when-compile (require 'cl)) +(require 'cl-lib) (require 'ox-ascii) (declare-function org-bbdb-anniv-export-ical "org-bbdb" nil) @@ -46,7 +46,7 @@ (defcustom org-icalendar-combined-agenda-file "~/org.ics" "The file name for the iCalendar file covering all agenda files. -This file is created with the command \\[org-icalendar-combine-agenda-files]. +This file is created with the command `\\[org-icalendar-combine-agenda-files]'. The file name should be absolute. It will be overwritten without warning." :group 'org-export-icalendar :type 'file) @@ -77,7 +77,7 @@ for timed events. If non-zero, alarms are created. (defcustom org-icalendar-exclude-tags nil "Tags that exclude a tree from export. This variable allows specifying different exclude tags from other -back-ends. It can also be set with the ICAL_EXCLUDE_TAGS +back-ends. It can also be set with the ICALENDAR_EXCLUDE_TAGS keyword." :group 'org-export-icalendar :type '(repeat (string :tag "Tag"))) @@ -85,10 +85,11 @@ keyword." (defcustom org-icalendar-use-deadline '(event-if-not-todo todo-due) "Contexts where iCalendar export should use a deadline time stamp. -This is a list with several symbols in it. Valid symbol are: +This is a list with possibly several symbols in it. Valid symbols are: + `event-if-todo' Deadlines in TODO entries become calendar events. `event-if-not-todo' Deadlines in non-TODO entries become calendar events. -`todo-due' Use deadlines in TODO entries as due-dates" +`todo-due' Use deadlines in TODO entries as due-dates." :group 'org-export-icalendar :type '(set :greedy t (const :tag "Deadlines in non-TODO entries become events" @@ -101,7 +102,8 @@ This is a list with several symbols in it. Valid symbol are: (defcustom org-icalendar-use-scheduled '(todo-start) "Contexts where iCalendar export should use a scheduling time stamp. -This is a list with several symbols in it. Valid symbol are: +This is a list with possibly several symbols in it. Valid symbols are: + `event-if-todo' Scheduling time stamps in TODO entries become an event. `event-if-not-todo' Scheduling time stamps in non-TODO entries become an event. `todo-start' Scheduling time stamps in TODO entries become start date. @@ -256,11 +258,18 @@ re-read the iCalendar file.") '((:exclude-tags "ICALENDAR_EXCLUDE_TAGS" nil org-icalendar-exclude-tags split) (:with-timestamps nil "<" org-icalendar-with-timestamps) - (:with-vtodo nil nil org-icalendar-include-todo) - ;; The following property will be non-nil when export has been - ;; started from org-agenda-mode. In this case, any entry without - ;; a non-nil "ICALENDAR_MARK" property will be ignored. - (:icalendar-agenda-view nil nil nil)) + ;; Other variables. + (:icalendar-alarm-time nil nil org-icalendar-alarm-time) + (:icalendar-categories nil nil org-icalendar-categories) + (:icalendar-date-time-format nil nil org-icalendar-date-time-format) + (:icalendar-include-bbdb-anniversaries nil nil org-icalendar-include-bbdb-anniversaries) + (:icalendar-include-body nil nil org-icalendar-include-body) + (:icalendar-include-sexps nil nil org-icalendar-include-sexps) + (:icalendar-include-todo nil nil org-icalendar-include-todo) + (:icalendar-store-UID nil nil org-icalendar-store-UID) + (:icalendar-timezone nil nil org-icalendar-timezone) + (:icalendar-use-deadline nil nil org-icalendar-use-deadline) + (:icalendar-use-scheduled nil nil org-icalendar-use-scheduled)) :filters-alist '((:filter-headline . org-icalendar-clear-blank-lines)) :menu-entry @@ -275,22 +284,18 @@ re-read the iCalendar file.") ;;; Internal Functions -(defun org-icalendar-create-uid (file &optional bell h-markers) +(defun org-icalendar-create-uid (file &optional bell) "Set ID property on headlines missing it in FILE. When optional argument BELL is non-nil, inform the user with -a message if the file was modified. With optional argument -H-MARKERS non-nil, it is a list of markers for the headlines -which will be updated." - (let ((pt (if h-markers (goto-char (car h-markers)) (point-min))) - modified-flag) +a message if the file was modified." + (let (modified-flag) (org-map-entries (lambda () (let ((entry (org-element-at-point))) - (unless (or (< (point) pt) (org-element-property :ID entry)) + (unless (org-element-property :ID entry) (org-id-get-create) (setq modified-flag t) - (forward-line)) - (when h-markers (setq org-map-continue-from (pop h-markers))))) + (forward-line)))) nil nil 'comment) (when (and bell modified-flag) (message "ID properties created in file \"%s\"" file) @@ -318,19 +323,17 @@ A headline is blocked when either ;; Check :ORDERED: node property. (catch 'blockedp (let ((current headline)) - (mapc (lambda (parent) - (cond - ((not (org-element-property :todo-keyword parent)) - (throw 'blockedp nil)) - ((org-not-nil (org-element-property :ORDERED parent)) - (let ((sibling current)) - (while (setq sibling (org-export-get-previous-element - sibling info)) - (when (eq (org-element-property :todo-type sibling) 'todo) - (throw 'blockedp t))))) - (t (setq current parent)))) - (org-export-get-genealogy headline)) - nil)))) + (dolist (parent (org-element-lineage headline)) + (cond + ((not (org-element-property :todo-keyword parent)) + (throw 'blockedp nil)) + ((org-not-nil (org-element-property :ORDERED parent)) + (let ((sibling current)) + (while (setq sibling (org-export-get-previous-element + sibling info)) + (when (eq (org-element-property :todo-type sibling) 'todo) + (throw 'blockedp t))))) + (t (setq current parent)))))))) (defun org-icalendar-use-UTC-date-time-p () "Non-nil when `org-icalendar-date-time-format' requires UTC time." @@ -393,8 +396,8 @@ Universal Time, ignoring `org-icalendar-date-time-format'." ;; Convert timestamp into internal time in order to use ;; `format-time-string' and fix any mistake (i.e. MI >= 60). (encode-time 0 mi h d m y) - (not (not (or utc (and with-time-p - (org-icalendar-use-UTC-date-time-p))))))))) + (and (or utc (and with-time-p (org-icalendar-use-UTC-date-time-p))) + t))))) (defun org-icalendar-dtstamp () "Return DTSTAMP property, as a string." @@ -405,27 +408,25 @@ Universal Time, ignoring `org-icalendar-date-time-format'." ENTRY is a headline or an inlinetask element. INFO is a plist used as a communication channel." (mapconcat - 'identity + #'identity (org-uniquify (let (categories) - (mapc (lambda (type) - (case type - (category - (push (org-export-get-category entry info) categories)) - (todo-state - (let ((todo (org-element-property :todo-keyword entry))) - (and todo (push todo categories)))) - (local-tags - (setq categories - (append (nreverse (org-export-get-tags entry info)) - categories))) - (all-tags - (setq categories - (append (nreverse (org-export-get-tags entry info nil t)) - categories))))) - org-icalendar-categories) - ;; Return list of categories, following specified order. - (nreverse categories))) ",")) + (dolist (type org-icalendar-categories (nreverse categories)) + (cl-case type + (category + (push (org-export-get-category entry info) categories)) + (todo-state + (let ((todo (org-element-property :todo-keyword entry))) + (and todo (push todo categories)))) + (local-tags + (setq categories + (append (nreverse (org-export-get-tags entry info)) + categories))) + (all-tags + (setq categories + (append (nreverse (org-export-get-tags entry info nil t)) + categories))))))) + ",")) (defun org-icalendar-transcode-diary-sexp (sexp uid summary) "Transcode a diary sexp into iCalendar format. @@ -457,7 +458,7 @@ or subject for the event." (mapconcat (lambda (line) ;; Limit each line to a maximum of 75 characters. If it is - ;; longer, fold it by using "\n " as a continuation marker. + ;; longer, fold it by using "\r\n " as a continuation marker. (let ((len (length line))) (if (<= len 75) line (let ((folded-line (substring line 0 75)) @@ -467,17 +468,17 @@ or subject for the event." ;; line, real contents must be split at 74 chars. (while (< (setq chunk-end (+ chunk-start 74)) len) (setq folded-line - (concat folded-line "\n " + (concat folded-line "\r\n " (substring line chunk-start chunk-end)) chunk-start chunk-end)) - (concat folded-line "\n " (substring line chunk-start)))))) - (org-split-string s "\n") "\n"))) + (concat folded-line "\r\n " (substring line chunk-start)))))) + (org-split-string s "\n") "\r\n"))) ;;; Filters -(defun org-icalendar-clear-blank-lines (headline back-end info) +(defun org-icalendar-clear-blank-lines (headline _back-end _info) "Remove blank lines in HEADLINE export. HEADLINE is a string representing a transcoded headline. BACK-END and INFO are ignored." @@ -522,99 +523,97 @@ inlinetask within the section." (cons 'org-data (cons nil (org-element-contents first)))))))) (concat - (unless (and (plist-get info :icalendar-agenda-view) - (not (org-element-property :ICALENDAR-MARK entry))) - (let ((todo-type (org-element-property :todo-type entry)) - (uid (or (org-element-property :ID entry) (org-id-new))) - (summary (org-icalendar-cleanup-string - (or (org-element-property :SUMMARY entry) - (org-export-data - (org-element-property :title entry) info)))) - (loc (org-icalendar-cleanup-string - (org-element-property :LOCATION entry))) - ;; Build description of the entry from associated - ;; section (headline) or contents (inlinetask). - (desc - (org-icalendar-cleanup-string - (or (org-element-property :DESCRIPTION entry) - (let ((contents (org-export-data inside info))) - (cond - ((not (org-string-nw-p contents)) nil) - ((wholenump org-icalendar-include-body) - (let ((contents (org-trim contents))) - (substring - contents 0 (min (length contents) - org-icalendar-include-body)))) - (org-icalendar-include-body (org-trim contents))))))) - (cat (org-icalendar-get-categories entry info))) - (concat - ;; Events: Delegate to `org-icalendar--vevent' to - ;; generate "VEVENT" component from scheduled, deadline, - ;; or any timestamp in the entry. - (let ((deadline (org-element-property :deadline entry))) - (and deadline - (memq (if todo-type 'event-if-todo 'event-if-not-todo) - org-icalendar-use-deadline) - (org-icalendar--vevent - entry deadline (concat "DL-" uid) - (concat "DL: " summary) loc desc cat))) - (let ((scheduled (org-element-property :scheduled entry))) - (and scheduled - (memq (if todo-type 'event-if-todo 'event-if-not-todo) - org-icalendar-use-scheduled) - (org-icalendar--vevent - entry scheduled (concat "SC-" uid) - (concat "S: " summary) loc desc cat))) - ;; When collecting plain timestamps from a headline and - ;; its title, skip inlinetasks since collection will - ;; happen once ENTRY is one of them. + (let ((todo-type (org-element-property :todo-type entry)) + (uid (or (org-element-property :ID entry) (org-id-new))) + (summary (org-icalendar-cleanup-string + (or (org-element-property :SUMMARY entry) + (org-export-data + (org-element-property :title entry) info)))) + (loc (org-icalendar-cleanup-string + (org-element-property :LOCATION entry))) + ;; Build description of the entry from associated section + ;; (headline) or contents (inlinetask). + (desc + (org-icalendar-cleanup-string + (or (org-element-property :DESCRIPTION entry) + (let ((contents (org-export-data inside info))) + (cond + ((not (org-string-nw-p contents)) nil) + ((wholenump org-icalendar-include-body) + (let ((contents (org-trim contents))) + (substring + contents 0 (min (length contents) + org-icalendar-include-body)))) + (org-icalendar-include-body (org-trim contents))))))) + (cat (org-icalendar-get-categories entry info))) + (concat + ;; Events: Delegate to `org-icalendar--vevent' to generate + ;; "VEVENT" component from scheduled, deadline, or any + ;; timestamp in the entry. + (let ((deadline (org-element-property :deadline entry))) + (and deadline + (memq (if todo-type 'event-if-todo 'event-if-not-todo) + org-icalendar-use-deadline) + (org-icalendar--vevent + entry deadline (concat "DL-" uid) + (concat "DL: " summary) loc desc cat))) + (let ((scheduled (org-element-property :scheduled entry))) + (and scheduled + (memq (if todo-type 'event-if-todo 'event-if-not-todo) + org-icalendar-use-scheduled) + (org-icalendar--vevent + entry scheduled (concat "SC-" uid) + (concat "S: " summary) loc desc cat))) + ;; When collecting plain timestamps from a headline and its + ;; title, skip inlinetasks since collection will happen once + ;; ENTRY is one of them. + (let ((counter 0)) + (mapconcat + #'identity + (org-element-map (cons (org-element-property :title entry) + (org-element-contents inside)) + 'timestamp + (lambda (ts) + (when (let ((type (org-element-property :type ts))) + (cl-case (plist-get info :with-timestamps) + (active (memq type '(active active-range))) + (inactive (memq type '(inactive inactive-range))) + ((t) t))) + (let ((uid (format "TS%d-%s" (cl-incf counter) uid))) + (org-icalendar--vevent + entry ts uid summary loc desc cat)))) + info nil (and (eq type 'headline) 'inlinetask)) + "")) + ;; Task: First check if it is appropriate to export it. If + ;; so, call `org-icalendar--vtodo' to transcode it into + ;; a "VTODO" component. + (when (and todo-type + (cl-case (plist-get info :icalendar-include-todo) + (all t) + (unblocked + (and (eq type 'headline) + (not (org-icalendar-blocked-headline-p + entry info)))) + ((t) (eq todo-type 'todo)))) + (org-icalendar--vtodo entry uid summary loc desc cat)) + ;; Diary-sexp: Collect every diary-sexp element within ENTRY + ;; and its title, and transcode them. If ENTRY is + ;; a headline, skip inlinetasks: they will be handled + ;; separately. + (when org-icalendar-include-sexps (let ((counter 0)) - (mapconcat - #'identity - (org-element-map (cons (org-element-property :title entry) - (org-element-contents inside)) - 'timestamp - (lambda (ts) - (when (let ((type (org-element-property :type ts))) - (case (plist-get info :with-timestamps) - (active (memq type '(active active-range))) - (inactive (memq type '(inactive inactive-range))) - ((t) t))) - (let ((uid (format "TS%d-%s" (incf counter) uid))) - (org-icalendar--vevent - entry ts uid summary loc desc cat)))) - info nil (and (eq type 'headline) 'inlinetask)) - "")) - ;; Task: First check if it is appropriate to export it. - ;; If so, call `org-icalendar--vtodo' to transcode it - ;; into a "VTODO" component. - (when (and todo-type - (case (plist-get info :with-vtodo) - (all t) - (unblocked - (and (eq type 'headline) - (not (org-icalendar-blocked-headline-p - entry info)))) - ((t) (eq todo-type 'todo)))) - (org-icalendar--vtodo entry uid summary loc desc cat)) - ;; Diary-sexp: Collect every diary-sexp element within - ;; ENTRY and its title, and transcode them. If ENTRY is - ;; a headline, skip inlinetasks: they will be handled - ;; separately. - (when org-icalendar-include-sexps - (let ((counter 0)) - (mapconcat #'identity - (org-element-map - (cons (org-element-property :title entry) - (org-element-contents inside)) - 'diary-sexp - (lambda (sexp) - (org-icalendar-transcode-diary-sexp - (org-element-property :value sexp) - (format "DS%d-%s" (incf counter) uid) - summary)) - info nil (and (eq type 'headline) 'inlinetask)) - "")))))) + (mapconcat #'identity + (org-element-map + (cons (org-element-property :title entry) + (org-element-contents inside)) + 'diary-sexp + (lambda (sexp) + (org-icalendar-transcode-diary-sexp + (org-element-property :value sexp) + (format "DS%d-%s" (cl-incf counter) uid) + summary)) + info nil (and (eq type 'headline) 'inlinetask)) + ""))))) ;; If ENTRY is a headline, call current function on every ;; inlinetask within it. In agenda export, this is independent ;; from the mark (or lack thereof) on the entry. @@ -627,7 +626,7 @@ inlinetask within the section." contents)))) (defun org-icalendar--vevent - (entry timestamp uid summary location description categories) + (entry timestamp uid summary location description categories) "Create a VEVENT component. ENTRY is either a headline or an inlinetask element. TIMESTAMP @@ -651,7 +650,7 @@ Return VEVENT component as a string." ;; RRULE. (when (org-element-property :repeater-type timestamp) (format "RRULE:FREQ=%s;INTERVAL=%d\n" - (case (org-element-property :repeater-unit timestamp) + (cl-case (org-element-property :repeater-unit timestamp) (hour "HOURLY") (day "DAILY") (week "WEEKLY") (month "MONTHLY") (year "YEARLY")) (org-element-property :repeater-value timestamp))) @@ -821,7 +820,8 @@ Return ICS file name." ;; links will not be collected at the end of sections. (let ((outfile (org-export-output-file-name ".ics" subtreep))) (org-export-to-file 'icalendar outfile - async subtreep visible-only body-only '(:ascii-charset utf-8) + async subtreep visible-only body-only + '(:ascii-charset utf-8 :ascii-links-to-notes nil) (lambda (file) (run-hook-with-args 'org-icalendar-after-save-hook file) nil)))) @@ -835,27 +835,23 @@ external process." ;; Asynchronous export is not interactive, so we will not call ;; `org-check-agenda-file'. Instead we remove any non-existent ;; agenda file from the list. - (let ((files (org-remove-if-not 'file-exists-p (org-agenda-files t)))) + (let ((files (cl-remove-if-not #'file-exists-p (org-agenda-files t)))) (org-export-async-start (lambda (results) - (mapc (lambda (f) (org-export-add-to-stack f 'icalendar)) - results)) + (dolist (f results) (org-export-add-to-stack f 'icalendar))) `(let (output-files) - (mapc (lambda (file) - (with-current-buffer (org-get-agenda-file-buffer file) - (push (expand-file-name (org-icalendar-export-to-ics)) - output-files))) - ',files) - output-files))) + (dolist (file ',files outputfiles) + (with-current-buffer (org-get-agenda-file-buffer file) + (push (expand-file-name (org-icalendar-export-to-ics)) + output-files)))))) (let ((files (org-agenda-files t))) (org-agenda-prepare-buffers files) (unwind-protect - (mapc (lambda (file) - (catch 'nextfile - (org-check-agenda-file file) - (with-current-buffer (org-get-agenda-file-buffer file) - (org-icalendar-export-to-ics)))) - files) + (dolist (file files) + (catch 'nextfile + (org-check-agenda-file file) + (with-current-buffer (org-get-agenda-file-buffer file) + (org-icalendar-export-to-ics)))) (org-release-buffers org-agenda-new-buffers))))) ;;;###autoload @@ -870,56 +866,52 @@ The file is stored under the name chosen in `org-icalendar-combined-agenda-file'." (interactive) (if async - (let ((files (org-remove-if-not 'file-exists-p (org-agenda-files t)))) + (let ((files (cl-remove-if-not #'file-exists-p (org-agenda-files t)))) (org-export-async-start - (lambda (dummy) + (lambda (_) (org-export-add-to-stack (expand-file-name org-icalendar-combined-agenda-file) 'icalendar)) - `(apply 'org-icalendar--combine-files nil ',files))) - (apply 'org-icalendar--combine-files nil (org-agenda-files t)))) + `(apply #'org-icalendar--combine-files ',files))) + (apply #'org-icalendar--combine-files (org-agenda-files t)))) (defun org-icalendar-export-current-agenda (file) "Export current agenda view to an iCalendar FILE. This function assumes major mode for current buffer is `org-agenda-mode'." - (let (org-export-babel-evaluate ; Don't evaluate Babel block - (org-icalendar-combined-agenda-file file) - (marker-list - ;; Collect the markers pointing to entries in the current - ;; agenda buffer. - (let (markers) - (save-excursion - (goto-char (point-min)) - (while (not (eobp)) - (let ((m (or (org-get-at-bol 'org-hd-marker) - (org-get-at-bol 'org-marker)))) - (and m (push m markers))) - (beginning-of-line 2))) - (nreverse markers)))) - (apply 'org-icalendar--combine-files - ;; Build restriction alist. - (let (restriction) - ;; Sort markers in each association within RESTRICTION. - (mapcar (lambda (x) (setcdr x (sort (copy-sequence (cdr x)) '<)) x) - (dolist (m marker-list restriction) - (let* ((pos (marker-position m)) - (file (buffer-file-name - (org-base-buffer (marker-buffer m)))) - (file-markers (assoc file restriction))) - ;; Add POS in FILE association if one exists - ;; or create a new association for FILE. - (if file-markers (push pos (cdr file-markers)) - (push (list file pos) restriction)))))) - (org-agenda-files nil 'ifmode)))) - -(defun org-icalendar--combine-files (restriction &rest files) + (let* ((org-export-babel-evaluate) ; Don't evaluate Babel block. + (contents + (org-export-string-as + (with-output-to-string + (save-excursion + (let ((p (point-min))) + (while (setq p (next-single-property-change p 'org-hd-marker)) + (let ((m (get-text-property p 'org-hd-marker))) + (when m + (with-current-buffer (marker-buffer m) + (org-with-wide-buffer + (goto-char (marker-position m)) + (princ + (org-element-normalize-string + (buffer-substring + (point) (progn (outline-next-heading) (point))))))))) + (forward-line))))) + 'icalendar t + '(:ascii-charset utf-8 :ascii-links-to-notes nil + :icalendar-include-todo all)))) + (with-temp-file file + (insert + (org-icalendar--vcalendar + org-icalendar-combined-name + user-full-name + (or (org-string-nw-p org-icalendar-timezone) (cadr (current-time-zone))) + org-icalendar-combined-description + contents))) + (run-hook-with-args 'org-icalendar-after-save-hook file))) + +(defun org-icalendar--combine-files (&rest files) "Combine entries from multiple files into an iCalendar file. -RESTRICTION, when non-nil, is an alist where key is a file name -and value a list of buffer positions pointing to entries that -should appear in the calendar. It only makes sense if the -function was called from an agenda buffer. FILES is a list of -files to build the calendar from." +FILES is a list of files to build the calendar from." (org-agenda-prepare-buffers files) (unwind-protect (progn @@ -943,29 +935,12 @@ files to build the calendar from." (catch 'nextfile (org-check-agenda-file file) (with-current-buffer (org-get-agenda-file-buffer file) - (let ((marks (cdr (assoc (expand-file-name file) - restriction)))) - ;; Create ID if necessary. - (when org-icalendar-store-UID - (org-icalendar-create-uid file t marks)) - (unless (and restriction (not marks)) - ;; Add a hook adding :ICALENDAR_MARK: property - ;; to each entry appearing in agenda view. - ;; Use `apply-partially' because the function - ;; still has to accept one argument. - (let ((org-export-before-processing-hook - (cons (apply-partially - (lambda (m-list dummy) - (mapc (lambda (m) - (org-entry-put - m "ICALENDAR-MARK" "t")) - m-list)) - (sort marks '>)) - org-export-before-processing-hook))) - (org-export-as - 'icalendar nil nil t - (list :ascii-charset 'utf-8 - :icalendar-agenda-view restriction)))))))) + ;; Create ID if necessary. + (when org-icalendar-store-UID + (org-icalendar-create-uid file t)) + (org-export-as + 'icalendar nil nil t + '(:ascii-charset utf-8 :ascii-links-to-notes nil))))) files "") ;; BBDB anniversaries. (when (and org-icalendar-include-bbdb-anniversaries diff --git a/lisp/org/ox-latex.el b/lisp/org/ox-latex.el index 3eee86a3ae7..f11a8a63a2a 100644 --- a/lisp/org/ox-latex.el +++ b/lisp/org/ox-latex.el @@ -1,4 +1,4 @@ -;;; ox-latex.el --- LaTeX Back-End for Org Export Engine +;;; ox-latex.el --- LaTeX Back-End for Org Export Engine -*- lexical-binding: t; -*- ;; Copyright (C) 2011-2017 Free Software Foundation, Inc. @@ -26,7 +26,7 @@ ;;; Code: -(eval-when-compile (require 'cl)) +(require 'cl-lib) (require 'ox) (require 'ox-publish) @@ -43,8 +43,6 @@ (center-block . org-latex-center-block) (clock . org-latex-clock) (code . org-latex-code) - (comment . (lambda (&rest args) "")) - (comment-block . (lambda (&rest args) "")) (drawer . org-latex-drawer) (dynamic-block . org-latex-dynamic-block) (entity . org-latex-entity) @@ -65,13 +63,13 @@ (latex-fragment . org-latex-latex-fragment) (line-break . org-latex-line-break) (link . org-latex-link) + (node-property . org-latex-node-property) (paragraph . org-latex-paragraph) (plain-list . org-latex-plain-list) (plain-text . org-latex-plain-text) (planning . org-latex-planning) - (property-drawer . (lambda (&rest args) "")) + (property-drawer . org-latex-property-drawer) (quote-block . org-latex-quote-block) - (quote-section . org-latex-quote-section) (radio-target . org-latex-radio-target) (section . org-latex-section) (special-block . org-latex-special-block) @@ -88,8 +86,10 @@ (timestamp . org-latex-timestamp) (underline . org-latex-underline) (verbatim . org-latex-verbatim) - (verse-block . org-latex-verse-block)) - :export-block '("LATEX" "TEX") + (verse-block . org-latex-verse-block) + ;; Pseudo objects and elements. + (latex-math-block . org-latex-math-block) + (latex-matrices . org-latex-matrices)) :menu-entry '(?l "Export to LaTeX" ((?L "As LaTeX buffer" org-latex-export-as-latex) @@ -99,13 +99,57 @@ (lambda (a s v b) (if a (org-latex-export-to-pdf t s v b) (org-open-file (org-latex-export-to-pdf nil s v b))))))) - :options-alist '((:latex-class "LATEX_CLASS" nil org-latex-default-class t) - (:latex-class-options "LATEX_CLASS_OPTIONS" nil nil t) - (:latex-header "LATEX_HEADER" nil nil newline) - (:latex-header-extra "LATEX_HEADER_EXTRA" nil nil newline) - (:latex-hyperref-p nil "texht" org-latex-with-hyperref t) - ;; Redefine regular options. - (:date "DATE" nil "\\today" t))) + :filters-alist '((:filter-options . org-latex-math-block-options-filter) + (:filter-paragraph . org-latex-clean-invalid-line-breaks) + (:filter-parse-tree org-latex-math-block-tree-filter + org-latex-matrices-tree-filter) + (:filter-verse-block . org-latex-clean-invalid-line-breaks)) + :options-alist + '((:latex-class "LATEX_CLASS" nil org-latex-default-class t) + (:latex-class-options "LATEX_CLASS_OPTIONS" nil nil t) + (:latex-header "LATEX_HEADER" nil nil newline) + (:latex-header-extra "LATEX_HEADER_EXTRA" nil nil newline) + (:description "DESCRIPTION" nil nil parse) + (:keywords "KEYWORDS" nil nil parse) + (:subtitle "SUBTITLE" nil nil parse) + ;; Other variables. + (:latex-active-timestamp-format nil nil org-latex-active-timestamp-format) + (:latex-caption-above nil nil org-latex-caption-above) + (:latex-classes nil nil org-latex-classes) + (:latex-default-figure-position nil nil org-latex-default-figure-position) + (:latex-default-table-environment nil nil org-latex-default-table-environment) + (:latex-default-table-mode nil nil org-latex-default-table-mode) + (:latex-diary-timestamp-format nil nil org-latex-diary-timestamp-format) + (:latex-footnote-defined-format nil nil org-latex-footnote-defined-format) + (:latex-footnote-separator nil nil org-latex-footnote-separator) + (:latex-format-drawer-function nil nil org-latex-format-drawer-function) + (:latex-format-headline-function nil nil org-latex-format-headline-function) + (:latex-format-inlinetask-function nil nil org-latex-format-inlinetask-function) + (:latex-hyperref-template nil nil org-latex-hyperref-template t) + (:latex-image-default-height nil nil org-latex-image-default-height) + (:latex-image-default-option nil nil org-latex-image-default-option) + (:latex-image-default-width nil nil org-latex-image-default-width) + (:latex-images-centered nil nil org-latex-images-centered) + (:latex-inactive-timestamp-format nil nil org-latex-inactive-timestamp-format) + (:latex-inline-image-rules nil nil org-latex-inline-image-rules) + (:latex-link-with-unknown-path-format nil nil org-latex-link-with-unknown-path-format) + (:latex-listings nil nil org-latex-listings) + (:latex-listings-langs nil nil org-latex-listings-langs) + (:latex-listings-options nil nil org-latex-listings-options) + (:latex-minted-langs nil nil org-latex-minted-langs) + (:latex-minted-options nil nil org-latex-minted-options) + (:latex-prefer-user-labels nil nil org-latex-prefer-user-labels) + (:latex-subtitle-format nil nil org-latex-subtitle-format) + (:latex-subtitle-separate nil nil org-latex-subtitle-separate) + (:latex-table-scientific-notation nil nil org-latex-table-scientific-notation) + (:latex-tables-booktabs nil nil org-latex-tables-booktabs) + (:latex-tables-centered nil nil org-latex-tables-centered) + (:latex-text-markup-alist nil nil org-latex-text-markup-alist) + (:latex-title-command nil nil org-latex-title-command) + (:latex-toc-command nil nil org-latex-toc-command) + (:latex-compiler "LATEX_COMPILER" nil org-latex-compiler) + ;; Redefine regular options. + (:date "DATE" nil "\\today" parse))) @@ -164,11 +208,112 @@ ("uk" . "ukrainian")) "Alist between language code and corresponding Babel option.") +(defconst org-latex-polyglossia-language-alist + '(("am" "amharic") + ("ast" "asturian") + ("ar" "arabic") + ("bo" "tibetan") + ("bn" "bengali") + ("bg" "bulgarian") + ("br" "breton") + ("bt-br" "brazilian") + ("ca" "catalan") + ("cop" "coptic") + ("cs" "czech") + ("cy" "welsh") + ("da" "danish") + ("de" "german" "german") + ("de-at" "german" "austrian") + ("de-de" "german" "german") + ("dv" "divehi") + ("el" "greek") + ("en" "english" "usmax") + ("en-au" "english" "australian") + ("en-gb" "english" "uk") + ("en-nz" "english" "newzealand") + ("en-us" "english" "usmax") + ("eo" "esperanto") + ("es" "spanish") + ("et" "estonian") + ("eu" "basque") + ("fa" "farsi") + ("fi" "finnish") + ("fr" "french") + ("fu" "friulan") + ("ga" "irish") + ("gd" "scottish") + ("gl" "galician") + ("he" "hebrew") + ("hi" "hindi") + ("hr" "croatian") + ("hu" "magyar") + ("hy" "armenian") + ("id" "bahasai") + ("ia" "interlingua") + ("is" "icelandic") + ("it" "italian") + ("kn" "kannada") + ("la" "latin" "modern") + ("la-modern" "latin" "modern") + ("la-classic" "latin" "classic") + ("la-medieval" "latin" "medieval") + ("lo" "lao") + ("lt" "lithuanian") + ("lv" "latvian") + ("mr" "maranthi") + ("ml" "malayalam") + ("nl" "dutch") + ("nb" "norsk") + ("nn" "nynorsk") + ("nko" "nko") + ("no" "norsk") + ("oc" "occitan") + ("pl" "polish") + ("pms" "piedmontese") + ("pt" "portuges") + ("rm" "romansh") + ("ro" "romanian") + ("ru" "russian") + ("sa" "sanskrit") + ("hsb" "usorbian") + ("dsb" "lsorbian") + ("sk" "slovak") + ("sl" "slovenian") + ("se" "samin") + ("sq" "albanian") + ("sr" "serbian") + ("sv" "swedish") + ("syr" "syriac") + ("ta" "tamil") + ("te" "telugu") + ("th" "thai") + ("tk" "turkmen") + ("tr" "turkish") + ("uk" "ukrainian") + ("ur" "urdu") + ("vi" "vietnamese")) + "Alist between language code and corresponding Polyglossia option") + + + (defconst org-latex-table-matrix-macros '(("bordermatrix" . "\\cr") - ("qbordermatrix" . "\\cr") - ("kbordermatrix" . "\\\\")) + ("qbordermatrix" . "\\cr") + ("kbordermatrix" . "\\\\")) "Alist between matrix macros and their row ending.") +(defconst org-latex-math-environments-re + (format + "\\`[ \t]*\\\\begin{%s\\*?}" + (regexp-opt + '("equation" "eqnarray" "math" "displaymath" + "align" "gather" "multline" "flalign" "alignat" + "xalignat" "xxalignat" + "subequations" + ;; breqn + "dmath" "dseries" "dgroup" "darray" + ;; empheq + "empheq"))) + "Regexp of LaTeX math environments.") ;;; User Configurable Variables @@ -178,6 +323,79 @@ :tag "Org Export LaTeX" :group 'org-export) +;;;; Generic + +(defcustom org-latex-caption-above '(table) + "When non-nil, place caption string at the beginning of elements. +Otherwise, place it near the end. When value is a list of +symbols, put caption above selected elements only. Allowed +symbols are: `image', `table', `src-block' and `special-block'." + :group 'org-export-latex + :version "26.1" + :package-version '(Org . "8.3") + :type '(choice + (const :tag "For all elements" t) + (const :tag "For no element" nil) + (set :tag "For the following elements only" :greedy t + (const :tag "Images" image) + (const :tag "Tables" table) + (const :tag "Source code" src-block) + (const :tag "Special blocks" special-block)))) + +(defcustom org-latex-prefer-user-labels nil + "Use user-provided labels instead of internal ones when non-nil. + +When this variable is non-nil, Org will use the value of +CUSTOM_ID property, NAME keyword or Org target as the key for the +\\label commands generated. + +By default, Org generates its own internal labels during LaTeX +export. This process ensures that the \\label keys are unique +and valid, but it means the keys are not available in advance of +the export process. + +Setting this variable gives you control over how Org generates +labels during LaTeX export, so that you may know their keys in +advance. One reason to do this is that it allows you to refer to +various elements using a single label both in Org's link syntax +and in embedded LaTeX code. + +For example, when this variable is non-nil, a headline like this: + + ** Some section + :PROPERTIES: + :CUSTOM_ID: sec:foo + :END: + This is section [[#sec:foo]]. + #+BEGIN_EXPORT latex + And this is still section \\ref{sec:foo}. + #+END_EXPORT + +will be exported to LaTeX as: + + \\subsection{Some section} + \\label{sec:foo} + This is section \\ref{sec:foo}. + And this is still section \\ref{sec:foo}. + +Note, however, that setting this variable introduces a limitation +on the possible values for CUSTOM_ID and NAME. When this +variable is non-nil, Org passes their value to \\label unchanged. +You are responsible for ensuring that the value is a valid LaTeX +\\label key, and that no other \\label commands with the same key +appear elsewhere in your document. (Keys may contain letters, +numbers, and the following punctuation: '_' '.' '-' ':'.) There +are no such limitations on CUSTOM_ID and NAME when this variable +is nil. + +For headlines that do not define the CUSTOM_ID property or +elements without a NAME, Org will continue to use its default +labeling scheme to generate labels and resolve links into proper +references." + :group 'org-export-latex + :type 'boolean + :version "26.1" + :package-version '(Org . "8.3")) ;;;; Preamble @@ -264,11 +482,15 @@ AUTO will automatically be replaced with a coding system derived from `buffer-file-coding-system'. See also the variable `org-latex-inputenc-alist' for a way to influence this mechanism. -Likewise, if your header contains \"\\usepackage[AUTO]{babel}\", -AUTO will be replaced with the language related to the language -code specified by `org-export-default-language', which see. Note -that constructions such as \"\\usepackage[french,AUTO,english]{babel}\" -are permitted. +Likewise, if your header contains \"\\usepackage[AUTO]{babel}\" +or \"\\usepackage[AUTO]{polyglossia}\", AUTO will be replaced +with the language related to the language code specified by +`org-export-default-language'. Note that constructions such as +\"\\usepackage[french,AUTO,english]{babel}\" are permitted. For +Polyglossia the language will be set via the macros +\"\\setmainlanguage\" and \"\\setotherlanguage\". See also +`org-latex-guess-babel-language' and +`org-latex-guess-polyglossia-language'. The sectioning structure ------------------------ @@ -328,11 +550,42 @@ are written as utf8 files." (defcustom org-latex-title-command "\\maketitle" "The command used to insert the title just after \\begin{document}. -If this string contains the formatting specification \"%s\" then -it will be used as a formatting string, passing the title as an -argument." + +This format string may contain these elements: + + %a for AUTHOR keyword + %t for TITLE keyword + %s for SUBTITLE keyword + %k for KEYWORDS line + %d for DESCRIPTION line + %c for CREATOR line + %l for Language keyword + %L for capitalized language keyword + %D for DATE keyword + +If you need to use a \"%\" character, you need to escape it +like that: \"%%\". + +Setting :latex-title-command in publishing projects will take +precedence over this variable." :group 'org-export-latex - :type 'string) + :type '(string :tag "Format string")) + +(defcustom org-latex-subtitle-format "\\\\\\medskip\n\\large %s" + "Format string used for transcoded subtitle. +The format string should have at most one \"%s\"-expression, +which is replaced with the subtitle." + :group 'org-export-latex + :version "26.1" + :package-version '(Org . "8.3") + :type '(string :tag "Format string")) + +(defcustom org-latex-subtitle-separate nil + "Non-nil means the subtitle is not typeset as part of title." + :group 'org-export-latex + :version "26.1" + :package-version '(Org . "8.3") + :type 'boolean) (defcustom org-latex-toc-command "\\tableofcontents\n\n" "LaTeX command to set the table of contents, list of figures, etc. @@ -341,10 +594,36 @@ the toc:nil option, not to those generated with #+TOC keyword." :group 'org-export-latex :type 'string) -(defcustom org-latex-with-hyperref t - "Toggle insertion of \\hypersetup{...} in the preamble." +(defcustom org-latex-hyperref-template + "\\hypersetup{\n pdfauthor={%a},\n pdftitle={%t},\n pdfkeywords={%k}, + pdfsubject={%d},\n pdfcreator={%c}, \n pdflang={%L}}\n" + "Template for hyperref package options. + +This format string may contain these elements: + + %a for AUTHOR keyword + %t for TITLE keyword + %s for SUBTITLE keyword + %k for KEYWORDS line + %d for DESCRIPTION line + %c for CREATOR line + %l for Language keyword + %L for capitalized language keyword + %D for DATE keyword + +If you need to use a \"%\" character, you need to escape it +like that: \"%%\". + +As a special case, a nil value prevents template from being +inserted. + +Setting :latex-hyperref-template in publishing projects will take +precedence over this variable." :group 'org-export-latex - :type 'boolean) + :version "26.1" + :package-version '(Org . "8.3") + :type '(choice (const :tag "No template" nil) + (string :tag "Format string"))) ;;;; Headline @@ -352,17 +631,15 @@ the toc:nil option, not to those generated with #+TOC keyword." 'org-latex-format-headline-default-function "Function for formatting the headline's text. -This function will be called with 5 arguments: -TODO the todo keyword (string or nil). +This function will be called with six arguments: +TODO the todo keyword (string or nil) TODO-TYPE the type of todo (symbol: `todo', `done', nil) PRIORITY the priority of the headline (integer or nil) -TEXT the main headline text (string). -TAGS the tags as a list of strings (list of strings or nil). - -The function result will be used in the section format string. +TEXT the main headline text (string) +TAGS the tags (list of strings or nil) +INFO the export options (plist) -Use `org-latex-format-headline-default-function' by default, -which format headlines like for Org version prior to 8.0." +The function result will be used in the section format string." :group 'org-export-latex :version "24.4" :package-version '(Org . "8.0") @@ -376,6 +653,16 @@ which format headlines like for Org version prior to 8.0." :group 'org-export-latex :type 'string) +(defcustom org-latex-footnote-defined-format "\\textsuperscript{\\ref{%s}}" + "Format string used to format reference to footnote already defined. +%s will be replaced by the label of the referred footnote." + :group 'org-export-latex + :type '(choice + (const :tag "Use plain superscript (default)" "\\textsuperscript{\\ref{%s}}") + (const :tag "Use Memoir/KOMA-Script footref" "\\footref{%s}") + (string :tag "Other format string")) + :version "26.1" + :package-version '(Org . "9.0")) ;;;; Timestamps @@ -397,6 +684,14 @@ which format headlines like for Org version prior to 8.0." ;;;; Links +(defcustom org-latex-images-centered t + "When non-nil, images are centered." + :group 'org-export-latex + :version "26.1" + :package-version '(Org . "9.0") + :type 'boolean + :safe #'booleanp) + (defcustom org-latex-image-default-option "" "Default option for images." :group 'org-export-latex @@ -422,10 +717,13 @@ environment." :package-version '(Org . "8.0") :type 'string) -(defcustom org-latex-default-figure-position "htb" - "Default position for latex figures." +(defcustom org-latex-default-figure-position "htbp" + "Default position for LaTeX figures." :group 'org-export-latex - :type 'string) + :type 'string + :version "26.1" + :package-version '(Org . "9.0") + :safe #'stringp) (defcustom org-latex-inline-image-rules '(("file" . "\\.\\(pdf\\|jpeg\\|jpg\\|png\\|ps\\|eps\\|tikz\\|pgf\\|svg\\)\\'")) @@ -489,12 +787,14 @@ When modifying this variable, it may be useful to change :type '(choice (const :tag "Table" table) (const :tag "Matrix" math) (const :tag "Inline matrix" inline-math) - (const :tag "Verbatim" verbatim))) + (const :tag "Verbatim" verbatim)) + :safe (lambda (s) (memq s '(table math inline-math verbatim)))) (defcustom org-latex-tables-centered t "When non-nil, tables are exported in a center environment." :group 'org-export-latex - :type 'boolean) + :type 'boolean + :safe #'booleanp) (defcustom org-latex-tables-booktabs nil "When non-nil, display tables in a formal \"booktabs\" style. @@ -505,13 +805,8 @@ attributes." :group 'org-export-latex :version "24.4" :package-version '(Org . "8.0") - :type 'boolean) - -(defcustom org-latex-table-caption-above t - "When non-nil, place caption string at the beginning of the table. -Otherwise, place it near the end." - :group 'org-export-latex - :type 'boolean) + :type 'boolean + :safe #'booleanp) (defcustom org-latex-table-scientific-notation "%s\\,(%s)" "Format string to display numbers in scientific notation. @@ -526,11 +821,10 @@ When nil, no transformation is made." (string :tag "Format string") (const :tag "No formatting" nil))) - ;;;; Text markup (defcustom org-latex-text-markup-alist '((bold . "\\textbf{%s}") - (code . verb) + (code . protectedtexttt) (italic . "\\emph{%s}") (strike-through . "\\sout{%s}") (underline . "\\uline{%s}") @@ -550,14 +844,15 @@ to typeset and try to protect special characters. If no association can be found for a given markup, text will be returned as-is." :group 'org-export-latex + :version "26.1" + :package-version '(Org . "8.3") :type 'alist :options '(bold code italic strike-through underline verbatim)) ;;;; Drawers -(defcustom org-latex-format-drawer-function - (lambda (name contents) contents) +(defcustom org-latex-format-drawer-function (lambda (_ contents) contents) "Function called to format a drawer in LaTeX code. The function must accept two parameters: @@ -575,44 +870,24 @@ The default function simply returns the value of CONTENTS." ;;;; Inlinetasks -(defcustom org-latex-format-inlinetask-function 'ignore +(defcustom org-latex-format-inlinetask-function + 'org-latex-format-inlinetask-default-function "Function called to format an inlinetask in LaTeX code. -The function must accept six parameters: - TODO the todo keyword, as a string - TODO-TYPE the todo type, a symbol among `todo', `done' and nil. - PRIORITY the inlinetask priority, as a string - NAME the inlinetask name, as a string. - TAGS the inlinetask tags, as a list of strings. - CONTENTS the contents of the inlinetask, as a string. - -The function should return the string to be exported. +The function must accept seven parameters: + TODO the todo keyword (string or nil) + TODO-TYPE the todo type (symbol: `todo', `done', nil) + PRIORITY the inlinetask priority (integer or nil) + NAME the inlinetask name (string) + TAGS the inlinetask tags (list of strings or nil) + CONTENTS the contents of the inlinetask (string or nil) + INFO the export options (plist) -For example, the variable could be set to the following function -in order to mimic default behavior: - -\(defun org-latex-format-inlinetask (todo type priority name tags contents) -\"Format an inline task element for LaTeX export.\" - (let ((full-title - (concat - (when todo - (format \"\\\\textbf{\\\\textsf{\\\\textsc{%s}}} \" todo)) - (when priority (format \"\\\\framebox{\\\\#%c} \" priority)) - title - (when tags - (format \"\\\\hfill{}\\\\textsc{:%s:}\" - (mapconcat \\='identity tags \":\"))))) - (format (concat \"\\\\begin{center}\\n\" - \"\\\\fbox{\\n\" - \"\\\\begin{minipage}[c]{.6\\\\textwidth}\\n\" - \"%s\\n\\n\" - \"\\\\rule[.8em]{\\\\textwidth}{2pt}\\n\\n\" - \"%s\" - \"\\\\end{minipage}}\" - \"\\\\end{center}\") - full-title contents))" +The function should return the string to be exported." :group 'org-export-latex - :type 'function) + :type 'function + :version "26.1" + :package-version '(Org . "8.3")) ;; Src blocks @@ -640,7 +915,7 @@ the minted package to `org-latex-packages-alist', for example using customize, or with (require \\='ox-latex) - (add-to-list \\='org-latex-packages-alist \\='(\"\" \"minted\")) + (add-to-list \\='org-latex-packages-alist \\='(\"newfloat\" \"minted\")) In addition, it is necessary to install pygments \(http://pygments.org), and to configure the variable @@ -656,7 +931,8 @@ into previewing problems, please consult :type '(choice (const :tag "Use listings" t) (const :tag "Use minted" minted) - (const :tag "Export verbatim" nil))) + (const :tag "Export verbatim" nil)) + :safe (lambda (s) (memq s '(t nil minted)))) (defcustom org-latex-listings-langs '((emacs-lisp "Lisp") (lisp "Lisp") (clojure "Lisp") @@ -668,7 +944,9 @@ into previewing problems, please consult (shell-script "bash") (gnuplot "Gnuplot") (ocaml "Caml") (caml "Caml") - (sql "SQL") (sqlite "sql")) + (sql "SQL") (sqlite "sql") + (makefile "make") + (R "r")) "Alist mapping languages to their listing language counterpart. The key is a symbol, the major mode symbol without the \"-mode\". The value is the string that should be inserted as the language @@ -676,6 +954,8 @@ parameter for the listings package. If the mode name and the listings name are the same, the language does not need an entry in this list - but it does not hurt if it is present." :group 'org-export-latex + :version "24.4" + :package-version '(Org . "8.3") :type '(repeat (list (symbol :tag "Major mode ") @@ -697,7 +977,13 @@ will typeset the code in a small size font with underlined, bold black keywords. Note that the same options will be applied to blocks of all -languages." +languages. If you need block-specific options, you may use the +following syntax: + + #+ATTR_LATEX: :options key1=value1,key2=value2 + #+BEGIN_SRC + ... + #+END_SRC" :group 'org-export-latex :type '(repeat (list @@ -744,41 +1030,132 @@ will result in src blocks being exported with \\begin{minted}[bgcolor=bg,frame=lines]{} as the start of the minted environment. Note that the same -options will be applied to blocks of all languages." +options will be applied to blocks of all languages. If you need +block-specific options, you may use the following syntax: + + #+ATTR_LATEX: :options key1=value1,key2=value2 + #+BEGIN_SRC + ... + #+END_SRC" :group 'org-export-latex :type '(repeat (list (string :tag "Minted option name ") (string :tag "Minted option value")))) -(defvar org-latex-custom-lang-environments nil +(defcustom org-latex-custom-lang-environments nil "Alist mapping languages to language-specific LaTeX environments. It is used during export of src blocks by the listings and minted -latex packages. For example, +latex packages. The environment may be a simple string, composed of +only letters and numbers. In this case, the string is directly the +name of the latex environment to use. The environment may also be +a format string. In this case the format string will be directly +exported. This format string may contain these elements: + + %s for the formatted source + %c for the caption + %f for the float attribute + %l for an appropriate label + %o for the LaTeX attributes + +For example, (setq org-latex-custom-lang-environments - \\='((python \"pythoncode\"))) + \\='((python \"pythoncode\") + (ocaml \"\\\\begin{listing} +\\\\begin{minted}[%o]{ocaml} +%s\\\\end{minted} +\\\\caption{%c} +\\\\label{%l}\"))) -would have the effect that if org encounters begin_src python -during latex export it will output +would have the effect that if Org encounters a Python source block +during LaTeX export it will produce \\begin{pythoncode} - \\end{pythoncode}") + \\end{pythoncode} + +and if Org encounters an Ocaml source block during LaTeX export it +will produce + + \\begin{listing} + \\begin{minted}[]{ocaml} + + \\end{minted} + \\caption{} + \\label{